• Editor
  • (Solved-ish) A normal map skeleton shader for unity

Related Discussions
...
danthat yazdı

Bah, disappointed to install Spine, set it all up and then stumble across the thread discussing the issue I'm having!

I was having the same problem in SmoothMoves, had hoped I'd be able to use Spine / TK2d instead.

Is that possible? Are there on-going efforts to get this Officially fixed? Decent sprite lighting is kind of vital...

Hey dan. I'm using spine/tk2d and have normal mapping working. If you are specifically trying to get this effect in your game, then yes it's possible. Just follow along with the implementation details in this thread and it should lead you there 🙂

4 ay sonra

Sorry for necroing.

Where can we find the working LitNormal Skeleton shader?
And does it work fine with the current SkeletonComponent code or were there changes?

What changes needed to be made to make them work right when flipped?

I would also appreciate some help in the matters that Pharan is pointing.
The Skeleton Lit shader that's now included in the runtimes is very different than the code discussed in this thread, so I don't know where to start.
Lighting seems to be working although I haven't managed to make shadow casting work.
How could I enable normals with the current shader? And anybody has an idea as to why I can't get shadows to work?

Normals are currently just Vector3(0, 0, -1). For them to work flipped you would need 1 instead of -1. I haven't had a chance to look at what it would take to use a normal map.

4 ay sonra

Sorry to revive but does anyone know working surface shader that is equivalent to the ones come with Spine Unity(skeleton, skeleton lit shader)? I've tried all the shaders written here but they all seem to have problem blending/sorting skeleton. I'm trying to add translucent lighting effect but need surface version of the shader to do it.


It's been solved. Since I started this, I'll just drop my code which won't help many people :p
Ignore the shader name. Basically it renders skeletal animation with lighting and shadow and ignores which direction the model is facing towards a light source, just taking distance in account.

Shader "Custom/TranslucentSpine" {

  Properties {
         _MainTex ("RGBA Texture Image", 2D) = "white" {} 
         _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
        _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
   }
   
SubShader {
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } LOD 100 Cull Off ZWrite Off Pass { Tags {"LightMode" = "ForwardBase" } Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _MainTex; uniform float _Cutoff; uniform float4 _LightColor0; uniform float4 _Color; struct vertexInput { float4 vertex : POSITION; float4 texcoord : TEXCOORD0; float3 normal : NORMAL; }; struct vertexOutput { float4 pos : SV_POSITION; float4 tex : TEXCOORD0; float4 col : COLOR; float3 diffuseColor : TEXCOORD1; }; vertexOutput vert(vertexInput input) { vertexOutput output; float4x4 modelMatrix = _Object2World; float4x4 modelMatrixInverse = _World2Object; float3 normalDirection = normalize(float3(mul(float4(input.normal, 0.0), modelMatrixInverse))); float3 viewDirection = normalize(float3(float4(_WorldSpaceCameraPos, 1.0)- mul(modelMatrix, input.vertex))); float3 lightDirection; float attenuation; if (0.0 == _WorldSpaceLightPos0.w){ // directional light attenuation = 1.0; lightDirection = normalize(float3(_WorldSpaceLightPos0)); } else { // point or spot light float3 vertexToLightSource = float3(_WorldSpaceLightPos0 - mul(modelMatrix, input.vertex)); float distance = length(vertexToLightSource); attenuation = 1.0 / distance; // linear attenuation lightDirection = normalize(vertexToLightSource); } float3 ambientLighting = float3(UNITY_LIGHTMODEL_AMBIENT) * float3(_Color); float3 diffuseReflection = attenuation * float3(_LightColor0) * float3(_Color) * max(0.0, 5); output.diffuseColor = ambientLighting + diffuseReflection*0.5; output.tex = input.texcoord; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); return output; } float4 frag(vertexOutput input) : COLOR { fixed4 tex = tex2D(_MainTex, float2(input.tex)); tex.rgb = input.diffuseColor * tex.rgb; return tex; } ENDCG } Pass { Tags {"LightMode" = "ForwardAdd" } Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _MainTex; uniform float _Cutoff; uniform float4 _LightColor0; uniform float4 _Color; struct vertexInput { float4 vertex : POSITION; float4 texcoord : TEXCOORD0; float3 normal : NORMAL; }; struct vertexOutput { float4 pos : SV_POSITION; float4 tex : TEXCOORD0; float4 col : COLOR; float3 diffuseColor : TEXCOORD1; }; vertexOutput vert(vertexInput input) { vertexOutput output; float4x4 modelMatrix = _Object2World; float4x4 modelMatrixInverse = _World2Object; float3 normalDirection = normalize(float3(mul(float4(input.normal, 0.0), modelMatrixInverse))); float3 viewDirection = normalize(float3(float4(_WorldSpaceCameraPos, 1.0)- mul(modelMatrix, input.vertex))); float3 lightDirection; float attenuation; if (0.0 == _WorldSpaceLightPos0.w){ // directional light attenuation = 1.0; lightDirection = normalize(float3(_WorldSpaceLightPos0)); } else { // point or spot light float3 vertexToLightSource = float3(_WorldSpaceLightPos0 - mul(modelMatrix, input.vertex)); float distance = length(vertexToLightSource); attenuation = 1.0 / distance; // linear attenuation lightDirection = normalize(vertexToLightSource); } float3 ambientLighting = float3(UNITY_LIGHTMODEL_AMBIENT) * float3(_Color); float3 diffuseReflection = attenuation * float3(_LightColor0) * float3(_Color) * max(0.0, 5); output.diffuseColor = ambientLighting + diffuseReflection*0.5; output.tex = input.texcoord; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); return output; } float4 frag(vertexOutput input) : COLOR { fixed4 tex = tex2D(_MainTex, float2(input.tex)); tex.rgb = input.diffuseColor * tex.rgb; return tex; } ENDCG } } Fallback "Transparent/Cutout/Diffuse" }
3 ay sonra

@Nate i get some strange result using the code with spine tk2D on mobile,
ok, i'v change every thing to only use the unity (not the tk2D) and everything works now, soooooOOO cool


If you notice, the edges of your sprites now look jagged. That's a result of using the cutoff. Would need to switch back to a non-cutout shader to get rid of that. I believe other problems arise when I did that though (I'm no shader expert)

As for light reacting to your sprites in the wrong way, did you try modifying the ComputeTangents function? The part you might want to play with is the line:
tangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
This controls the handedness of the tangent. Since my game is top down and I'm never flipping the sprite I had to always have this set to 1 otherwise my normals were pointing in the wrong direction when rotating the sprite.

Edit: Looks like you were using Cutoff before too, so the jagged edges were probably still present for you previously.

@Duré @Nate @stray_train,

hi guys , the edges of my sprites now look jagged, the alpha also is trange, i'v try the dragon demo but the dragon don't accept shadow, the stray_train does
so i 'v use it, but the edge look strange and part of my Hero don't show up on few animation, alway the samei supose because thet are are at -1 in scale
any idear ?

how to improve it