ComputeScreenPos解释

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;
}
inline float4 ComputeNonStereoScreenPos(float4 pos) {
    float4 o = pos * 0.5f;
    o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w;
    o.zw = pos.zw;
    return o;
}

这里传入的是齐次坐标,所谓的齐次坐标是还没有在NDC中的那个坐标,对于透视投影来说,其还是在平截头体中,而对于正交投影来说,其坐标在-w和w,以及-h和h之间。那么此时需要将其进行透视除法,才能将坐标转换到规范化坐标系内,对于OpenGL来说是在-1到1之间的立方体内,而对于dx则是在-1到1以及z在0到1之间的长方体内。

ok,我们接下来讲讲什么是屏幕坐标空间,屏幕是有宽度和高度的,假设宽度为width,高度为height。则屏幕的左下角为0,0,而右上角为width和height。而其对应的左下角的uv为0和0,以及右上角为1,1。
那么经过透视除法是将其xy映射到了-1到1之间,那么就需要将此NDC坐标转换到0到1之间,那么就得除以2,加上0.5。
所以变换公式应该为:
ComputeScreenPos解释_第1张图片
那么再看看上面的代码:

inline float4 ComputeNonStereoScreenPos(float4 pos) {
    float4 o = pos * 0.5f;
    o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w;
    o.zw = pos.zw;
    return o;
}

传入的pos为齐次坐标,也就是还没有进行透视除法,还不是NDC坐标。
所以第1步是:
ComputeScreenPos解释_第2张图片
第2步:注意这里加上o.w是已经除以2的clipW了。
ComputeScreenPos解释_第3张图片
第3步:
把z和w分量重新设置回去,因为屏幕坐标中的z是无意义的,所以保持不变还是怎样无所谓。而w分量应该是原来的clipW而不是除以2之后的clipW/2,这里使用pos的w分量赋值,所以得到:
ComputeScreenPos解释_第4张图片
可见还要在片段着色器中进行透视除法,除以clipW,即可得到屏幕坐标空间下的uv坐标。
将screenX和screenY同时除以clipW之后,得到:
ComputeScreenPos解释_第5张图片
这里的w=clipW。

你可能感兴趣的:(Unity,unity)