-
Notifications
You must be signed in to change notification settings - Fork 229
/
ShadowVolumeForSphereOnly.shader
104 lines (89 loc) · 2.9 KB
/
ShadowVolumeForSphereOnly.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
/* "Shadow Volume" technique - the simplest example. Works for 3D Object / Sphere.
It extrudes mesh vertices which are not lit by Directional Light (where angle is below zero).
It is done twice, in first and second pass. First pass renders mesh with backface culling.
Second pass renders mesh with frontface culling. With proper stencil buffer setup, we get a difference
between volume shape from both cull modes. It is a shadow !
When vertices are displaced with vertex shader, but base object is not in camera frustum, extruded vertices will be invisible.
It is possible to edit mesh bounds as workaround:
this.GetComponent<MeshFilter>().sharedMesh.bounds = new Bounds(new Vector3(0f, 0f, 0f), new Vector3(500f, 500f, 500f)); */
Shader "Shadow Volume For Sphere Only"
{
SubShader
{
Tags { "RenderType"="Opaque" "Queue"="Overlay"}
ZWrite Off
Pass
{
Cull Back
ZTest Greater
ColorMask 0
Stencil
{
Ref 1
Comp Always
Pass Replace
}
CGPROGRAM
#pragma vertex VSMain
#pragma fragment PSMain
void VSMain (inout float4 vertex : POSITION, in float3 normal : NORMAL)
{
float4 worldPos = mul(unity_ObjectToWorld, vertex);
float3 normalDir = normalize(mul(unity_ObjectToWorld, float4(normal, 0.0))).xyz;
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float angle = dot(lightDir, normalDir);
if (angle < 0.0) worldPos.xyz = worldPos.xyz - lightDir * 1000.0f;
vertex = mul(UNITY_MATRIX_VP, worldPos);
}
void PSMain (float4 vertex : POSITION, out float4 fragColor : SV_Target)
{
fragColor = 0.1;
}
ENDCG
}
Pass
{
Cull Front
ZTest Greater
Stencil
{
Ref 1
Comp NotEqual
}
CGPROGRAM
#pragma vertex VSMain
#pragma fragment PSMain
void VSMain (inout float4 vertex : POSITION, in float3 normal : NORMAL)
{
float4 worldPos = mul(unity_ObjectToWorld, vertex);
float3 normalDir = normalize(mul(unity_ObjectToWorld, float4(normal, 0.0))).xyz;
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float angle = dot(lightDir, normalDir);
if (angle < 0.0) worldPos.xyz = worldPos.xyz - lightDir * 1000.0f;
vertex = mul(UNITY_MATRIX_VP, worldPos);
}
void PSMain (float4 vertex : POSITION, out float4 fragColor : SV_Target)
{
fragColor = 0.1;
}
ENDCG
}
Pass
{
CGPROGRAM
#pragma vertex VSMain
#pragma fragment PSMain
void VSMain (inout float4 vertex : POSITION, inout float3 normal : NORMAL)
{
normal = normalize(mul(unity_ObjectToWorld, float4(normal, 0.0))).xyz;
vertex = UnityObjectToClipPos(vertex);
}
void PSMain (float4 vertex : POSITION, float3 normal : NORMAL, out float4 fragColor : SV_Target)
{
float angle = dot(normalize(_WorldSpaceLightPos0.xyz), normal);
fragColor = float4(angle.xxx, 1.0);
}
ENDCG
}
}
}