在模拟水体或镜面的效果是,周围的环境会反射在这些平面上。一般的做法把反射后环境渲染在一张texture上(RTT),再把这张texture作为水面(或镜面)的纹理最终渲染出来.
1. reflection plane 的确认。也就是水面或镜面的平面plane是的位置。我们只要反射水平面以上的东西,所以,这个reflection plane 也是clip plane; 注意plane 的法线方向,所谓的平面上方是指在法线方向一侧. 所以 plane{0,1,0,0} 和plane {0,-1,0,0}是不一样的.
2. reflection plane 的变换
与 固定管线不同, programmable pipeline 的Plane变换发生在 view和porj投射后的空间。最终要变换到clip空间,还要对变换矩阵作iverse 和 transpose:
matWVP = matWorld*matView* matProj;
D3DXMatrixInverse(&matWVP,0,&matWVP);
D3DXMatrixTranspose(&matWVP,&matWVP);
D3DXPlaneTransform(&clipUpPlane,&ReflectPlaneUp,&matWVP);
3. reflection 矩阵. DirectX 提供接口D3DXMatrixReflect( &g_matReflect,&ReflectPlane); 可以取得相对于ReflectPlane 的反射矩阵.
然后
matWorld = matWorld*g_matReflect;
matWorldViewProj = matWorld*matView* matProj;
就是反射后的视口变换矩阵.
4.计算GetScreenTexCoords
我们已经把经平面反射后的世界渲染到一个texture( 该texture的长宽跟窗口等同),如何影射到反射面呢?
在 vertex shader阶段,已经计算好了顶点的视口坐标,据此得到ScreenTexCoords:
float4 vResult;
vResult.x = ( vPos.x * 0.5 + vPos.w * 0.5 );
vResult.y = ( vPos.w * 0.5 - vPos.y * 0.5 );
vResult.z = vPos.w;
vResult.w = vPos.w;
在 pixel shader中,vResult.xy/vResult.w 作为纹理坐标 就可以了
float4 texColor = tex2D( texSampler,(texCoord2.xy / texCoord2.w) );
源码在web:http://file.mofile.com/ 提取码:6890315678898997