前腐后继 发表于 2006-12-13 11:30:00

[翻译]使用DirectX9进行遮盖剔除

<strong> <br/><br/></strong>对象剔除是图形编程中一个重要的方面。渲染那些看不见的物体是十分耗时的。然而,就目前来说当务之急是优化剔除算法本身。因为通常剔除算法会消耗大量的处理时间。 <p></p><p>传统的算法对于一般情况的处理已经提升得很快了也改进得足够多了,但还是留下了些许遗憾。一些算法剔除了太多的物体,而另一些剔除的数量却不够多。</p><p>遮盖剔除的原理告诉我们一个事实,那就是一个物体即便在视锥内,仍有可能被遮住而看不见。</p><p><img src="http://images.gamedev.net/features/programming/occlusionculling/scene.jpg" border="0" alt=""/><br/><img src="http://images.gamedev.net/features/programming/occlusionculling/render.jpg" border="0" alt=""/></p><p>这里,如图1.1所示,有五个多边形被显示在屏幕上。然而,在最后的渲染结果中(如图1.2所示),实际只有三个物体可以看得见。简单的视锥剔除算法会导致所有的物体都被渲染,原因是它们都在视锥内。就象在图1.1中一样,即使另外两个物体完全被遮住,它们仍会被渲染,这将耗费许多时间。</p><p>遮盖剔除通常会判断哪个物体会真正看得见,只有这些物体才会被渲染,从而节省了大量的时间。遮盖物(occluder)就是那些以遮住其它物体的东西(比如:图1.1中的那个巨大的红色盒子)。部分被遮盖的物体就是那些只能部分看见的物体(蓝色的五边形和紫色的楔形),这是需要被渲染的。完全被遮的物体就是完全看不见的物体(绿色的球体和桔红色的盒子),它们在渲染过程中将被排除掉。</p><p>关于遮盖剔除的更多信息,请参看由Tomas&nbsp;M&amp;ouml;ller&nbsp;和&nbsp;Eric&nbsp;Haines写的Occlusion&nbsp;</p><p>Culling&nbsp;Algorithms地(<a href="http://bbs.gameres.com/Occlusion&nbsp;Culling&nbsp;Algorithms" target="_blank"><font color="#9c0000">Occlusion&nbsp;Culling&nbsp;Algorithms</font></a>)</p><p><font color="#663399">介绍IDirect3DQuery9</font></p><p>IDirect3DQuery9&nbsp;接口是Directx9的一个新特性。它允许开发人员能访问大量的统计数据,这其中包括优化信息、由资源管理器所处理的对象以及三角形处理信息。</p><p>IDirect3DQuery9&nbsp;还能执行遮盖请求,它将计算在屏幕上可见的象素数目。只有在请求开始和请求结束之间渲染的象素才会被计算在内。如果计算的结果为0,那么说明物体的所有顶点都被遮住了,这个物体就当前摄像机所处的位置来说是看不见的。另外,如果计算的结果是大于0的,那么物体是可见的。</p><p>Query&nbsp;Type&nbsp;Datatype&nbsp;Use&nbsp;<br/>D3DQUERYTYPE_VCACHE&nbsp;D3DDEVINFO_VCACHE&nbsp;Information&nbsp;about&nbsp;optimization,&nbsp;</p><p>pertaining&nbsp;to&nbsp;data&nbsp;layout&nbsp;for&nbsp;vertex&nbsp;caching&nbsp;<br/>D3DQUERYTYPE_RESOURCEMANAGER&nbsp;D3DDEVINFO_RESOURCEMANAGER&nbsp;Number&nbsp;of&nbsp;objects&nbsp;</p><p>sent,&nbsp;created,&nbsp;evicted,&nbsp;and&nbsp;managed&nbsp;in&nbsp;video&nbsp;memory&nbsp;<br/>D3DQUERYTYPE_VERTEXSTATS&nbsp;D3DDEVINFO_D3DVERTEXSTATS&nbsp;Number&nbsp;of&nbsp;triangles&nbsp;that&nbsp;</p><p>have&nbsp;been&nbsp;processed&nbsp;and&nbsp;clipped&nbsp;<br/>D3DQUERYTYPE_EVENT&nbsp;bool&nbsp;For&nbsp;any&nbsp;and&nbsp;all&nbsp;asynchronous&nbsp;events&nbsp;issued&nbsp;from&nbsp;API&nbsp;</p><p>calls&nbsp;<br/>D3DQUERYTYPE_OCCLUSION&nbsp;DWORD&nbsp;The&nbsp;number&nbsp;of&nbsp;pixels&nbsp;that&nbsp;pass&nbsp;Z-testing,&nbsp;or&nbsp;</p><p>are&nbsp;visible&nbsp;on-screen.&nbsp;<br/>Table&nbsp;2.1:&nbsp;Uses&nbsp;of&nbsp;IDirect3DQuery9&nbsp;</p><p>ATI的Occlusion&nbsp;Query(<a href="http://www.ati.com/developer/samples/dx9/OcclusionQuery.html" target="_blank"><font color="#9c0000">http://www.ati.com/developer/samples/dx9/OcclusionQuery.html</font></a>)演示给出了使用IDirect3DQuery9的基础。</p><p><font color="#663399">使用&nbsp;DirectX9进行遮盖剔除</font></p><p>IDirect3DQuery9的出现提供了一个简单而有效的遮盖剔除的方法。基本过程如下:</p><p>1. 渲染各物体的包围网格(bounding&nbsp;mesh)。<br/>2. 对每一个物体执行如下操作:<br/>  A。开始询问。<br/>  B。再一次渲染各物体的包围盒。<br/>  C。终止询问。<br/>  D。获取遮盖询问的数据。如果物体可见那么数据会大于0,此物体需要进行实际的渲染。否则物体将被排除。</p><p><font color="#663399">第一步:</font><br/>  对于遮盖测试物体的实际网格包含了太多的顶点,而包围网格的顶点数要少得多,它将被用作替代物。那为什么用包围网格而不是包围盒或包围球呢?</p><p><img src="http://images.gamedev.net/features/programming/occlusionculling/Bounding%20Types.jpg" border="0" alt=""/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;图3.1各种类型的包围体</p><p>图3.1展示了多种类型的包围体,包括盒体、球体和网格。注意在这个特定的例子中包围网格和包围球的顶点数目是一样的。可是,即使顶点数目比较接近,在体积的接近程度上,包围网格的体积上和原始网格的的体积是最接近的。这在遮盖处理中很重要,要不大量的顶点会错误地渲染或剔除掉。</p><p>然而包围网格不能像包围盒或包围球那样通过某个算法来产生。它需要实时地建模和加载,就象普通的网格一样。每一个对象的包围网格先渲染一次以确保Z-buffer中有整个场景的深度信息。如果遮盖询问在整个场景的深度信息加入Z-buffer之前就开始了,那么即使被要求询问的物体在最终的场景里完全被遮挡住,可能也会被错误地认为是可见的。</p><p><font color="#663399">第二步:</font><br/>  现在所有物体的包围网格深度数据已经在Z-buffer中了,我们还要再做一次同样的事,这一次遮盖询问将被用来判断每个物体的可视状态。如果询问后发现没有可见的象素,这个物体最后将不会被渲染。如果发现有一个或多个可见的象素点,那这个物体就会被加入到渲染处理过程里。</p><p>  需要重点注意的是遮盖剔除的渲染不应在全尺寸的主缓冲里进行。用一个小些的缓冲(320&nbsp;X&nbsp;240可以很好地工作)可以提升效率。</p><p><font color="#663399">代码</font></p><p><font color="#6633cc">类型声明</font></p><p>Sobject(代码表4.1)是主对象实体。CMesh是一个封装了加载、渲染和释放ID3DXMesh接口的类。</p><p>struct&nbsp;SObject<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;CMesh*&nbsp;meshReference;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Reference&nbsp;to&nbsp;a&nbsp;mesh&nbsp;object<br/>&nbsp;&nbsp;&nbsp;&nbsp;CMesh*&nbsp;boundingMesh;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Reference&nbsp;to&nbsp;low-poly&nbsp;bounding&nbsp;mesh</p><p>&nbsp;&nbsp;&nbsp;&nbsp;D3DXVECTOR3&nbsp;pos;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Position&nbsp;of&nbsp;this&nbsp;object<br/>&nbsp;&nbsp;&nbsp;&nbsp;D3DXMATRIX&nbsp;matTranslate;&nbsp;//&nbsp;Translation&nbsp;matrix&nbsp;for&nbsp;this&nbsp;object</p><p>&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;render;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;If&nbsp;true,&nbsp;render&nbsp;the&nbsp;object<br/>&nbsp;&nbsp;&nbsp;&nbsp;float&nbsp;distanceToCamera;&nbsp;&nbsp;//&nbsp;The&nbsp;distance&nbsp;to&nbsp;the&nbsp;camera&nbsp;(player&nbsp;position)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Constructor<br/>&nbsp;&nbsp;&nbsp;&nbsp;SObject(&nbsp;CMesh*&nbsp;meshRef,&nbsp;CMesh*&nbsp;boundMesh,&nbsp;D3DXVECTOR3&nbsp;position&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;meshReference&nbsp;=&nbsp;meshRef;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boundingMesh&nbsp;=&nbsp;boundMesh;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pos&nbsp;=&nbsp;position;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;render&nbsp;=&nbsp;false;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;distanceToCamera&nbsp;=&nbsp;0.0f;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>};<br/>Code&nbsp;Listing&nbsp;4.1:&nbsp;SObject&nbsp;definition</p><p><font color="#6633cc">对象声明</font></p><p>遮盖剔除的处理过程中,我们还需要声明LPDIRECT3DQUERY9,&nbsp;LPD3DXRENDERTOSURFACE,&nbsp;LPDIRECT3DSURFACE9,&nbsp;和&nbsp;LPDIRECT3DTEXTURE9&nbsp;</p><p>LPDIRECT3D9&nbsp;d3dObject;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Direct3D&nbsp;Object<br/>LPDIRECT3DDEVICE9&nbsp;d3dDevice;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Direct3D&nbsp;Device</p><p>LPDIRECT3DQUERY9&nbsp;d3dQuery;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;The&nbsp;occlusion&nbsp;query<br/>LPD3DXRENDERTOSURFACE&nbsp;occlusionRender;&nbsp;//&nbsp;Occlusion's&nbsp;render&nbsp;to&nbsp;surface<br/>LPDIRECT3DSURFACE9&nbsp;occlusionSurface;&nbsp;&nbsp;&nbsp;//&nbsp;Occlusion's&nbsp;surface&nbsp;that&nbsp;it&nbsp;uses<br/>LPDIRECT3DTEXTURE9&nbsp;occlusionTexture;&nbsp;&nbsp;&nbsp;//&nbsp;Texture&nbsp;to&nbsp;get&nbsp;surface&nbsp;from</p><p>std::vector&lt;SObject&gt;&nbsp;objects;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Vector&nbsp;of&nbsp;objects<br/>Code&nbsp;Listing&nbsp;4.2:&nbsp;Declarations&nbsp;of&nbsp;objects&nbsp;pertaining&nbsp;to&nbsp;the&nbsp;occlusion&nbsp;</p><p>culling&nbsp;procedure</p><p><font color="#6633cc">设置遮盖对象</font></p><p>首先询问要被创建,此外还有纹理和要渲染的缓冲。在创建纹理过程里我们要用到D3DUSAGE_RENDERTARGET&nbsp;,因为我们要在其上进行渲染。而缓冲通过LPDIRECT3DTEXTURE9&nbsp;中的GetSurfaceLevel()来获得。我们还要用LPD3DXRENDERTOSURFACE&nbsp;接口把Z-buffer的格式值设置成D3DFMT_D16。</p><p>//-----------------------------------------------------------------------------<br/>//&nbsp;Name:&nbsp;SetupOcclusion()<br/>//&nbsp;Desc:&nbsp;Create&nbsp;the&nbsp;objects&nbsp;needed&nbsp;for&nbsp;the&nbsp;occlusion&nbsp;culling<br/>//-----------------------------------------------------------------------------<br/>HRESULT&nbsp;SetupOcclusion()<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Create&nbsp;the&nbsp;query<br/>&nbsp;&nbsp;&nbsp;&nbsp;d3dDevice-&gt;CreateQuery(&nbsp;D3DQUERYTYPE_OCCLUSION,&nbsp;&amp;d3dQuery&nbsp;);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Get&nbsp;the&nbsp;display&nbsp;mode&nbsp;to&nbsp;obtain&nbsp;the&nbsp;format<br/>&nbsp;&nbsp;&nbsp;&nbsp;D3DDISPLAYMODE&nbsp;mode;<br/>&nbsp;&nbsp;&nbsp;&nbsp;d3dDevice-&gt;GetDisplayMode(&nbsp;0,&nbsp;&amp;mode&nbsp;);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Create&nbsp;the&nbsp;texture&nbsp;first,&nbsp;so&nbsp;we&nbsp;can&nbsp;get&nbsp;access&nbsp;to&nbsp;it's&nbsp;surface<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;FAILED(&nbsp;D3DXCreateTexture(&nbsp;d3dDevice,&nbsp;320,&nbsp;240,&nbsp;1,&nbsp;</p><p>D3DUSAGE_RENDERTARGET,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode.Format,&nbsp;D3DPOOL_DEFAULT,&nbsp;</p><p>&amp;occlusionTexture&nbsp;)&nbsp;)&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;E_FAIL;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}</p><p>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Obtain&nbsp;the&nbsp;surface&nbsp;(what&nbsp;we&nbsp;really&nbsp;need)<br/>&nbsp;&nbsp;&nbsp;&nbsp;D3DSURFACE_DESC&nbsp;desc;<br/>&nbsp;&nbsp;&nbsp;&nbsp;occlusionTexture-&gt;GetSurfaceLevel(0,&nbsp;&amp;occlusionSurface);<br/>&nbsp;&nbsp;&nbsp;&nbsp;occlusionSurface-&gt;GetDesc(&amp;desc);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Create&nbsp;the&nbsp;render&nbsp;to&nbsp;surface<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;FAILED(&nbsp;D3DXCreateRenderToSurface(&nbsp;d3dDevice,&nbsp;desc.Width,&nbsp;</p><p>desc.Height,&nbsp;desc.Format,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TRUE,&nbsp;D3DFMT_D16,&nbsp;</p><p>&amp;occlusionRender&nbsp;)&nbsp;)&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;E_FAIL;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}</p><p>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;S_OK;<br/>}<br/>Code&nbsp;Listing&nbsp;4.3:&nbsp;The&nbsp;SetupOcclusion()&nbsp;function</p><p><font color="#6633cc">剔除物体</font></p><p>OcclusionCull()函数实现了先前提到的算法。首先,D3DXRENDERTOSURFACE&nbsp;被激活</p><p>并被清空。接下来渲染对象的包围网格。再次渲染包围网格并获取遮盖询问数据。最后缓冲中的场景被中止并使其无效(即不实际渲染到屏幕)。</p><p>//-----------------------------------------------------------------------------<br/>//&nbsp;Name:&nbsp;OcclusionCull()<br/>//&nbsp;Desc:&nbsp;Cull&nbsp;the&nbsp;objects<br/>//-----------------------------------------------------------------------------<br/>HRESULT&nbsp;OcclusionCull()<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Begin&nbsp;occlusionRender<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;SUCCEEDED(&nbsp;occlusionRender-&gt;BeginScene(&nbsp;occlusionSurface,&nbsp;NULL&nbsp;)&nbsp;)&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Clear&nbsp;the&nbsp;occlusionRender's&nbsp;surface<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d3dDevice-&gt;Clear(0,&nbsp;NULL,&nbsp;D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DCOLOR_XRGB(&nbsp;200,&nbsp;200,&nbsp;200&nbsp;),&nbsp;1.0f,&nbsp;0);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;First,&nbsp;render&nbsp;every&nbsp;object's&nbsp;bounding&nbsp;box<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;objects.size();&nbsp;i++&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objects.boundingMesh-&gt;Render(&nbsp;d3dDevice,&nbsp;</p><p>objects.matTranslate&nbsp;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Now,&nbsp;render&nbsp;each&nbsp;box&nbsp;again,&nbsp;except&nbsp;this&nbsp;time,&nbsp;count&nbsp;how&nbsp;many&nbsp;</p><p>pixels&nbsp;are&nbsp;visible<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;by&nbsp;using&nbsp;an&nbsp;occlusion&nbsp;query.&nbsp;We&nbsp;are&nbsp;guaranteed&nbsp;to&nbsp;get&nbsp;the&nbsp;right&nbsp;</p><p>amount,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;since&nbsp;all&nbsp;the&nbsp;bounding&nbsp;boxes&nbsp;have&nbsp;already&nbsp;been&nbsp;rendered<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(&nbsp;int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;objects.size();&nbsp;i++&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Start&nbsp;the&nbsp;query<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d3dQuery-&gt;Issue(&nbsp;D3DISSUE_BEGIN&nbsp;);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Render<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objects.boundingMesh-&gt;Render(&nbsp;d3dDevice,&nbsp;</p><p>objects.matTranslate&nbsp;);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;End&nbsp;the&nbsp;query,&nbsp;get&nbsp;the&nbsp;data<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d3dQuery-&gt;Issue(&nbsp;D3DISSUE_END&nbsp;);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Loop&nbsp;until&nbsp;the&nbsp;data&nbsp;becomes&nbsp;available<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;pixelsVisible&nbsp;=&nbsp;0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(d3dQuery-&gt;GetData((void&nbsp;*)&nbsp;&amp;pixelsVisible,&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sizeof(DWORD),&nbsp;D3DGETDATA_FLUSH)&nbsp;==&nbsp;</p><p>S_FALSE);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;pixelsVisible&nbsp;==&nbsp;0&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objects.render&nbsp;=&nbsp;false;&nbsp;//&nbsp;No&nbsp;pixels&nbsp;visible,&nbsp;do&nbsp;not&nbsp;</p><p>render<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objects.render&nbsp;=&nbsp;true;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Pixels&nbsp;visible,&nbsp;render<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;End&nbsp;the&nbsp;occlusion&nbsp;render&nbsp;scene<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;occlusionRender-&gt;EndScene(&nbsp;0&nbsp;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;User&nbsp;is&nbsp;pressing&nbsp;the&nbsp;'M'&nbsp;key,&nbsp;save&nbsp;this&nbsp;buffer&nbsp;to&nbsp;.BMP&nbsp;file<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;keys['M']&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DXSaveSurfaceToFile(&nbsp;"buffer.bmp",&nbsp;D3DXIFF_BMP,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;occlusionSurface,&nbsp;NULL,&nbsp;NULL&nbsp;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}</p><p>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;S_OK;<br/>}<br/>Code&nbsp;Listing&nbsp;4.4:&nbsp;The&nbsp;OcclusionCull()&nbsp;function</p><p><font color="#6633cc">渲染循环</font></p><p>渲染循环包含创建所有资源(包括摄像机和转换矩阵)和物体的剔除。最后在最终场景中可视的物体将会被渲染。</p><p>//-----------------------------------------------------------------------------<br/>//&nbsp;Name:&nbsp;Render<br/>//&nbsp;Desc:&nbsp;Render&nbsp;a&nbsp;frame<br/>//-----------------------------------------------------------------------------<br/>HRESULT&nbsp;Render()<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Setup&nbsp;the&nbsp;matrices&nbsp;for&nbsp;this&nbsp;frame<br/>&nbsp;&nbsp;&nbsp;&nbsp;SetupMatrices();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Cull&nbsp;the&nbsp;objects<br/>&nbsp;&nbsp;&nbsp;&nbsp;OcclusionCull();</p><p>&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;SUCCEEDED(&nbsp;d3dDevice-&gt;BeginScene()&nbsp;)&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Clear&nbsp;the&nbsp;main&nbsp;device<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d3dDevice-&gt;Clear(&nbsp;0,&nbsp;NULL,&nbsp;D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DCOLOR_XRGB(255,0,0),&nbsp;1.0f,&nbsp;0&nbsp;);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Render&nbsp;the&nbsp;appropriate&nbsp;objects<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Leave&nbsp;out&nbsp;objects&nbsp;that&nbsp;are&nbsp;occluded<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(&nbsp;int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;objects.size();&nbsp;i++&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;objects.render&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objects.meshReference-&gt;Render(&nbsp;d3dDevice,&nbsp;</p><p>objects.matTranslate&nbsp;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d3dDevice-&gt;EndScene();<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Present&nbsp;the&nbsp;scene<br/>&nbsp;&nbsp;&nbsp;&nbsp;d3dDevice-&gt;Present(&nbsp;NULL,&nbsp;NULL,&nbsp;NULL,&nbsp;NULL&nbsp;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;S_OK;<br/>}<br/>Code&nbsp;Listing&nbsp;4.5:&nbsp;The&nbsp;simplified&nbsp;render&nbsp;loop</p>
页: [1]
查看完整版本: [翻译]使用DirectX9进行遮盖剔除