通常,当你想绘制位图或者对视频表面进行填充时,你只能手工一个像素一个像素地进行。
例如:
UCHAR *video_buffer; ///points to VRAM or offscreen surface(离屏表面)
UCHAR *bitmap[8*8] ;holds our bitmap in row major form
///curde(粗) bitmap copy
///outer loop is for each row
for (int index_y = 0; index_y < 8; index_y++)
{
///inner loop is for each row
for(int index_x = 0; index_x < 8;index_x++)
{
video_buffer[x + index_x + (y + index_y)*640] = bitmap[index_x + index_y*8];
}end for index_x
}///end for index_y
上面操作的问题:1、出奇的慢; 2、没有考虑到透明度的存在,也就是说如果你在位图中有个被黑色围绕的物体,黑色将一并被拷贝
优化(考虑了透明度------用色彩0):
void Blit8*8(int x, int y,UCHAR *video_buffer , UCHAR *bitmap)
{
video _buffer = video_buffer + (x + y*640)
video_buffer += (x + (y << 9) + (y << 7));
UCHAR pixxel ; ///used to read/write pixels
for (int index_y = 0; index_y < 8; index_y++)
{
///inner loop is for each row
for(int index_x = 0; index_x < 8;index_x++)
{
if(pixel = bitmap[index_x])
video_buffer[index_x ] = pixel;
}end for index_x
bitmap += 8;
video_buffer += 640;
}///end for index_y
}
但是这个函数还有有太多的限制,不够好!!!!
利用硬件blitter:
内存填充意味着用某些值填充VRAM中的一块区域。大致过程是:先锁定表面,然后利用memset()或memcpy()操作和填充表面内存。
但是这个方法有一些问题:首先,既然采用主cpu进行内存填充,所以主总线是传输的一部分。其次,组成表面的VRAM不一定完全是线性的,这时,你将不得一线一线
的填充或者移动。
但是,利用硬件Blitter,你将可以立即直接填充或者移动大块VRAM和DirectDraw表面。
DirectDraw有两个用于显存块移动的函数Blt()和BltFast()。
为什么有两个不同的blitter函数?原因是Blt()功能全但较复杂,BltFast较简单但具有较少的参数。另外,Blt使用DirectDraw裁剪器,而BltFast没有。
Blt和BltFast都是从目标表面的接口上调用。
int Game_Main(void *parms = NULL, int num_parms = 0)
{
// this is the main loop of the game, do all your processing
// here
DDBLTFX ddbltfx; // the blitter fx structure
RECT dest_rect; // used to hold the destination RECT
// make sure this isn't executed again
if (window_closed)
return(0);
// for now test if user is hitting ESC and send WM_CLOSE
if (KEYDOWN(VK_ESCAPE))
{
PostMessage(main_window_handle,WM_CLOSE,0,0);
window_closed = 1;
} // end if
// first initialize the DDBLTFX structure
DDRAW_INIT_STRUCT(ddbltfx);
// now set the color word info to the color we desire
// in this case, we are assuming an 8-bit mode, hence,
// well use a color index from 0-255, but if this was a
// 16/24/32 bit example then we would fill the WORD with
// the RGB encoding for the pixel - remember!
ddbltfx.dwFillColor = _RGB16BIT565(rand()%256, rand()%256, rand()%256);
// get a random rectangle
int x1 = rand()%SCREEN_WIDTH;
int y1 = rand()%SCREEN_HEIGHT;
int x2 = rand()%SCREEN_WIDTH;
int y2 = rand()%SCREEN_HEIGHT;
// now set up the RECT structure to fill the region from
// (x1,y1) to (x2,y2) on the destination surface
dest_rect.left = x1;
dest_rect.top = y1;
dest_rect.right = x2;
dest_rect.bottom = y2;
// make the blitter call ///使用硬件Blitter
if (FAILED(lpddsprimary->Blt(&dest_rect, // pointer to dest RECT
NULL, // pointer to source surface
NULL, // pointer to source RECT
DDBLT_COLORFILL | DDBLT_WAIT,
// do a color fill and wait if you have to
&ddbltfx))) // pointer to DDBLTFX holding info
return(0);
// return success or failure or your own return code here
return(1);
} // end Game_Main
具体详细操作见P259.
从一个表面向另一个表面复制位图,见下节...........