找回密码
 立即注册
查看: 530|回复: 0

[笔记] Unity Shader中的ComputeScreenPos函数

[复制链接]
发表于 2021-1-22 14:38 | 显示全部楼层 |阅读模式
Unity shader提供了内置函数ComputeScreenPos,其定义位于UnityCG.cginc中,大致如下:
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;
}
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;
}
其中的宏UNITY_SINGLE_PASS_STEREO用于控制在不同平台上计算方式的差异
看该函数的命名第一直觉是该函数返回的是屏幕空间下的坐标值,但是该函数返回的是齐次坐标下的屏幕坐标值。让我们剔除不必要的代码,来看核心的计算代码,如下
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为顶点变换到齐次坐标系下的坐标,也就是说,在shader中,你需要这么使用:
o.pos = UnityObjectToClipPos(v.vertex);
o.screenPos = ComputeScreenPos(o.pos);
接着来回顾下如何从齐次坐标变换到屏幕坐标:我们知道,顶点在变换到齐次坐标后,其x和y分量的范围在[-w, w]。假设目前屏幕的宽度为width,高度为height,那么屏幕坐标的计算方法为:
screenPosX = ((x / w) * 0.5 + 0.5) * width
screenPosY = ((y / w) * 0.5 + 0.5) * height


我们来看ComputeScreenPos是如何做的,它的计算方法为:
o.x = (pos.x * 0.5 + pos.w * 0.5)
o.y = (pos.y * 0.5 * _ProjectionParams.x + pos.w * 0.5)
其中_ProjectionParams.x用于在使用翻转投影矩阵时(此时其值为-1.0)翻转y的坐标值。
现在我们将屏幕坐标的计算方法变换到ComputeScreenPos使用的计算方法,如下:
screenPosX / width = ((x / w) * 0.5 + 0.5)
screenPosY / height = ((y / w) * 0.5 + 0.5)

两边同时乘w:

screenPosX / width * w = ((x * 0.5 + w * 0.5)
screenPosY / height * w = ((y * 0.5 + w * 0.5)
和unity shader 计算方法比较   
float4 o = pos * 0.5f;
o.xy = float2(o.x, o.y_ProjectionParams.x) + o.w;
o.zw = pos.zw;
展开将o.x=pos.x*0.5代入公式
o.x=pos.x0.5+pos.w*0.5


现在一目了然了,ComputeScreenPos返回的值是齐次坐标系下的屏幕坐标值,其范围为[0, w]。那么为什么Unity要这么做呢?Unity的本意是希望你把该坐标值用作tex2Dproj指令的参数值,tex2Dproj会在对纹理采样前除以w分量。当然你也可以像下面代码那样自己除以w分量后进行采样,但是效率不如内置指令tex2Dproj:

pos = UnityObjectToClipPos(v.vertex);
screenPos = ComputeScreenPos(o.pos);
tex2D(_ScreenTex, float2(screenPos.xy / screenPos.w))
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-6-4 23:52 , Processed in 0.087414 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表