【问题标题】:Can vertex alpha be set for a surface shader appdata input?可以为表面着色器应用数据输入设置顶点 alpha 吗?
【发布时间】:2019-12-20 22:54:19
【问题描述】:

我的着色器做了一些数学运算来确定顶点 alpha,所以我有一个函数可以在数据传递到我的 surf 函数之前执行此操作。

    #pragma surface surf Standard alpha
    #pragma target 3.0

    struct Input
    {
        float2 uv_MainTex;
        float tranparency;
    };

    void foo(inout appdata_full v, out Input o) {
        UNITY_INITIALIZE_OUTPUT(Input, o);
        float someAlpha;
        [...some maths to create someAlpha value...]
        v.color.a = someAlpha;
        o.transparency = v.color.a;
    }

    half _Glossiness;
    half _Metallic;
    fixed4 _Color;

    UNITY_INSTANCING_BUFFER_START(Props)
    UNITY_INSTANCING_BUFFER_END(Props)

    void surf (Input IN, inout SurfaceOutputStandard o)
    {
        fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
        o.Albedo = c.rgb;
        o.Metallic = _Metallic;
        o.Smoothness = _Glossiness;
        o.Alpha = c.a;
    }

然后,当我使用 Input IN 时,我希望在设置 alpha 时反映 someAlpha:

o.Alpha = c.a; //Can I do c.a * IN.transparency ?

目前,绝对没有任何事情发生。如何在 surf 中使用我想要的 alpha 值?

【问题讨论】:

    标签: unity3d shader hlsl cg


    【解决方案1】:

    是的。您可以将 COLOR 语义添加到您的 Input 对象:

    struct Input {
        float4 uv_MainTex;
        float4 color : COLOR;
        };
    

    然后在foo 中分配给它(尽管如果您有#pragma surface surf,这可能不是必需的):

    void foo(inout appdata_full v, out Input o) {
        UNITY_INITIALIZE_OUTPUT(Input, o);
        float someAlpha;
        [...some maths to create someAlpha value...]
        v.color.a = someAlpha;
    
        o.color = v.color;
    }
    

    然后在surf中使用:

    void surf (Input IN, inout SurfaceOutputStandard o)
    {
        fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
        fixed4 vertexColor = IN.color;
        o.Albedo = c.rgb;
        o.Metallic = _Metallic;
        o.Smoothness = _Glossiness;
        o.Alpha = vertexColor.a * c.a; 
    }
    

    最后,将#pragma surface surf Standard alpha 更改为:

    #pragma surface surf Standard alpha vertex:foo
    

    【讨论】:

    • 我试过这个并没有得到任何结果。我什至尝试设置 o.vertColor = 0;但在 surf 函数中将 o.Alpha 设置为 vertexColor.a(或 IN.vertColor.a)时,该值似乎没有任何影响。
    • 我已经添加了编译指示。根据 Input struct docs,float4 var : COLOR 上的变量名似乎不是问题。
    • @Nol 感谢您现在提供该信息。似乎它根本没有使用您的顶点着色器。将您的 #pragma surface surf Standard alpha 更改为 #pragma surface surf Standard alpha vertex:vert
    • 太棒了!我从来没有注意到,我只需要将我的foo 定义为顶点着色器。它与我的非表面着色器版本不太一样,但现在它只是数学。谢谢!
    • 哦,是的 foo 不是 vert。很高兴我能帮上忙!
    【解决方案2】:

    我无法确认批准答案中的内容。我运行了一些测试并查看了生成的代码。

    表面着色器将始终将顶点程序中的颜色设置为:

    o.color = v.color;
    

    不管它实际上说什么。所以如果你有:

    struct Input {
        fixed4 color : COLOR;
    };
    
    void vert(inout appdata v, out Input o) {
        o.color = v.color * fixed4(2,1,1,1);
    }
    

    Unity 会生成这个:

    v2f_surf vert_surf (appdata v) {
      UNITY_SETUP_INSTANCE_ID(v);
      v2f_surf o;
      [...]
      Input customInputData;
      vert (v, customInputData);
      [...]
      o.color = v.color;
      [...]
    }
    

    所以你可以做的就是把你的代码放在 surf 函数中:

    float4 vertexColor = IN.color * fixed4(2,1,1,1);
                
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多