搭建Windows渲染环境

来源:互联网 发布:刚性兑付 知乎 编辑:程序博客网 时间:2024/06/06 09:04

之前已经讨论过操作系统无关的图形库部分,这一篇将重点放在windows渲染环境上.

事实上windows api自带一个图形库gdi,gdi对于dib的支持比较好,可以创建一个dib对象,每一帧向dib位图指针提交rgb数据,然后把生成的位图提交到屏幕,于是就能在屏幕中看到渲染的图形了.


创建和释放位图


void initDIB(HDC dibDC,int width,int height) {BITMAPINFO bmi;memset(&bmi,0,sizeof(bmi));bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);bmi.bmiHeader.biWidth=width;bmi.bmiHeader.biHeight=-height;bmi.bmiHeader.biPlanes=1;bmi.bmiHeader.biBitCount=32;bmi.bmiHeader.biCompression=BI_RGB;screenDIB=CreateDIBSection(NULL,&bmi,DIB_RGB_COLORS,(void**)&screenBits,NULL,0);dibBefore=(HBITMAP)SelectObject(dibDC,screenDIB);}void releaseDIB(HDC dibDC) {if(screenDIB!=NULL) {SelectObject(dibDC,dibBefore);DeleteObject(screenDIB);screenDIB=NULL;}}
首先创建一个32位位图,如果取24位位图那么长宽为任意值时将会出问题;位图宽为屏幕宽度,高为屏幕高度的负数,因为dib的y轴是从下向上的,而windows屏幕坐标系是从上往下的,所以需要取反.这些问题都在<windows程序设计>一书中有提到过.

缩放代码:
case WM_SIZE:swidth=LOWORD(lParam); sheight=HIWORD(lParam);resize(LOWORD(lParam),HIWORD(lParam));releaseDIB(dibDC);initDIB(dibDC,LOWORD(lParam),HIWORD(lParam));InvalidateRect(hWnd,NULL,FALSE);break;
每次缩放都要先释放原来的渲染环境,然后建立新的渲染环境,接着再刷新窗口.

提交像素

void swapBuffer() {if(frontBuffer==frameBuffer1) {frontBuffer=frameBuffer2;backBuffer=frameBuffer1;} else {frontBuffer=frameBuffer1;backBuffer=frameBuffer2;}if(!buffersReady) {buffersReady=true;return;}FrameBuffer* fb=frontBuffer;for(int i=0;i<fb->height;i++) {for(int j=0;j<fb->width;j++) {int index=(i*fb->width+j)*3;unsigned char red=fb->colorBuffer[index];unsigned char green=fb->colorBuffer[index+1];unsigned char blue=fb->colorBuffer[index+2];index=(i*fb->width+j)*4;screenBits[index]=blue;screenBits[index+1]=green;screenBits[index+2]=red;}}}

在做完交换缓冲区步骤以后将rgb颜色值提交给dib对应的数据指针,32位位图的组织结构如下:
typedef struct tagRGBQUAD {BYTErgbBlue;BYTErgbGreen;BYTErgbRed;BYTErgbReserved;} RGBQUAD,*LPRGBQUAD;
从高位到低位读就是ARGB,这边的A并不起作用,不用设值.

消息循环


这是windows消息循环:
while(!willExit) {if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {if(msg.message==WM_QUIT)willExit=true;else {TranslateMessage(&msg);DispatchMessage(&msg);}} else {runWindow();draw();BitBlt(hdc,0,0,swidth,sheight,dibDC,0,0,SRCCOPY);}}
每一帧都把dib的内容拷贝到屏幕上.

最终效果


这就是最终渲染到屏幕上的效果:



搭建完了windows渲染环境,软渲染程序就基本上完成了,虽然速度不快,但还是能勉强接受的.

参考资料:<Windows程序设计> <3D游戏编程大师技巧>

0 0