使用模板缓冲创建一个投影

对于投影来说,本质和镜面反射一样。
创建一个模型,然后将该模型的所有顶点通过矩阵坍缩到一个平面上。
然后在对应的平面使用模板缓冲,再将该模型绘制到这个平面上。
当然直接投影的话,地面上的阴影并不像影子,因为他的贴图跟模型是一样,因此我们要把它的贴图换成黑色贴图,半透明也可。

先上图
shadow

转换成投影顶点的矩阵为函数为
[cc lang=”actionscript3″]
//计算光照投影矩阵
public static function getShadowMatrix(n : Vector3D, p : Vector3D, light : Vector3D, out : Vector.) : Vector.
{
n.normalize();
//平行光的话,需要标准化光线方向,并逆转平面法线
if(light.w == 0){
light.normalize();
n.scaleBy(-1);
}
var d:Number=-n.dotProduct(p);
var k:Number=n.x*light.x+n.y*light.y+n.z*light.z+d*light.w;

if(null == out) out = new Vector.();

out.push(k-n.x*light.x, -n.x*light.y, -n.x*light.z, -n.x*light.w);
out.push(-n.y*light.x, k-n.y*light.y, -n.y*light.z, -n.y*light.w);
out.push(-n.z*light.x, -n.z*light.y, k-n.z*light.z, -n.z*light.w);
out.push(-d*light.x, -d*light.y, -d*light.z, k-d*light.w);

return out;
}
[/cc]

之后还是跟渲染镜面反射一样, 开启模板缓冲
[cc lang=”actionscript3″]
/**
* 绘制投影
*/

//关闭深度测试
m_context.setDepthTest(false,Context3DCompareMode.LESS);

//设置模板值为0,之后绘制的三角形会使模板值递增
m_context.setStencilReferenceValue(0);
m_context.setStencilActions(Context3DTriangleFace.BACK,
Context3DCompareMode.EQUAL, Context3DStencilAction.INCREMENT_SATURATE);

m_wall.render(m_cameraMatrix, m_projMatrix, m_shader);

m_context.setStencilReferenceValue(1);

//混合模式为 1 * dest + 0 * 0 = dest. 目标颜色为墙体颜色和阴影颜色的混合
m_context.setBlendFactors(Context3DBlendFactor.SOURCE_COLOR, Context3DBlendFactor.DESTINATION_COLOR);

m_shadowTeapot.render(m_cameraMatrix,m_projMatrix,m_shader);
m_shadowTeapot.moveTo(m_teapot.position.x,m_teapot.position.y,m_teapot.position.z);
m_shadowTeapot.rotation(t, Vector3D.Y_AXIS);

m_context.setCulling(Context3DTriangleFace.FRONT);
[/cc]

绘制完投影后,我们要清空缓存,然后在绘制镜面来填充模板,之后都和镜面反射的render一样了.

[cc lang=”actionscript3″]
/**
* 绘制反射
*/

//清空模板
m_context.clear(0,0,0,1,1,0,Context3DClearMask.STENCIL);

//设置模板值为0,之后绘制的三角形会使模板值递增
m_context.setStencilReferenceValue(0);
m_context.setStencilActions(Context3DTriangleFace.FRONT,
Context3DCompareMode.EQUAL, Context3DStencilAction.INCREMENT_SATURATE);

m_mirrorMesh.render(m_cameraMatrix,m_projMatrix,m_shader);

//混合模式为 1 * dest + 0 * 0 = dest. 目标颜色为镜子颜色和飞船颜色的混合
m_context.setBlendFactors(Context3DBlendFactor.DESTINATION_COLOR, Context3DBlendFactor.ZERO);
m_context.setCulling(Context3DTriangleFace.BACK);
m_context.setStencilReferenceValue(1);

m_mirrorTeapot.render(m_cameraMatrix,m_projMatrix,m_shader);
m_mirrorTeapot.moveTo(m_teapot.position.x,m_teapot.position.y,m_teapot.position.z);
m_mirrorTeapot.rotation(t, Vector3D.Y_AXIS);
[/cc]

demo is here

发表评论

电子邮件地址不会被公开。 必填项已用*标注