Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

I need help with Normal Map Shader

Discussion in 'Shaders' started by TreantBG, Apr 26, 2022.

  1. TreantBG

    TreantBG

    Joined:
    Sep 7, 2021
    Posts:
    2
    Hello guys i want to visualize the normal colors of a character with a shader.
    I have this code:

    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. Shader "!Debug/Normals" {
    4. SubShader {
    5.     Pass {
    6.         Fog { Mode Off }
    7. CGPROGRAM
    8. #pragma vertex vert
    9. #pragma fragment frag
    10.  
    11. // vertex input: position, normal
    12. struct appdata {
    13.     float4 vertex : POSITION;
    14.     float3 normal : NORMAL;
    15. };
    16.  
    17. struct v2f {
    18.     float4 pos : SV_POSITION;
    19.     fixed4 color : COLOR;
    20. };
    21. v2f vert (appdata v) {
    22.     v2f o;
    23.     o.pos = UnityObjectToClipPos( v.vertex );
    24.     o.color.xyz = v.normal * 0.5 + 0.5;
    25.     o.color.w = 1.0;
    26.     return o;
    27. }
    28. fixed4 frag (v2f i) : COLOR0 { return i.color; }
    29. ENDCG
    30.     }
    31. }
    32. }
    And it produces the following images:

    Screenshot 2022-04-26 135909.png


    Unfortunately i want to use another color scheme for the normal map like that used by SpriteIlluminator
    Screenshot 2022-04-26 140112.png

    the formula for this color scheme is: (normal + 1) / 2 * 255

    When i edit this line of the shader:
    o.color.xyz = v.normal * 0.5 + 0.5;
    the color wheel is changing but i cannot get it right

    (im doing that because i want to export spritesheet for 2d game that uses the same color scheme like SpriteIlluminator for the normal map ilumination)

    Can you help me edit the shader's formula?
    Thanks
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,255
    You're outputting the local space normals of the object. Unity uses a left handed coordinate system for local and world space, but OpenGL tangent space normal maps are right handed. To explain that in a more straightforward way, the local Z (blue color) is pointing away from the camera in your shader, but points towards the camera in a normal map.

    The "easiest" solution is to do this:
    Code (csharp):
    1. o.color.xyz = v.normal;
    2. o.color.z *= -1.0;
    3. o.color.xyz = o.color.xyz * 0.5 + 0.5;
    4. o.color.w = 1.0;
    However it should be noted this isn't really correct either, as depending on your camera orientation the resulting normals may not be facing the correct orientation for tangent space normals. For example, it looks like your camera is facing slightly downward, and that's going to translate into the tangent space normal map's normals also being rotated like that which you likely do not want.

    So the more correct solution is to transform the object space normals into view space, like this:
    Code (csharp):
    1. Shader "!Debug/Normals" {
    2. SubShader {
    3.     Pass {
    4.         Fog { Mode Off }
    5. CGPROGRAM
    6. #pragma vertex vert
    7. #pragma fragment frag
    8.  
    9. // vertex input: position, normal
    10. struct appdata {
    11.     float4 vertex : POSITION;
    12.     float3 normal : NORMAL;
    13. };
    14.  
    15. struct v2f {
    16.     float4 pos : SV_POSITION;
    17.     float3 viewNormal : TEXCOORD0;
    18. };
    19. v2f vert (appdata v) {
    20.     v2f o;
    21.     o.pos = UnityObjectToClipPos( v.vertex );
    22.     o.viewNormal = mul((float3x3)UNITY_MATRIX_V, UnityObjectToWorldNormal(v.normal));
    23.     return o;
    24. }
    25. fixed4 frag (v2f i) : COLOR0 {
    26.     return float4(normalize(i.viewNormal) * 0.5 + 0.5, 1.0);
    27. }
    28. ENDCG
    29.     }
    30. }
    31. }
     
  3. TreantBG

    TreantBG

    Joined:
    Sep 7, 2021
    Posts:
    2
    Hey thanks the solution was to reverse the z axis.

    I have already solved the problem with rotating the object and the camera orientation.

    Thank you very much, will post the result tomorrow
     
    bgolus likes this.