模板缓冲技术

 

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可使目标层中数据不改变,而只写入模板缓冲中。

 

 

但是体积阴影有一缺点,当视线进入阴影椎内会出现问题,且填充率严重不足,(如图)。

 

文件下载