shader 重建世界坐标

本文介绍了两种在屏幕后处理中重建世界坐标的常用方法:通过VP矩阵逆运算和屏幕射线插值方式。深入探讨了如何利用这些技术在片段着色器中计算像素级的世界坐标,对于理解游戏引擎中的渲染流程具有重要意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

重建世界坐标 
   一、为什么 : 屏幕后处理得不到准确的世界空间下的物体的坐标, 都会使用深度纹理来重建每个像素在世界空间下的位置
   二、怎么做 :
    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;

shader反射模糊是通过在屏幕空间中模拟光线的反射来实现的。该方法使用了深度和法线贴图来重建视锥内的世界,并计算反射光线与深度纹理的交点。然后,将该交点处的着色信息叠加到反射点上,从而实现反射效果。 具体来说,首先需要将视锥内的四个顶点传入着色器。可以使用内置的Blit函数绘制一个Quad,然后通过坐标转换和裁剪来获得Quad顶点的屏幕位置和UV坐标。接着,在片段着色器中,可以使用这些UV坐标来计算反射点的位置,并将其与深度纹理进行比较,以找到交点。最后,将交点处的着色信息叠加到反射点,从而实现反射模糊效果。 请注意,为了进行坐标转换,在Shader中使用了传入的矩阵而不是内置的矩阵。此外,还使用了GL.LoadOrtho函数来进行坐标转换。 以下是一个简单的实现示例: ```csharp v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : SV_Target { float2 reflectionUV = i.uv * 0.5 + 0.5; // 计算反射点的UV坐标 float depth = tex2D(_CameraDepthTexture, reflectionUV).r; // 获取深度纹理值 // 根据深度纹理值计算反射点的位置 float4 reflectionPos = float4(i.vertex.xy / i.vertex.w, depth, 1); // 将反射点的位置转换为屏幕坐标 float2 screenPos = reflectionPos.xy / reflectionPos.w * 0.5 + 0.5; // 获取反射点处的着色信息并叠加到该点 fixed4 color = tex2D(_CameraColorTexture, screenPos); return color; } ``` 请注意,这只是一个简单的实现示例,具体的反射模糊效果可能需要根据实际需求进行调整和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值