Welcome to mirror list, hosted at ThFree Co, Russian Federation.

closure_lib.glsl « shaders « eevee « engines « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e572245ace981dc50a7cb35657774b0ad45ae56c (plain)
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(renderpass_lib.glsl)

#ifndef VOLUMETRICS

uniform int outputSsrId = 1;
uniform int outputSssId = 1;

#endif

struct Closure {
#ifdef VOLUMETRICS
  vec3 absorption;
  vec3 scatter;
  vec3 emission;
  float anisotropy;

#else /* SURFACE */
  vec3 radiance;
  vec3 transmittance;
  float holdout;
  vec4 ssr_data;
  vec2 ssr_normal;
  int flag;
#  ifdef USE_SSS
  vec3 sss_irradiance;
  vec3 sss_albedo;
  float sss_radius;
#  endif

#endif
};

/* Prototype */
Closure nodetree_exec(void);

/* clang-format off */
/* Avoid multiline defines. */
#ifdef VOLUMETRICS
#  define CLOSURE_DEFAULT Closure(vec3(0), vec3(0), vec3(0), 0.0)
#elif !defined(USE_SSS)
#  define CLOSURE_DEFAULT Closure(vec3(0), vec3(0), 0.0, vec4(0), vec2(0), 0)
#else
#  define CLOSURE_DEFAULT Closure(vec3(0), vec3(0), 0.0, vec4(0), vec2(0), 0, vec3(0), vec3(0), 0.0)
#endif
/* clang-format on */

#define FLAG_TEST(flag, val) (((flag) & (val)) != 0)

#define CLOSURE_SSR_FLAG 1
#define CLOSURE_SSS_FLAG 2
#define CLOSURE_HOLDOUT_FLAG 4

#ifdef VOLUMETRICS
Closure closure_mix(Closure cl1, Closure cl2, float fac)
{
  Closure cl;
  cl.absorption = mix(cl1.absorption, cl2.absorption, fac);
  cl.scatter = mix(cl1.scatter, cl2.scatter, fac);
  cl.emission = mix(cl1.emission, cl2.emission, fac);
  cl.anisotropy = mix(cl1.anisotropy, cl2.anisotropy, fac);
  return cl;
}

Closure closure_add(Closure cl1, Closure cl2)
{
  Closure cl;
  cl.absorption = cl1.absorption + cl2.absorption;
  cl.scatter = cl1.scatter + cl2.scatter;
  cl.emission = cl1.emission + cl2.emission;
  cl.anisotropy = (cl1.anisotropy + cl2.anisotropy) / 2.0; /* Average phase (no multi lobe) */
  return cl;
}

Closure closure_emission(vec3 rgb)
{
  Closure cl = CLOSURE_DEFAULT;
  cl.emission = rgb;
  return cl;
}

#else /* SURFACE */

Closure closure_mix(Closure cl1, Closure cl2, float fac)
{
  Closure cl;
  cl.holdout = mix(cl1.holdout, cl2.holdout, fac);

  if (FLAG_TEST(cl1.flag, CLOSURE_HOLDOUT_FLAG)) {
    fac = 1.0;
  }
  else if (FLAG_TEST(cl2.flag, CLOSURE_HOLDOUT_FLAG)) {
    fac = 0.0;
  }

  cl.transmittance = mix(cl1.transmittance, cl2.transmittance, fac);
  cl.radiance = mix(cl1.radiance, cl2.radiance, fac);
  cl.flag = cl1.flag | cl2.flag;
  cl.ssr_data = mix(cl1.ssr_data, cl2.ssr_data, fac);
  bool use_cl1_ssr = FLAG_TEST(cl1.flag, CLOSURE_SSR_FLAG);
  /* When mixing SSR don't blend roughness and normals but only specular (ssr_data.xyz).*/
  cl.ssr_data.w = (use_cl1_ssr) ? cl1.ssr_data.w : cl2.ssr_data.w;
  cl.ssr_normal = (use_cl1_ssr) ? cl1.ssr_normal : cl2.ssr_normal;

#  ifdef USE_SSS
  cl.sss_albedo = mix(cl1.sss_albedo, cl2.sss_albedo, fac);
  bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
  /* It also does not make sense to mix SSS radius or irradiance. */
  cl.sss_radius = (use_cl1_sss) ? cl1.sss_radius : cl2.sss_radius;
  cl.sss_irradiance = (use_cl1_sss) ? cl1.sss_irradiance : cl2.sss_irradiance;
#  endif
  return cl;
}

Closure closure_add(Closure cl1, Closure cl2)
{
  Closure cl;
  cl.transmittance = cl1.transmittance + cl2.transmittance;
  cl.radiance = cl1.radiance + cl2.radiance;
  cl.holdout = cl1.holdout + cl2.holdout;
  cl.flag = cl1.flag | cl2.flag;
  cl.ssr_data = cl1.ssr_data + cl2.ssr_data;
  bool use_cl1_ssr = FLAG_TEST(cl1.flag, CLOSURE_SSR_FLAG);
  /* When mixing SSR don't blend roughness and normals.*/
  cl.ssr_data.w = (use_cl1_ssr) ? cl1.ssr_data.w : cl2.ssr_data.w;
  cl.ssr_normal = (use_cl1_ssr) ? cl1.ssr_normal : cl2.ssr_normal;

#  ifdef USE_SSS
  cl.sss_albedo = cl1.sss_albedo + cl2.sss_albedo;
  bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
  /* It also does not make sense to mix SSS radius or irradiance. */
  cl.sss_radius = (use_cl1_sss) ? cl1.sss_radius : cl2.sss_radius;
  cl.sss_irradiance = (use_cl1_sss) ? cl1.sss_irradiance : cl2.sss_irradiance;
#  endif
  return cl;
}

Closure closure_emission(vec3 rgb)
{
  Closure cl = CLOSURE_DEFAULT;
  cl.radiance = rgb;
  return cl;
}

#endif

#ifndef VOLUMETRICS

void closure_load_ssr_data(
    vec3 ssr_spec, float roughness, vec3 N, vec3 viewVec, int ssr_id, inout Closure cl)
{
  /* Still encode to avoid artifacts in the SSR pass. */
  vec3 vN = normalize(mat3(ViewMatrix) * N);
  cl.ssr_normal = normal_encode(vN, viewVec);

  if (ssr_id == outputSsrId) {
    cl.ssr_data = vec4(ssr_spec, roughness);
    cl.flag |= CLOSURE_SSR_FLAG;
  }
}

void closure_load_sss_data(
    float radius, vec3 sss_irradiance, vec3 sss_albedo, int sss_id, inout Closure cl)
{
#  ifdef USE_SSS
  if (sss_id == outputSssId) {
    cl.sss_irradiance = sss_irradiance;
    cl.sss_radius = radius;
    cl.sss_albedo = sss_albedo;
    cl.flag |= CLOSURE_SSS_FLAG;
    cl.radiance += render_pass_diffuse_mask(sss_albedo, vec3(0));
  }
  else
#  endif
  {
    cl.radiance += render_pass_diffuse_mask(sss_albedo, sss_irradiance * sss_albedo);
  }
}

#endif