1 Shader "Hidden/SunShaftsComposite" {
2 Properties {
3 _MainTex ("Base", 2D) = "" {}
4 _ColorBuffer ("Color", 2D) = "" {}
5 _Skybox ("Skybox", 2D) = "" {}
6 }
7
8 CGINCLUDE
9
10 #include "UnityCG.cginc"
11
12 struct v2f {
13 float4 pos : SV_POSITION;
14 float2 uv : TEXCOORD0;
15 #if UNITY_UV_STARTS_AT_TOP
16 float2 uv1 : TEXCOORD1;
17 #endif
18 };
19
20 struct v2f_radial {
21 float4 pos : SV_POSITION;
22 float2 uv : TEXCOORD0;
23 float2 blurVector : TEXCOORD1;
24 };
25
26 sampler2D _MainTex;
27 sampler2D _ColorBuffer;
28 sampler2D _Skybox;
29 sampler2D_float _CameraDepthTexture;
30
31 uniform half4 _SunThreshold;
32
33 uniform half4 _SunColor;
34 uniform half4 _BlurRadius4;
35 uniform half4 _SunPosition;
36 uniform half4 _MainTex_TexelSize;
37
38 #define SAMPLES_FLOAT 6.0f
39 #define SAMPLES_INT 6
40
41 v2f vert( appdata_img v ) {
42 v2f o;
43 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
44 o.uv = v.texcoord.xy;
45
46 #if UNITY_UV_STARTS_AT_TOP
47 o.uv1 = v.texcoord.xy;
48 if (_MainTex_TexelSize.y < 0)
49 o.uv1.y = 1-o.uv1.y;
50 #endif
51
52 return o;
53 }
54
55 half4 fragScreen(v2f i) : SV_Target {
56 half4 colorA = tex2D (_MainTex, i.uv.xy);
57 #if UNITY_UV_STARTS_AT_TOP
58 half4 colorB = tex2D (_ColorBuffer, i.uv1.xy);
59 #else
60 half4 colorB = tex2D (_ColorBuffer, i.uv.xy);
61 #endif
62 half4 depthMask = saturate (colorB * _SunColor);
63 return 1.0f - (1.0f-colorA) * (1.0f-depthMask);
64 }
65
66 half4 fragAdd(v2f i) : SV_Target {
67 half4 colorA = tex2D (_MainTex, i.uv.xy);
68 #if UNITY_UV_STARTS_AT_TOP
69 half4 colorB = tex2D (_ColorBuffer, i.uv1.xy);
70 #else
71 half4 colorB = tex2D (_ColorBuffer, i.uv.xy);
72 #endif
73 half4 depthMask = saturate (colorB * _SunColor);
74 return colorA + depthMask;
75 }
76
77 v2f_radial vert_radial( appdata_img v ) {
78 v2f_radial o;
79 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
80
81 o.uv.xy = v.texcoord.xy;
82 o.blurVector = (_SunPosition.xy - v.texcoord.xy) * _BlurRadius4.xy;
83
84 return o;
85 }
86
87 half4 frag_radial(v2f_radial i) : SV_Target
88 {
89 half4 color = half4(0,0,0,0);
90 for(int j = 0; j < SAMPLES_INT; j++)
91 {
92 half4 tmpColor = tex2D(_MainTex, i.uv.xy);
93 color += tmpColor;
94 i.uv.xy += i.blurVector;
95 }
96 return color / SAMPLES_FLOAT;
97 }
98
99 half TransformColor (half4 skyboxValue) {
100 return dot(max(skyboxValue.rgb - _SunThreshold.rgb, half3(0,0,0)), half3(1,1,1)); // threshold and convert to greyscale
101 }
102
103 half4 frag_depth (v2f i) : SV_Target {
104 #if UNITY_UV_STARTS_AT_TOP
105 float depthSample = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv1.xy);
106 #else
107 float depthSample = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv.xy);
108 #endif
109
110 half4 tex = tex2D (_MainTex, i.uv.xy);
111
112 depthSample = Linear01Depth (depthSample);
113
114 // consider maximum radius
115 #if UNITY_UV_STARTS_AT_TOP
116 half2 vec = _SunPosition.xy - i.uv1.xy;
117 #else
118 half2 vec = _SunPosition.xy - i.uv.xy;
119 #endif
120 half dist = saturate (_SunPosition.w - length (vec.xy));
121
122 half4 outColor = 0;
123
124 // consider shafts blockers
125 if (depthSample > 0.99)
126 outColor = TransformColor (tex) * dist;
127
128 return outColor;
129 }
130
131 half4 frag_nodepth (v2f i) : SV_Target {
132 #if UNITY_UV_STARTS_AT_TOP
133 float4 sky = (tex2D (_Skybox, i.uv1.xy));
134 #else
135 float4 sky = (tex2D (_Skybox, i.uv.xy));
136 #endif
137
138 float4 tex = (tex2D (_MainTex, i.uv.xy));
139
140 // consider maximum radius
141 #if UNITY_UV_STARTS_AT_TOP
142 half2 vec = _SunPosition.xy - i.uv1.xy;
143 #else
144 half2 vec = _SunPosition.xy - i.uv.xy;
145 #endif
146 half dist = saturate (_SunPosition.w - length (vec));
147
148 half4 outColor = 0;
149
150 // find unoccluded sky pixels
151 // consider pixel values that differ significantly between framebuffer and sky-only buffer as occluded
152 if (Luminance ( abs(sky.rgb - tex.rgb)) < 0.2)
153 outColor = TransformColor (sky) * dist;
154
155 return outColor;
156 }
157
158
159
160 ENDCG
161
162 Subshader {
163
164 Pass {
165 ZTest Always Cull Off ZWrite Off
166
167 CGPROGRAM
168
169 #pragma vertex vert
170 #pragma fragment fragScreen
171
172 ENDCG
173 }
174
175 Pass {
176 ZTest Always Cull Off ZWrite Off
177
178 CGPROGRAM
179
180 #pragma vertex vert_radial
181 #pragma fragment frag_radial
182
183 ENDCG
184 }
185
186 Pass {
187 ZTest Always Cull Off ZWrite Off
188
189 CGPROGRAM
190
191 #pragma vertex vert
192 #pragma fragment frag_depth
193
194 ENDCG
195 }
196
197 Pass {
198 ZTest Always Cull Off ZWrite Off
199
200 CGPROGRAM
201
202 #pragma vertex vert
203 #pragma fragment frag_nodepth
204
205 ENDCG
206 }
207
208 Pass {
209 ZTest Always Cull Off ZWrite Off
210
211 CGPROGRAM
212
213 #pragma vertex vert
214 #pragma fragment fragAdd
215
216 ENDCG
217 }
218 }
219
220 Fallback off
221
222 } // shader