一.模板缓冲区:
板缓冲区(Stencil Buffer)与后台缓冲区大小相同,类似于深度缓冲区可以控制相似是否写入。
模板可以通过设置简单的参数及测试方法允许或者拒绝像素的写入。
利用模板缓冲技术可以实现阴影体 镜面反射 渐入渐出等效果。
这里只介绍阴影体和镜面的实现方式。
二.镜面反射:
镜面反射实现思路比较简单利用模板测试的方式分三次绘制即可实现:
1. 绘制除镜面成像以外的所有场景对象.
2. 绘制镜面区域设置通过设置模板掩码及模板值标记出镜面区域例如:
设置模板比较函数为总是通过,通过之后将模板值设置为0xffffffff
(Device->SetRenderState( D3DRS_STENCILREF, 0x1 );
Device->SetRenderState( D3DRS_STENCILMASK, 0xffffffff );
Device->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
Device->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE );
然后绘制镜面)此时就将镜面区域的模板值设置为了0xffffffff。
3. 计算场景对象在镜面中的位置 开启模板测试 设置可以在模板
值为0xffffffff的区域内绘制,即可保证在镜面区域内绘制出镜面中的场景.
( Device->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_EQUAL);
Device->SetRenderState( D3DRS_STENCILMASK, 0xffffffff );
然后绘制镜面中场景物件即可。 )
三.动态阴影:
相比镜面反射,动态阴影的实现则更为复杂些。其具体步骤可以简单归纳为:
1. 计算轮廓边:
a. 将光线方向转化到模型空间
b. 遍历模型所有面,由面法线与光线方向计算夹角,取得所有夹角小
于90度的面及边
c. 判断所有边中只出现过一次的边则为轮廓边
2. 由轮廓边及光线方向可将轮廓边的每个顶点沿光线方向
延伸出一条射线形成阴影体。
3. 通过设置模板缓冲绘制阴影区域:(也是动态阴影绘制最复杂部分)
a. 设置背面裁剪绘制阴影体,在绘制阴影体时设置模板缓冲区总是通过,
且通过之后模板值自增1.
b. 设置证明裁剪绘制阴影体,在绘制阴影体是设置模板缓冲总是通过,
且通过之后模板值自减1.
4. 绘制阴影,开启模板测试,将模板掩码设置为1,测试函数设置为小于等于,
在测试通过区域绘制阴影。
注:
基本原理如下:
如图: 上面三角形区域是轮廓边 整个三棱柱为阴影体, 而所需绘制
的阴影部分则为红色圈区域 - 绿色圈区域。因此先绘制红色边区域(也
就是背面剔除 绘制)将此部分区域也就是红色圈模板自增1, 然后正面剔
除绘制背面区域也就是绿色区域将模板值自减1,此时剩下的模板值为1的
区域就是阴影区域。
三.其他:
除镜面和阴影外模板还可以用于实现渐入渐出等效果,另外关于模板掩码
模板值 模板比较函数 三个值得关系是用模板值与上模板掩码 在用比较
函数进行比较 比较结果为通过时可以绘制。
设模板掩码为 MASK 模板值为 VALUE 比较函数为 FUC 则模板测试的过程为 FUC( MASK & VALUE )