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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpu/shaders')
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl23
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl82
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl53
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl37
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl574
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl29
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl32
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl16
9 files changed, 328 insertions, 520 deletions
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl
index eea8d19efce..d718cc3f4fe 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl
@@ -4,7 +4,7 @@ void node_ambient_occlusion(
{
vec3 bent_normal;
vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
- result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal);
+ result_ao = occlusion_compute(normalize(normal), viewPosition, rand, bent_normal);
result_color = result_ao * color;
}
#else
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
index d7b6143d2a1..01a16e194ca 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
@@ -1,12 +1,27 @@
#ifndef VOLUMETRICS
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(node_bsdf_diffuse, Diffuse)
+
void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
{
- N = normalize(N);
+ CLOSURE_VARS_DECLARE_1(Diffuse);
+
+ in_Diffuse_0.N = N; /* Normalized during eval. */
+ in_Diffuse_0.albedo = color.rgb;
+
+ CLOSURE_EVAL_FUNCTION_1(node_bsdf_diffuse, Diffuse);
+
result = CLOSURE_DEFAULT;
- eevee_closure_diffuse(N, color.rgb, 1.0, true, result.radiance);
- result.radiance = render_pass_diffuse_mask(color.rgb, result.radiance * color.rgb);
- closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
+
+ out_Diffuse_0.radiance = render_pass_diffuse_mask(vec3(1.0), out_Diffuse_0.radiance);
+ out_Diffuse_0.radiance *= color.rgb;
+
+ result.radiance = out_Diffuse_0.radiance;
+
+ /* TODO(fclem) Try to not use this. */
+ closure_load_ssr_data(vec3(0.0), 0.0, in_Diffuse_0.N, -1.0, result);
}
+
#else
/* Stub diffuse because it is not compatible with volumetrics. */
# define node_bsdf_diffuse(a, b, c, d) (d = CLOSURE_DEFAULT)
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl
index 443bab7529b..429c4ed41ac 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl
@@ -1,4 +1,7 @@
#ifndef VOLUMETRICS
+
+CLOSURE_EVAL_FUNCTION_DECLARE_3(node_eevee_specular, Diffuse, Glossy, Glossy)
+
void node_eevee_specular(vec4 diffuse,
vec4 specular,
float roughness,
@@ -12,34 +15,63 @@ void node_eevee_specular(vec4 diffuse,
float ssr_id,
out Closure result)
{
- normal = normalize(normal);
-
- vec3 out_diff, out_spec, ssr_spec;
- eevee_closure_default_clearcoat(normal,
- diffuse.rgb,
- specular.rgb,
- vec3(1.0),
- int(ssr_id),
- roughness,
- clearcoat_normal,
- clearcoat * 0.25,
- clearcoat_roughness,
- occlusion,
- true,
- out_diff,
- out_spec,
- ssr_spec);
-
- float alpha = 1.0 - transp;
+ CLOSURE_VARS_DECLARE_3(Diffuse, Glossy, Glossy);
+
+ in_common.occlusion = occlusion;
+
+ in_Diffuse_0.N = normal; /* Normalized during eval. */
+ in_Diffuse_0.albedo = diffuse.rgb;
+
+ in_Glossy_1.N = normal; /* Normalized during eval. */
+ in_Glossy_1.roughness = roughness;
+
+ in_Glossy_2.N = clearcoat_normal; /* Normalized during eval. */
+ in_Glossy_2.roughness = clearcoat_roughness;
+
+ CLOSURE_EVAL_FUNCTION_3(node_eevee_specular, Diffuse, Glossy, Glossy);
+
result = CLOSURE_DEFAULT;
- result.radiance = render_pass_diffuse_mask(diffuse.rgb, out_diff * diffuse.rgb);
- result.radiance += render_pass_glossy_mask(vec3(1.0), out_spec);
- result.radiance += render_pass_emission_mask(emissive.rgb);
- result.radiance *= alpha;
- result.transmittance = vec3(transp);
- closure_load_ssr_data(ssr_spec * alpha, roughness, normal, viewCameraVec, int(ssr_id), result);
+ {
+ /* Diffuse. */
+ out_Diffuse_0.radiance = render_pass_diffuse_mask(vec3(1), out_Diffuse_0.radiance);
+ out_Diffuse_0.radiance *= in_Diffuse_0.albedo;
+ result += out_Diffuse_0.radiance;
+ }
+ {
+ /* Glossy. */
+ float NV = dot(in_Glossy_1.N, cameraVec);
+ vec2 split_sum = brdf_lut(NV, in_Glossy_1.roughness);
+ vec3 brdf = F_brdf_single_scatter(specular.rgb, vec3(1.0), split_sum);
+
+ out_Glossy_1.radiance = closure_mask_ssr_radiance(out_Glossy_1.radiance, ssr_id);
+ out_Glossy_1.radiance *= brdf;
+ out_Glossy_1.radiance = render_pass_glossy_mask(spec_color, out_Glossy_1.radiance);
+ closure_load_ssr_data(
+ out_Glossy_1.radiance, in_Glossy_1.roughness, in_Glossy_1.N, ssr_id, result);
+ }
+ {
+ /* Clearcoat. */
+ float NV = dot(in_Glossy_2.N, cameraVec);
+ vec2 split_sum = brdf_lut(NV, in_Glossy_2.roughness);
+ vec3 brdf = F_brdf_single_scatter(vec3(0.04), vec3(1.0), split_sum);
+
+ out_Glossy_2.radiance *= brdf * clearcoat * 0.25;
+ out_Glossy_2.radiance = render_pass_glossy_mask(vec3(1), out_Glossy_2.radiance);
+ result.radiance += out_Glossy_2.radiance;
+ }
+ {
+ /* Emission. */
+ vec3 out_emission_radiance = render_pass_emission_mask(emission.rgb);
+ result.radiance += out_emission_radiance;
+ }
+
+ float trans = 1.0 - trans;
+ result.transmittance = vec3(trans);
+ result.radiance *= alpha;
+ result.ssr_data.rgb *= alpha;
}
+
#else
/* Stub specular because it is not compatible with volumetrics. */
# define node_eevee_specular(a, b, c, d, e, f, g, h, i, j, k, result) (result = CLOSURE_DEFAULT)
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl
index c328b4800bc..ba02ae6d886 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl
@@ -1,4 +1,7 @@
#ifndef VOLUMETRICS
+
+CLOSURE_EVAL_FUNCTION_DECLARE_2(node_bsdf_glass, Glossy, Refraction)
+
void node_bsdf_glass(vec4 color,
float roughness,
float ior,
@@ -7,32 +10,38 @@ void node_bsdf_glass(vec4 color,
float ssr_id,
out Closure result)
{
- N = normalize(N);
- vec3 out_spec, out_refr, ssr_spec;
- vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb :
- color.rgb; /* Simulate 2 transmission event */
- eevee_closure_glass(N,
- vec3(1.0),
- /* HACK: Pass the multiscatter flag as the sign to not add closure
- * variations or increase register usage. */
- (use_multiscatter != 0.0) ? vec3(1.0) : -vec3(1.0),
- int(ssr_id),
- roughness,
- 1.0,
- ior,
- true,
- out_spec,
- out_refr,
- ssr_spec);
- float fresnel = F_eta(ior, dot(N, cameraVec));
- vec3 vN = mat3(ViewMatrix) * N;
+ CLOSURE_VARS_DECLARE_2(Glossy, Refraction);
+
+ in_Glossy_0.N = N; /* Normalized during eval. */
+ in_Glossy_0.roughness = roughness;
+
+ in_Refraction_1.N = N; /* Normalized during eval. */
+ in_Refraction_1.roughness = roughness;
+ in_Refraction_1.ior = ior;
+
+ CLOSURE_EVAL_FUNCTION_2(node_bsdf_glass, Glossy, Refraction);
+
result = CLOSURE_DEFAULT;
- result.radiance = render_pass_glossy_mask(refr_color, out_refr * refr_color) * (1.0 - fresnel);
- result.radiance += render_pass_glossy_mask(color.rgb, out_spec * color.rgb) * fresnel;
+ float fresnel = F_eta(in_Refraction_1.ior, dot(in_Glossy_0.N, cameraVec));
+
+ vec2 split_sum = brdf_lut(dot(in_Glossy_0.N, cameraVec), in_Glossy_0.roughness);
+ vec3 brdf = (use_multiscatter != 0.0) ? F_brdf_multi_scatter(vec3(1.0), vec3(1.0), split_sum) :
+ F_brdf_single_scatter(vec3(1.0), vec3(1.0), split_sum);
+ out_Glossy_0.radiance = closure_mask_ssr_radiance(out_Glossy_0.radiance, ssr_id);
+ out_Glossy_0.radiance *= brdf;
+ out_Glossy_0.radiance = render_pass_glossy_mask(vec3(1.0), out_Glossy_0.radiance);
+ out_Glossy_0.radiance *= color.rgb * fresnel;
closure_load_ssr_data(
- ssr_spec * color.rgb * fresnel, roughness, N, viewCameraVec, int(ssr_id), result);
+ out_Glossy_0.radiance, in_Glossy_0.roughness, in_Glossy_0.N, ssr_id, result);
+
+ out_Refraction_1.radiance = render_pass_glossy_mask(vec3(1.0), out_Refraction_1.radiance);
+ out_Refraction_1.radiance *= color.rgb * (1.0 - fresnel);
+ /* Simulate 2nd absorption event. */
+ out_Refraction_1.radiance *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0);
+ result.radiance += out_Refraction_1.radiance;
}
+
#else
/* Stub glass because it is not compatible with volumetrics. */
# define node_bsdf_glass(a, b, c, d, e, f, result) (result = CLOSURE_DEFAULT)
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl
index 36675cf720d..ca7c3749597 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl
@@ -1,23 +1,32 @@
#ifndef VOLUMETRICS
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(node_bsdf_glossy, Glossy)
+
void node_bsdf_glossy(
vec4 color, float roughness, vec3 N, float use_multiscatter, float ssr_id, out Closure result)
{
- N = normalize(N);
- vec3 out_spec, ssr_spec;
- eevee_closure_glossy(N,
- vec3(1.0),
- use_multiscatter != 0.0 ? vec3(1.0) : vec3(-1.0), /* HACK */
- int(ssr_id),
- roughness,
- 1.0,
- true,
- out_spec,
- ssr_spec);
- vec3 vN = mat3(ViewMatrix) * N;
+ bool do_ssr = (ssrToggle && int(ssr_id) == outputSsrId);
+
+ CLOSURE_VARS_DECLARE_1(Glossy);
+
+ in_Glossy_0.N = N; /* Normalized during eval. */
+ in_Glossy_0.roughness = roughness;
+
+ CLOSURE_EVAL_FUNCTION_1(node_bsdf_glossy, Glossy);
+
result = CLOSURE_DEFAULT;
- result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec) * color.rgb;
- closure_load_ssr_data(ssr_spec * color.rgb, roughness, N, viewCameraVec, int(ssr_id), result);
+
+ vec2 split_sum = brdf_lut(dot(in_Glossy_0.N, cameraVec), in_Glossy_0.roughness);
+ vec3 brdf = (use_multiscatter != 0.0) ? F_brdf_multi_scatter(vec3(1.0), vec3(1.0), split_sum) :
+ F_brdf_single_scatter(vec3(1.0), vec3(1.0), split_sum);
+ out_Glossy_0.radiance = closure_mask_ssr_radiance(out_Glossy_0.radiance, ssr_id);
+ out_Glossy_0.radiance *= brdf;
+ out_Glossy_0.radiance = render_pass_glossy_mask(vec3(1.0), out_Glossy_0.radiance);
+ out_Glossy_0.radiance *= color.rgb;
+ closure_load_ssr_data(
+ out_Glossy_0.radiance, in_Glossy_0.roughness, in_Glossy_0.N, ssr_id, result);
}
+
#else
/* Stub glossy because it is not compatible with volumetrics. */
# define node_bsdf_glossy(a, b, c, d, e, result) (result = CLOSURE_DEFAULT)
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
index 3bd578e1ffc..15958dcf65e 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
@@ -1,41 +1,20 @@
#ifndef VOLUMETRICS
vec3 tint_from_color(vec3 color)
{
- float lum = dot(color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
- return (lum > 0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
+ float lum = dot(color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
+ return (lum > 0.0) ? color / lum : vec3(0.0); /* normalize lum. to isolate hue+sat */
}
-void convert_metallic_to_specular_tinted(vec3 basecol,
- vec3 basecol_tint,
- float metallic,
- float specular_fac,
- float specular_tint,
- out vec3 diffuse,
- out vec3 f0)
-{
- vec3 tmp_col = mix(vec3(1.0), basecol_tint, specular_tint);
- f0 = mix((0.08 * specular_fac) * tmp_col, basecol, metallic);
- diffuse = basecol * (1.0 - metallic);
-}
-
-/* Output sheen is to be multiplied by sheen_color. */
-void principled_sheen(float NV,
- vec3 basecol_tint,
- float sheen,
- float sheen_tint,
- out float out_sheen,
- out vec3 sheen_color)
+float principled_sheen(float NV)
{
float f = 1.0 - NV;
- /* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps,
- * therefore we need to clamp value. */
- f = clamp(f, 0.0, 1.0);
/* Empirical approximation (manual curve fitting). Can be refined. */
- out_sheen = f * f * f * 0.077 + f * 0.01 + 0.00026;
-
- sheen_color = sheen * mix(vec3(1.0), basecol_tint, sheen_tint);
+ float sheen = f * f * f * 0.077 + f * 0.01 + 0.00026;
+ return sheen;
}
+CLOSURE_EVAL_FUNCTION_DECLARE_4(node_bsdf_principled, Diffuse, Glossy, Glossy, Refraction)
+
void node_bsdf_principled(vec4 base_color,
float subsurface,
vec3 subsurface_radius,
@@ -59,434 +38,163 @@ void node_bsdf_principled(vec4 base_color,
vec3 N,
vec3 CN,
vec3 T,
- vec3 I,
- float use_multiscatter,
+ const float do_diffuse,
+ const float do_clearcoat,
+ const float do_refraction,
+ const float do_multiscatter,
float ssr_id,
float sss_id,
vec3 sss_scale,
out Closure result)
{
- N = normalize(N);
- ior = max(ior, 1e-5);
- metallic = saturate(metallic);
- transmission = saturate(transmission);
- float m_transmission = 1.0 - transmission;
-
- float dielectric = 1.0 - metallic;
- transmission *= dielectric;
- sheen *= dielectric;
- subsurface_color *= dielectric;
-
- vec3 diffuse, f0, out_diff, out_spec, out_refr, ssr_spec, sheen_color;
- float out_sheen;
- vec3 ctint = tint_from_color(base_color.rgb);
- convert_metallic_to_specular_tinted(
- base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
-
- float NV = dot(N, cameraVec);
- principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color);
-
- vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
-
- /* Far from being accurate, but 2 glossy evaluation is too expensive.
- * Most noticeable difference is at grazing angles since the bsdf lut
- * f0 color interpolation is done on top of this interpolation. */
- vec3 f0_glass = mix(vec3(1.0), base_color.rgb, specular_tint);
- float fresnel = F_eta(ior, NV);
- vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel;
- f0 = mix(f0, spec_col, transmission);
- f90 = mix(f90, spec_col, transmission);
-
- /* Really poor approximation but needed to workaround issues with renderpasses. */
- spec_col = mix(vec3(1.0), spec_col, transmission);
/* Match cycles. */
- spec_col += float(clearcoat > 1e-5);
-
- vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface);
-
- float sss_scalef = avg(sss_scale) * subsurface;
- eevee_closure_principled(N,
- mixed_ss_base_color,
- f0,
- /* HACK: Pass the multiscatter flag as the sign to not add closure
- * variations or increase register usage. */
- (use_multiscatter != 0.0) ? f90 : -f90,
- int(ssr_id),
- roughness,
- CN,
- clearcoat * 0.25,
- clearcoat_roughness,
- 1.0,
- sss_scalef,
- ior,
- true,
- out_diff,
- out_spec,
- out_refr,
- ssr_spec);
-
- vec3 refr_color = base_color.rgb;
- refr_color *= (refractionDepth > 0.0) ? refr_color :
- vec3(1.0); /* Simulate 2 transmission event */
- refr_color *= saturate(1.0 - fresnel) * transmission;
-
- sheen_color *= m_transmission;
- mixed_ss_base_color *= m_transmission;
-
- result = CLOSURE_DEFAULT;
- result.radiance = render_pass_glossy_mask(refr_color, out_refr * refr_color);
- result.radiance += render_pass_glossy_mask(spec_col, out_spec);
- /* Coarse approx. */
- result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color);
- result.radiance += render_pass_emission_mask(emission.rgb * emission_strength);
- result.radiance *= alpha;
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
-
- mixed_ss_base_color *= alpha;
- closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result);
- result.transmittance = vec3(1.0 - alpha);
-}
-
-void node_bsdf_principled_dielectric(vec4 base_color,
- float subsurface,
- vec3 subsurface_radius,
- vec4 subsurface_color,
- float metallic,
- float specular,
- float specular_tint,
- float roughness,
- float anisotropic,
- float anisotropic_rotation,
- float sheen,
- float sheen_tint,
- float clearcoat,
- float clearcoat_roughness,
- float ior,
- float transmission,
- float transmission_roughness,
- vec4 emission,
- float emission_strength,
- float alpha,
- vec3 N,
- vec3 CN,
- vec3 T,
- vec3 I,
- float use_multiscatter,
- float ssr_id,
- float sss_id,
- vec3 sss_scale,
- out Closure result)
-{
- N = normalize(N);
metallic = saturate(metallic);
- float dielectric = 1.0 - metallic;
-
- vec3 diffuse, f0, out_diff, out_spec, ssr_spec, sheen_color;
- float out_sheen;
- vec3 ctint = tint_from_color(base_color.rgb);
- convert_metallic_to_specular_tinted(
- base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
-
- vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
-
- float NV = dot(N, cameraVec);
- principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color);
-
- eevee_closure_default(N,
- diffuse,
- f0,
- /* HACK: Pass the multiscatter flag as the sign to not add closure
- * variations or increase register usage. */
- (use_multiscatter != 0.0) ? f90 : -f90,
- int(ssr_id),
- roughness,
- 1.0,
- true,
- out_diff,
- out_spec,
- ssr_spec);
+ transmission = saturate(transmission);
+ float diffuse_weight = (1.0 - transmission) * (1.0 - metallic);
+ transmission *= (1.0 - metallic);
+ float specular_weight = (1.0 - transmission);
+ clearcoat = max(clearcoat, 0.0);
+ transmission_roughness = 1.0 - (1.0 - roughness) * (1.0 - transmission_roughness);
- result = CLOSURE_DEFAULT;
- result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec);
- result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color);
- result.radiance += render_pass_diffuse_mask(diffuse, out_diff * diffuse);
- result.radiance += render_pass_emission_mask(emission.rgb * emission_strength);
- result.radiance *= alpha;
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+ CLOSURE_VARS_DECLARE_4(Diffuse, Glossy, Glossy, Refraction);
- result.transmittance = vec3(1.0 - alpha);
-}
+ in_Diffuse_0.N = N; /* Normalized during eval. */
+ in_Diffuse_0.albedo = mix(base_color.rgb, subsurface_color.rgb, subsurface);
-void node_bsdf_principled_metallic(vec4 base_color,
- float subsurface,
- vec3 subsurface_radius,
- vec4 subsurface_color,
- float metallic,
- float specular,
- float specular_tint,
- float roughness,
- float anisotropic,
- float anisotropic_rotation,
- float sheen,
- float sheen_tint,
- float clearcoat,
- float clearcoat_roughness,
- float ior,
- float transmission,
- float transmission_roughness,
- vec4 emission,
- float emission_strength,
- float alpha,
- vec3 N,
- vec3 CN,
- vec3 T,
- vec3 I,
- float use_multiscatter,
- float ssr_id,
- float sss_id,
- vec3 sss_scale,
- out Closure result)
-{
- N = normalize(N);
- vec3 out_spec, ssr_spec;
-
- vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
-
- eevee_closure_glossy(N,
- base_color.rgb,
- /* HACK: Pass the multiscatter flag as the sign to not add closure
- * variations or increase register usage. */
- (use_multiscatter != 0.0) ? f90 : -f90,
- int(ssr_id),
- roughness,
- 1.0,
- true,
- out_spec,
- ssr_spec);
+ in_Glossy_1.N = N; /* Normalized during eval. */
+ in_Glossy_1.roughness = roughness;
- result = CLOSURE_DEFAULT;
- result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec);
- result.radiance += render_pass_emission_mask(emission.rgb * emission_strength);
- result.radiance *= alpha;
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+ in_Glossy_2.N = CN; /* Normalized during eval. */
+ in_Glossy_2.roughness = clearcoat_roughness;
- result.transmittance = vec3(1.0 - alpha);
-}
+ in_Refraction_3.N = N; /* Normalized during eval. */
+ in_Refraction_3.roughness = do_multiscatter != 0.0 ? roughness : transmission_roughness;
+ in_Refraction_3.ior = ior;
+
-void node_bsdf_principled_clearcoat(vec4 base_color,
- float subsurface,
- vec3 subsurface_radius,
- vec4 subsurface_color,
- float metallic,
- float specular,
- float specular_tint,
- float roughness,
- float anisotropic,
- float anisotropic_rotation,
- float sheen,
- float sheen_tint,
- float clearcoat,
- float clearcoat_roughness,
- float ior,
- float transmission,
- float transmission_roughness,
- vec4 emission,
- float emission_strength,
- float alpha,
- vec3 N,
- vec3 CN,
- vec3 T,
- vec3 I,
- float use_multiscatter,
- float ssr_id,
- float sss_id,
- vec3 sss_scale,
- out Closure result)
-{
- vec3 out_spec, ssr_spec;
- N = normalize(N);
-
- vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
-
- eevee_closure_clearcoat(N,
- base_color.rgb,
- /* HACK: Pass the multiscatter flag as the sign to not add closure
- * variations or increase register usage. */
- (use_multiscatter != 0.0) ? f90 : -f90,
- int(ssr_id),
- roughness,
- CN,
- clearcoat * 0.25,
- clearcoat_roughness,
- 1.0,
- true,
- out_spec,
- ssr_spec);
- /* Match cycles. */
- float spec_col = 1.0 + float(clearcoat > 1e-5);
+ CLOSURE_EVAL_FUNCTION_4(node_bsdf_principled, Diffuse, Glossy, Glossy, Refraction);
result = CLOSURE_DEFAULT;
- result.radiance = render_pass_glossy_mask(vec3(spec_col), out_spec);
- result.radiance += render_pass_emission_mask(emission.rgb * emission_strength);
- result.radiance *= alpha;
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+ /* This will tag the whole eval for optimisation. */
+ if (do_diffuse == 0.0) {
+ out_Diffuse_0.radiance = vec3(0);
+ }
+ if (do_clearcoat == 0.0) {
+ out_Glossy_2.radiance = vec3(0);
+ }
+ if (do_refraction == 0.0) {
+ out_Refraction_3.radiance = vec3(0);
+ }
+
+ /* Glossy_1 will always be evaluated. */
+ float NV = dot(in_Glossy_1.N, cameraVec);
+
+ vec3 base_color_tint = tint_from_color(base_color.rgb);
+
+ /* TODO(fclem) This isn't good for rough glass using multiscatter (since the fresnel is applied
+ * on each microfacet in cycles). */
+ float fresnel = F_eta(in_Refraction_3.ior, NV);
+
+ {
+ /* Glossy reflections.
+ * Separate Glass reflections and main specular reflections to match Cycles renderpasses. */
+ out_Glossy_1.radiance = closure_mask_ssr_radiance(out_Glossy_1.radiance, ssr_id);
+
+ vec2 split_sum = brdf_lut(NV, roughness);
+
+ vec3 glossy_radiance_final = vec3(0.0);
+ if (transmission > 1e-5) {
+ /* Glass Reflection: Reuse radiance from Glossy1. */
+ vec3 out_glass_refl_radiance = out_Glossy_1.radiance;
+
+ /* Poor approximation since we baked the LUT using a fixed IOR. */
+ vec3 f0 = mix(vec3(1.0), base_color.rgb, specular_tint);
+ vec3 f90 = vec3(1);
+
+ vec3 brdf = (do_multiscatter != 0.0) ? F_brdf_multi_scatter(f0, f90, split_sum) :
+ F_brdf_single_scatter(f0, f90, split_sum);
+
+ out_glass_refl_radiance *= brdf;
+ out_glass_refl_radiance = render_pass_glossy_mask(vec3(1), out_glass_refl_radiance);
+ out_glass_refl_radiance *= fresnel * transmission;
+ glossy_radiance_final += out_glass_refl_radiance;
+ }
+ if (specular_weight > 1e-5) {
+ vec3 dielectric_f0_color = mix(vec3(1.0), base_color_tint, specular_tint);
+ vec3 metallic_f0_color = base_color.rgb;
+ vec3 f0 = mix((0.08 * specular) * dielectric_f0_color, metallic_f0_color, metallic);
+ /* Cycles does this blending using the microfacet fresnel factor. However, our fresnel
+ * is already baked inside the split sum LUT. We approximate using by modifying the
+ * changing the f90 color directly in a non linear fashion. */
+ vec3 f90 = mix(f0, vec3(1), fast_sqrt(specular));
+
+ vec3 brdf = (do_multiscatter != 0.0) ? F_brdf_multi_scatter(f0, f90, split_sum) :
+ F_brdf_single_scatter(f0, f90, split_sum);
+
+ out_Glossy_1.radiance *= brdf;
+ out_Glossy_1.radiance = render_pass_glossy_mask(vec3(1), out_Glossy_1.radiance);
+ out_Glossy_1.radiance *= specular_weight;
+ glossy_radiance_final += out_Glossy_1.radiance;
+ }
+
+ closure_load_ssr_data(
+ glossy_radiance_final, in_Glossy_1.roughness, in_Glossy_1.N, ssr_id, result);
+ }
+
+ if (diffuse_weight > 1e-5) {
+ /* Mask over all diffuse radiance. */
+ out_Diffuse_0.radiance *= diffuse_weight;
+
+ /* Sheen Coarse approximation: We reuse the diffuse radiance and just scale it. */
+ vec3 sheen_color = mix(vec3(1), base_color_tint, sheen_tint);
+ vec3 out_sheen_radiance = out_Diffuse_0.radiance * principled_sheen(NV);
+ out_sheen_radiance = render_pass_diffuse_mask(vec3(1), out_sheen_radiance);
+ out_sheen_radiance *= sheen * sheen_color;
+ result.radiance += out_sheen_radiance;
+
+ /* Diffuse / Subsurface. */
+ float scale = avg(sss_scale) * subsurface;
+ closure_load_sss_data(scale, out_Diffuse_0.radiance, in_Diffuse_0.albedo, int(sss_id), result);
+ }
+
+ if (transmission > 1e-5) {
+ /* TODO(fclem) This could be going to a transmission render pass instead. */
+ out_Refraction_3.radiance = render_pass_glossy_mask(vec3(1), out_Refraction_3.radiance);
+ out_Refraction_3.radiance *= base_color.rgb;
+ /* Simulate 2nd transmission event. */
+ out_Refraction_3.radiance *= (refractionDepth > 0.0) ? base_color.rgb : vec3(1);
+ out_Refraction_3.radiance *= (1.0 - fresnel) * transmission;
+ result.radiance += out_Refraction_3.radiance;
+ }
+
+ if (clearcoat > 1e-5) {
+ float NV = dot(in_Glossy_2.N, cameraVec);
+ vec2 split_sum = brdf_lut(NV, in_Glossy_2.roughness);
+ vec3 brdf = F_brdf_single_scatter(vec3(0.04), vec3(1.0), split_sum);
+
+ out_Glossy_2.radiance *= brdf * clearcoat * 0.25;
+ out_Glossy_2.radiance = render_pass_glossy_mask(vec3(1), out_Glossy_2.radiance);
+ result.radiance += out_Glossy_2.radiance;
+ }
+
+ {
+ vec3 out_emission_radiance = render_pass_emission_mask(emission.rgb);
+ out_emission_radiance *= emission_strength;
+ result.radiance += out_emission_radiance;
+ }
result.transmittance = vec3(1.0 - alpha);
-}
-
-void node_bsdf_principled_subsurface(vec4 base_color,
- float subsurface,
- vec3 subsurface_radius,
- vec4 subsurface_color,
- float metallic,
- float specular,
- float specular_tint,
- float roughness,
- float anisotropic,
- float anisotropic_rotation,
- float sheen,
- float sheen_tint,
- float clearcoat,
- float clearcoat_roughness,
- float ior,
- float transmission,
- float transmission_roughness,
- vec4 emission,
- float emission_strength,
- float alpha,
- vec3 N,
- vec3 CN,
- vec3 T,
- vec3 I,
- float use_multiscatter,
- float ssr_id,
- float sss_id,
- vec3 sss_scale,
- out Closure result)
-{
- metallic = saturate(metallic);
- N = normalize(N);
-
- vec3 diffuse, f0, out_diff, out_spec, ssr_spec, sheen_color;
- float out_sheen;
- vec3 ctint = tint_from_color(base_color.rgb);
- convert_metallic_to_specular_tinted(
- base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
-
- subsurface_color = subsurface_color * (1.0 - metallic);
- vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface);
- float sss_scalef = avg(sss_scale) * subsurface;
-
- float NV = dot(N, cameraVec);
- principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color);
-
- vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
-
- eevee_closure_skin(N,
- mixed_ss_base_color,
- f0,
- /* HACK: Pass the multiscatter flag as the sign to not add closure variations
- * or increase register usage. */
- (use_multiscatter != 0.0) ? f90 : -f90,
- int(ssr_id),
- roughness,
- 1.0,
- sss_scalef,
- true,
- out_diff,
- out_spec,
- ssr_spec);
-
- result = CLOSURE_DEFAULT;
- result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec);
- result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color);
- result.radiance += render_pass_emission_mask(emission.rgb * emission_strength);
result.radiance *= alpha;
-
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
-
- mixed_ss_base_color *= alpha;
- closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result);
-
- result.transmittance = vec3(1.0 - alpha);
+ result.ssr_data.rgb *= alpha;
+# ifdef USE_SSS
+ result.sss_irradiance *= alpha;
+# endif
}
-void node_bsdf_principled_glass(vec4 base_color,
- float subsurface,
- vec3 subsurface_radius,
- vec4 subsurface_color,
- float metallic,
- float specular,
- float specular_tint,
- float roughness,
- float anisotropic,
- float anisotropic_rotation,
- float sheen,
- float sheen_tint,
- float clearcoat,
- float clearcoat_roughness,
- float ior,
- float transmission,
- float transmission_roughness,
- vec4 emission,
- float emission_strength,
- float alpha,
- vec3 N,
- vec3 CN,
- vec3 T,
- vec3 I,
- float use_multiscatter,
- float ssr_id,
- float sss_id,
- vec3 sss_scale,
- out Closure result)
-{
- ior = max(ior, 1e-5);
- N = normalize(N);
-
- vec3 f0, out_spec, out_refr, ssr_spec;
- f0 = mix(vec3(1.0), base_color.rgb, specular_tint);
-
- eevee_closure_glass(N,
- vec3(1.0),
- vec3((use_multiscatter != 0.0) ? 1.0 : -1.0),
- int(ssr_id),
- roughness,
- 1.0,
- ior,
- true,
- out_spec,
- out_refr,
- ssr_spec);
-
- vec3 refr_color = base_color.rgb;
- refr_color *= (refractionDepth > 0.0) ? refr_color :
- vec3(1.0); /* Simulate 2 transmission events */
-
- float fresnel = F_eta(ior, dot(N, cameraVec));
- vec3 spec_col = F_color_blend(ior, fresnel, f0);
- spec_col *= fresnel;
- refr_color *= (1.0 - fresnel);
-
- ssr_spec *= spec_col;
-
- result = CLOSURE_DEFAULT;
- result.radiance = render_pass_glossy_mask(refr_color, out_refr * refr_color);
- result.radiance += render_pass_glossy_mask(spec_col, out_spec * spec_col);
- result.radiance += render_pass_emission_mask(emission.rgb * emission_strength);
- result.radiance *= alpha;
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
- result.transmittance = vec3(1.0 - alpha);
-}
#else
/* clang-format off */
/* Stub principled because it is not compatible with volumetrics. */
-# define node_bsdf_principled(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT)
-# define node_bsdf_principled_dielectric(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT)
-# define node_bsdf_principled_metallic(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT)
-# define node_bsdf_principled_clearcoat(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT)
-# define node_bsdf_principled_subsurface(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT)
-# define node_bsdf_principled_glass(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, result) (result = CLOSURE_DEFAULT)
+# define node_bsdf_principled(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, bb, cc, dd, result) (result = CLOSURE_DEFAULT)
/* clang-format on */
#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
index cd043020a7f..db820efa42e 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
@@ -1,15 +1,30 @@
#ifndef VOLUMETRICS
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(node_bsdf_refraction, Refraction)
+
void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result)
{
- N = normalize(N);
- vec3 out_refr;
- color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */
- eevee_closure_refraction(N, roughness, ior, true, out_refr);
- vec3 vN = mat3(ViewMatrix) * N;
+ CLOSURE_VARS_DECLARE_1(Refraction);
+
+ in_Refraction_0.N = N; /* Normalized during eval. */
+ in_Refraction_0.roughness = roughness;
+ in_Refraction_0.ior = ior;
+
+ CLOSURE_EVAL_FUNCTION_1(node_bsdf_refraction, Refraction);
+
result = CLOSURE_DEFAULT;
- result.ssr_normal = normal_encode(vN, viewCameraVec);
- result.radiance = render_pass_glossy_mask(color.rgb, out_refr * color.rgb);
+
+ out_Refraction_0.radiance = render_pass_glossy_mask(vec3(1.0), out_Refraction_0.radiance);
+ out_Refraction_0.radiance *= color.rgb;
+ /* Simulate 2nd absorption event. */
+ out_Refraction_0.radiance *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0);
+
+ result.radiance = out_Refraction_0.radiance;
+
+ /* TODO(fclem) Try to not use this. */
+ result.ssr_normal = normal_encode(mat3(ViewMatrix) * in_Refraction_0.N, viewCameraVec);
}
+
#else
/* Stub refraction because it is not compatible with volumetrics. */
# define node_bsdf_refraction(a, b, c, d, e) (e = CLOSURE_DEFAULT)
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
index c13b55513da..5a68f802659 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
@@ -1,4 +1,7 @@
#ifndef VOLUMETRICS
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(node_subsurface_scattering, Diffuse)
+
void node_subsurface_scattering(vec4 color,
float scale,
vec3 radius,
@@ -8,20 +11,29 @@ void node_subsurface_scattering(vec4 color,
float sss_id,
out Closure result)
{
- N = normalize(N);
- vec3 out_diff;
- vec3 vN = mat3(ViewMatrix) * N;
+ CLOSURE_VARS_DECLARE_1(Diffuse);
+
+ in_Diffuse_0.N = N; /* Normalized during eval. */
+ in_Diffuse_0.albedo = color.rgb;
+
+ CLOSURE_EVAL_FUNCTION_1(node_subsurface_scattering, Diffuse);
+
result = CLOSURE_DEFAULT;
- closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
- eevee_closure_subsurface(N, color.rgb, 1.0, scale, true, out_diff);
+ /* Not perfect for texture_blur values between 0.0 and 1.0.
+ * Interpolate between separated color and color applied on irradiance. */
+ float one_minus_texture_blur = 1.0 - texture_blur;
+ vec3 sss_albedo = color.rgb * texture_blur + one_minus_texture_blur;
+ vec3 radiance_tint = color.rgb * one_minus_texture_blur + texture_blur;
+ /* Consider output radiance as irradiance. */
+ out_Diffuse_0.radiance *= radiance_tint;
+
+ closure_load_sss_data(scale, out_Diffuse_0.radiance, sss_albedo, int(sss_id), result);
- /* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */
- vec3 sss_albedo = mix(color.rgb, vec3(1.0), texture_blur);
- out_diff *= mix(vec3(1.0), color.rgb, texture_blur);
- result.radiance = render_pass_sss_mask(sss_albedo);
- closure_load_sss_data(scale, out_diff, sss_albedo, int(sss_id), result);
+ /* TODO(fclem) Try to not use this. */
+ closure_load_ssr_data(vec3(0.0), 0.0, in_Diffuse_0.N, -1.0, result);
}
+
#else
/* Stub subsurface scattering because it is not compatible with volumetrics. */
# define node_subsurface_scattering(a, b, c, d, e, f, g, h) (h = CLOSURE_DEFAULT)
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl
index 79bfd9b24bb..80bd3941b22 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl
@@ -1,12 +1,20 @@
#ifndef VOLUMETRICS
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(node_bsdf_translucent, Translucent)
+
void node_bsdf_translucent(vec4 color, vec3 N, out Closure result)
{
- N = normalize(N);
+ CLOSURE_VARS_DECLARE_1(Translucent);
+
+ in_Translucent_0.N = -N; /* Normalized during eval. */
+
+ CLOSURE_EVAL_FUNCTION_1(node_bsdf_translucent, Translucent);
+
result = CLOSURE_DEFAULT;
- eevee_closure_diffuse(-N, color.rgb, 1.0, false, result.radiance);
- closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
- result.radiance = render_pass_diffuse_mask(color.rgb, result.radiance * color.rgb);
+ closure_load_ssr_data(vec3(0.0), 0.0, -in_Translucent_0.N, -1.0, result);
+ result.radiance = render_pass_diffuse_mask(color.rgb, out_Translucent_0.radiance * color.rgb);
}
+
#else
/* Stub translucent because it is not compatible with volumetrics. */
# define node_bsdf_translucent(a, b, c) (c = CLOSURE_DEFAULT)