【问题标题】:Screen coordinates in fragment shader片段着色器中的屏幕坐标
【发布时间】:2014-05-17 20:19:37
【问题描述】:

在片段着色器中,如下所示:

Shader "ColorReplacement" {

    Properties {
        _MainTex ("Greyscale (R) Alpha (A)", 2D) = "white" {}
    }
    SubShader {
        ZTest LEqual
        ZWrite On
        Pass {
            Name "ColorReplacement"
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
        #pragma target 3.0
                #include "UnityCG.cginc"


                struct v2f
                {
                    float4  pos : SV_POSITION;
                    float4  uv : TEXCOORD0;
                }; 

                v2f vert (appdata_tan v)
                {
                    v2f o;
                    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                    o.uv = v.texcoord.xy;
                    return o;
                }

                sampler2D _MainTex;

                float4 frag(v2f i) : COLOR
                {

                }
            ENDCG
        }
    }
    Fallback off
 }

有没有办法知道i.uv在屏幕上的坐标?

我对着色器完全陌生。着色器应用于在屏幕某处绘制的对象,传递给frag 的第一个像素可能不对应于屏幕的第一个像素(视口),有没有办法知道这个像素在屏幕坐标?


编辑 是的,我想获取屏幕上的片段位置。 Unity 接受用 Cg 和 HLSL 编写的顶点和片段程序。但我不知道如何将此着色器转换为 HLSL。

gl_FragCoord 在 Cg 中的等价物是 WPOS。我可以运行以下着色器:

Shader "Custom/WindowCoordinates/Base" {
SubShader {
    Pass {
        CGPROGRAM

        #pragma vertex vert
        #pragma fragment frag
        #pragma target 3.0

        #include "UnityCG.cginc"

        float4 vert(appdata_base v) : POSITION {
            return mul (UNITY_MATRIX_MVP, v.vertex);
        }

        fixed4 frag(float4 sp:WPOS) : COLOR {
            return fixed4(sp.xy/_ScreenParams.xy,0.0,1.0);
        }
        ENDCG
    }
}
}

它以我想要的方式使用屏幕位置,但我是如此菜鸟,以至于我什至无法混合两个着色器来获得我想要的:在我的着色器中,我试图访问v2f.pos,即在上面的着色器中以相同的方式计算sp,但我得到了错误:

Program 'frag', variable/member "pos" has semantic "POSITION" which is not visible in this profile

如果我将 pos 更改为 WPOS 而不是 SV_POSITION 我会收到类似的错误:

Program 'vert', variable/member "pos" has semantic "WPOS" which is not visible in this profile at line 35

这很奇怪,因为我使用的是与上述着色器相同的target 3.0

【问题讨论】:

  • 你解决了吗? :)
  • 不 :( 最终做了一个解决方法

标签: unity3d shader fragment-shader vertex-shader cg


【解决方案1】:

在 GLSL 片段阶段,有一个内置变量 gl_FragCoord,它携带视口内的片段像素位置。如果视口覆盖整个屏幕,这就是您所需要的。如果视口仅覆盖屏幕的一个子窗口,则必须将 xy 偏移量传递给视口并将其添加到 gl_FragCoord.xy 以获取屏幕位置。现在您的着色器代码不是用 GLSL 编写的,而是用 Cg 编写的(似乎带有 Unity 扩展)。但它应该有一些可用的对应关系。

【讨论】:

  • 这还不够,他必须计算纹素大小才能获得正确的屏幕坐标。
  • 我根据你的回答更新了我的问题,你们可以看看吗?谢谢!
【解决方案2】:

我建议你阅读一些关于着色器的书籍或手册,这里有一个简单的解决方案

      vec2 texelSize = 1.0 / vec2(textureSize(yourTexSampler, 0));
  vec2 screenCoords = gl_FragCoord.xy * texelSize;

我不记得在 Cg 中如何调用 gl_FragCoord,因此请在文档中搜索。对于 textureSize() - - 替换为输入纹理的宽度/高度。

Here is 我前段时间问的问题完全相同。

也可以看看this

【讨论】:

  • 我的印象是OP想要获取屏幕上的目标片段位置。如果它是关于纹理的像素,那么是的,你也可以缩放它。
  • Unity 在_MainTex_TexelSize.xy 中提供了纹素尺寸。您的texelSize 计算是不必要的。
  • 不用乘除除法,只需将碎片坐标除以屏幕大小即可。
【解决方案3】:

According to docs 有一个辅助函数——ComputeScreenPos。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 2021-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多