- static Matrix4x4 CalculateReflectionMatrix(Matrix4x4 reflectionMat, Vector4 plane)
- {
- reflectionMat.m00 = (1.0F - 2.0F * plane[0] * plane[0]);
- reflectionMat.m01 = (-2.0F * plane[0] * plane[1]);
- reflectionMat.m02 = (-2.0F * plane[0] * plane[2]);
- reflectionMat.m03 = (-2.0F * plane[3] * plane[0]);
- reflectionMat.m10 = (-2.0F * plane[1] * plane[0]);
- reflectionMat.m11 = (1.0F - 2.0F * plane[1] * plane[1]);
- reflectionMat.m12 = (-2.0F * plane[1] * plane[2]);
- reflectionMat.m13 = (-2.0F * plane[3] * plane[1]);
- reflectionMat.m20 = (-2.0F * plane[2] * plane[0]);
- reflectionMat.m21 = (-2.0F * plane[2] * plane[1]);
- reflectionMat.m22 = (1.0F - 2.0F * plane[2] * plane[2]);
- reflectionMat.m23 = (-2.0F * plane[3] * plane[2]);
- reflectionMat.m30 = 0.0F;
- reflectionMat.m31 = 0.0F;
- reflectionMat.m32 = 0.0F;
- reflectionMat.m33 = 1.0F;
- return reflectionMat;
- [align=left]}
点击此处复制文本其中代码中4维数组plane存的是点法线式平面方程的参数。
投影矩阵
反射相机的投影矩阵并非常规的投影矩阵,反射面上的斜投影面才是反射相机真正的投影面,
所以需要用斜投影面代替掉常规的投影面。示例代码中给出了斜投影矩阵,
原理和推导过程参看本文末尾给出的参考文献链接。这里给出示意图:
绘制流程
1.创建反射摄像机reflectionCamera,reflectionCamera默认disable,用一张RenderTexutre来保存reflectionCamera绘制的结果,用来在之后的shader里采样。
2.在LateUpdate中根据当前摄像机去构造反射摄像机变换矩阵,涉及到反射面reflectiveSurface的选取,示例中是选取合适的路面做反射面,然后手动调用绘制,绘制前设置前面剔除,绘制完置回。
- private void RenderReflectionFor (Camera cam, Camera reflectCamera)
- {
- …
- //构造反射平面
- Vector3 pos = reflectiveSurface.transform.position;
- pos.y = reflectiveSurface.position.y;
- Vector3 normal = reflectiveSurface.transform.up;
- float d = -Vector3.Dot(normal, pos) - clipPlaneOffset;
- Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);
-
- //构造反射视图矩阵
- Matrix4x4 reflection = Matrix4x4.zero;
- reflection = CalculateReflectionMatrix(reflection, reflectionPlane);
- //得到反射摄像机位置
- oldpos = cam.transform.position;
- Vector3 newpos = reflection.MultiplyPoint (oldpos);
-
- //得到反射摄像机视图矩阵
- reflectCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;
-
- //得到反射摄像机投影矩阵
- Vector4 clipPlane = CameraSpacePlane(reflectCamera, pos, normal, 1.0f);
-
- Matrix4x4 projection = cam.projectionMatrix;
- projection = CalculateObliqueMatrix(projection, clipPlane);
- reflectCamera.projectionMatrix = projection;
-
- …
- GL.SetRevertBackfacing(true);
- reflectCamera.RenderWithShader (replacementShader, "Reflection");
- GL.SetRevertBackfacing(false);
- }
点击此处复制文本Shader
反射面的材质接受反射相机绘制好的RenderTexture做为贴图对其采样。
示例中的反射面——地面shader增加了uv扰动参数和噪声贴图用来达到扭曲效果,
还叠加了一个水花效果,这样的话使得雨天地面反射更加真实,而不是干净得像一面镜子。