Hello, i have recently started using spine, and Im really happy with it.
I noticed on the forums that some people have attempted to create bumpmapped shaders with varying luck, and since I needed this for my project I decided to make an attempt myself.
I am relatively new to writing shaders, so I only have a vague idea of what im actually doing :p
The shader does seem to work when I only use Directional Light, but when I add the second pass the blending seems to get messed up and bodyparts show through.
This is with Directional Light only: (The current bumpmap is temporary)
Loading Image
And this is with an additional Point Light:
Loading Image
If anyone can help me find out where I went wrong, it would be much appreciated 🙂
Shader "Spine/MySkeletonShader" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex("Texture)", 2D)="white"{}
_BumpMap ("Normal Texture", 2D) = "bump" {}
_BumpDepth("BumpDepth", Range(0.0, 1.0))=1
}
SubShader {
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
Pass {
Tags{"LightMode"="ForwardBase"}
Blend SrcAlpha OneMinusSrcAlpha
zWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform float4 _Color;
uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;
uniform sampler2D _BumpMap;
uniform half4 _BumpMap_ST;
uniform half _BumpDepth;
uniform float4 _LightColor0;
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
half4 tangent : TANGENT;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD1;
fixed4 lightDirection : TEXCOORD2;
fixed3 viewDirection : TEXCOORD3;
fixed3 normalWorld : TEXCOORD4;
fixed3 tangentWorld : TEXCOORD5;
fixed3 binormalWorld : TEXCOORD6;
};
vertexOutput vert(vertexInput v) {
vertexOutput o;
half4 posWorld = mul(_Object2World, v.vertex);
o.viewDirection = normalize(_WorldSpaceCameraPos.xyz - posWorld.xyz);
o.normalWorld = float3(0.0, 0.0, -1.0);//normalize(mul(half4(v.normal, 0.0), _World2Object).xyz);
o.tangentWorld = float3(1.0, 0.0, 0.0); //normalize(mul(_Object2World, v.tangent).xyz);
o.binormalWorld = normalize(cross(o.normalWorld, o.tangentWorld));
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.tex = v.texcoord;
half3 fragmentToLightSource = _WorldSpaceLightPos0.xyz - posWorld.xyz;
o.lightDirection=fixed4(
normalize(lerp(_WorldSpaceLightPos0.xyz, fragmentToLightSource, _WorldSpaceLightPos0.w)),
lerp(1.0, 1.0/length(fragmentToLightSource), _WorldSpaceLightPos0.w)
);
return o;
}
float4 frag(vertexOutput i) : COLOR {
fixed4 tex = tex2D(_MainTex, i.tex.xy*_MainTex_ST.xy + _MainTex_ST.zw);
fixed4 texN = tex2D(_BumpMap, i.tex.xy * _BumpMap_ST.xy + _BumpMap_ST.zw);
float alpha = tex.a*_Color.a;
fixed3 localCoords = fixed3(2.0 * texN.ag - float2(1.0, 1.0), _BumpDepth);
//localCoords.z = 1.0 - 0.5 * dot(localCoords, localCoords);
half3x3 local2WorldTranspose = half3x3(
i.tangentWorld,
i.binormalWorld,
i.normalWorld
);
fixed3 normalDirection = normalize(mul(localCoords, local2WorldTranspose));
fixed nDotL = saturate(dot(normalDirection, i.lightDirection.xyz));
fixed3 diffuseReflection = i.lightDirection.w * _LightColor0.xyz * nDotL;
fixed3 lightFinal = UNITY_LIGHTMODEL_AMBIENT.xyz + diffuseReflection;
//return float4(diffuseReflection.xyz, 1.0);
return float4(tex.xyz * lightFinal * _Color.rgb, alpha);
}
ENDCG
}
Pass {
Tags{"LightMode"="ForwardAdd"}
Blend One One
zWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform float4 _Color;
uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;
uniform sampler2D _BumpMap;
uniform half4 _BumpMap_ST;
uniform half _BumpDepth;
uniform float4 _LightColor0;
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
half4 tangent : TANGENT;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD1;
fixed4 lightDirection : TEXCOORD2;
fixed3 viewDirection : TEXCOORD3;
fixed3 normalWorld : TEXCOORD4;
fixed3 tangentWorld : TEXCOORD5;
fixed3 binormalWorld : TEXCOORD6;
};
vertexOutput vert(vertexInput v) {
vertexOutput o;
half4 posWorld = mul(_Object2World, v.vertex);
o.viewDirection = normalize(_WorldSpaceCameraPos.xyz - posWorld.xyz);
o.normalWorld = float3(0.0, 0.0, -1.0);//normalize(mul(half4(v.normal, 0.0), _World2Object).xyz);
o.tangentWorld = float3(1.0, 0.0, 0.0); //normalize(mul(_Object2World, v.tangent).xyz);
o.binormalWorld = normalize(cross(o.normalWorld, o.tangentWorld));
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.tex = v.texcoord;
half3 fragmentToLightSource = _WorldSpaceLightPos0.xyz - posWorld.xyz;
o.lightDirection=fixed4(
normalize(lerp(_WorldSpaceLightPos0.xyz, fragmentToLightSource, _WorldSpaceLightPos0.w)),
lerp(1.0, 1.0/length(fragmentToLightSource), _WorldSpaceLightPos0.w)
);
return o;
}
float4 frag(vertexOutput i) : COLOR {
fixed4 tex = tex2D(_MainTex, i.tex.xy*_MainTex_ST.xy + _MainTex_ST.zw);
fixed4 texN = tex2D(_BumpMap, i.tex.xy * _BumpMap_ST.xy + _BumpMap_ST.zw);
float alpha = tex.a*_Color.a;
fixed3 localCoords = fixed3(2.0 * texN.ag - float2(1.0, 1.0), _BumpDepth);
//localCoords.z = 1.0 - 0.5 * dot(localCoords, localCoords);
half3x3 local2WorldTranspose = half3x3(
i.tangentWorld,
i.binormalWorld,
i.normalWorld
);
fixed3 normalDirection = normalize(mul(localCoords, local2WorldTranspose));
fixed nDotL = saturate(dot(normalDirection, i.lightDirection.xyz));
fixed3 diffuseReflection = i.lightDirection.w * _LightColor0.xyz * nDotL;
fixed3 lightFinal = diffuseReflection;
//return float4(diffuseReflection.xyz, 1.0);
return float4(tex.xyz * lightFinal, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}