
第四章、全屏模式和深度缓冲.docx
3页第四章:全屏幕模式和深度缓冲Introduction (序)在此章中,我们把以往单个的文件(Main.cpp)转换成了两个类:CGame和CCuboidCGame包含了主要的代 码,例如游戏的初始化和循环、渲染工作都有它来完成CCuboid用来创建立方体对象:你可以指定位置与尺寸 CCuboid也包含一个渲染函数,将会在CGame的渲染函数中被调用其实程序并没有作什么太大的改动,你会发 现它会像以往一样容易理解我们改动了程序使它成为了全屏幕的模式,这在某方面这要比窗口式的强多了;我们还 会接触一下深度缓冲从现在起,程序代码不会像以往一样全部放在教程中了(因为很长,放进来也不容易看);取 而代之,我会只放进来一些有意义的代码片断,其实这样也好Depth Buffers (深度缓冲)嗯,深度缓冲,听起来挺神秘的,是吧?但我要告诉你,这又是一个简单的概念深度缓冲(又称Z-buffer)的作用 是确保多边形能够正确地显示在它们本来的深度(相对于摄像机)上例如在你的场景中有两个矩形:一个是蓝色 的而另一个是绿色的;蓝色的Z值为10,绿色的Z值为20 (摄像机在原点);这就意味着蓝色的在绿色的前面(看下面的图示)。
深度缓冲能确定哪个对象在另一个对象的前面,正确的将被渲染DirectX会测试对象在屏幕上 的像素点到摄像机的远近,并把得出的值保存在深度缓冲中;接着,DirectX会测试同一位置另一对象的像素点,并 和刚才的像素进行比较:如果更近,就刷新刚才的纪录,否则就不理睬(有东西在它前面挡着它)这会决定此位置 像素点的颜色到底是蓝色的 Objedt2Rendering Su rfa ceFig 4.1要在程序中使用深度缓冲是很简单的事情,所有要做的只有:在初始化D3D的函数中选择正确的格式、激活深度缓 冲和确保在渲染函数中清空深度缓冲在此章的源代码中,CGame的InitialiseD3D模块里,我增加了一些选择 深度缓冲格式的源代码D3DPRESENT_PARAMETERS结构中,有两个参数要设置: d3dpp.AutoDepthStencilFormat = D3DFMT_D16;d3dpp.EnableAutoDepthStencil = TRUE;要激活深度缓冲,需要在你的InitialiseD3D模块中增加此行代码: mpD3DDevice->SetRenderState(D3DRS ZENABLE, D3DZB TRUE);然后确保在CGame的Render模块中增加了 D3DCLEAR_ZBUFFER标识使设备清除函数(Clear)能正确地清空深度缓冲:m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); — — —Full Screen (全屏幕)要使用全屏幕模式,我们需要调整一下InitialiseD3D模块:把D3DPRESENT_PARAMETERS结构的 “Windowed”参数设置为FALSE,通知D3D我们要使用全屏幕模式;然后,乖们还需要设置D3DPRESENT_PARAMETERS结构中的两个全屏幕参数:FullScreen_RefreshRateInHz用于设置屏幕刷新率, FullScreen_PresentationInterval 用于设置页翻动的最大速度,我们选择了 D3DPRESENT_INTERVAL_ONE 标识来限定仅当屏幕刷新时完成页翻动。
译者注:上面的后几句是按照原意翻译的,但我想这样可能不太好懂,我要在此大概地说明一下:当电子束从上至下 完成了屏幕上的每一行水平回扫后,会被暂时关闭,回到屏幕的左上角;此过程所需的时间被称为垂直回扫周期或 屏幕空白周期有时,程序能完成的刷新速率(页翻动速度)可能要比屏幕刷新率还高,所以我们要使它在限定的 垂直回扫周期内完成刷新工作,否则将产生“图像撕裂”原文上述的设定为至少等待一个垂直回扫周期(一次的屏 幕刷新完成后)来完成页翻动操作d3dpp.Windowed = FALSE;d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;d3dpp.FullScreen PresentationInterval = D3DPRESENT INTERVAL ONE;嗯,我们还应该选择正确的后缓冲区格式我写了一个模块CheckDisplayMode用来测试正确的格式,此模块会在InitialiseD3D模块中被调用D3DFORMAT CGame::CheckDisplayMode(UINT nWidth, UINT nHeight, UINT nDepth) ( UINT x; D3DDISPLAYMODE d3ddm; for(x = 0; x < m_pD3D->GetAdapterModeCount(0); x++) { —m_pD3D->EnumAdapterModes(0, x, &d3ddm); if(d3ddm.Width == nWidth) { if(d3ddm.Height == nHeight) { if((d3ddm.Format == D3DFMT_R5G6B5) || (d3ddm.Format == D3DFMT_X1R5G5B5) || (d3ddm.Format == D3DFMT_X4R4G4B4)) { —if(nDepth == 16) { return d3ddm.Format; } } else if((d3ddm.Format == D3DFMT_R8G8B8) || (d3ddm.Format == D3DFMT_X8R8G8B8)) { —if(nDepth == 32) { return d3ddm.Format; } } } } } return D3DFMT_UNKNOWN; } —还有一件要做的事就是我们修改了 WinMain函数中的创建窗口部分,我们用了 GetSystemMetrics函数得到了当 前屏幕的宽与高,然后将我们的窗口设置成了与屏幕一样大。
Logging (实时记录)我们的程序还有了写纪录的功能,这在调试时是很有用的我为CGame添加了 EnableLogging和WriteToLog 模块,而且在WinMain刚刚完成CGame的初始化时就调用了 EnableLogging,它会清理当前的纪录然后激活纪 录功能一旦记录功能被激活了,WriteToLog就能单纯地向记录文件中写记录了当程序关闭后,记录工作就会完 成你要记住:程序的显示速率不会高于屏幕刷新率,那是因为我们设置了 FullScreen_PresentationInterval为 D3DPRESENT_INTERVAL_ONE程序运行后记录文件会存在于你的程序目录中,名为“ Log.txt”运行程序会得到下面的画面:六个不同大小和位置的立方体,怎么样?Summary (摘要)老外说:We haven't really added a lot of code in this tutorial, but we have re-organised it into classes. Take some time to familiarise yourself with the new structure, you'll see that most of the functions are unchanged. Full screen rendering and depth buffers are pretty straightforward; now that we've created them we don't really need to worry about them any further. In the next tutorial we will look into matrix transformations. We touched on them in the last tutorial, but this time we will go a little further and demonstrate the power of matrix transformations.俺说:此章中,我们学习了全屏幕模式与深度缓冲,这是令人兴奋的。
其实慢慢学来,一切并非想象的那样难你认 为呢?好了,又翻译了一章,还真有点累,去歇一会儿了先・••..啊,对了,下一章我们要学的是:神奇的 矩阵变换读者:切~拉长音卖关子)。












