1

My shader does some math to determine vertex alpha, so I've got a function to do that before the data gets passed into my surf function.

    #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;
    }

Then when I use Input IN I want someAlpha to be reflected when the alpha is set:

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

Currently, absolutely nothing happens. How can I use the alpha value I want in surf?

Ruzihm
  • 19,749
  • 5
  • 36
  • 48
Nol
  • 344
  • 3
  • 15

2 Answers2

0

Yes. You can add a COLOR semantic to your Input object:

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

Then assign to it in foo (although this may not be necessary if you have #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;
}

Then use it in 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; 
}

Finally, tell Unity to use foo as a vertex shader before the surface shader by changing #pragma surface surf Standard alpha to:

#pragma surface surf Standard alpha vertex:foo
Ruzihm
  • 19,749
  • 5
  • 36
  • 48
  • 1
    I tried this out and didn't get any result. I even tried setting o.vertColor = 0; but that value doesn't seem to have any effect when o.Alpha is set to vertexColor.a (or IN.vertColor.a) in the surf function. – Nol Dec 31 '19 at 17:41
  • I've added the pragma. It doesn't seem like variable name on `float4 var : COLOR` is the issue, according to Input struct docs. – Nol Dec 31 '19 at 19:56
  • 1
    @Nol Thanks for including that information now. Seems like it's not using your vertex shader at all. Change your `#pragma surface surf Standard alpha` to `#pragma surface surf Standard alpha vertex:vert` – Ruzihm Dec 31 '19 at 20:04
  • 1
    Brilliant! I never noticed, I just needed to define my `foo` as a vertex shader. It's not working quite the same as my non-surface shader version, but now it's just math. Thank you! – Nol Dec 31 '19 at 20:14
  • Oh yeah `foo` not `vert`. glad i could help! – Ruzihm Dec 31 '19 at 20:14
0

I cannot confirm what is written in the approved answer. I ran a few tests and had a look at the generated code.

The surface shader will always set the color in vertex program to:

o.color = v.color;

No matter what it actuall says. So if you have:

struct Input {
    fixed4 color : COLOR;
};

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

Unity will generate this:

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

So what you can do, is to put your code in the surf function instead:

float4 vertexColor = IN.color * fixed4(2,1,1,1);
            
jettatore
  • 371
  • 3
  • 5