重建世界坐标
一、为什么 : 屏幕后处理得不到准确的世界空间下的物体的坐标, 都会使用深度纹理来重建每个像素在世界空间下的位置
二、怎么做 :
1 利用vp矩阵重建
先得到vp矩阵的逆矩阵
得到ndc的坐标
利用vp逆矩阵,将ndc坐标转化成世界空间下坐标
由于是在片元着色器中进行计算处理, 会比较耗费性能
详细原理,可以了解一下,shader中从观察空间到屏幕空间所做的一些列操作
2 屏幕射线插值的方式重建
其中: 0 -> bottomLeft; 1 -> bottomRight ; 2 -> topLeft ; 3 -> topRight
-- c#
vector3 toRight = right * halfWidth
vector3 toTop = up * halfHeight
topLeft = forward + toTop - toRight
topRight = forward + toTop + toRight
bottomLeft = forward - toTop - toRight
bottomRight = forward - toTop + toRight
//set matrix
Matrix4x4 frustumDir = Matrix4x4.identity;
frustumDir.SetRow(0,bottomLeft);
frustumDir.SetRow(1,bottomRight);
frustumDir.SetRow(2,topLeft);
frustumDir.SetRow(3,topRight);
mat.SetMatrix("_FrustumDir", frustumDir);
-- shader vertex
//uv值和对应的索引的关系 ,对应上图
// x =0 , y = 0 result 0
// x =0 , y = 1 result 2
// x = 1 , y = 0 result 1
// x = 1 , y = 1 result 3
int ix = (int)o.uv.z;int iy = (int)o.uv.w;
o.frustumDir = _FrustumDir[ix + 2 * iy];
-- shader fragment
//vertex到fragment的过程中是有个东西叫插值的,这个插值正好能把每个像素所在的向量求出。
float depth = UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, i.uv.zw));
float linearEyeDepth = LinearEyeDepth(depth);
float3 worldPos = _WorldSpaceCameraPos + linearEyeDepth * i.frustumDir.xyz;