美文网首页
平面反射

平面反射

作者: LEO_青蛙 | 来源:发表于2020-06-22 22:16 被阅读0次
平面反射

GitHub项目地址

平面反射的实现步骤:

1、抓取屏幕图像——渲染纹理RenderTexture+额外摄像机
2、反射矩阵(ReflectMatrix)——获得反射的屏幕图像
3、斜裁剪矩阵(ObliqueMatrix)——裁剪掉反射平面以下的部分
4、高斯模糊——模糊反射的倒影
5、将反射纹理渲染到地面

1、抓取屏幕图像

之前的文章已经提过了,抓取屏幕图像有两种方法:
1、GrabPass
2、渲染纹理RenderTexture+额外摄像机
这里需要使用第二种方法:

private Camera mainCamera, reflectCamera;
private RenderTexture reflectTex;
private Renderer render;
private Material reflectMaterial;
void Start()
{
  mainCamera = Camera.main;
  GameObject go = new GameObject("ReflectCamera", typeof(Camera));
  reflectCamera = go.GetComponent<Camera>();
  reflectCamera.fieldOfView = mainCamera.fieldOfView;
  reflectCamera.aspect = mainCamera.aspect;
  reflectCamera.cullingMask = mainCamera.cullingMask;
  //自己控制渲染的层级
  //reflectCamera.cullingMask = 1 << LayerMask.NameToLayer("Player");
  reflectCamera.enabled = false;

  reflectTex = RenderTexture.GetTemporary(1024, 1024, 24);
  reflectCamera.targetTexture = reflectTex;

  render = GetComponent<Renderer>();
  reflectMaterial = render.sharedMaterial;
}

2、反射矩阵(ReflectMatrix)

顶点反射
反射矩阵
反射矩阵的推导过程https://zhuanlan.zhihu.com/p/92633614
//计算plane平面的反射矩阵
private void CalculateReflectMatrix(ref Matrix4x4 matrix, Vector4 plane)
{
  matrix.m00 = (1F - 2F * plane[0] * plane[0]);
  matrix.m01 = (-2F * plane[0] * plane[1]);
  matrix.m02 = (-2F * plane[0] * plane[2]);
  matrix.m03 = (-2F * plane[3] * plane[0]);

  matrix.m10 = (-2F * plane[1] * plane[0]);
  matrix.m11 = (1F - 2F * plane[1] * plane[1]);
  matrix.m12 = (-2F * plane[1] * plane[2]);
  matrix.m13 = (-2F * plane[3] * plane[1]);

  matrix.m20 = (-2F * plane[2] * plane[0]);
  matrix.m21 = (-2F * plane[2] * plane[1]);
  matrix.m22 = (1F - 2F * plane[2] * plane[2]);
  matrix.m23 = (-2F * plane[3] * plane[2]);
}

3、斜裁剪矩阵(ObliqueMatrix)

需要裁减红色部分

Unity已经为我们提供了获取斜裁减矩阵的方法CalculateObliqueMatrix,我们只需要注意这个方法的参数是视图空间的平面。

//为了反射相机近裁剪平面紧贴我们的反射平面,防止错误渲染
//我们需要重新计算反射相机的投影矩阵,斜裁剪矩阵(ObliqueMatrix)
Vector4 viewPlane = CameraSpacePlane(reflectCamera.worldToCameraMatrix, transform.position, normal);
reflectCamera.projectionMatrix = reflectCamera.CalculateObliqueMatrix(viewPlane);
//计算视图空间的平面
private Vector4 CameraSpacePlane(Matrix4x4 worldToCameraMatrix, Vector3 pos, Vector3 normal)
{
  Vector3 viewPos = worldToCameraMatrix.MultiplyPoint3x4(pos);
  Vector3 viewNormal = worldToCameraMatrix.MultiplyVector(normal).normalized;
  float w = -Vector3.Dot(viewPos, viewNormal);
  return new Vector4(viewNormal.x, viewNormal.y, viewNormal.z, w);
}

斜裁剪矩阵的推导过程https://zhuanlan.zhihu.com/p/92633614

4、高斯模糊

高斯模糊我前面的文章已经介绍过了,这里不详细写了。


平面反射+高斯模糊

5、将反射纹理渲染到地面

最后一步,我们需要将获取到的反射纹理渲染到地面。
我们只需要在渲染地面的时候,叠加反射纹理即可。

sampler2D _ReflectTex;
//vert
o.uvReflect = ComputeScreenPos(o.vertex);
//frag
fixed4 reflectCol = tex2Dproj(_ReflectTex, i.uvReflect);

相关文章

  • 镜面反射矩阵的推导

    镜面反射是以镜面作为反射平面,实物与反射物到反射平面的距离相等,实物与反射物方向相反,所以,反射矩阵由反射平面确定...

  • 平面反射

    GitHub项目地址 平面反射的实现步骤: 1、抓取屏幕图像——渲染纹理RenderTexture+额外摄像机2、...

  • 数字人C4D基础知识之一:反射扭曲

    【问题】 吧友茶兔子私信问: 数字人您好,我想问一下反射扭曲怎么做,就是物体反射在平面的时候,平面下的物体是扭曲的...

  • 镜中人

    平面镜成像原理:平面镜成像是一种物理现象。是指太阳或者灯的光照射到人的身上,被反射到镜面上平面镜又将光反射到人的眼...

  • 平面镜反射

    镜子是自己生活中必不可缺的一物品,我早上看一次,中午看一次,晚上看一次,半夜看一次,然后被吓半死。还有个神奇的规律...

  • 镜面反射的倾斜矩阵

    镜面反射使用倾斜矩阵,是为了解决在反射面下面的物体也会被渲染到反射面上的bug。 解决的办法是把反射平面作为反射相...

  • 光的反射

    光的反射 张岩松 我们都知道光的反射是要有发光源,反光物和光线 反射光线与入射光线与法线在同一平面上,反射光线和入...

  • 平面镜反射规律

    光——是一种与人类生活非常贴近,并且人类现在已经不得不需要它,需要它就不能生活的一种元素,光不仅能带给我们身体上的...

  • 小玩童科学探索馆第二十七次课

    实验名称:潜望镜 实验原理: 利用平面镜对光的反射改变光的路线 实验目的: 1.了解平面镜反光 2.了解潜望镜的原...

  • 初二物理学虎期末冲刺打卡计划day14

    图中AB、CD是由发光点S发出并经平面镜反射的两条光线,在图中画出S和它在平面镜中的像S′.

网友评论

      本文标题:平面反射

      本文链接:https://www.haomeiwen.com/subject/qhnffktx.html