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:
authorClément Foucault <foucault.clem@gmail.com>2022-04-14 19:47:58 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-04-14 19:47:58 +0300
commit80859a6cb2726a39fb22cb49f06e0355dc9390a7 (patch)
treefd3f8ead5a247a79ea11e4aacc720843bbc5e2c2 /source/blender/draw/engines/eevee/shaders
parent66dc4d4efb88ecf2d18bfa08ab9c43b024ebd2fb (diff)
GPU: Make nodetree GLSL Codegen render engine agnostic
This commit removes all EEVEE specific code from the `gpu_shader_material*.glsl` files. It defines a clear interface to evaluate the closure nodes leaving more flexibility to the render engine. Some of the long standing workaround are fixed: - bump mapping support is no longer duplicating a lot of node and is instead compiled into a function call. - bump rewiring to Normal socket is no longer needed as we now use a global `g_data.N` for that. Closure sampling with upstread weight eval is now supported if the engine needs it. This also makes all the material GLSL sources use `GPUSource` for better debugging experience. The `GPUFunction` parsing now happens in `GPUSource` creation. The whole `GPUCodegen` now uses the `ShaderCreateInfo` and is object type agnostic. Is has also been rewritten in C++. This patch changes a view behavior for EEVEE: - Mix shader node factor imput is now clamped. - Tangent Vector displacement behavior is now matching cycles. - The chosen BSDF used for SSR might change. - Hair shading may have very small changes on very large hairs when using hair polygon stripes. - ShaderToRGB node will remove any SSR and SSS form a shader. - SSS radius input now is no longer a scaling factor but defines an average radius. The SSS kernel "shape" (radii) are still defined by the socket default values. Appart from the listed changes no other regressions are expected.
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders')
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl35
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl15
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl325
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl113
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl252
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_empty.glsl7
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_empty_volume.glsl8
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_frag.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_vert.glsl35
-rw-r--r--source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl21
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_vert.glsl92
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_frag.glsl141
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_lib.glsl166
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_vert.glsl108
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl111
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl6
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl6
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl28
-rw-r--r--source/blender/draw/engines/eevee/shaders/world_vert.glsl24
25 files changed, 1210 insertions, 311 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
index 4da30dd74ee..d8adf302e37 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -26,6 +26,10 @@
# endif
#endif
+#ifndef GPU_FRAGMENT_SHADER
+# define gl_FragCoord vec4(0.0)
+#endif
+
uniform sampler2D horizonBuffer;
/* aoSettings flags */
@@ -424,3 +428,34 @@ OcclusionData occlusion_load(vec3 vP, float custom_occlusion)
return data;
}
+
+#ifndef GPU_FRAGMENT_SHADER
+# undef gl_FragCoord
+#endif
+
+float ambient_occlusion_eval(vec3 normal,
+ float max_distance,
+ const float inverted,
+ const float sample_count)
+{
+ /* Avoid multiline define causing compiler issues. */
+ /* clang-format off */
+#if defined(GPU_FRAGMENT_SHADER) && (defined(MESH_SHADER) || defined(HAIR_SHADER)) && !defined(DEPTH_SHADER) && !defined(VOLUMETRICS)
+ /* clang-format on */
+ vec3 bent_normal;
+ vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
+ OcclusionData data = occlusion_search(
+ viewPosition, maxzBuffer, max_distance, inverted, sample_count);
+
+ vec3 V = cameraVec(worldPosition);
+ vec3 N = normalize(normal);
+ vec3 Ng = safe_normalize(cross(dFdx(worldPosition), dFdy(worldPosition)));
+
+ float unused_error, visibility;
+ vec3 unused;
+ occlusion_eval(data, V, N, Ng, inverted, visibility, unused_error, unused);
+ return visibility;
+#else
+ return 1.0;
+#endif
+}
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
index 5cd82d298d5..574b24b3650 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
@@ -1,6 +1,8 @@
#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. */
@@ -88,6 +90,7 @@ void closure_Diffuse_eval_end(ClosureInputDiffuse cl_in,
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);
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
index 4271ac9105b..0deaf4054d2 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
@@ -4,6 +4,8 @@
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl)
#pragma BLENDER_REQUIRE(bsdf_common_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
+#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
struct ClosureInputGlossy {
vec3 N; /** Shading normal. */
@@ -143,6 +145,7 @@ void closure_Glossy_eval_end(ClosureInputGlossy cl_in,
ClosureEvalCommon cl_common,
inout ClosureOutputGlossy cl_out)
{
+ cl_out.radiance = render_pass_glossy_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);
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl
index a96d8ad3dac..3f07f80571a 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl
@@ -1,8 +1,14 @@
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
+// #pragma (gpu_shader_codegen_lib.glsl)
#pragma BLENDER_REQUIRE(lights_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
+#ifndef GPU_FRAGMENT_SHADER
+# define gl_FragCoord vec4(0.0)
+# define gl_FrontFacing true
+#endif
+
/**
* Extensive use of Macros to be able to change the maximum amount of evaluated closure easily.
* NOTE: GLSL does not support variadic macros.
@@ -240,7 +246,11 @@ ClosureEvalCommon closure_Common_eval_init(ClosureInputCommon cl_in)
cl_eval.N = safe_normalize(gl_FrontFacing ? worldNormal : -worldNormal);
cl_eval.vN = safe_normalize(gl_FrontFacing ? viewNormal : -viewNormal);
cl_eval.vP = viewPosition;
+#ifdef GPU_FRAGMENT_SHADER
cl_eval.Ng = safe_normalize(cross(dFdx(cl_eval.P), dFdy(cl_eval.P)));
+#else
+ cl_eval.Ng = cl_eval.N;
+#endif
cl_eval.vNg = transform_direction(ViewMatrix, cl_eval.Ng);
cl_eval.occlusion_data = occlusion_load(cl_eval.vP, cl_in.occlusion);
@@ -337,3 +347,8 @@ ClosureGridData closure_grid_eval_init(int id, inout ClosureEvalCommon cl_common
}
/** \} */
+
+#ifndef GPU_FRAGMENT_SHADER
+# undef gl_FragCoord
+# undef gl_FrontFacing
+#endif
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl
index 8129988920c..5c6769b185a 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl
@@ -4,6 +4,8 @@
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl)
#pragma BLENDER_REQUIRE(ssr_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
+#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
struct ClosureInputRefraction {
vec3 N; /** Shading normal. */
@@ -123,6 +125,7 @@ void closure_Refraction_eval_end(ClosureInputRefraction cl_in,
ClosureEvalCommon cl_common,
inout ClosureOutputRefraction cl_out)
{
+ cl_out.radiance = render_pass_glossy_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);
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl
new file mode 100644
index 00000000000..fa94b5ed272
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl
@@ -0,0 +1,325 @@
+
+#pragma BLENDER_REQUIRE(closure_eval_diffuse_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_glossy_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_refraction_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_translucent_lib.glsl)
+#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
+
+#ifdef USE_SHADER_TO_RGBA
+bool do_sss = false;
+bool do_ssr = false;
+#else
+bool do_sss = true;
+bool do_ssr = true;
+#endif
+
+vec3 out_sss_radiance;
+vec3 out_sss_color;
+float out_sss_radius;
+
+float out_ssr_roughness;
+vec3 out_ssr_color;
+vec3 out_ssr_N;
+
+bool aov_is_valid = false;
+vec3 out_aov;
+
+bool output_sss(ClosureDiffuse diffuse, ClosureOutputDiffuse diffuse_out)
+{
+ if (diffuse.sss_id == 0u || !do_sss || !sssToggle || outputSssId == 0) {
+ return false;
+ }
+ if (renderPassSSSColor) {
+ return false;
+ }
+ out_sss_radiance = diffuse_out.radiance;
+ out_sss_color = diffuse.color * diffuse.weight;
+ out_sss_radius = avg(diffuse.sss_radius);
+ do_sss = false;
+ return true;
+}
+
+bool output_ssr(ClosureReflection reflection)
+{
+ if (!do_ssr || !ssrToggle || outputSsrId == 0) {
+ return false;
+ }
+ out_ssr_roughness = reflection.roughness;
+ out_ssr_color = reflection.color * reflection.weight;
+ out_ssr_N = reflection.N;
+ do_ssr = false;
+ return true;
+}
+
+void output_aov(vec4 color, float value, uint hash)
+{
+ /* Keep in sync with `render_pass_aov_hash` and `EEVEE_renderpasses_aov_hash`. */
+ hash <<= 1u;
+
+ if (renderPassAOV && !aov_is_valid && hash == render_pass_aov_hash()) {
+ aov_is_valid = true;
+ if (render_pass_aov_is_color()) {
+ out_aov = color.rgb;
+ }
+ else {
+ out_aov = vec3(value);
+ }
+ }
+}
+
+/* Single BSDFs. */
+CLOSURE_EVAL_FUNCTION_DECLARE_1(DiffuseBSDF, Diffuse)
+Closure closure_eval(ClosureDiffuse diffuse)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_1(Diffuse);
+
+ in_Diffuse_0.N = diffuse.N;
+ in_Diffuse_0.albedo = diffuse.color;
+
+ CLOSURE_EVAL_FUNCTION_1(DiffuseBSDF, Diffuse);
+
+ Closure closure = CLOSURE_DEFAULT;
+ if (!output_sss(diffuse, out_Diffuse_0)) {
+ closure.radiance += out_Diffuse_0.radiance * diffuse.color * diffuse.weight;
+ }
+ return closure;
+}
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(TranslucentBSDF, Translucent)
+Closure closure_eval(ClosureTranslucent translucent)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_1(Translucent);
+
+ in_Translucent_0.N = translucent.N;
+
+ CLOSURE_EVAL_FUNCTION_1(TranslucentBSDF, Translucent);
+
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += out_Translucent_0.radiance * translucent.color * translucent.weight;
+ return closure;
+}
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(GlossyBSDF, Glossy)
+Closure closure_eval(ClosureReflection reflection)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_1(Glossy);
+
+ in_Glossy_0.N = reflection.N;
+ in_Glossy_0.roughness = reflection.roughness;
+
+ CLOSURE_EVAL_FUNCTION_1(GlossyBSDF, Glossy);
+
+ Closure closure = CLOSURE_DEFAULT;
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(RefractionBSDF, Refraction)
+Closure closure_eval(ClosureRefraction refraction)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_1(Refraction);
+
+ in_Refraction_0.N = refraction.N;
+ in_Refraction_0.roughness = refraction.roughness;
+ in_Refraction_0.ior = refraction.ior;
+
+ CLOSURE_EVAL_FUNCTION_1(RefractionBSDF, Refraction);
+
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += out_Refraction_0.radiance * refraction.color * refraction.weight;
+ return closure;
+}
+
+Closure closure_eval(ClosureEmission emission)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += render_pass_emission_mask(emission.emission) * emission.weight;
+ return closure;
+}
+
+Closure closure_eval(ClosureTransparency transparency)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.transmittance += transparency.transmittance * transparency.weight;
+ closure.holdout += transparency.holdout * transparency.weight;
+ return closure;
+}
+
+/* Glass BSDF. */
+CLOSURE_EVAL_FUNCTION_DECLARE_2(GlassBSDF, Glossy, Refraction)
+Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_2(Glossy, Refraction);
+
+ in_Glossy_0.N = reflection.N;
+ in_Glossy_0.roughness = reflection.roughness;
+ in_Refraction_1.N = refraction.N;
+ in_Refraction_1.roughness = refraction.roughness;
+ in_Refraction_1.ior = refraction.ior;
+
+ CLOSURE_EVAL_FUNCTION_2(GlassBSDF, Glossy, Refraction);
+
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += out_Refraction_1.radiance * refraction.color * refraction.weight;
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+/* Dielectric BSDF */
+CLOSURE_EVAL_FUNCTION_DECLARE_2(DielectricBSDF, Diffuse, Glossy)
+Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_2(Diffuse, Glossy);
+
+ in_Diffuse_0.N = diffuse.N;
+ in_Diffuse_0.albedo = diffuse.color;
+ in_Glossy_1.N = reflection.N;
+ in_Glossy_1.roughness = reflection.roughness;
+
+ CLOSURE_EVAL_FUNCTION_2(DielectricBSDF, Diffuse, Glossy);
+
+ Closure closure = CLOSURE_DEFAULT;
+ if (!output_sss(diffuse, out_Diffuse_0)) {
+ closure.radiance += out_Diffuse_0.radiance * diffuse.color * diffuse.weight;
+ }
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+/* Specular BSDF */
+CLOSURE_EVAL_FUNCTION_DECLARE_3(SpecularBSDF, Diffuse, Glossy, Glossy)
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_3(Diffuse, Glossy, Glossy);
+
+ in_Diffuse_0.N = diffuse.N;
+ in_Diffuse_0.albedo = diffuse.color;
+ in_Glossy_1.N = reflection.N;
+ in_Glossy_1.roughness = reflection.roughness;
+ in_Glossy_2.N = clearcoat.N;
+ in_Glossy_2.roughness = clearcoat.roughness;
+
+ CLOSURE_EVAL_FUNCTION_3(SpecularBSDF, Diffuse, Glossy, Glossy);
+
+ Closure closure = CLOSURE_DEFAULT;
+ if (!output_sss(diffuse, out_Diffuse_0)) {
+ closure.radiance += out_Diffuse_0.radiance * diffuse.color * diffuse.weight;
+ }
+ closure.radiance += out_Glossy_2.radiance * clearcoat.color * clearcoat.weight;
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+/* Principled BSDF */
+CLOSURE_EVAL_FUNCTION_DECLARE_4(PrincipledBSDF, Diffuse, Glossy, Glossy, Refraction)
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat,
+ ClosureRefraction refraction)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_4(Diffuse, Glossy, Glossy, Refraction);
+
+ in_Diffuse_0.N = diffuse.N;
+ in_Diffuse_0.albedo = diffuse.color;
+ in_Glossy_1.N = reflection.N;
+ in_Glossy_1.roughness = reflection.roughness;
+ in_Glossy_2.N = clearcoat.N;
+ in_Glossy_2.roughness = clearcoat.roughness;
+ in_Refraction_3.N = refraction.N;
+ in_Refraction_3.roughness = refraction.roughness;
+ in_Refraction_3.ior = refraction.ior;
+
+ CLOSURE_EVAL_FUNCTION_4(PrincipledBSDF, Diffuse, Glossy, Glossy, Refraction);
+
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += out_Glossy_2.radiance * clearcoat.color * clearcoat.weight;
+ closure.radiance += out_Refraction_3.radiance * refraction.color * refraction.weight;
+ if (!output_sss(diffuse, out_Diffuse_0)) {
+ closure.radiance += out_Diffuse_0.radiance * diffuse.color * diffuse.weight;
+ }
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+CLOSURE_EVAL_FUNCTION_DECLARE_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy)
+Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_2(Glossy, Glossy);
+
+ in_Glossy_0.N = reflection.N;
+ in_Glossy_0.roughness = reflection.roughness;
+ in_Glossy_1.N = clearcoat.N;
+ in_Glossy_1.roughness = clearcoat.roughness;
+
+ CLOSURE_EVAL_FUNCTION_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy);
+
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += out_Glossy_1.radiance * clearcoat.color * clearcoat.weight;
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+/* Not supported for surface shaders. */
+Closure closure_eval(ClosureVolumeScatter volume_scatter)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureVolumeAbsorption volume_absorption)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureVolumeScatter volume_scatter,
+ ClosureVolumeAbsorption volume_absorption,
+ ClosureEmission emission)
+{
+ return CLOSURE_DEFAULT;
+}
+
+/* Not implemented yet. */
+Closure closure_eval(ClosureHair hair)
+{
+ return CLOSURE_DEFAULT;
+}
+
+vec4 closure_to_rgba(Closure closure)
+{
+ return vec4(closure.radiance, 1.0 - saturate(avg(closure.transmittance)));
+}
+
+Closure closure_add(Closure cl1, Closure cl2)
+{
+ Closure cl;
+ cl.radiance = cl1.radiance + cl2.radiance;
+ cl.transmittance = cl1.transmittance + cl2.transmittance;
+ cl.holdout = cl1.holdout + cl2.holdout;
+ return cl;
+}
+
+Closure closure_mix(Closure cl1, Closure cl2, float fac)
+{
+ /* Weights have already been applied. */
+ return closure_add(cl1, cl2);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl
index 706b75cb7f9..89a6f10e634 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl
@@ -3,6 +3,8 @@
#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 ClosureInputTranslucent {
vec3 N; /** Shading normal. */
@@ -69,6 +71,7 @@ void closure_Translucent_eval_end(ClosureInputTranslucent cl_in,
ClosureEvalCommon cl_common,
inout ClosureOutputTranslucent 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);
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl
new file mode 100644
index 00000000000..e450b8ad3c8
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl
@@ -0,0 +1,113 @@
+
+void output_aov(vec4 color, float value, uint hash)
+{
+ /* Unsupported. */
+}
+
+/* Surface BSDFs. */
+Closure closure_eval(ClosureDiffuse diffuse)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureTranslucent translucent)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureReflection reflection)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureRefraction refraction)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureEmission emission)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.emission = emission.emission;
+ return closure;
+}
+Closure closure_eval(ClosureTransparency transparency)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat,
+ ClosureRefraction refraction)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureHair hair)
+{
+ return CLOSURE_DEFAULT;
+}
+
+Closure closure_eval(ClosureVolumeScatter volume_scatter)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.scatter = volume_scatter.scattering;
+ closure.anisotropy = volume_scatter.anisotropy;
+ return closure;
+}
+Closure closure_eval(ClosureVolumeAbsorption volume_absorption)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.absorption = volume_absorption.absorption;
+ return closure;
+}
+Closure closure_eval(ClosureVolumeScatter volume_scatter,
+ ClosureVolumeAbsorption volume_absorption,
+ ClosureEmission emission)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.absorption = volume_absorption.absorption;
+ closure.scatter = volume_scatter.scattering;
+ closure.anisotropy = volume_scatter.anisotropy;
+ closure.emission = emission.emission;
+ return closure;
+}
+
+vec4 closure_to_rgba(Closure closure)
+{
+ /* Not supported */
+ return vec4(0.0);
+}
+
+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;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl
index 9022a9d3130..0096cd1747f 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl
@@ -1,6 +1,8 @@
-#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
-#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
+#pragma BLENDER_REQUIRE(gpu_shader_codegen_lib.glsl)
+/* #pragma (common_math_geom_lib.glsl) */
+/* #pragma (common_uniforms_lib.glsl) */
+/* #pragma (renderpass_lib.glsl) */
#ifndef VOLUMETRICS
@@ -20,15 +22,6 @@ struct Closure {
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
/* Metal Default Constructor - Requred for C++ constructor syntax. */
@@ -45,191 +38,76 @@ struct Closure {
}
# else
/* Explicit Closure constructors -- To support GLSL syntax */
- inline Closure(vec3 in_radiance,
- vec3 in_transmittance,
- float in_holdout,
- vec4 in_ssr_data,
- vec2 in_ssr_normal,
- int in_flag
-# ifdef USE_SSS
- ,
- vec3 in_sss_irradiance,
- vec3 in_sss_albedo,
- float in_sss_radius
-# endif /* USE_SSS */
- )
- : radiance(in_radiance),
- transmittance(in_transmittance),
- holdout(in_holdout),
- ssr_data(in_ssr_data),
- ssr_normal(in_ssr_normal),
- flag(in_flag)
-# ifdef USE_SSS
- ,
- sss_irradiance(in_sss_irradiance),
- sss_albedo(in_sss_albedo),
- sss_radius(in_sss_radius)
-# endif /* USE_SSS */
+ inline Closure(vec3 in_radiance, vec3 in_transmittance, float in_holdout)
+ : radiance(in_radiance), transmittance(in_transmittance), holdout(in_holdout)
{
}
-# endif /* VOLUMETRICS */
-#endif /* GPU_METAL */
+# endif /* VOLUMETRICS */
+#endif /* GPU_METAL */
};
#ifndef GPU_METAL
/* Prototype */
-Closure nodetree_exec(void);
+Closure nodetree_exec();
+vec4 closure_to_rgba(Closure);
+void output_aov(vec4 color, float value, uint hash);
+vec3 coordinate_camera(vec3 P);
+vec3 coordinate_screen(vec3 P);
+vec3 coordinate_reflect(vec3 P, vec3 N);
+vec3 coordinate_incoming(vec3 P);
+
+/* Single BSDFs. */
+Closure closure_eval(ClosureDiffuse diffuse);
+Closure closure_eval(ClosureTranslucent translucent);
+Closure closure_eval(ClosureReflection reflection);
+Closure closure_eval(ClosureRefraction refraction);
+Closure closure_eval(ClosureEmission emission);
+Closure closure_eval(ClosureTransparency transparency);
+Closure closure_eval(ClosureVolumeScatter volume_scatter);
+Closure closure_eval(ClosureVolumeAbsorption volume_absorption);
+Closure closure_eval(ClosureHair hair);
+
+/* Glass BSDF. */
+Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction);
+/* Dielectric BSDF. */
+Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection);
+/* ClearCoat BSDF. */
+Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat);
+/* Volume BSDF. */
+Closure closure_eval(ClosureVolumeScatter volume_scatter,
+ ClosureVolumeAbsorption volume_absorption,
+ ClosureEmission emission);
+/* Specular BSDF. */
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat);
+/* Principled BSDF. */
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat,
+ ClosureRefraction refraction);
+
+Closure closure_add(Closure cl1, Closure cl2);
+Closure closure_mix(Closure cl1, Closure cl2, float fac);
+
+float ambient_occlusion_eval(vec3 normal,
+ float distance,
+ const float inverted,
+ const float sample_count);
+
+/* WORKAROUND: Included later with libs. This is because we are mixing include systems. */
+vec3 safe_normalize(vec3 N);
+float fast_sqrt(float a);
+vec3 cameraVec(vec3 P);
+vec2 btdf_lut(float a, float b, float c);
+vec2 brdf_lut(float a, float b);
+vec3 F_brdf_multi_scatter(vec3 a, vec3 b, vec2 c);
+vec3 F_brdf_single_scatter(vec3 a, vec3 b, vec2 c);
+float F_eta(float a, float b);
#endif
-/* 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
-
-/* Let radiance passthrough or replace it to get the BRDF and color
- * to applied to the SSR result. */
-vec3 closure_mask_ssr_radiance(vec3 radiance, float ssr_id)
-{
- return (ssrToggle && int(ssr_id) == outputSsrId) ? vec3(1.0) : radiance;
-}
-
-void closure_load_ssr_data(
- vec3 ssr_radiance, float roughness, vec3 N, float 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, viewCameraVec(viewPosition));
-
- if (ssrToggle && int(ssr_id) == outputSsrId) {
- cl.ssr_data = vec4(ssr_radiance, roughness);
- cl.flag |= CLOSURE_SSR_FLAG;
- }
- else {
- cl.radiance += ssr_radiance;
- }
-}
-
-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;
- /* Irradiance will be convolved by SSSS pass. Do not add to radiance. */
- sss_irradiance = vec3(0);
- }
-# endif
- cl.radiance += render_pass_diffuse_mask(vec3(1), sss_irradiance) * sss_albedo;
-}
-
+# define CLOSURE_DEFAULT Closure(vec3(0), vec3(0), 0.0)
#endif
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_empty.glsl b/source/blender/draw/engines/eevee/shaders/eevee_empty.glsl
new file mode 100644
index 00000000000..e00bcc4e557
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/eevee_empty.glsl
@@ -0,0 +1,7 @@
+
+/* Empty GLSL source to satisfy the GPUShaderCreateInfo requirements. */
+/* Needed includes for shader nodes. */
+#pragma BLENDER_REQUIRE(closure_type_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_attribute_lib.glsl)
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_empty_volume.glsl b/source/blender/draw/engines/eevee/shaders/eevee_empty_volume.glsl
new file mode 100644
index 00000000000..a748c0092b6
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/eevee_empty_volume.glsl
@@ -0,0 +1,8 @@
+
+/* Empty GLSL source to satisfy the GPUShaderCreateInfo requirements. */
+/* Needed includes for shader nodes. */
+#pragma BLENDER_REQUIRE(closure_type_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_attribute_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_volume_lib.glsl)
diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
index 1aff93e01f8..e86c5e06c99 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -11,6 +11,7 @@ layout(std140) uniform sssProfile
{
vec4 sss_kernel[MAX_SSS_SAMPLES];
vec4 radii_max_radius;
+ float avg_inv_radius;
int sss_samples;
};
@@ -26,7 +27,7 @@ void main(void)
vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO: precompute. */
vec2 uvs = gl_FragCoord.xy * pixel_size;
vec3 sss_irradiance = texture(sssIrradiance, uvs).rgb;
- float sss_radius = texture(sssRadius, uvs).r * radii_max_radius.w;
+ float sss_radius = texture(sssRadius, uvs).r * radii_max_radius.w * avg_inv_radius;
float depth = texture(depthBuffer, uvs).r;
float depth_view = get_view_z_from_depth(depth);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
index 3cf21dc32d1..5e1725ace97 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
@@ -23,12 +23,13 @@ layout(std140) uniform sssProfile
{
vec4 sss_kernel[MAX_SSS_SAMPLES];
vec4 radii_max_radius;
+ float avg_inv_radius;
int sss_samples;
};
vec3 sss_profile(float s)
{
- s /= radii_max_radius.w;
+ s /= radii_max_radius.w * avg_inv_radius;
return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb;
}
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
index fd08dfda060..c8eea8d7860 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
@@ -2,15 +2,12 @@
/* Required by some nodes. */
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_type_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_diffuse_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_glossy_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_translucent_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_refraction_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_surface_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
#ifdef USE_ALPHA_HASH
@@ -73,6 +70,7 @@ float hashed_alpha_threshold(vec3 co)
void main()
{
#if defined(USE_ALPHA_HASH)
+ g_data = init_globals();
Closure cl = nodetree_exec();
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
deleted file mode 100644
index f650e2eeb8c..00000000000
--- a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
+++ /dev/null
@@ -1,35 +0,0 @@
-
-#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
-#pragma BLENDER_REQUIRE(common_view_lib.glsl)
-
-#ifndef HAIR_SHADER
-in vec3 pos;
-#endif
-
-void main()
-{
- GPU_INTEL_VERTEX_SHADER_WORKAROUND
-
-#ifdef HAIR_SHADER
- float time, thick_time, thickness;
- vec3 worldPosition, tan, binor;
- hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0),
- ModelMatrixInverse,
- ViewMatrixInverse[3].xyz,
- ViewMatrixInverse[2].xyz,
- worldPosition,
- tan,
- binor,
- time,
- thickness,
- thick_time);
-#else
- vec3 worldPosition = point_object_to_world(pos);
-#endif
-
- gl_Position = point_world_to_ndc(worldPosition);
-
-#ifdef CLIP_PLANES
- gl_ClipDistance[0] = dot(vec4(worldPosition.xyz, 1.0), clipPlanes[0]);
-#endif
-}
diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl
index 3e0a5e76d00..f276e4f26ca 100644
--- a/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl
@@ -1,4 +1,4 @@
-#define EEVEE_AOV_HASH_COLOR_TYPE_MASK 1
+#define EEVEE_AOV_HASH_COLOR_TYPE_MASK 1u
/* ---------------------------------------------------------------------- */
/** \name Resources
@@ -14,7 +14,7 @@ layout(std140) uniform renderpass_block
bool renderPassSSSColor;
bool renderPassEnvironment;
bool renderPassAOV;
- int renderPassAOVActive;
+ uint renderPassAOVActive;
};
/** \} */
@@ -23,19 +23,14 @@ layout(std140) uniform renderpass_block
/** \name Functions
* \{ */
-vec3 render_pass_diffuse_mask(vec3 diffuse_color, vec3 diffuse_light)
+vec3 render_pass_diffuse_mask(vec3 diffuse_light)
{
- return renderPassDiffuse ? (renderPassDiffuseLight ? diffuse_light : diffuse_color) : vec3(0.0);
+ return renderPassDiffuse ? (renderPassDiffuseLight ? diffuse_light : vec3(1.0)) : vec3(0.0);
}
-vec3 render_pass_sss_mask(vec3 sss_color)
+vec3 render_pass_glossy_mask(vec3 specular_light)
{
- return renderPassSSSColor ? sss_color : vec3(0.0);
-}
-
-vec3 render_pass_glossy_mask(vec3 specular_color, vec3 specular_light)
-{
- return renderPassGlossy ? (renderPassGlossyLight ? specular_light : specular_color) : vec3(0.0);
+ return renderPassGlossy ? (renderPassGlossyLight ? specular_light : vec3(1.0)) : vec3(0.0);
}
vec3 render_pass_emission_mask(vec3 emission_light)
@@ -45,10 +40,10 @@ vec3 render_pass_emission_mask(vec3 emission_light)
bool render_pass_aov_is_color()
{
- return (renderPassAOVActive & EEVEE_AOV_HASH_COLOR_TYPE_MASK) != 0;
+ return (renderPassAOVActive & EEVEE_AOV_HASH_COLOR_TYPE_MASK) != 0u;
}
-int render_pass_aov_hash()
+uint render_pass_aov_hash()
{
return renderPassAOVActive & ~EEVEE_AOV_HASH_COLOR_TYPE_MASK;
}
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
index cbfa9737a84..0e8e8dd9d01 100644
--- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
@@ -1,5 +1,6 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
@@ -12,6 +13,7 @@ void main()
#ifdef HAIR_SHADER
hairStrandID = hair_get_strand_id();
+ hairBary = hair_get_barycentric();
vec3 pos, binor;
hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0),
ModelMatrixInverse,
@@ -52,3 +54,93 @@ void main()
# endif
#endif
}
+
+#ifdef HAIR_SHADER
+# ifdef OBINFO_LIB
+vec3 attr_load_orco(samplerBuffer cd_buf)
+{
+ vec3 P = hair_get_strand_pos();
+ vec3 lP = transform_point(ModelMatrixInverse, P);
+ return OrcoTexCoFactors[0].xyz + lP * OrcoTexCoFactors[1].xyz;
+}
+# endif
+
+vec4 attr_load_tangent(samplerBuffer cd_buf)
+{
+ /* Not supported. */
+ return vec4(0.0, 0.0, 0.0, 1.0);
+}
+
+vec3 attr_load_uv(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgb;
+}
+
+vec4 attr_load_color(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgba;
+}
+
+vec4 attr_load_vec4(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgba;
+}
+
+vec3 attr_load_vec3(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgb;
+}
+
+vec2 attr_load_vec2(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rg;
+}
+
+float attr_load_float(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).r;
+}
+
+#else
+
+# ifdef OBINFO_LIB
+vec3 attr_load_orco(samplerBuffer cd_buf)
+{
+ vec3 P = hair_get_strand_pos();
+ vec3 lP = transform_point(ModelMatrixInverse, P);
+ return OrcoTexCoFactors[0].xyz + lP * OrcoTexCoFactors[1].xyz;
+}
+# endif
+
+vec4 attr_load_tangent(vec4 tangent)
+{
+ tangent.xyz = safe_normalize(normal_object_to_world(tangent.xyz));
+ return tangent;
+}
+
+/* Simple passthrough. */
+vec4 attr_load_vec4(vec4 attr)
+{
+ return attr;
+}
+vec3 attr_load_vec3(vec3 attr)
+{
+ return attr;
+}
+vec2 attr_load_vec2(vec2 attr)
+{
+ return attr;
+}
+vec2 attr_load_float(vec2 attr)
+{
+ return attr;
+}
+vec4 attr_load_color(vec4 attr)
+{
+ return attr;
+}
+vec3 attr_load_uv(vec3 attr)
+{
+ return attr;
+}
+#endif
diff --git a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
index 889bf439d5f..9ad7a4fdbc1 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
@@ -2,16 +2,14 @@
/* Required by some nodes. */
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_type_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_diffuse_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_glossy_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_translucent_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_refraction_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_surface_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
#pragma BLENDER_REQUIRE(volumetric_lib.glsl)
+#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
#ifdef USE_ALPHA_BLEND
/* Use dual source blending to be able to make a whole range of effects. */
@@ -22,18 +20,74 @@ layout(location = 0, index = 1) out vec4 outTransmittance;
layout(location = 0) out vec4 outRadiance;
layout(location = 1) out vec2 ssrNormals;
layout(location = 2) out vec4 ssrData;
-# ifdef USE_SSS
layout(location = 3) out vec3 sssIrradiance;
layout(location = 4) out float sssRadius;
layout(location = 5) out vec3 sssAlbedo;
+
+#endif
+
+uniform float backgroundAlpha;
+
+#ifdef EEVEE_DISPLACEMENT_BUMP
+
+# ifndef GPU_METAL
+/* Prototype. */
+vec3 displacement_exec();
# endif
+/* Return new shading normal. */
+vec3 displacement_bump()
+{
+ vec2 dHd;
+ dF_branch(dot(displacement_exec(), g_data.N + dF_impl(g_data.N)), dHd);
+
+ vec3 dPdx = dFdx(g_data.P);
+ vec3 dPdy = dFdy(g_data.P);
+
+ /* Get surface tangents from normal. */
+ vec3 Rx = cross(dPdy, g_data.N);
+ vec3 Ry = cross(g_data.N, dPdx);
+
+ /* Compute surface gradient and determinant. */
+ float det = dot(dPdx, Rx);
+
+ vec3 surfgrad = dHd.x * Rx + dHd.y * Ry;
+
+ float facing = FrontFacing ? 1.0 : -1.0;
+ return normalize(abs(det) * g_data.N - facing * sign(det) * surfgrad);
+}
+
#endif
void main()
{
+ g_data = init_globals();
+
+#ifdef EEVEE_DISPLACEMENT_BUMP
+ g_data.N = displacement_bump();
+#endif
+
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ attrib_load();
+#endif
+
+ out_ssr_color = vec3(0.0);
+ out_ssr_roughness = 0.0;
+ out_ssr_N = g_data.N;
+
+ out_sss_radiance = vec3(0.0);
+ out_sss_radius = 0.0;
+ out_sss_color = vec3(0.0);
+
Closure cl = nodetree_exec();
+#ifdef WORLD_BACKGROUND
+ if (!renderPassEnvironment) {
+ cl.holdout += 1.0 - backgroundAlpha;
+ cl.radiance *= backgroundAlpha;
+ }
+#endif
+
float holdout = saturate(1.0 - cl.holdout);
float transmit = saturate(avg(cl.transmittance));
float alpha = 1.0 - transmit;
@@ -53,38 +107,40 @@ void main()
outTransmittance = vec4(cl.transmittance, transmit) * holdout;
#else
outRadiance = vec4(cl.radiance, holdout);
- ssrNormals = cl.ssr_normal;
- ssrData = cl.ssr_data;
-# ifdef USE_SSS
- sssIrradiance = cl.sss_irradiance;
- sssRadius = cl.sss_radius;
- sssAlbedo = cl.sss_albedo;
-# endif
+ ssrNormals = normal_encode(normalize(mat3(ViewMatrix) * out_ssr_N), vec3(0.0));
+ ssrData = vec4(out_ssr_color, out_ssr_roughness);
+ sssIrradiance = out_sss_radiance;
+ sssRadius = out_sss_radius;
+ sssAlbedo = out_sss_color;
#endif
- /* For Probe capture */
-#ifdef USE_SSS
- float fac = float(!sssToggle);
-
- /* TODO(fclem): we shouldn't need this.
- * Just disable USE_SSS when USE_REFRACTION is enabled. */
-# ifdef USE_REFRACTION
+#ifdef USE_REFRACTION
/* SSRefraction pass is done after the SSS pass.
* In order to not lose the diffuse light totally we
* need to merge the SSS radiance to the main radiance. */
- fac = 1.0;
-# endif
-
- outRadiance.rgb += cl.sss_irradiance.rgb * cl.sss_albedo.rgb * fac;
+ const bool use_refraction = true;
+#else
+ const bool use_refraction = false;
#endif
+ /* For Probe capture */
+ if (!sssToggle || use_refraction) {
+ outRadiance.rgb += out_sss_radiance * out_sss_color;
+ }
#ifndef USE_ALPHA_BLEND
float alpha_div = safe_rcp(alpha);
outRadiance.rgb *= alpha_div;
ssrData.rgb *= alpha_div;
-# ifdef USE_SSS
sssAlbedo.rgb *= alpha_div;
-# endif
+
+ if (renderPassAOV) {
+ if (aov_is_valid) {
+ outRadiance = vec4(out_aov, 1.0);
+ }
+ else {
+ outRadiance = vec4(0.0);
+ }
+ }
#endif
#ifdef LOOKDEV
@@ -92,3 +148,34 @@ void main()
gl_FragDepth = 0.0;
#endif
}
+
+/* Only supported attrib for world/background shaders. */
+vec3 attr_load_orco(vec4 orco)
+{
+ return g_data.P;
+}
+/* Unsupported. */
+vec4 attr_load_tangent(vec4 tangent)
+{
+ return vec4(0);
+}
+vec4 attr_load_vec4(vec4 attr)
+{
+ return vec4(0);
+}
+vec3 attr_load_vec3(vec3 attr)
+{
+ return vec3(0);
+}
+vec2 attr_load_vec2(vec2 attr)
+{
+ return vec2(0);
+}
+vec4 attr_load_color(vec4 attr)
+{
+ return vec4(0);
+}
+vec3 attr_load_uv(vec3 attr)
+{
+ return vec3(0);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl
index d7fc5e0b52a..1f2f7cb65cc 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl
@@ -1,12 +1,23 @@
/** This describe the entire interface of the shader. */
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+
#define SURFACE_INTERFACE \
vec3 worldPosition; \
vec3 viewPosition; \
vec3 worldNormal; \
vec3 viewNormal;
-#if defined(STEP_RESOLVE) || defined(STEP_RAYTRACE)
+#ifndef IN_OUT
+# if defined(GPU_VERTEX_SHADER)
+# define IN_OUT out
+# elif defined(GPU_FRAGMENT_SHADER)
+# define IN_OUT in
+# endif
+#endif
+
+#ifndef EEVEE_GENERATED_INTERFACE
+# if defined(STEP_RESOLVE) || defined(STEP_RAYTRACE)
/* SSR will set these global variables itself.
* Also make false positive compiler warnings disappear by setting values. */
vec3 worldPosition = vec3(0);
@@ -14,22 +25,23 @@ vec3 viewPosition = vec3(0);
vec3 worldNormal = vec3(0);
vec3 viewNormal = vec3(0);
-#elif defined(GPU_GEOMETRY_SHADER)
+# elif defined(GPU_GEOMETRY_SHADER)
in ShaderStageInterface{SURFACE_INTERFACE} dataIn[];
out ShaderStageInterface{SURFACE_INTERFACE} dataOut;
-# define PASS_SURFACE_INTERFACE(vert) \
- dataOut.worldPosition = dataIn[vert].worldPosition; \
- dataOut.viewPosition = dataIn[vert].viewPosition; \
- dataOut.worldNormal = dataIn[vert].worldNormal; \
- dataOut.viewNormal = dataIn[vert].viewNormal;
+# define PASS_SURFACE_INTERFACE(vert) \
+ dataOut.worldPosition = dataIn[vert].worldPosition; \
+ dataOut.viewPosition = dataIn[vert].viewPosition; \
+ dataOut.worldNormal = dataIn[vert].worldNormal; \
+ dataOut.viewNormal = dataIn[vert].viewNormal;
-#else /* GPU_VERTEX_SHADER || GPU_FRAGMENT_SHADER*/
+# else /* GPU_VERTEX_SHADER || GPU_FRAGMENT_SHADER*/
IN_OUT ShaderStageInterface{SURFACE_INTERFACE};
-#endif
+# endif
+#endif /* EEVEE_GENERATED_INTERFACE */
#ifdef HAIR_SHADER
IN_OUT ShaderHairInterface
@@ -40,6 +52,7 @@ IN_OUT ShaderHairInterface
float hairThickness;
float hairTime;
flat int hairStrandID;
+ vec2 hairBary;
};
#endif
@@ -52,3 +65,138 @@ IN_OUT ShaderPointCloudInterface
flat int pointID;
};
#endif
+
+#if defined(GPU_FRAGMENT_SHADER) && defined(CODEGEN_LIB)
+
+# if defined(USE_BARYCENTRICS) && !defined(HAIR_SHADER)
+vec3 barycentric_distances_get()
+{
+ /* NOTE: No need to undo perspective divide since it is not applied yet. */
+ vec3 pos0 = (ProjectionMatrixInverse * gpu_position_at_vertex(0)).xyz;
+ vec3 pos1 = (ProjectionMatrixInverse * gpu_position_at_vertex(1)).xyz;
+ vec3 pos2 = (ProjectionMatrixInverse * gpu_position_at_vertex(2)).xyz;
+ vec3 edge21 = pos2 - pos1;
+ vec3 edge10 = pos1 - pos0;
+ vec3 edge02 = pos0 - pos2;
+ vec3 d21 = safe_normalize(edge21);
+ vec3 d10 = safe_normalize(edge10);
+ vec3 d02 = safe_normalize(edge02);
+ vec3 dists;
+ float d = dot(d21, edge02);
+ dists.x = sqrt(dot(edge02, edge02) - d * d);
+ d = dot(d02, edge10);
+ dists.y = sqrt(dot(edge10, edge10) - d * d);
+ d = dot(d10, edge21);
+ dists.z = sqrt(dot(edge21, edge21) - d * d);
+ return dists.xyz;
+}
+# endif
+
+GlobalData init_globals(void)
+{
+ GlobalData surf;
+
+# if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ surf.P = -cameraVec(worldPosition);
+ surf.N = surf.Ng = -surf.P;
+ surf.ray_length = 0.0;
+# else
+ surf.P = worldPosition;
+ surf.N = safe_normalize(worldNormal);
+ surf.Ng = safe_normalize(cross(dFdx(surf.P), dFdy(surf.P)));
+ surf.ray_length = distance(surf.P, cameraPos);
+# endif
+ surf.barycentric_coords = vec2(0.0);
+ surf.barycentric_dists = vec3(0.0);
+ if (!FrontFacing) {
+ surf.N = -surf.N;
+ }
+# ifdef HAIR_SHADER
+ /* Shade as a cylinder. */
+ vec3 B = normalize(cross(worldNormal, hairTangent));
+ float cos_theta;
+ if (hairThicknessRes == 1) {
+ /* Random cosine normal distribution on the hair surface. */
+ cos_theta = texelfetch_noise_tex(gl_FragCoord.xy).x * 2.0 - 1.0;
+ }
+ else {
+ /* Shade as a cylinder. */
+ cos_theta = hairThickTime / hairThickness;
+ }
+ float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));
+ surf.N = safe_normalize(worldNormal * sin_theta + B * cos_theta);
+ surf.T = hairTangent;
+ surf.is_strand = true;
+ surf.hair_time = hairTime;
+ surf.hair_thickness = hairThickness;
+ surf.hair_strand_id = hairStrandID;
+# ifdef USE_BARYCENTRICS
+ surf.barycentric_coords = hair_resolve_barycentric(hairBary);
+# endif
+# else
+ surf.T = vec3(0.0);
+ surf.is_strand = false;
+ surf.hair_time = 0.0;
+ surf.hair_thickness = 0.0;
+ surf.hair_strand_id = 0;
+# ifdef USE_BARYCENTRICS
+ surf.barycentric_coords = gpu_BaryCoord.xy;
+ surf.barycentric_dists = barycentric_distances_get();
+# endif
+# endif
+ surf.ray_type = rayType;
+ surf.ray_depth = 0.0;
+ return surf;
+}
+#endif
+
+vec3 coordinate_camera(vec3 P)
+{
+ vec3 vP;
+#if defined(PROBE_CAPTURE)
+ /* Unsupported. It would make the probe camera-dependent. */
+ vP = P;
+#elif defined(WORLD_BACKGROUND)
+ vP = transform_direction(ViewMatrix, P);
+#else
+ vP = transform_point(ViewMatrix, P);
+#endif
+ vP.z = -vP.z;
+ return vP;
+}
+
+vec3 coordinate_screen(vec3 P)
+{
+ vec3 window = vec3(0.0);
+#if defined(PROBE_CAPTURE)
+ /* Unsupported. It would make the probe camera-dependent. */
+ window.xy = vec2(0.5);
+
+#elif defined(WORLD_BACKGROUND)
+ window.xy = project_point(ProjectionMatrix, viewPosition).xy * 0.5 + 0.5;
+ window.xy = window.xy * CameraTexCoFactors.xy + CameraTexCoFactors.zw;
+
+#else /* MESH */
+ window.xy = project_point(ViewProjectionMatrix, P).xy * 0.5 + 0.5;
+ window.xy = window.xy * CameraTexCoFactors.xy + CameraTexCoFactors.zw;
+#endif
+ return window;
+}
+
+vec3 coordinate_reflect(vec3 P, vec3 N)
+{
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ return N;
+#else
+ return -reflect(cameraVec(P), N);
+#endif
+}
+
+vec3 coordinate_incoming(vec3 P)
+{
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ return -P;
+#else
+ return cameraVec(P);
+#endif
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
index 51e9eda6cc2..6c6b810422b 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
@@ -1,6 +1,9 @@
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_surface_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
#ifndef HAIR_SHADER
@@ -18,6 +21,7 @@ void main()
#ifdef HAIR_SHADER
hairStrandID = hair_get_strand_id();
+ hairBary = hair_get_barycentric();
vec3 pos, binor;
hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0),
ModelMatrixInverse,
@@ -53,11 +57,103 @@ void main()
/* No need to normalize since this is just a rotation. */
viewNormal = normal_world_to_view(worldNormal);
-# ifdef USE_ATTR
-# ifdef HAIR_SHADER
- pos = hair_get_strand_pos();
-# endif
- pass_attr(pos, NormalMatrix, ModelMatrixInverse);
-# endif
+
+ attrib_load();
#endif
}
+
+#ifdef HAIR_SHADER
+# ifdef OBINFO_LIB
+vec3 attr_load_orco(samplerBuffer cd_buf)
+{
+ vec3 P = hair_get_strand_pos();
+ vec3 lP = transform_point(ModelMatrixInverse, P);
+ return OrcoTexCoFactors[0].xyz + lP * OrcoTexCoFactors[1].xyz;
+}
+# endif
+
+vec4 attr_load_tangent(samplerBuffer cd_buf)
+{
+ return vec4(hairTangent, 1.0);
+}
+
+vec3 attr_load_uv(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgb;
+}
+
+vec4 attr_load_color(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgba;
+}
+
+vec4 attr_load_vec4(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgba;
+}
+
+vec3 attr_load_vec3(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgb;
+}
+
+vec2 attr_load_vec2(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rg;
+}
+
+float attr_load_float(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).r;
+}
+
+#else
+
+# ifdef OBINFO_LIB
+vec3 attr_load_orco(vec4 orco)
+{
+ /* We know when there is no orco layer when orco.w is 1.0 because it uses the generic vertex
+ * attrib (which is [0,0,0,1]). */
+ if (orco.w == 0.0) {
+ return orco.xyz * 0.5 + 0.5;
+ }
+ else {
+ /* If the object does not have any deformation, the orco layer calculation is done on the fly
+ * using the orco_madd factors. */
+ return OrcoTexCoFactors[0].xyz + pos * OrcoTexCoFactors[1].xyz;
+ }
+}
+# endif
+
+vec4 attr_load_tangent(vec4 tangent)
+{
+ tangent.xyz = normal_object_to_world(tangent.xyz);
+ return tangent;
+}
+
+/* Simple passthrough. */
+vec4 attr_load_vec4(vec4 attr)
+{
+ return attr;
+}
+vec3 attr_load_vec3(vec3 attr)
+{
+ return attr;
+}
+vec2 attr_load_vec2(vec2 attr)
+{
+ return attr;
+}
+float attr_load_float(float attr)
+{
+ return attr;
+}
+vec4 attr_load_color(vec4 attr)
+{
+ return attr;
+}
+vec3 attr_load_uv(vec3 attr)
+{
+ return attr;
+}
+#endif
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
index 4ff42892f7d..e0a79872928 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
@@ -1,6 +1,5 @@
#pragma BLENDER_REQUIRE(volumetric_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_type_lib.glsl)
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
@@ -18,9 +17,7 @@ flat in int slice;
vec3 worldPosition = vec3(0.0);
vec3 viewPosition = vec3(0.0);
vec3 viewNormal = vec3(0.0);
-#ifdef MESH_SHADER
-vec3 volumeObjectLocalCoord = vec3(0.0);
-#endif
+vec3 volumeOrco = vec3(0.0);
layout(location = 0) out vec4 volumeScattering;
layout(location = 1) out vec4 volumeExtinction;
@@ -29,6 +26,52 @@ layout(location = 3) out vec4 volumePhase;
/* Store volumetric properties into the froxel textures. */
+#ifdef MESH_SHADER
+GlobalData init_globals(void)
+{
+ GlobalData surf;
+ surf.P = worldPosition;
+ surf.N = vec3(0.0);
+ surf.Ng = vec3(0.0);
+ surf.is_strand = false;
+ surf.hair_time = 0.0;
+ surf.hair_thickness = 0.0;
+ surf.hair_strand_id = 0;
+ surf.barycentric_coords = vec2(0.0);
+ surf.barycentric_dists = vec3(0.0);
+ surf.ray_type = RAY_TYPE_CAMERA;
+ surf.ray_depth = 0.0;
+ surf.ray_length = distance(surf.P, cameraPos);
+ return surf;
+}
+
+vec3 coordinate_camera(vec3 P)
+{
+ vec3 vP;
+ vP = transform_point(ViewMatrix, P);
+ vP.z = -vP.z;
+ return vP;
+}
+
+vec3 coordinate_screen(vec3 P)
+{
+ vec3 window = vec3(0.0);
+ window.xy = project_point(ViewProjectionMatrix, P).xy * 0.5 + 0.5;
+ window.xy = window.xy * CameraTexCoFactors.xy + CameraTexCoFactors.zw;
+ return window;
+}
+
+vec3 coordinate_reflect(vec3 P, vec3 N)
+{
+ return vec3(0.0);
+}
+
+vec3 coordinate_incoming(vec3 P)
+{
+ return cameraVec(P);
+}
+#endif
+
void main()
{
ivec3 volume_cell = ivec3(ivec2(gl_FragCoord.xy), slice);
@@ -37,14 +80,12 @@ void main()
viewPosition = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z);
worldPosition = point_view_to_world(viewPosition);
#ifdef MESH_SHADER
- volumeObjectLocalCoord = point_world_to_object(worldPosition);
+ volumeOrco = point_world_to_object(worldPosition);
/* TODO: redundant transform */
- volumeObjectLocalCoord = (volumeObjectLocalCoord - volumeOrcoLoc + volumeOrcoSize) /
- (volumeOrcoSize * 2.0);
- volumeObjectLocalCoord = (volumeObjectToTexture * vec4(volumeObjectLocalCoord, 1.0)).xyz;
+ volumeOrco = (volumeOrco - volumeOrcoLoc + volumeOrcoSize) / (volumeOrcoSize * 2.0);
+ volumeOrco = (volumeObjectToTexture * vec4(volumeOrco, 1.0)).xyz;
- if (any(lessThan(volumeObjectLocalCoord, vec3(0.0))) ||
- any(greaterThan(volumeObjectLocalCoord, vec3(1.0)))) {
+ if (any(lessThan(volumeOrco, vec3(0.0))) || any(greaterThan(volumeOrco, vec3(1.0)))) {
/* Note: Discard is not an explicit return in Metal prior to versions 2.3.
* adding return after discard ensures consistent behaviour and avoids GPU
* side-effects where control flow continues with undefined values. */
@@ -54,21 +95,25 @@ void main()
#endif
#ifdef CLEAR
- Closure cl = CLOSURE_DEFAULT;
+ volumeScattering = vec4(0.0, 0.0, 0.0, 1.0);
+ volumeExtinction = vec4(0.0, 0.0, 0.0, 1.0);
+ volumeEmissive = vec4(0.0, 0.0, 0.0, 1.0);
+ volumePhase = vec4(0.0, 0.0, 0.0, 0.0);
#else
+# ifdef MESH_SHADER
+ g_data = init_globals();
+ attrib_load();
+# endif
Closure cl = nodetree_exec();
-#endif
-
-#ifdef MESH_SHADER
+# ifdef MESH_SHADER
cl.scatter *= volumeDensityScale;
cl.absorption *= volumeDensityScale;
cl.emission *= volumeDensityScale;
-#endif
+# endif
volumeScattering = vec4(cl.scatter, 1.0);
volumeExtinction = vec4(cl.absorption + cl.scatter, 1.0);
volumeEmissive = vec4(cl.emission, 1.0);
-
/* Do not add phase weight if no scattering. */
if (all(equal(cl.scatter, vec3(0.0)))) {
volumePhase = vec4(0.0);
@@ -76,4 +121,38 @@ void main()
else {
volumePhase = vec4(cl.anisotropy, vec3(1.0));
}
+#endif
+}
+
+vec3 attr_load_orco(vec4 orco)
+{
+ return volumeOrco;
+}
+vec4 attr_load_tangent(vec4 tangent)
+{
+ return vec4(0);
+}
+vec4 attr_load_vec4(vec4 attr)
+{
+ return vec4(0);
+}
+vec3 attr_load_vec3(vec3 attr)
+{
+ return vec3(0);
+}
+vec2 attr_load_vec2(vec2 attr)
+{
+ return vec2(0);
+}
+float attr_load_float(float attr)
+{
+ return 0.0;
+}
+vec4 attr_load_color(vec4 attr)
+{
+ return vec4(0);
+}
+vec3 attr_load_uv(vec3 attr)
+{
+ return vec3(0);
}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl
index 5226da57a06..1269761ffa4 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl
@@ -1,11 +1,7 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
-#ifdef MESH_SHADER
-/* TODO: tight slices. */
-layout(triangles) in;
-layout(triangle_strip, max_vertices = 3) out;
-#else /* World */
+#ifdef STANDALONE
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
#endif
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
index 527bbd18896..26b60c992e1 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
@@ -11,8 +11,10 @@ uniform sampler3D volumeScattering; /* Result of the scatter step */
uniform sampler3D volumeExtinction;
#ifdef USE_VOLUME_OPTI
-uniform layout(r11f_g11f_b10f) writeonly restrict image3D finalScattering_img;
-uniform layout(r11f_g11f_b10f) writeonly restrict image3D finalTransmittance_img;
+uniform layout(r11f_g11f_b10f)
+writeonly restrict image3D finalScattering_img;
+uniform layout(r11f_g11f_b10f)
+writeonly restrict image3D finalTransmittance_img;
vec3 finalScattering;
vec3 finalTransmittance;
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
index b70747ecec3..b574e8cdb4c 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
@@ -30,8 +30,30 @@ void main()
vPos.w = 1.0;
PASS_RESOURCE_ID
+}
+
+/* Stubs */
+vec2 btdf_lut(float a, float b, float c)
+{
+ return vec2(0.0);
+}
+
+vec2 brdf_lut(float a, float b)
+{
+ return vec2(0.0);
+}
-#ifdef USE_ATTR
- pass_attr(vec3(0.0), mat3(1), mat4(1));
-#endif
+vec3 F_brdf_multi_scatter(vec3 a, vec3 b, vec2 c)
+{
+ return vec3(0.0);
+}
+
+vec3 F_brdf_single_scatter(vec3 a, vec3 b, vec2 c)
+{
+ return vec3(0.0);
+}
+
+float F_eta(float a, float b)
+{
+ return 0.0;
}
diff --git a/source/blender/draw/engines/eevee/shaders/world_vert.glsl b/source/blender/draw/engines/eevee/shaders/world_vert.glsl
new file mode 100644
index 00000000000..29892a7ffb4
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/world_vert.glsl
@@ -0,0 +1,24 @@
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
+
+#pragma BLENDER_REQUIRE(closure_eval_surface_lib.glsl)
+
+in vec2 pos;
+
+RESOURCE_ID_VARYING
+
+void main()
+{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ PASS_RESOURCE_ID
+
+ gl_Position = vec4(pos, 1.0, 1.0);
+ viewPosition = project_point(ProjectionMatrixInverse, vec3(pos, 0.0));
+ worldPosition = project_point(ViewProjectionMatrixInverse, vec3(pos, 0.0));
+ /* Not usable. */
+ viewNormal = vec3(0.0);
+ worldNormal = vec3(0.0);
+}