Why does this sprite's normal map only light correctly from one direction?

Base Sprites

I’m trying to use a Normal/Depth map to light a 2D sprite. These are the Diffuse and Normal/Depth sprites (two separate sprites in Unity):
78745-diffuse-normaldepth.png

The Weird Issue

The problem is, the character is lit correctly when “facing” the light, but is not lit correctly from behind when “facing” away:

I am new to Unity, so I’m wondering if there’s some gotcha here I don’t know about? Maybe something with normals or something, I dunno…any help would be greatly appreciated!

Details:

  • I’m using the Sprite Lamp “Standard” shader.
  • The light is a standard Unity spotlight at Z position = -1 (no rotation or scaling).
  • The arc of light you can see behind the character is the spotlight falling on a wall sprite at Z position = 4.
  • The character sprite is at Z position = 0 (no rotation or scaling).
  • I flip the X Scale of the character sprite to make him face left or right.

Edit:

I guess I should mention that both the Diffuse and Normal/Depth maps are imported as Sprites, which I believe automatically get rendered on both sides along the Z-axis so you can flip their X Scales without disappearing them. Sprite Lamp was made with 2D in mind, so it allows you to use Sprites for your maps instead of other kinds of Textures that may be drawn on only one side (causing normals to point away from the camera).

I believe this is one of those odd cases where working in 2d is actually much harder than working in 3d… I don’t know the details of the shader you’re using but my gut feeling is that it’s a double-sided shader, which won’t work with normal maps - you can “flip” a texture from left-to-right by using xscale *= -1, as you have done, but doing this to a normal map will mess up the tangents so the light will apparently be coming from “behind” the object instead, as your screenshots show.

So you need to render the back face and front face side in a separate pass and manually hardcode the tangent vector. There’s an example in this thread that shows how.

I figured this out, It happens when you have two or more source lights affecting an sprite, so you have two options:

  1. Delete one of the source lights
  2. [Recomended] set the culling mask of one of the light sources to affect everything except the layer where your sprite is.