- Home /
how do you flip a sprite that has a normal map material applied to it?
I try the basic -x scale flip, but the sprite just disappears after that. I was thinking it has something to do with the material, can these not be flipped this way? I'm asking because I want to use normal maps for lighting effects on my player character(and npcs) in a 2d game. I asked this same question over at the normal 2d forums, no reply, thought maybe the devs or more knowledgeable unity people could help. Thanks for your time!
Are you using one of the "sprite" materials or using another material type?
The sprite materials automatically render the image on both sides of the sprite so when you scale negatively it just displays the other side. If the material is not a sprite material then the object essentially rotates around the y-axis 180 degrees.
$$anonymous$$y guess is you're using a non-sprite material to achieve normal mapping. If you go into 3d view you'll be able to see the sprite on the backside.
Some possible options to achieve your desired affect:
Write a custom sprite shader (Requires knowledge of shaders)
Create flipped graphics/animations for each image (Results in more assets)
Use code to flip the sprite in LateUpdate ($$anonymous$$ore CPU intensive)
I have yet to try it but option 1 is probably the most preferable.
Answer by GiyomuGames · Jun 16, 2015 at 06:10 AM
Hi,
I modified a surface shader I found online and made it work for sprites regardless of their x scale. It's not optimized as both sides will always be drawn, but for a 2D game it should not be an issue. The shader will also add the sprite renderer color in case you use it.
Shader "Sprites/Bumped Diffuse both sides with Shadows"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_BumpMap ("Normalmap", 2D) = "bump" {}
_Color ("Tint", Color) = (1,1,1,1)
[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
_Cutoff ("Alpha Cutoff", Range (0,1)) = 0.5
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="TransparentCutOut"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
LOD 300
// Render back faces first
Cull Front
Lighting On
ZWrite Off
Fog { Mode Off }
CGPROGRAM
#pragma surface surf Lambert alpha vertex:vert addshadow alphatest:_Cutoff
#pragma multi_compile DUMMY PIXELSNAP_ON
sampler2D _MainTex;
sampler2D _BumpMap;
fixed4 _Color;
float _ScaleX;
struct Input
{
float2 uv_MainTex;
float2 uv_BumpMap;
fixed4 color : COLOR;
};
void vert (inout appdata_full v, out Input o)
{
#if defined(PIXELSNAP_ON) && !defined(SHADER_API_FLASH)
v.vertex = UnityPixelSnap (v.vertex);
#endif
float3 normal = v.normal;
v.normal = float3(0,0,-1);
v.tangent = float4(1, 0, 0, 1);
UNITY_INITIALIZE_OUTPUT(Input, o);
o.color += _Color;
}
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * IN.color;
o.Albedo = c.rgb;
o.Alpha = c.a;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
// Now render front faces first
Cull Back
Lighting On
ZWrite Off
Fog { Mode Off }
CGPROGRAM
#pragma surface surf Lambert alpha vertex:vert addshadow alphatest:_Cutoff
#pragma multi_compile DUMMY PIXELSNAP_ON
sampler2D _MainTex;
sampler2D _BumpMap;
fixed4 _Color;
float _ScaleX;
struct Input
{
float2 uv_MainTex;
float2 uv_BumpMap;
fixed4 color: COLOR;
};
void vert (inout appdata_full v, out Input o)
{
#if defined(PIXELSNAP_ON) && !defined(SHADER_API_FLASH)
v.vertex = UnityPixelSnap (v.vertex);
#endif
float3 normal = v.normal;
v.normal = float3(0,0,1);
v.tangent = float4(1, 0, 0, 1);
UNITY_INITIALIZE_OUTPUT(Input, o);
o.color += _Color;
}
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * IN.color;
o.Albedo = c.rgb;
o.Alpha = c.a;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
o.Normal.z *= -1;
}
ENDCG
}
Fallback "Transparent/Cutout/Diffuse"
}
I'm new to shaders and this shader really helped me out. I turned off culling for both passes, and was able to have shadow casting for flipped sprites on the same side as my nonflipped sprites. However, I noticed there is no "Pass{}" statement in here. Is that not necessary for each pass? I'm trying to add a shadow collector to the shader, but it's not working, how would I go about doing this?
Hello dantamont,
I am actually quite new to shaders myself, but I think there are no "Pass {}" statements for surface shaders. They are generated automatically (you can see them if you open the generated code from Unity interface).
This disabled order in layer and receiving shadows.
How do I get these back?
It worked for me! Until now is flawless, thank you very much!
Answer by keblight · May 30, 2015 at 07:05 PM
Thanks for the reply, I think you are right. I don't know any shader stuff, I think, if I want to go ahead with the normal map stuff I'll have to double up the assets(left/right facing player/npcs etc..) thanks.