5f4a4c9f89fb2ae411e5c5b65243567f501d09d9
[blender.git] / source / blender / draw / engines / eevee / shaders / lit_surface_frag.glsl
1
2 uniform int light_count;
3 uniform int probe_count;
4 uniform int grid_count;
5 uniform int planar_count;
6
7 uniform bool specToggle;
8 uniform bool ssrToggle;
9
10 uniform float refractionDepth;
11
12 #ifndef UTIL_TEX
13 #define UTIL_TEX
14 uniform sampler2DArray utilTex;
15 #endif /* UTIL_TEX */
16
17 in vec3 worldPosition;
18 in vec3 viewPosition;
19
20 #ifdef USE_FLAT_NORMAL
21 flat in vec3 worldNormal;
22 flat in vec3 viewNormal;
23 #else
24 in vec3 worldNormal;
25 in vec3 viewNormal;
26 #endif
27
28 uniform float maxRoughness;
29 uniform int rayCount;
30
31 /* ----------- default -----------  */
32
33 vec3 eevee_surface_lit(vec3 N, vec3 albedo, vec3 f0, float roughness, float ao, int ssr_id, out vec3 ssr_spec)
34 {
35         /* Zero length vectors cause issues, see: T51979. */
36 #if 0
37         N = normalize(N);
38 #else
39         {
40                 float len = length(N);
41                 if (isnan(len)) {
42                         return vec3(0.0);
43                 }
44                 N /= len;
45         }
46 #endif
47
48         roughness = clamp(roughness, 1e-8, 0.9999);
49         float roughnessSquared = roughness * roughness;
50
51         vec3 V = cameraVec;
52
53         /* ---------------- SCENE LAMPS LIGHTING ----------------- */
54
55 #ifdef HAIR_SHADER
56         vec3 norm_view = cross(V, N);
57         norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
58 #endif
59
60         vec3 diff = vec3(0.0);
61         vec3 spec = vec3(0.0);
62         for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
63                 LightData ld = lights_data[i];
64
65                 vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
66                 l_vector.xyz = ld.l_position - worldPosition;
67                 l_vector.w = length(l_vector.xyz);
68
69                 vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, l_vector);
70
71 #ifdef HAIR_SHADER
72                 vec3 norm_lamp, view_vec;
73                 float occlu_trans, occlu;
74                 light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
75
76                 diff += l_color_vis * light_diffuse(ld, -norm_lamp, V, l_vector) * occlu_trans;
77                 spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, f0) * occlu;
78 #else
79                 diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
80                 spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0);
81 #endif
82         }
83
84         /* Accumulate outgoing radiance */
85         vec3 out_light = diff * albedo + spec * float(specToggle);
86
87 #ifdef HAIR_SHADER
88         N = -norm_view;
89 #endif
90
91         /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
92
93         /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
94         vec4 spec_accum = vec4(0.0);
95
96         /* SSR lobe is applied later in a defered style */
97         if (!(ssrToggle && ssr_id == outputSsrId)) {
98                 /* Planar Reflections */
99                 for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) {
100                         PlanarData pd = planars_data[i];
101
102                         float fade = probe_attenuation_planar(pd, worldPosition, N, roughness);
103
104                         if (fade > 0.0) {
105                                 vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, roughness, fade);
106                                 accumulate_light(spec, fade, spec_accum);
107                         }
108                 }
109
110                 /* Specular probes */
111                 vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
112
113                 /* Starts at 1 because 0 is world probe */
114                 for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) {
115                         CubeData cd = probes_data[i];
116
117                         float fade = probe_attenuation_cube(cd, worldPosition);
118
119                         if (fade > 0.0) {
120                                 vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness);
121                                 accumulate_light(spec, fade, spec_accum);
122                         }
123                 }
124
125                 /* World Specular */
126                 if (spec_accum.a < 0.999) {
127                         vec3 spec = probe_evaluate_world_spec(spec_dir, roughness);
128                         accumulate_light(spec, 1.0, spec_accum);
129                 }
130         }
131
132         vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
133
134         /* Ambient Occlusion */
135         vec3 bent_normal;
136         float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
137
138         /* Get Brdf intensity */
139         vec2 uv = lut_coords(dot(N, V), roughness);
140         vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
141
142         ssr_spec = F_ibl(f0, brdf_lut);
143         if (!(ssrToggle && ssr_id == outputSsrId)) {
144                 ssr_spec *= specular_occlusion(dot(N, V), final_ao, roughness);
145         }
146         out_light += spec_accum.rgb * ssr_spec * float(specToggle);
147
148         /* ---------------- DIFFUSE ENVIRONMENT LIGHTING ----------------- */
149
150         /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
151         vec4 diff_accum = vec4(0.0);
152
153         /* Start at 1 because 0 is world irradiance */
154         for (int i = 1; i < MAX_GRID && i < grid_count && diff_accum.a < 0.999; ++i) {
155                 GridData gd = grids_data[i];
156
157                 vec3 localpos;
158                 float fade = probe_attenuation_grid(gd, worldPosition, localpos);
159
160                 if (fade > 0.0) {
161                         vec3 diff = probe_evaluate_grid(gd, worldPosition, bent_normal, localpos);
162                         accumulate_light(diff, fade, diff_accum);
163                 }
164         }
165
166         /* World Diffuse */
167         if (diff_accum.a < 0.999 && grid_count > 0) {
168                 vec3 diff = probe_evaluate_world_diff(bent_normal);
169                 accumulate_light(diff, 1.0, diff_accum);
170         }
171
172         out_light += diff_accum.rgb * albedo * gtao_multibounce(final_ao, albedo);
173
174         return out_light;
175 }
176
177 /* ----------- CLEAR COAT -----------  */
178
179 vec3 eevee_surface_clearcoat_lit(
180         vec3 N, vec3 albedo, vec3 f0, float roughness,
181         vec3 C_N, float C_intensity, float C_roughness, /* Clearcoat params */
182         float ao, int ssr_id, out vec3 ssr_spec)
183 {
184         roughness = clamp(roughness, 1e-8, 0.9999);
185         float roughnessSquared = roughness * roughness;
186         C_roughness = clamp(C_roughness, 1e-8, 0.9999);
187         float C_roughnessSquared = C_roughness * C_roughness;
188
189         /* Zero length vectors cause issues, see: T51979. */
190 #if 0
191         N = normalize(N);
192         C_N = normalize(C_N);
193 #else
194         {
195                 float len = length(N);
196                 if (isnan(len)) {
197                         return vec3(0.0);
198                 }
199                 N /= len;
200
201                 len = length(C_N);
202                 if (isnan(len)) {
203                         return vec3(0.0);
204                 }
205                 C_N /= len;
206         }
207 #endif
208
209         vec3 V = cameraVec;
210
211         /* ---------------- SCENE LAMPS LIGHTING ----------------- */
212
213 #ifdef HAIR_SHADER
214         vec3 norm_view = cross(V, N);
215         norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
216 #endif
217
218         vec3 diff = vec3(0.0);
219         vec3 spec = vec3(0.0);
220         for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
221                 LightData ld = lights_data[i];
222
223                 vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
224                 l_vector.xyz = ld.l_position - worldPosition;
225                 l_vector.w = length(l_vector.xyz);
226
227                 vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, l_vector);
228
229 #ifdef HAIR_SHADER
230                 vec3 norm_lamp, view_vec;
231                 float occlu_trans, occlu;
232                 light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
233
234                 diff += l_color_vis * light_diffuse(ld, -norm_lamp, V, l_vector) * occlu_trans;
235                 spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, f0) * occlu;
236                 spec += l_color_vis * light_specular(ld, C_N, view_vec, l_vector, C_roughnessSquared, f0) * C_intensity * occlu;
237 #else
238                 diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
239                 spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0);
240                 spec += l_color_vis * light_specular(ld, C_N, V, l_vector, C_roughnessSquared, f0) * C_intensity;
241 #endif
242         }
243
244         /* Accumulate outgoing radiance */
245         vec3 out_light = diff * albedo + spec * float(specToggle);
246
247 #ifdef HAIR_SHADER
248         N = -norm_view;
249 #endif
250
251         /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
252
253         /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
254         vec4 spec_accum = vec4(0.0);
255         vec4 C_spec_accum = vec4(0.0);
256
257         /* Planar Reflections */
258         for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) {
259                 PlanarData pd = planars_data[i];
260
261                 /* Fade on geometric normal. */
262                 float fade = probe_attenuation_planar(pd, worldPosition, worldNormal, roughness);
263
264                 if (fade > 0.0) {
265                         if (!(ssrToggle && ssr_id == outputSsrId)) {
266                                 vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, roughness, fade);
267                                 accumulate_light(spec, fade, spec_accum);
268                         }
269
270                         vec3 C_spec = probe_evaluate_planar(float(i), pd, worldPosition, C_N, V, C_roughness, fade);
271                         accumulate_light(C_spec, fade, C_spec_accum);
272                 }
273         }
274
275         /* Specular probes */
276         vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
277         vec3 C_spec_dir = get_specular_reflection_dominant_dir(C_N, V, C_roughnessSquared);
278
279         /* Starts at 1 because 0 is world probe */
280         for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) {
281                 CubeData cd = probes_data[i];
282
283                 float fade = probe_attenuation_cube(cd, worldPosition);
284
285                 if (fade > 0.0) {
286                         if (!(ssrToggle && ssr_id == outputSsrId)) {
287                                 vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness);
288                                 accumulate_light(spec, fade, spec_accum);
289                         }
290
291                         vec3 C_spec = probe_evaluate_cube(float(i), cd, worldPosition, C_spec_dir, C_roughness);
292                         accumulate_light(C_spec, fade, C_spec_accum);
293                 }
294         }
295
296         /* World Specular */
297         if (spec_accum.a < 0.999) {
298                 if (!(ssrToggle && ssr_id == outputSsrId)) {
299                         vec3 spec = probe_evaluate_world_spec(spec_dir, roughness);
300                         accumulate_light(spec, 1.0, spec_accum);
301                 }
302
303                 vec3 C_spec = probe_evaluate_world_spec(C_spec_dir, C_roughness);
304                 accumulate_light(C_spec, 1.0, C_spec_accum);
305         }
306
307         vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
308
309         /* Ambient Occlusion */
310         vec3 bent_normal;
311         float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
312
313         /* Get Brdf intensity */
314         vec2 uv = lut_coords(dot(N, V), roughness);
315         vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
316
317         ssr_spec = F_ibl(f0, brdf_lut);
318         if (!(ssrToggle && ssr_id == outputSsrId)) {
319                 ssr_spec *= specular_occlusion(dot(N, V), final_ao, roughness);
320         }
321         out_light += spec_accum.rgb * ssr_spec * float(specToggle);
322
323         uv = lut_coords(dot(C_N, V), C_roughness);
324         brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
325
326         out_light += C_spec_accum.rgb * F_ibl(vec3(0.04), brdf_lut) * specular_occlusion(dot(C_N, V), final_ao, C_roughness) * float(specToggle) * C_intensity;
327
328         /* ---------------- DIFFUSE ENVIRONMENT LIGHTING ----------------- */
329
330         /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
331         vec4 diff_accum = vec4(0.0);
332
333         /* Start at 1 because 0 is world irradiance */
334         for (int i = 1; i < MAX_GRID && i < grid_count && diff_accum.a < 0.999; ++i) {
335                 GridData gd = grids_data[i];
336
337                 vec3 localpos;
338                 float fade = probe_attenuation_grid(gd, worldPosition, localpos);
339
340                 if (fade > 0.0) {
341                         vec3 diff = probe_evaluate_grid(gd, worldPosition, bent_normal, localpos);
342                         accumulate_light(diff, fade, diff_accum);
343                 }
344         }
345
346         /* World Diffuse */
347         if (diff_accum.a < 0.999 && grid_count > 0) {
348                 vec3 diff = probe_evaluate_world_diff(bent_normal);
349                 accumulate_light(diff, 1.0, diff_accum);
350         }
351
352         out_light += diff_accum.rgb * albedo * gtao_multibounce(final_ao, albedo);
353
354         return out_light;
355 }
356
357 /* ----------- Diffuse -----------  */
358
359 vec3 eevee_surface_diffuse_lit(vec3 N, vec3 albedo, float ao)
360 {
361         vec3 V = cameraVec;
362
363         /* Zero length vectors cause issues, see: T51979. */
364 #if 0
365         N = normalize(N);
366 #else
367         {
368                 float len = length(N);
369                 if (isnan(len)) {
370                         return vec3(0.0);
371                 }
372                 N /= len;
373         }
374 #endif
375
376         /* ---------------- SCENE LAMPS LIGHTING ----------------- */
377
378 #ifdef HAIR_SHADER
379         vec3 norm_view = cross(V, N);
380         norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
381 #endif
382
383         vec3 diff = vec3(0.0);
384         for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
385                 LightData ld = lights_data[i];
386
387                 vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
388                 l_vector.xyz = ld.l_position - worldPosition;
389                 l_vector.w = length(l_vector.xyz);
390
391                 vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, l_vector);
392
393 #ifdef HAIR_SHADER
394                 vec3 norm_lamp, view_vec;
395                 float occlu_trans, occlu;
396                 light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
397
398                 diff += l_color_vis * light_diffuse(ld, -norm_lamp, V, l_vector) * occlu_trans;
399 #else
400                 diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
401 #endif
402         }
403
404         /* Accumulate outgoing radiance */
405         vec3 out_light = diff * albedo;
406
407 #ifdef HAIR_SHADER
408         N = -norm_view;
409 #endif
410
411         /* ---------------- DIFFUSE ENVIRONMENT LIGHTING ----------------- */
412
413         vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
414
415         /* Ambient Occlusion */
416         vec3 bent_normal;
417         float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
418
419         /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
420         vec4 diff_accum = vec4(0.0);
421
422         /* Start at 1 because 0 is world irradiance */
423         for (int i = 1; i < MAX_GRID && i < grid_count && diff_accum.a < 0.999; ++i) {
424                 GridData gd = grids_data[i];
425
426                 vec3 localpos;
427                 float fade = probe_attenuation_grid(gd, worldPosition, localpos);
428
429                 if (fade > 0.0) {
430                         vec3 diff = probe_evaluate_grid(gd, worldPosition, bent_normal, localpos);
431                         accumulate_light(diff, fade, diff_accum);
432                 }
433         }
434
435         /* World Diffuse */
436         if (diff_accum.a < 0.999 && grid_count > 0) {
437                 vec3 diff = probe_evaluate_world_diff(bent_normal);
438                 accumulate_light(diff, 1.0, diff_accum);
439         }
440
441         out_light += diff_accum.rgb * albedo * gtao_multibounce(final_ao, albedo);
442
443         return out_light;
444 }
445
446 /* ----------- Glossy -----------  */
447
448 vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao, int ssr_id, out vec3 ssr_spec)
449 {
450         roughness = clamp(roughness, 1e-8, 0.9999);
451         float roughnessSquared = roughness * roughness;
452
453         vec3 V = cameraVec;
454
455         /* Zero length vectors cause issues, see: T51979. */
456 #if 0
457         N = normalize(N);
458 #else
459         {
460                 float len = length(N);
461                 if (isnan(len)) {
462                         return vec3(0.0);
463                 }
464                 N /= len;
465         }
466 #endif
467
468         /* ---------------- SCENE LAMPS LIGHTING ----------------- */
469
470 #ifdef HAIR_SHADER
471         vec3 norm_view = cross(V, N);
472         norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
473 #endif
474
475         vec3 spec = vec3(0.0);
476         for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
477                 LightData ld = lights_data[i];
478
479                 vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
480                 l_vector.xyz = ld.l_position - worldPosition;
481                 l_vector.w = length(l_vector.xyz);
482
483                 vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, l_vector);
484
485 #ifdef HAIR_SHADER
486                 vec3 norm_lamp, view_vec;
487                 float occlu_trans, occlu;
488                 light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
489
490                 spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, f0) * occlu;
491 #else
492                 spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0);
493 #endif
494         }
495
496         /* Accumulate outgoing radiance */
497         vec3 out_light = spec * float(specToggle);
498
499 #ifdef HAIR_SHADER
500         N = -norm_view;
501 #endif
502
503         /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
504
505         /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
506         vec4 spec_accum = vec4(0.0);
507
508         if (!(ssrToggle && ssr_id == outputSsrId)) {
509                 /* Planar Reflections */
510                 for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) {
511                         PlanarData pd = planars_data[i];
512
513                         float fade = probe_attenuation_planar(pd, worldPosition, N, roughness);
514
515                         if (fade > 0.0) {
516                                 vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, roughness, fade);
517                                 accumulate_light(spec, fade, spec_accum);
518                         }
519                 }
520
521                 /* Specular probes */
522                 vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
523
524                 /* Starts at 1 because 0 is world probe */
525                 for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) {
526                         CubeData cd = probes_data[i];
527
528                         float fade = probe_attenuation_cube(cd, worldPosition);
529
530                         if (fade > 0.0) {
531                                 vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness);
532                                 accumulate_light(spec, fade, spec_accum);
533                         }
534                 }
535
536                 /* World Specular */
537                 if (spec_accum.a < 0.999) {
538                         vec3 spec = probe_evaluate_world_spec(spec_dir, roughness);
539                         accumulate_light(spec, 1.0, spec_accum);
540                 }
541         }
542
543         vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
544
545         /* Get Brdf intensity */
546         vec2 uv = lut_coords(dot(N, V), roughness);
547         vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
548
549         ssr_spec = F_ibl(f0, brdf_lut);
550         if (!(ssrToggle && ssr_id == outputSsrId)) {
551                 /* Ambient Occlusion */
552                 vec3 bent_normal;
553                 float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
554
555                 ssr_spec *= specular_occlusion(dot(N, V), final_ao, roughness);
556         }
557         out_light += spec_accum.rgb * ssr_spec * float(specToggle);
558
559         return out_light;
560 }
561
562 /* ----------- Transmission -----------  */
563
564 vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior)
565 {
566         /* Zero length vectors cause issues, see: T51979. */
567 #if 0
568         N = normalize(N);
569 #else
570         {
571                 float len = length(N);
572                 if (isnan(len)) {
573                         return vec3(0.0);
574                 }
575                 N /= len;
576         }
577 #endif
578         vec3 V = cameraVec;
579         ior = (gl_FrontFacing) ? ior : 1.0 / ior;
580
581         roughness = clamp(roughness, 1e-8, 0.9999);
582         float roughnessSquared = roughness * roughness;
583
584         /* ---------------- SCENE LAMPS LIGHTING ----------------- */
585
586         /* No support for now. Supporting LTCs mean having a 3D LUT.
587          * We could support point lights easily though. */
588
589         /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
590
591         /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
592         vec4 trans_accum = vec4(0.0);
593
594         /* Refract the view vector using the depth heuristic.
595          * Then later Refract a second time the already refracted
596          * ray using the inverse ior. */
597         float final_ior = (refractionDepth > 0.0) ? 1.0 / ior : ior;
598         vec3 refr_V = (refractionDepth > 0.0) ? -refract(-V, N, final_ior) : V;
599         vec3 refr_pos = (refractionDepth > 0.0) ? line_plane_intersect(worldPosition, refr_V, worldPosition - N * refractionDepth, N) : worldPosition;
600
601 #ifdef USE_REFRACTION
602         /* Screen Space Refraction */
603         if (ssrToggle && roughness < maxRoughness + 0.2) {
604                 vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw;
605
606                 /* Find approximated position of the 2nd refraction event. */
607                 vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) : viewPosition;
608
609                 float ray_ofs = 1.0 / float(rayCount);
610                 vec4 spec = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand, 0.0);
611                 if (rayCount > 1) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs);
612                 if (rayCount > 2) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0,  1.0, -1.0), 2.0 * ray_ofs);
613                 if (rayCount > 3) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0, -1.0,  1.0), 3.0 * ray_ofs);
614                 spec /= float(rayCount);
615                 spec.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness);
616                 accumulate_light(spec.rgb, spec.a, trans_accum);
617         }
618 #endif
619
620         /* Specular probes */
621         /* NOTE: This bias the IOR */
622         vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior);
623
624         /* Starts at 1 because 0 is world probe */
625         for (int i = 1; i < MAX_PROBE && i < probe_count && trans_accum.a < 0.999; ++i) {
626                 CubeData cd = probes_data[i];
627
628                 float fade = probe_attenuation_cube(cd, worldPosition);
629
630                 if (fade > 0.0) {
631                         vec3 spec = probe_evaluate_cube(float(i), cd, refr_pos, refr_dir, roughnessSquared);
632                         accumulate_light(spec, fade, trans_accum);
633                 }
634         }
635
636         /* World Specular */
637         if (trans_accum.a < 0.999) {
638                 vec3 spec = probe_evaluate_world_spec(refr_dir, roughnessSquared);
639                 accumulate_light(spec, 1.0, trans_accum);
640         }
641
642         float btdf = get_btdf_lut(utilTex, dot(N, V), roughness, ior);
643
644         return trans_accum.rgb * btdf;
645 }
646
647 vec3 eevee_surface_glass(vec3 N, vec3 transmission_col, float roughness, float ior, int ssr_id, out vec3 ssr_spec)
648 {
649         /* Zero length vectors cause issues, see: T51979. */
650 #if 0
651         N = normalize(N);
652 #else
653         {
654                 float len = length(N);
655                 if (isnan(len)) {
656                         return vec3(0.0);
657                 }
658                 N /= len;
659         }
660 #endif
661         vec3 V = cameraVec;
662         ior = (gl_FrontFacing) ? ior : 1.0 / ior;
663
664         if (!specToggle) return vec3(0.0);
665
666         roughness = clamp(roughness, 1e-8, 0.9999);
667         float roughnessSquared = roughness * roughness;
668
669         /* ---------------- SCENE LAMPS LIGHTING ----------------- */
670
671 #ifdef HAIR_SHADER
672         vec3 norm_view = cross(V, N);
673         norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
674 #endif
675
676         vec3 spec = vec3(0.0);
677         for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
678                 LightData ld = lights_data[i];
679
680                 vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
681                 l_vector.xyz = ld.l_position - worldPosition;
682                 l_vector.w = length(l_vector.xyz);
683
684                 vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, l_vector);
685
686 #ifdef HAIR_SHADER
687                 vec3 norm_lamp, view_vec;
688                 float occlu_trans, occlu;
689                 light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
690
691                 spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, vec3(1.0)) * occlu;
692 #else
693                 spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, vec3(1.0));
694 #endif
695         }
696
697         /* Accumulate outgoing radiance */
698         vec3 out_light = spec;
699
700 #ifdef HAIR_SHADER
701         N = -norm_view;
702 #endif
703
704
705         /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
706
707         /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
708         vec4 spec_accum = vec4(0.0);
709
710         /* Planar Reflections */
711         if (!(ssrToggle && ssr_id == outputSsrId)) {
712                 for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999 && roughness < 0.1; ++i) {
713                         PlanarData pd = planars_data[i];
714
715                         float fade = probe_attenuation_planar(pd, worldPosition, N, roughness);
716
717                         if (fade > 0.0) {
718                                 vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, roughness, fade);
719                                 accumulate_light(spec, fade, spec_accum);
720                         }
721                 }
722         }
723
724         /* Refract the view vector using the depth heuristic.
725          * Then later Refract a second time the already refracted
726          * ray using the inverse ior. */
727         float final_ior = (refractionDepth > 0.0) ? 1.0 / ior : ior;
728         vec3 refr_V = (refractionDepth > 0.0) ? -refract(-V, N, final_ior) : V;
729         vec3 refr_pos = (refractionDepth > 0.0) ? line_plane_intersect(worldPosition, refr_V, worldPosition - N * refractionDepth, N) : worldPosition;
730
731         vec4 trans_accum = vec4(0.0);
732
733 #ifdef USE_REFRACTION
734         /* Screen Space Refraction */
735         if (ssrToggle && roughness < maxRoughness + 0.2) {
736                 vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw;
737
738                 /* Find approximated position of the 2nd refraction event. */
739                 vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) : viewPosition;
740
741                 float ray_ofs = 1.0 / float(rayCount);
742                 vec4 spec = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand, 0.0);
743                 if (rayCount > 1) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs);
744                 if (rayCount > 2) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0,  1.0, -1.0), 2.0 * ray_ofs);
745                 if (rayCount > 3) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0, -1.0,  1.0), 3.0 * ray_ofs);
746                 spec /= float(rayCount);
747                 spec.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness);
748                 accumulate_light(spec.rgb, spec.a, trans_accum);
749         }
750 #endif
751
752         /* Specular probes */
753         vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior);
754         vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
755
756         /* Starts at 1 because 0 is world probe */
757         for (int i = 1; i < MAX_PROBE && i < probe_count && (spec_accum.a < 0.999 || trans_accum.a < 0.999); ++i) {
758                 CubeData cd = probes_data[i];
759
760                 float fade = probe_attenuation_cube(cd, worldPosition);
761
762                 if (fade > 0.0) {
763                         if (!(ssrToggle && ssr_id == outputSsrId)) {
764                                 vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness);
765                                 accumulate_light(spec, fade, spec_accum);
766                         }
767
768                         spec = probe_evaluate_cube(float(i), cd, refr_pos, refr_dir, roughnessSquared);
769                         accumulate_light(spec, fade, trans_accum);
770                 }
771         }
772
773         /* World Specular */
774         if (spec_accum.a < 0.999) {
775                 if (!(ssrToggle && ssr_id == outputSsrId)) {
776                         vec3 spec = probe_evaluate_world_spec(spec_dir, roughness);
777                         accumulate_light(spec, 1.0, spec_accum);
778                 }
779         }
780
781         if (trans_accum.a < 0.999) {
782                 spec = probe_evaluate_world_spec(refr_dir, roughnessSquared);
783                 accumulate_light(spec, 1.0, trans_accum);
784         }
785
786         /* Ambient Occlusion */
787         /* TODO : when AO will be cheaper */
788         float final_ao = 1.0;
789
790         float NV = dot(N, V);
791         /* Get Brdf intensity */
792         vec2 uv = lut_coords(NV, roughness);
793         vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
794
795         float fresnel = F_eta(ior, NV);
796
797         /* Apply fresnel on lamps. */
798         out_light *= vec3(fresnel);
799
800         ssr_spec = vec3(fresnel) * F_ibl(vec3(1.0), brdf_lut);
801         if (!(ssrToggle && ssr_id == outputSsrId)) {
802                 ssr_spec *= specular_occlusion(dot(N, V), final_ao, roughness);
803         }
804         out_light += spec_accum.rgb * ssr_spec;
805
806
807         float btdf = get_btdf_lut(utilTex, NV, roughness, ior);
808
809         out_light += vec3(1.0 - fresnel) * transmission_col * trans_accum.rgb * btdf;
810
811         return out_light;
812 }