主要是用模板缓冲区来实现。
DepthStencilState StencilShadow
{
DepthEnable = true;
DepthWriteMask = ZERO;
DepthFunc = LESS;
StencilEnable = true;
StencilReadMask = 0xFFFFFFFF;
StencilWriteMask = 0xFFFFFFFF;
FrontFaceStencilFunc = ALWAYS;
FrontFaceStencilPass = INCR;
FrontFaceStencilFail = Keep;
BackFaceStencilFunc = ALWAYS;
BackFaceStencilPass = DECR;
BackFaceStencilFail = Keep;
};
BlendState AdditiveBlending
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = TRUE;
SrcBlend = SRC_ALPHA ;
DestBlend = INV_SRC_ALPHA ;
BlendOp = ADD;
SrcBlendAlpha = ZERO;
DestBlendAlpha = ZERO;
BlendOpAlpha = ADD;
RenderTargetWriteMask[0] = 0x0F;
};
Rendering Shadows
At the top level, the rendering steps look like the following:
- If ambient lighting is enabled, render the entire scene with ambient only.
- For each light in the scene, do the following:
- Disable depth-buffer and frame-buffer writing.
- Prepare the stencil buffer render states for rendering the shadow volume.
- Render the shadow volume mesh with a vertex extruding shader. This sets up the stencil buffer according to whether or not the pixels are in the shadow volume.
- Prepare the stencil buffer render states for lighting.
- Prepare the additive blending mode.
- Render the scene for lighting with only the light being processed.
Shadow Volume并不是一个没有缺陷的技术。除了高像素填充率和阴影边界检测外,在绘制过程中还可能出现错误。错误的主要原因是当一个几何模型在计算自阴影时,它的面通常被完全照亮或者完全变暗,这取决于这个面是否朝向光源。光照计算必须使用顶点法向而非表面法向。对于接近平行光源的面,它会被完全照亮或者完全变暗,而实际上应该部分处于光源中。这是从stencil shadow volume中继承来的问题,在计算阴影时必须被考虑。这个问题可以通过增加mesh密度来解决,这也增加了处理mesh的时间。顶点法向和面法向越接近,表面的问题就越少。如果程序不能把问题限制在可接受的范围内,就必须考虑使用其他的算法,比如PRT或者Shadow Map。