Search Unity

Resolved Billboard shader not transforming normals correctly

Discussion in 'Shaders' started by carcasanchez, Sep 10, 2021.

  1. carcasanchez

    carcasanchez

    Joined:
    Jul 15, 2018
    Posts:
    177
    Hi everyone,

    I'm doing a 2.5 game a-la Bleak Sword, and I wanted to use the logical rotation of the object for gameplay, while mantaining the sprite looking always to an arbitrary direction (Z in this case).
    I am working with a billboard shader that works fine, except if I rotate the object, the normals rotate with the object instead of retaining the billboard position (you can apreciate the lighting change, which should not be happening):
    upload_2021-9-10_17-45-41.png
    upload_2021-9-10_17-51-14.png

    IIRC, this should work just by assigning (0, 0, -1) to the normal channel in the shader, but for reasons, none of my attemps seems to untie normal direction from object rotation.
    Here is the shader in question (the relevant part, at least):

    Code (CSharp):
    1.  void vert(inout appdata_full v, out Input o)
    2.         {
    3.             UNITY_INITIALIZE_OUTPUT(Input, o);
    4.             // apply object scale
    5.             v.vertex.xy *= float2(length(unity_ObjectToWorld._m00_m10_m20), length(unity_ObjectToWorld._m01_m11_m21));
    6.          
    7.             float3 forward = float3(0, 0, 1);
    8.             float3 up = float3(0, 1, 0);
    9.             float3 right = float3(1, 0, 0);
    10.      
    11.             float4x4 rotationMatrix = float4x4(right, 0,
    12.                 up, 0,
    13.                 forward, 0,
    14.                 0, 0, 0, 1);
    15.  
    16.             v.vertex = mul(v.vertex, rotationMatrix);
    17.             v.normal = -forward;
    18.             // undo object to world transform surface shader will apply
    19.             v.vertex.xyz = mul((float3x3)unity_WorldToObject, v.vertex.xyz);
    20.  
    21.         }
    22.  
    23.  
    24.             void surf(Input i, inout SurfaceOutput o) {                
    25.                 fixed4 col = tex2D(_MainTex, i.uv_MainTex);
    26.  
    27.                 clip(col.a-0.0001);
    28.                 col *= _Color;
    29.                 o.Albedo = col.rgb;
    30.                 o.Normal = UnpackNormal(tex2D(_NormalMap, i.uv_NormalMap));
    31.                 o.Emission = _Emission;
    32.             }
     

    Attached Files:

  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    If you're using normal maps, you also need to rotate the
    v.tangent.xyz
    .
     
  3. carcasanchez

    carcasanchez

    Joined:
    Jul 15, 2018
    Posts:
    177
    Thanks! That was it, now it works perfectly