676aa2c97489d69f3c271eed0da48404a678ca09
[blender.git] / source / blender / draw / engines / eevee / shaders / lamps_lib.glsl
1
2 uniform sampler2DArray shadowTexture;
3
4 layout(std140) uniform shadow_block {
5         ShadowData        shadows_data[MAX_SHADOW];
6         ShadowCubeData    shadows_cube_data[MAX_SHADOW_CUBE];
7         ShadowCascadeData shadows_cascade_data[MAX_SHADOW_CASCADE];
8 };
9
10 layout(std140) uniform light_block {
11         LightData lights_data[MAX_LIGHT];
12 };
13
14 /* type */
15 #define POINT    0.0
16 #define SUN      1.0
17 #define SPOT     2.0
18 #define HEMI     3.0
19 #define AREA     4.0
20
21 /* ----------------------------------------------------------- */
22 /* ----------------------- Shadow tests ---------------------- */
23 /* ----------------------------------------------------------- */
24
25 float shadow_test_esm(float z, float dist, float exponent)
26 {
27         return saturate(exp(exponent * (z - dist)));
28 }
29
30 float shadow_test_pcf(float z, float dist)
31 {
32         return step(0, z - dist);
33 }
34
35 float shadow_test_vsm(vec2 moments, float dist, float bias, float bleed_bias)
36 {
37         float p = 0.0;
38
39         if (dist <= moments.x)
40                 p = 1.0;
41
42         float variance = moments.y - (moments.x * moments.x);
43         variance = max(variance, bias / 10.0);
44
45         float d = moments.x - dist;
46         float p_max = variance / (variance + d * d);
47
48         /* Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1] */
49         p_max = clamp((p_max - bleed_bias) / (1.0 - bleed_bias), 0.0, 1.0);
50
51         return max(p, p_max);
52 }
53
54
55 /* ----------------------------------------------------------- */
56 /* ----------------------- Shadow types ---------------------- */
57 /* ----------------------------------------------------------- */
58
59 float shadow_cubemap(ShadowData sd, ShadowCubeData scd, float texid, vec3 W)
60 {
61         vec3 cubevec = W - scd.position.xyz;
62         float dist = length(cubevec);
63
64         /* If fragment is out of shadowmap range, do not occlude */
65         /* XXX : we check radial distance against a cubeface distance.
66          * We loose quite a bit of valid area. */
67         if (dist > sd.sh_far)
68                 return 1.0;
69
70         cubevec /= dist;
71
72 #if defined(SHADOW_VSM)
73         vec2 moments = texture_octahedron(shadowTexture, vec4(cubevec, texid)).rg;
74 #else
75         float z = texture_octahedron(shadowTexture, vec4(cubevec, texid)).r;
76 #endif
77
78 #if defined(SHADOW_VSM)
79         return shadow_test_vsm(moments, dist, sd.sh_bias, sd.sh_bleed);
80 #elif defined(SHADOW_ESM)
81         return shadow_test_esm(z, dist - sd.sh_bias, sd.sh_exp);
82 #else
83         return shadow_test_pcf(z, dist - sd.sh_bias);
84 #endif
85 }
86
87 float evaluate_cascade(ShadowData sd, mat4 shadowmat, vec3 W, float range, float texid)
88 {
89         vec4 shpos = shadowmat * vec4(W, 1.0);
90         float dist = shpos.z * range;
91
92 #if defined(SHADOW_VSM)
93         vec2 moments = texture(shadowTexture, vec3(shpos.xy, texid)).rg;
94 #else
95         float z = texture(shadowTexture, vec3(shpos.xy, texid)).r;
96 #endif
97
98         float vis;
99 #if defined(SHADOW_VSM)
100         vis = shadow_test_vsm(moments, dist, sd.sh_bias, sd.sh_bleed);
101 #elif defined(SHADOW_ESM)
102         vis = shadow_test_esm(z, dist - sd.sh_bias, sd.sh_exp);
103 #else
104         vis = shadow_test_pcf(z, dist - sd.sh_bias);
105 #endif
106
107         /* If fragment is out of shadowmap range, do not occlude */
108         if (shpos.z < 1.0 && shpos.z > 0.0) {
109                 return vis;
110         }
111         else {
112                 return 1.0;
113         }
114 }
115
116 float shadow_cascade(ShadowData sd, ShadowCascadeData scd, float texid, vec3 W)
117 {
118         vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
119         vec4 weights = smoothstep(scd.split_end_distances, scd.split_start_distances.yzwx, view_z);
120         weights.yzw -= weights.xyz;
121
122         vec4 vis = vec4(1.0);
123         float range = abs(sd.sh_far - sd.sh_near); /* Same factor as in get_cascade_world_distance(). */
124
125         /* Branching using (weights > 0.0) is reaally slooow on intel so avoid it for now. */
126         vis.x = evaluate_cascade(sd, scd.shadowmat[0], W, range, texid + 0);
127         vis.y = evaluate_cascade(sd, scd.shadowmat[1], W, range, texid + 1);
128         vis.z = evaluate_cascade(sd, scd.shadowmat[2], W, range, texid + 2);
129         vis.w = evaluate_cascade(sd, scd.shadowmat[3], W, range, texid + 3);
130
131         float weight_sum = dot(vec4(1.0), weights);
132         if (weight_sum > 0.9999) {
133                 float vis_sum = dot(vec4(1.0), vis * weights);
134                 return vis_sum / weight_sum;
135         }
136         else {
137                 float vis_sum = dot(vec4(1.0), vis * step(0.001, weights));
138                 return mix(1.0, vis_sum, weight_sum);
139         }
140 }
141
142 /* ----------------------------------------------------------- */
143 /* --------------------- Light Functions --------------------- */
144 /* ----------------------------------------------------------- */
145 #define MAX_MULTI_SHADOW 4
146
147 float light_visibility(LightData ld, vec3 W, vec4 l_vector)
148 {
149         float vis = 1.0;
150
151         if (ld.l_type == SPOT) {
152                 float z = dot(ld.l_forward, l_vector.xyz);
153                 vec3 lL = l_vector.xyz / z;
154                 float x = dot(ld.l_right, lL) / ld.l_sizex;
155                 float y = dot(ld.l_up, lL) / ld.l_sizey;
156
157                 float ellipse = 1.0 / sqrt(1.0 + x * x + y * y);
158
159                 float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend);
160
161                 vis *= spotmask;
162                 vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
163         }
164         else if (ld.l_type == AREA) {
165                 vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
166         }
167
168 #if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW)
169         /* shadowing */
170         if (ld.l_shadowid >= 0.0) {
171                 ShadowData data = shadows_data[int(ld.l_shadowid)];
172                 if (ld.l_type == SUN) {
173                         /* TODO : MSM */
174                         // for (int i = 0; i < MAX_MULTI_SHADOW; ++i) {
175                                 vis *= shadow_cascade(
176                                         data, shadows_cascade_data[int(data.sh_data_start)],
177                                         data.sh_tex_start, W);
178                         // }
179                 }
180                 else {
181                         /* TODO : MSM */
182                         // for (int i = 0; i < MAX_MULTI_SHADOW; ++i) {
183                                 vis *= shadow_cubemap(
184                                         data, shadows_cube_data[int(data.sh_data_start)],
185                                         data.sh_tex_start, W);
186                         // }
187                 }
188         }
189 #endif
190
191         return vis;
192 }
193
194 float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector)
195 {
196 #ifdef USE_LTC
197         if (ld.l_type == SUN) {
198                 /* TODO disk area light */
199                 return direct_diffuse_sun(ld, N);
200         }
201         else if (ld.l_type == AREA) {
202                 return direct_diffuse_rectangle(ld, N, V, l_vector);
203         }
204         else {
205                 return direct_diffuse_sphere(ld, N, l_vector);
206         }
207 #else
208         if (ld.l_type == SUN) {
209                 return direct_diffuse_sun(ld, N, V);
210         }
211         else {
212                 return direct_diffuse_point(N, l_vector);
213         }
214 #endif
215 }
216
217 vec3 light_specular(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0)
218 {
219 #ifdef USE_LTC
220         if (ld.l_type == SUN) {
221                 /* TODO disk area light */
222                 return direct_ggx_sun(ld, N, V, roughness, f0);
223         }
224         else if (ld.l_type == AREA) {
225                 return direct_ggx_rectangle(ld, N, V, l_vector, roughness, f0);
226         }
227         else {
228                 return direct_ggx_sphere(ld, N, V, l_vector, roughness, f0);
229         }
230 #else
231         if (ld.l_type == SUN) {
232                 return direct_ggx_sun(ld, N, V, roughness, f0);
233         }
234         else {
235                 return direct_ggx_point(N, V, l_vector, roughness, f0);
236         }
237 #endif
238 }
239
240 #ifdef HAIR_SHADER
241 void light_hair_common(
242         LightData ld, vec3 N, vec3 V, vec4 l_vector, vec3 norm_view,
243         out float occlu_trans, out float occlu,
244         out vec3 norm_lamp, out vec3 view_vec)
245 {
246         const float transmission = 0.3; /* Uniform internal scattering factor */
247
248         vec3 lamp_vec;
249
250         if (ld.l_type == SUN || ld.l_type == AREA) {
251                 lamp_vec = ld.l_forward;
252         }
253         else {
254                 lamp_vec = -l_vector.xyz;
255         }
256
257         norm_lamp = cross(lamp_vec, N);
258         norm_lamp = normalize(cross(N, norm_lamp)); /* Normal facing lamp */
259
260         /* Rotate view vector onto the cross(tangent, light) plane */
261         view_vec = normalize(norm_lamp * dot(norm_view, V) + N * dot(N, V));
262
263         occlu = (dot(norm_view, norm_lamp) * 0.5 + 0.5);
264         occlu_trans = transmission + (occlu * (1.0 - transmission)); /* Includes transmission component */
265 }
266 #endif