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
|
#pragma BLENDER_REQUIRE(lights_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl)
#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
struct ClosureInputDiffuse {
vec3 N; /** Shading normal. */
vec3 albedo; /** Used for multibounce GTAO approximation. Not applied to final radiance. */
};
#ifdef GPU_METAL
/* C++ struct initialization. */
# define CLOSURE_INPUT_Diffuse_DEFAULT \
{ \
vec3(0.0), vec3(0.0) \
}
#else
# define CLOSURE_INPUT_Diffuse_DEFAULT ClosureInputDiffuse(vec3(0.0), vec3(0.0))
#endif
struct ClosureEvalDiffuse {
vec3 probe_sampling_dir; /** Direction to sample probes from. */
float ambient_occlusion; /** Final occlusion for distant lighting. */
};
/* Stubs. */
#define ClosureOutputDiffuse ClosureOutput
#define closure_Diffuse_planar_eval(cl_in, cl_eval, cl_common, data, cl_out)
#define closure_Diffuse_cubemap_eval(cl_in, cl_eval, cl_common, data, cl_out)
ClosureEvalDiffuse closure_Diffuse_eval_init(inout ClosureInputDiffuse cl_in,
ClosureEvalCommon cl_common,
out ClosureOutputDiffuse cl_out)
{
cl_in.N = safe_normalize(cl_in.N);
cl_out.radiance = vec3(0.0);
ClosureEvalDiffuse cl_eval;
cl_eval.ambient_occlusion = diffuse_occlusion(cl_common.occlusion_data,
cl_common.V,
cl_in.N,
cl_common.Ng,
cl_in.albedo,
cl_eval.probe_sampling_dir);
return cl_eval;
}
void closure_Diffuse_light_eval(ClosureInputDiffuse cl_in,
ClosureEvalDiffuse cl_eval,
ClosureEvalCommon cl_common,
ClosureLightData light,
inout ClosureOutputDiffuse cl_out)
{
float radiance = light_diffuse(light.data, cl_in.N, cl_common.V, light.L);
/* TODO(@fclem): We could try to shadow lights that are shadowless with the ambient_occlusion
* factor here. */
cl_out.radiance += light.data.l_color *
(light.data.l_diff * light.vis * light.contact_shadow * radiance);
}
void closure_Diffuse_grid_eval(ClosureInputDiffuse cl_in,
ClosureEvalDiffuse cl_eval,
ClosureEvalCommon cl_common,
ClosureGridData grid,
inout ClosureOutputDiffuse cl_out)
{
vec3 probe_radiance = probe_evaluate_grid(
grid.data, cl_common.P, cl_eval.probe_sampling_dir, grid.local_pos);
cl_out.radiance += grid.attenuation * probe_radiance;
}
void closure_Diffuse_indirect_end(ClosureInputDiffuse cl_in,
ClosureEvalDiffuse cl_eval,
ClosureEvalCommon cl_common,
inout ClosureOutputDiffuse cl_out)
{
/* If not enough light has been accumulated from probes, use the world specular cubemap
* to fill the remaining energy needed. */
if (cl_common.diffuse_accum > 0.0) {
vec3 probe_radiance = probe_evaluate_world_diff(cl_eval.probe_sampling_dir);
cl_out.radiance += cl_common.diffuse_accum * probe_radiance;
}
/* Apply occlusion on radiance before the light loop. */
cl_out.radiance *= cl_eval.ambient_occlusion;
}
void closure_Diffuse_eval_end(ClosureInputDiffuse cl_in,
ClosureEvalDiffuse cl_eval,
ClosureEvalCommon cl_common,
inout ClosureOutputDiffuse cl_out)
{
cl_out.radiance = render_pass_diffuse_mask(cl_out.radiance);
#if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND)
/* This makes shader resources become unused and avoid issues with samplers. (see T59747) */
cl_out.radiance = vec3(0.0);
return;
#endif
}
|