|
模板缓冲技术
1. 什么是模板缓冲?
模板缓冲允许你'隐藏'每个点的渲染.你首先要确定使用z缓冲的位深度- 16, 24 or 32.当使用24bit 模式时有8bits未用内存,它正好用来存储模板缓冲的数据. 在 D3D8有两种格式 - 24bit Z 和 8bit 模板缓冲或 24bit Z 和 4bit 模板缓冲 (4bits未用). 我们使用模板缓冲要知道一个重要的方程 (StencilRef And StencilMask) CompFunc (StencilBufferValue And StencilMask) 方程中有四项: 1. StencilRef - 进行比较的参考数值 2. StencilMask - 掩模 3. CompFunc - 这个过程定义了每个像数如何通过模板缓冲 4. StencilBufferValue - 模板缓冲当前存储的数据 前三项可在 Direct3DDevice8.SetRenderState( ) 中设置.
模板缓冲可以建立非常高级的特效棗阴影,反射... 模板深度表示屏幕上每个像数被重绘的次数。它是进行z缓冲的结果.下面是一个简单的例子: 首先,枚举可支持的模板缓冲 If D3D.CheckDepthStencilMatch(0, D3DDEVTYPE_HAL, _ DispMode.Format, DispMode.Format, _ D3DFMT_D24S8) = D3D_OK Then '我们使用 D24/S8格式 D3DWindow.AutoDepthStencilFormat = D3DFMT_D24S8
下面代码显示了如何配置模板缓冲通道 Private Sub SetupStencilBuffer() With D3DDevice .SetRenderState D3DRS_STENCILENABLE, 1 .SetRenderState D3DRS_STENCILFUNC, D3DCMP_ALWAYS .SetRenderState D3DRS_STENCILREF, 0 .SetRenderState D3DRS_STENCILMASK, 0 .SetRenderState D3DRS_STENCILWRITEMASK, &HFFFFFFFF .SetRenderState D3DRS_STENCILZFAIL, D3DSTENCILOP_INCRSAT .SetRenderState D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP .SetRenderState D3DRS_STENCILPASS, D3DSTENCILOP_INCRSAT End With End Sub 前两行声明了开起模板缓冲功能。设置测试比较为总是通过D3DCMP_ALWAYS,不论模板缓冲存储的数据是否大于或小于参考值STENCILREF。这样掩模STENCILMASK的值也无所谓。最后一行表示测试通过的话模板深度加1。
我们现在可以用各种颜色来渲染出模板深度,它表示每像数绘制了几次。现在不需要写入操作了, SetRenderState D3DRS_STENCILPASS, D3DSTENCILOP_KEEP用来保持模板深度的数据。SetRenderState D3DRS_STENCILFUNC, D3DCMP_NOTEQUAL表示进行不等于的比较操作 Private Sub RenderOverDraw() Dim TLVerts(0 To 3) As TLVERTEX '//needed to size the quad properly. Dim VP As D3DVIEWPORT8 D3DDevice.GetViewport VP '//set up the default parameters for the TL Quad. The colour will '//be altered for each level we draw. TLVerts(0).rhw = 1: TLVerts(1).rhw = 1: TLVerts(2).rhw = 1: TLVerts(3).rhw = 1 TLVerts(0).Color = D3DColorXRGB(255, 0, 0) TLVerts(1).Color = TLVerts(0).Color TLVerts(2).Color = TLVerts(0).Color TLVerts(3).Color = TLVerts(0).Color TLVerts(0).X = 0: TLVerts(0).Y = 0 TLVerts(1).X = VP.Width: TLVerts(1).Y = 0 TLVerts(2).X = 0: TLVerts(2).Y = VP.Height TLVerts(3).X = VP.Width: TLVerts(3).Y = VP.Height D3DDevice.SetTexture 0, Nothing D3DDevice.SetVertexShader FVF_TLVERTEX D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 0, 0 With D3DDevice If bWire Then .SetRenderState D3DRS_FILLMODE, D3DFILL_SOLID '//we dont care whats in the z buffer, so ignore it. .SetRenderState D3DRS_ZENABLE, 0 .SetRenderState D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP .SetRenderState D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP .SetRenderState D3DRS_STENCILPASS, D3DSTENCILOP_KEEP .SetRenderState D3DRS_STENCILFUNC, D3DCMP_NOTEQUAL .SetRenderState D3DRS_STENCILREF, 0 'DRAW LEVEL 1 OVERDRAW .SetRenderState D3DRS_STENCILMASK, &H1 TLVerts(0).Color = D3DColorXRGB(0, 0, 255)'兰色 TLVerts(1).Color = TLVerts(0).Color TLVerts(2).Color = TLVerts(0).Color TLVerts(3).Color = TLVerts(0).Color .DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TLVerts(0), Len(TLVerts(0)) 'DRAW LEVEL 2 OVERDRAW .SetRenderState D3DRS_STENCILMASK, &H2 TLVerts(0).Color = D3DColorXRGB(0, 255, 0) '绿色 TLVerts(1).Color = TLVerts(0).Color TLVerts(2).Color = TLVerts(0).Color TLVerts(3).Color = TLVerts(0).Color .DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TLVerts(0), Len(TLVerts(0)) 'DRAW LEVEL 3 OVERDRAW .SetRenderState D3DRS_STENCILMASK, &H4 TLVerts(0).Color = D3DColorXRGB(255, 128, 0) TLVerts(1).Color = TLVerts(0).Color TLVerts(2).Color = TLVerts(0).Color TLVerts(3).Color = TLVerts(0).Color .DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TLVerts(0), Len(TLVerts(0)) ... 'restore the various stage states... .SetRenderState D3DRS_ZENABLE, 1 .SetRenderState D3DRS_STENCILENABLE, 0 End With End Sub
每次渲染改变掩模的值(1st, 2nd, 3rd and 4th...次方),比如某一像数存储的数据为1,既它先前只绘制过一次,在第一次兰色渲染时掩模为&H1,参考值为0,方程(&H0 and &H1)<>( &H1and &H1)为真,通过测试,第2次绿色渲染时掩模为&H2,方程(&H0 and &H2)<>( &H1and &H2)为假,测试失败
模板缓冲体积阴影
图中的 (1) 和 (2) 都是面对观察者的面,所以它們所涵盖的 pixel,就是「射線會射入阴影椎的 pixel。而 (3) 則是背对观察者的面,所以它所涵蓋的 pixel 是射線會離開阴影椎的 pixel。所以,會和阴影錐有交集的 pixel,就是 (1) + (2) - (3) 的那些 pixel,也就是阴影所在的位置。 面對与背對可通过CULLMODE, D3DCULL_CW(D3DCULL_CCW)控制。D3DRS_SRCBLEND, D3DBLEND_ZERO D3DRS_DESTBLEND, D3DBLEND_ONE可使目标层中数据不改变,而只写入模板缓冲中。
但是体积阴影有一缺点,当视线进入阴影椎内会出现问题,且填充率严重不足,(如图)。
|