【Shader】ComputeScreenPos 的使用

 总结:

  1. (通常在顶点着色器中)使用 ComputeScreenPos 来计算 顶点位置 对应的 ScreenPos。
    1. 通常用法  float4 scrPos = ComputeScreenPos(UnityObjectToClipPos(v.vertex)); 
    2. ComputeScreenPos 所做的事情
      1. 接受的输入 顶点在裁剪空间(经过 MVP matrix 的变换) 的位置
      2. 将输出的范围 从 [-w, w] 转化为 [0, w]
    3. 如何使用 ComputeScreenPos 计算出的结果 screenPos
      1. screenPos / screenPos.w 之后,screenPos.xy 就会在落在 [0, 1] 范围内(这也是 tex2Dproj 会完成的事情)
  2. 使用 tex2Dproj 配合第一步中得出的 screenPos 来按屏幕 uv 采样 屏幕材质(如 _CameraDepthTexture 和 _CameraNormalTexture).

 

 

例子 使用 tex2D + screenPos 时: 

例子 使用 tex2Dproj + screenPos 时:

 

 

 

 

----- 以下转自 ComputeScreenPos解析-CSDN博客

今天学习Unity Shader做水特效时,看到两个函数ComputeScreenPos、tex2Dproj,相关代码如下:

……
i.proj = ComputeScreenPos(UnityObjectToClipPos(v.vertex));
……
half depth = LinearEyeDepth(tex2Dproj(_CameraDepthTexture, i.proj).r);
……

注意到ComputeScreenPos得到的结果用在了 tex2Dproj 函数中作为uv参数。看函数名ComputeScreenPos应该是计算屏幕坐标,得到的应该是具体的坐标值,不应该是uv值。遂查询该方法,定义如下:

inline float4 ComputeNonStereoScreenPos(float4 pos) {
    float4 o = pos * 0.5f;
  //                                  | 已知 pos.x[-1~1] pos.y[-1,1]
  // =(0.5x, 0.5y, 0.5z, 0.5w) | XY[-0.5~0.5]
  //                                  | W[0.5w], 齐次坐标 ( x/W, y/W, # ) o.xy
= float2(o.x, o.y*_ProjectionParams.x) + o.w;
  // =(0.5x + 0.5w, 0.5y * _Proj.x + 0.5w, 0.5z, 0.5w) | X [-0.5 ~ 0.5] + 0.5w
  //                                  | Y [-0.5高宽比 ~ 0.5高宽比] + 0.5w
  //                                  | W[0.5w], 齐次坐标 ( X/W + 1, Y * 高宽比/W + 1, # ) o.zw
= pos.zw;
  // =(0.5x + 0.5w, 0.5y * _Porj.x + 0.5w, z, w)            | X [-0.5 ~ 0.5] + 0.5w
  //                                  | Y [-0.5高宽比 ~ 0.5高宽比] + 0.5w
  //                                  | W[w], 齐次坐标 ( X/W + 0.5, Y * 高宽比/W + 0.5, # )
return o; } inline float4 ComputeScreenPos(float4 pos) { float4 o = ComputeNonStereoScreenPos(pos); #if defined(UNITY_SINGLE_PASS_STEREO) o.xy = TransformStereoScreenSpaceTex(o.xy, pos.w); #endif return o; }

发现ComputeScreenPos的输出的 XY 确实不是屏幕坐标,而是一个:

* ZW分量: z 为 clip space 的 z,w 为 clip space 的 w。

* XY分量:/w 之后 (0,0) 对应左下角,而 (1, 高宽比)对应右上角的一个坐标。 (直接作为 tex2Dproj 的坐标进行采样的时候就会除以w分量。)

 

我们需要在顶点着色器中使用ComputeScreenPos得到结果,在片元着色器中除以其次分量得到视口空间坐标,具体原因见《UnityShader入门精要》 4.93章节(92页)

posted @ 2024-07-14 14:50  bakabird1998  阅读(47)  评论(0编辑  收藏  举报