I need help with Normal Map Shader

Hello guys i want to visualize the normal colors of a character with a shader.
I have this code:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "!Debug/Normals" {
SubShader {
    Pass {
        Fog { Mode Off }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

// vertex input: position, normal
struct appdata {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
};

struct v2f {
    float4 pos : SV_POSITION;
    fixed4 color : COLOR;
};
v2f vert (appdata v) {
    v2f o;
    o.pos = UnityObjectToClipPos( v.vertex );
    o.color.xyz = v.normal * 0.5 + 0.5;
    o.color.w = 1.0;
    return o;
}
fixed4 frag (v2f i) : COLOR0 { return i.color; }
ENDCG
    }
}
}

And it produces the following images:

Unfortunately i want to use another color scheme for the normal map like that used by SpriteIlluminator
8078651--1044485--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

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:

o.color.xyz = v.normal;
o.color.z *= -1.0;
o.color.xyz = o.color.xyz * 0.5 + 0.5;
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:

Shader "!Debug/Normals" {
SubShader {
    Pass {
        Fog { Mode Off }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

// vertex input: position, normal
struct appdata {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
};

struct v2f {
    float4 pos : SV_POSITION;
    float3 viewNormal : TEXCOORD0;
};
v2f vert (appdata v) {
    v2f o;
    o.pos = UnityObjectToClipPos( v.vertex );
    o.viewNormal = mul((float3x3)UNITY_MATRIX_V, UnityObjectToWorldNormal(v.normal));
    return o;
}
fixed4 frag (v2f i) : COLOR0 {
    return float4(normalize(i.viewNormal) * 0.5 + 0.5, 1.0);
}
ENDCG
    }
}
}

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

1 Like