Search Unity

How can I get tangent on a surface shader ?

Discussion in 'Shaders' started by invadererik, Jun 1, 2013.

  1. invadererik

    invadererik

    Joined:
    Oct 31, 2010
    Posts:
    148
    I have this test shader(below), no errors, except some d3d11 warnings
    (Shader warning in 'Surface Vertex Test': Program 'frag_surf', 'surf': output parameter 'o' not completely initialized (compiling for d3d11) at line 51)

    How can I get rid of the warnings ?

    Code (csharp):
    1.  
    2. Shader "Surface Vertex Test"
    3. {
    4.     Properties
    5.     {
    6.          _MainTex ("Diffuse (RGB) Alpha (A)", 2D) = "white" {}
    7.     }
    8.    
    9.     SubShader
    10.     {  
    11.         CGPROGRAM
    12.         #pragma surface surf Custom vertex:vert
    13.                                                        
    14.             struct Input             
    15.             {
    16.                 float2 uv_MainTex;
    17.                
    18.                 half3 tangent_input;
    19.                 half3 binormal_input;                        
    20.             };
    21.  
    22.             struct SurfaceOutputCustom
    23.             {
    24.                 fixed3 Albedo;
    25.                 fixed3 Normal;
    26.                 fixed3 Emission;
    27.                 half Specular;
    28.                 fixed Gloss;
    29.                 fixed Alpha;
    30.                
    31.                 half3 tangent_input;
    32.                 half3 binormal_input;
    33.             };
    34.            
    35.             void vert(inout appdata_full i, out Input o)
    36.             {      
    37.                 half4 p_normal = mul(float4(i.normal,0.0f),_World2Object);
    38.                 half4 p_tangent = mul(_Object2World,i.tangent);
    39.                                            
    40.                 half3 normal_input = normalize(p_normal.xyz);
    41.                 half3 tangent_input = normalize(p_tangent.xyz);
    42.                 half3 binormal_input = cross(p_normal.xyz,tangent_input.xyz) * i.tangent.w;
    43.                
    44.                 o.tangent_input = tangent_input ;
    45.                 o.binormal_input = binormal_input ;
    46.             }
    47.                        
    48.             sampler2D _MainTex;
    49.            
    50.             void surf (Input IN, inout SurfaceOutputCustom o)
    51.             {            
    52.                 fixed4 albedo = tex2D(_MainTex, IN.uv_MainTex);
    53.                 o.Albedo = albedo.rgb;
    54.                 o.Alpha = albedo.a;
    55.                
    56.                 o.tangent_input = IN.tangent_input;
    57.                 o.binormal_input = IN.binormal_input ;
    58.             }
    59.            
    60.             inline fixed4 LightingCustom (SurfaceOutputCustom s, fixed3 lightDir, fixed3 viewDir, fixed atten)
    61.             {
    62.                 fixed4 c;
    63.                 c.rgb = s.tangent_input;
    64.                 c.a = 1.0;
    65.                 return c;
    66.             }
    67.            
    68.         ENDCG
    69.     }
    70.     FallBack "Transparent/Cutout/VertexLit"
    71. }
    72.  
     
    Last edited: Jun 1, 2013
  2. Pyromuffin

    Pyromuffin

    Joined:
    Aug 5, 2012
    Posts:
    85
    I believe this is a bug. I have experienced similar problems with custom input structures and DX11. I've reported the bug and they've reproduced it, but I've not heard that it's been resolved yet. As a (terrible) work around, you could disassemble the shader using #pragma debug and see where unity is failing to put your tangents into the struct and put them in yourself, but it's a really bad hack.
     
  3. cician

    cician

    Joined:
    Dec 10, 2012
    Posts:
    233
    Compiler for DX11 is picky about variable initialization. You have to initialize all the outputs, otherwise it doesn't compile correctly. UNITY_INITIALIZE_OUTPUT makes it easier.
    Also it threats errors as warnings most of the time, which is a bug IMO.

    Code (csharp):
    1. void vert(inout appdata_full i, out Input o)
    2. {      
    3.     UNITY_INITIALIZE_OUTPUT(Input, o);
    4.  
    5.     half4 p_normal = mul(float4(i.normal,0.0f),_World2Object);
    6.     half4 p_tangent = mul(_Object2World,i.tangent);
    7.                                            
    8.     half3 normal_input = normalize(p_normal.xyz);
    9.     half3 tangent_input = normalize(p_tangent.xyz);
    10.     half3 binormal_input = cross(p_normal.xyz,tangent_input.xyz) * i.tangent.w;
    11.                
    12.     o.tangent_input = tangent_input ;
    13.     o.binormal_input = binormal_input ;
    14. }
     
  4. invadererik

    invadererik

    Joined:
    Oct 31, 2010
    Posts:
    148
    awesome, thanks cician, UNITY_INITIALIZE_OUTPUT(Input, o); worked great = ]