Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

So I'm by no mean a shader coder, but I've been hacking around the last few days trying to get working a shader for the sprites of the skeletal animation tool Spine in Unity that can properly use normal maps and cast shadows. The current committed shader for the Unity runtime does lightning decently (albeit with the limitations of vertex lit shaders), but doesn't take normals.

I have achieved two results that get me halfway through :/

Normal V1: http://www.youtube.com/watch?v=lP-NJbHt7B0&feature=youtu.be As you can see, the normal effect looks really cool when moving the light around, however, I'm having a "blending" issue with the sprites of the character. There's of course a lot going on with this runtime that I guess you won't be able top help me with if you don't know how Spine works. BUT, maybe you see something in the way the shader works that can point me in the right direction?

Here's the code for this shader:

Shader "Transparent/Bumped Diffuse with Shadow" {
Properties {
   _Color ("Main Color", Color) = (1,1,1,1)
   _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
   _BumpMap ("Normalmap", 2D) = "bump" {}
   _Cutoff("Cutoff", Float) = 0.01
}

SubShader {
   Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="TransparentCutOut" }
   LOD 300

      CGPROGRAM
   #pragma surface surf Lambert alpha vertex:vert addshadow alphatest:_Cutoff
         #pragma multi_compile DUMMY PIXELSNAP_ON 


   sampler2D _MainTex;
   sampler2D _BumpMap;
   fixed4 _Color;

   struct Input {
      float2 uv_MainTex;
      float2 uv_BumpMap;
      fixed4 color; 
   };

void vert (inout appdata_full v, out Input o)
      {
         #if defined(PIXELSNAP_ON) && !defined(SHADER_API_FLASH)
         v.vertex = UnityPixelSnap (v.vertex);
         #endif
         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) * _Color;
      o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
      o.Albedo = c.rgb;
      o.Alpha = c.a;
   }
   ENDCG
}

Fallback "Transparent/Cutout/Diffuse"
}

Normal V2: I don't have enough rep to post another video link, but you can find V2 under my user in YouTube. This shader I put together with bits and pieces around, and the real intention was to get shadows working on Ortographic rendering through forward lighting. Shadow casting it's possible with this one, although not showed in this particular video. I'll keep you updated on that later. With this shader there's no blending but, although it can take normals, they are not working as intended with lighting. Something related to how tangent is working on it. The key from the previous shader to solve this seems to be this part:

void vert (inout appdata_full v, out Input o) { if defined(PIXELSNAP_ON) && !defined(SHADER_API_FLASH) v.vertex = UnityPixelSnap (v.vertex); endif v.normal = float3(0,0,-1); v.tangent = float4(1, 0, 0, 1);

UNITY_INITIALIZE_OUTPUT(Input, o); o.color = _Color; }

But I don't know how to implement it on V2 shader's code, below:

Shader "Spine/Skeleton Lit" {

    Properties {

      _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
        _Color ("Main Color", Color) = (1,1,1,1)

        _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)

        _Shininess ("Shininess", Range (0.03, 1)) = 0.078125

        _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}

        _BumpMap ("Normalmap", 2D) = "bump" {}

    }




    SubShader {

        Tags {"Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector"="True" }
        LOD 300
      Cull Off
      ZWrite Off
      Blend One OneMinusSrcAlpha
      Lighting Off


        Pass {

            Tags {"LightMode" = "ForwardBase"}                      // This Pass tag is important or Unity may not give it the correct light information.

            CGPROGRAM

                #pragma vertex vert

                #pragma fragment frag

               #pragma multi_compile_fwdadd_fullshadows                        // This line tells Unity to compile this pass for forward base.

                #pragma fragmentoption ARB_fog_exp2

                #pragma fragmentoption ARB_precision_hint_fastest

                #pragma target 3.0



                #include "UnityCG.cginc"

                #include "AutoLight.cginc"



                struct v2f

                {

                    float4  pos         : SV_POSITION;

                    float2  uv          : TEXCOORD0;

                    float3  viewDir     : TEXCOORD1;

                    float3  lightDir    : TEXCOORD2;

                    LIGHTING_COORDS(3,4)                            // Macro to send shadow & attenuation to the vertex shader.

                };



                v2f vert (appdata_tan v)

                {

                    v2f o;



                    o.pos = mul( UNITY_MATRIX_MVP, v.vertex);

                    o.uv = v.texcoord.xy;

                    TANGENT_SPACE_ROTATION;                         // Macro for unity to build the Object>Tangent rotation matrix "rotation".

                    o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex));

                    o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));



                    TRANSFER_VERTEX_TO_FRAGMENT(o);                 // Macro to send shadow & attenuation to the fragment shader.

                    return o;

                }



                sampler2D _MainTex;

                sampler2D _BumpMap;

                fixed4 _Color;

                half _Shininess;



                fixed4 _SpecColor;

                fixed4 _LightColor0; // Colour of the light used in this pass.

                 fixed _Cutoff;


                fixed4 frag(v2f i) : COLOR

                {

                         float3 lightColor = _LightColor0.rgb;


                    i.viewDir = normalize(i.viewDir);

                    i.lightDir = normalize(i.lightDir);



                    fixed atten = LIGHT_ATTENUATION(i); // Macro to get you the combined shadow & attenuation value.



                    fixed4 tex = tex2D(_MainTex, i.uv);

                    fixed gloss = tex.a;

                    tex *= _Color;

                    fixed3 normal = UnpackNormal(tex2D(_BumpMap, i.uv));



                    half3 h = normalize(i.lightDir + i.viewDir);



                    fixed diff = saturate(dot(normal, i.lightDir));



                    float nh = saturate(dot (normal, h));

                    float spec = pow(nh, _Shininess * 128.0) * gloss;



                    fixed4 c;


                    c.rgb = UNITY_LIGHTMODEL_AMBIENT.rgb * 2 * tex.rgb;         // Ambient term. Only do this in Forward Base. It only needs calculating once.

                    c.rgb += (tex.rgb * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2); // Diffuse and specular.

                    c.a = tex.a + _LightColor0.a * _SpecColor.a * spec * atten;

                    return c;

                }

            ENDCG

        }



        Pass {

            Tags {"LightMode" = "ForwardAdd" "Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector"="True" }                       // Again, this pass tag is important otherwise Unity may not give the correct light information.

            Blend One OneMinusSrcAlpha                                        // Additively blend this pass with the previous one(s). This pass gets run once per pixel light.

            CGPROGRAM

                #pragma vertex vert

                #pragma fragment frag

           // #pragma multi_compile_fwdadd                        // This line tells Unity to compile this pass for forward add, giving attenuation information for the light.

                #pragma multi_compile_fwdadd_fullshadows                      // This line tells Unity to compile this pass for forward add and give shadow information as well as attenuation. Swap this line for the one above if you want forward add with shadows.

                #pragma fragmentoption ARB_fog_exp2

                #pragma fragmentoption ARB_precision_hint_fastest

                #pragma target 3.0



                #include "UnityCG.cginc"

                #include "AutoLight.cginc"



                struct v2f

                {

                    float4  pos         : SV_POSITION;

                    float2  uv          : TEXCOORD0;

                    float3  viewDir     : TEXCOORD1;

                    float3  lightDir    : TEXCOORD2;

                    LIGHTING_COORDS(3,4)                            // Macro to send shadow & attenuation to the vertex shader.

                };



                v2f vert (appdata_tan v)

                {

                    v2f o;



                    o.pos = mul( UNITY_MATRIX_MVP, v.vertex);

                    o.uv = v.texcoord.xy;

                    TANGENT_SPACE_ROTATION;                         // Macro for unity to build the Object>Tangent rotation matrix "rotation".

                    o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex));

                    o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));



                    TRANSFER_VERTEX_TO_FRAGMENT(o);                 // Macro to send shadow & attenuation to the fragment shader.

                    return o;

                }



                sampler2D _MainTex;

                sampler2D _BumpMap;

                fixed4 _Color;

                half _Shininess;



                fixed4 _SpecColor;

                fixed4 _LightColor0; // Colour of the light used in this pass.



                fixed4 frag(v2f i) : COLOR

                {

                    i.viewDir = normalize(i.viewDir);

                    i.lightDir = normalize(i.lightDir);



                    fixed atten = LIGHT_ATTENUATION(i); // Macro to get you the combined shadow & attenuation value.



                    fixed4 tex = tex2D(_MainTex, i.uv);

                    fixed gloss = tex.a;

                    tex *= _Color;

                    fixed3 normal = UnpackNormal(tex2D(_BumpMap, i.uv));



                    half3 h = normalize(i.lightDir + i.viewDir);



                    fixed diff = saturate(dot(normal, i.lightDir));



                    float nh = saturate(dot (normal, h));

                    float spec = pow(nh, _Shininess * 128.0) * gloss;



                    fixed4 c;

                    c.rgb = (tex.rgb * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2); // Diffuse and specular.

                    c.a = tex.a + _LightColor0.a * _SpecColor.a * spec * atten;

                    return c;

                }


            ENDCG

        }

    }

    FallBack "Transparent/Cutout/Diffuse"    // Use VertexLit's shadow caster/receiver passes.

}

Help with this would be much appreciated :) Here's a link to the unitypackage with one of the shaders In case you have the time to check it around. Scripts and assets used on this package are property of Esoteric Software but publicly available on their repositories. https://dl.dropboxusercontent.com/u/9195292/goblinexamplenormal.unitypackage

Cheers!

share|improve this question

closed as unclear what you're asking by Anko, Josh Petrie Feb 8 '14 at 20:09

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

    
Is this a "fix my code for me" kind of question? It would be better to explain what you're trying to do and why it's not working. –  Anko Feb 8 '14 at 10:54
    
I don't know how to explain it otherwise, Anko. What kind of info would you like me to give? I suppose it is a help me fix my code question. I can't identify the problem so I don't know how to make it look different. I want to use a shader for this 2D Spine sprites that enable it to use normals and respond to lighting without the issues showed in the videos above. I'm asking for people to, please, point me in the right direction if they have an idea, not solving everything. This is what I achieved in the latest version youtube.com/watch?v=V9fQVHiAizE –  WrongTarget Feb 8 '14 at 20:11
    
's looking much better now, at least in Deferred lighting + Perspective. As soon as I switch to ortographic or forward, it messes up. Also, there's still that noticeable "separation" from the Goblin's parts. This is what my shader looks like right now: pastebin.com/YjXKkDHK –  WrongTarget Feb 8 '14 at 20:13

Browse other questions tagged or ask your own question.