Spine无需光照的阴影实现

阴影生成的实现方式

1.实时光照
2.脚底放置假的阴影面片模拟阴影
3.变幻模型在某个平面上投影形成2d压缩模型
4.project投影器

具体做法

这里我们使用方案3方案实现,因为spine是2d的投影替换为使用旋转和切变来实现。具体实现通过两个pass,第一个pass做模型的变换处理,生成一个阴影;第二个pass使用默认的渲染画出本身的模型。

github工程连接:https://github.com/xulinjia/spine_shadow
shader代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

Shader "Spine/SkeletonShadow" {
Properties {
_ShadowColor("ShadowColor",Color) = (0,0,0,0.5) //阴影颜色
_ShadowDdge("ShadowDege",range(0,1.507)) = 0 //绕x轴的旋转角度
_ShadowCutD("_ShadowCutD",float) = 0.5 //切变距离
_ShadowHeightScale("_ShadowHeight",float) = 1 // 影子高度比例
_Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
[NoScaleOffset] _MainTex ("Main Texture", 2D) = "black" {}
[Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0
[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
[HideInInspector][Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default

// Outline properties are drawn via custom editor.
[HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0
[HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1)
[HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024
[HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25
[HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0
[HideInInspector][MaterialToggle(_USE8NEIGHBOURHOOD_ON)] _Use8Neighbourhood("Sample 8 Neighbours", Float) = 1
[HideInInspector] _OutlineOpaqueAlpha("Opaque Alpha", Range(0,1)) = 1.0
[HideInInspector] _OutlineMipLevel("Outline Mip Level", Range(0,3)) = 0
}

SubShader {
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }

Fog { Mode Off }
Cull Off
ZWrite Off
Blend One OneMinusSrcAlpha
Lighting Off

Stencil {
Ref[_StencilRef]
Comp[_StencilComp]
Pass Keep
}

Pass {
Name "FastShadow"
Blend SrcAlpha Zero
CGPROGRAM
#pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "CGIncludes/Spine-Common.cginc"
sampler2D _MainTex;
fixed _Cutoff;
float4 _ShadowColor;
float _ShadowDdge;
float _ShadowCutD;
float _ShadowHeightScale;

struct VertexInput {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 vertexColor : COLOR;
};

struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 vertexColor : COLOR;
};

VertexOutput vert (VertexInput v) {
VertexOutput o;
float4 vt = v.vertex;
float4 vtn;
vt.y *= _ShadowHeightScale;
vtn.x = vt.x + vt.y * _ShadowCutD;
vtn.y = cos(_ShadowDdge) * vt.y;
vtn.z = sin(_ShadowDdge) * vt.y;
vtn.w = vt.w;
o.pos = UnityObjectToClipPos(vtn);
o.uv = v.uv;
o.vertexColor = PMAGammaToTargetSpace(v.vertexColor);
return o;
}

float4 frag (VertexOutput i) : SV_Target {
float4 texColor = tex2D(_MainTex, i.uv);

#if defined(_STRAIGHT_ALPHA_INPUT)
texColor.rgb *= texColor.a;
#endif
float4 shadowColor = _ShadowColor;
clip(texColor.a * i.vertexColor.a - 0.01);
return shadowColor;

}
ENDCG
}


Pass {
Name "Normal"

CGPROGRAM
#pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "CGIncludes/Spine-Common.cginc"
sampler2D _MainTex;

struct VertexInput {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 vertexColor : COLOR;
};

struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 vertexColor : COLOR;
};

VertexOutput vert (VertexInput v) {
VertexOutput o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.vertexColor = PMAGammaToTargetSpace(v.vertexColor);
return o;
}

float4 frag (VertexOutput i) : SV_Target {
float4 texColor = tex2D(_MainTex, i.uv);

#if defined(_STRAIGHT_ALPHA_INPUT)
texColor.rgb *= texColor.a;
#endif

return (texColor * i.vertexColor);
}
ENDCG
}

Pass {
Name "Caster"
Tags { "LightMode"="ShadowCaster" }
Offset 1, 1
ZWrite On
ZTest LEqual

Fog { Mode Off }
Cull Off
Lighting Off

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
sampler2D _MainTex;
fixed _Cutoff;

struct VertexOutput {
V2F_SHADOW_CASTER;
float4 uvAndAlpha : TEXCOORD1;
};

VertexOutput vert (appdata_base v, float4 vertexColor : COLOR) {
VertexOutput o;
o.uvAndAlpha = v.texcoord;
o.uvAndAlpha.a = vertexColor.a;
TRANSFER_SHADOW_CASTER(o)
return o;
}

float4 frag (VertexOutput i) : SV_Target {
fixed4 texcol = tex2D(_MainTex, i.uvAndAlpha.xy);
clip(texcol.a * i.uvAndAlpha.a - _Cutoff);
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}
CustomEditor "SpineShaderWithOutlineGUI"
}