This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/draw/engines/eevee/shaders/closure_lib.glsl
2020-09-10 09:45:25 +10:00

182 lines
4.8 KiB
GLSL

#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 multi-line 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