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>2019-08-12 02:47:30 +0300
committerClément Foucault <foucault.clem@gmail.com>2019-08-14 14:36:56 +0300
commitd5002f007e8d770dea15f0881cd9d0a4f3aaf824 (patch)
treefabe9add7890d37884e2a9bf3c6e48c01bd7ff8a /source/blender/draw/engines/eevee/shaders
parent8a338950c6ddde37ddefadd75c39d4d2efc7aee3 (diff)
Eevee: Improve Transparent BSDF behavior
Alpha blended Transparency is now using dual source blending making it fully compatible with cycles Transparent BSDF. Multiply and additive blend mode can be achieved using some nodes and are going to be removed.
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders')
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl221
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_frag.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_frag.glsl6
3 files changed, 121 insertions, 116 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index 274269846bc..412fa47dbec 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -164,6 +164,19 @@ float sum(vec4 v)
return dot(vec4(1.0), v);
}
+float avg(vec2 v)
+{
+ return dot(vec2(1.0 / 2.0), v);
+}
+float avg(vec3 v)
+{
+ return dot(vec3(1.0 / 3.0), v);
+}
+float avg(vec4 v)
+{
+ return dot(vec4(1.0 / 4.0), v);
+}
+
float saturate(float a)
{
return clamp(a, 0.0, 1.0);
@@ -716,6 +729,7 @@ float cone_cosine(float r)
}
/* --------- Closure ---------- */
+
#ifdef VOLUMETRICS
struct Closure {
@@ -725,6 +739,8 @@ struct Closure {
float anisotropy;
};
+Closure nodetree_exec(void); /* Prototype */
+
# define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), vec3(0.0), 0.0)
Closure closure_mix(Closure cl1, Closure cl2, float fac)
@@ -758,7 +774,7 @@ Closure closure_emission(vec3 rgb)
struct Closure {
vec3 radiance;
- float opacity;
+ vec3 transmittance;
# ifdef USE_SSS
vec4 sss_data;
# ifdef USE_SSS_ALBEDO
@@ -767,110 +783,113 @@ struct Closure {
# endif
vec4 ssr_data;
vec2 ssr_normal;
- int ssr_id;
+ int flag;
};
-/* This is hacking ssr_id to tag transparent bsdf */
-# define TRANSPARENT_CLOSURE_FLAG -2
-# define REFRACT_CLOSURE_FLAG -3
-# define NO_SSR -999
+Closure nodetree_exec(void); /* Prototype */
+
+# define FLAG_TEST(flag, val) (((flag) & (val)) != 0)
+
+# define CLOSURE_SSR_FLAG 1
+# define CLOSURE_SSS_FLAG 2
# ifdef USE_SSS
# ifdef USE_SSS_ALBEDO
# define CLOSURE_DEFAULT \
- Closure(vec3(0.0), 1.0, vec4(0.0), vec3(0.0), vec4(0.0), vec2(0.0), -1)
+ Closure(vec3(0.0), vec3(0.0), vec4(0.0), vec3(0.0), vec4(0.0), vec2(0.0), 0)
# else
-# define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec4(0.0), vec2(0.0), -1)
+# define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), vec4(0.0), vec4(0.0), vec2(0.0), 0)
# endif
# else
-# define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec2(0.0), -1)
+# define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), vec4(0.0), vec2(0.0), 0)
# endif
-uniform int outputSsrId;
+uniform int outputSsrId = 1;
+uniform int outputSssId = 1;
-Closure closure_mix(Closure cl1, Closure cl2, float fac)
+void closure_load_ssr_data(
+ vec3 ssr_spec, float roughness, vec3 N, vec3 viewVec, int ssr_id, inout Closure cl)
{
- Closure cl;
+ /* Still encode to avoid artifacts in the SSR pass. */
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ cl.ssr_normal = normal_encode(vN, viewVec);
+
+ if (ssr_id == outputSsrId) {
+ cl.ssr_data = vec4(ssr_spec, roughness);
+ cl.flag |= CLOSURE_SSR_FLAG;
+ }
+}
- if (cl1.ssr_id == TRANSPARENT_CLOSURE_FLAG) {
- cl.ssr_normal = cl2.ssr_normal;
- cl.ssr_data = cl2.ssr_data;
- cl.ssr_id = cl2.ssr_id;
# ifdef USE_SSS
- cl1.sss_data = cl2.sss_data;
+void closure_load_sss_data(float radius,
+ vec3 sss_radiance,
# ifdef USE_SSS_ALBEDO
- cl1.sss_albedo = cl2.sss_albedo;
+ vec3 sss_albedo,
# endif
-# endif
- }
- else if (cl2.ssr_id == TRANSPARENT_CLOSURE_FLAG) {
- cl.ssr_normal = cl1.ssr_normal;
- cl.ssr_data = cl1.ssr_data;
- cl.ssr_id = cl1.ssr_id;
-# ifdef USE_SSS
- cl2.sss_data = cl1.sss_data;
+ int sss_id,
+ inout Closure cl)
+{
+ if (sss_id == outputSssId) {
+ cl.sss_data = vec4(sss_radiance, radius);
# ifdef USE_SSS_ALBEDO
- cl2.sss_albedo = cl1.sss_albedo;
+ cl.sss_albedo = sss_albedo;
# endif
-# endif
- }
- else if (cl1.ssr_id == outputSsrId) {
- /* When mixing SSR don't blend roughness.
- *
- * It makes no sense to mix them really, so we take either one of them and
- * tone down its specularity (ssr_data.xyz) while keeping its roughness (ssr_data.w).
- */
- cl.ssr_data = mix(cl1.ssr_data.xyzw, vec4(vec3(0.0), cl1.ssr_data.w), fac);
- cl.ssr_normal = cl1.ssr_normal;
- cl.ssr_id = cl1.ssr_id;
+ cl.flag |= CLOSURE_SSS_FLAG;
}
else {
- cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac);
- cl.ssr_normal = cl2.ssr_normal;
- cl.ssr_id = cl2.ssr_id;
+ cl.radiance += sss_radiance;
+# ifdef USE_SSS_ALBEDO
+ cl.radiance += sss_radiance * sss_albedo;
+# endif
}
+}
+# endif
- cl.opacity = mix(cl1.opacity, cl2.opacity, fac);
- cl.radiance = mix(cl1.radiance * cl1.opacity, cl2.radiance * cl2.opacity, fac);
- cl.radiance /= max(1e-8, cl.opacity);
+Closure closure_mix(Closure cl1, Closure cl2, float fac)
+{
+ Closure cl;
+ 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
- /* Apply Mix on input */
- cl1.sss_data.rgb *= 1.0 - fac;
- cl2.sss_data.rgb *= fac;
-
- /* Select biggest radius. */
- bool use_cl1 = (cl1.sss_data.a > cl2.sss_data.a);
- cl.sss_data = (use_cl1) ? cl1.sss_data : cl2.sss_data;
-
+ cl.sss_data = mix(cl1.sss_data, cl2.sss_data, fac);
+ bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
+ /* It also does not make sense to mix SSS radius or albedo. */
+ cl.sss_data.w = (use_cl1_sss) ? cl1.sss_data.w : cl2.sss_data.w;
# ifdef USE_SSS_ALBEDO
- /* TODO Find a solution to this. Dither? */
- cl.sss_albedo = (use_cl1) ? cl1.sss_albedo : cl2.sss_albedo;
- /* Add radiance that was supposed to be filtered but was rejected. */
- cl.radiance += (use_cl1) ? cl2.sss_data.rgb * cl2.sss_albedo : cl1.sss_data.rgb * cl1.sss_albedo;
-# else
- /* Add radiance that was supposed to be filtered but was rejected. */
- cl.radiance += (use_cl1) ? cl2.sss_data.rgb : cl1.sss_data.rgb;
+ cl.sss_albedo = (use_cl1_sss) ? cl1.sss_albedo : cl2.sss_albedo;
# endif
# endif
-
return cl;
}
Closure closure_add(Closure cl1, Closure cl2)
{
- Closure cl = (cl1.ssr_id == outputSsrId) ? cl1 : cl2;
+ Closure cl;
+ cl.transmittance = cl1.transmittance + cl2.transmittance;
cl.radiance = cl1.radiance + cl2.radiance;
+ 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_data = (cl1.sss_data.a > 0.0) ? cl1.sss_data : cl2.sss_data;
- /* Add radiance that was supposed to be filtered but was rejected. */
- cl.radiance += (cl1.sss_data.a > 0.0) ? cl2.sss_data.rgb : cl1.sss_data.rgb;
+ cl.sss_data = cl1.sss_data + cl2.sss_data;
+ bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
+ /* It also does not make sense to mix SSS radius or albedo. */
+ cl.sss_data.w = (use_cl1_sss) ? cl1.sss_data.w : cl2.sss_data.w;
# ifdef USE_SSS_ALBEDO
- /* TODO Find a solution to this. Dither? */
- cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo;
+ cl.sss_albedo = (use_cl1_sss) ? cl1.sss_albedo : cl2.sss_albedo;
# endif
# endif
- cl.opacity = saturate(cl1.opacity + cl2.opacity);
return cl;
}
@@ -883,19 +902,23 @@ Closure closure_emission(vec3 rgb)
/* Breaking this across multiple lines causes issues for some older GLSL compilers. */
/* clang-format off */
-# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY)
+# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER)
/* clang-format on */
-layout(location = 0) out vec4 fragColor;
-layout(location = 1) out vec4 ssrNormals;
+# ifndef USE_ALPHA_BLEND
+layout(location = 0) out vec4 outRadiance;
+layout(location = 1) out vec2 ssrNormals;
layout(location = 2) out vec4 ssrData;
-# ifdef USE_SSS
+# ifdef USE_SSS
layout(location = 3) out vec4 sssData;
-# ifdef USE_SSS_ALBEDO
+# ifdef USE_SSS_ALBEDO
layout(location = 4) out vec4 sssAlbedo;
-# endif /* USE_SSS_ALBEDO */
-# endif /* USE_SSS */
-
-Closure nodetree_exec(void); /* Prototype */
+# endif
+# endif
+# else /* USE_ALPHA_BLEND */
+/* Use dual source blending to be able to make a whole range of effects. */
+layout(location = 0, index = 0) out vec4 outRadiance;
+layout(location = 0, index = 1) out vec4 outTransmittance;
+# endif /* USE_ALPHA_BLEND */
# if defined(USE_ALPHA_BLEND)
/* Prototype because this file is included before volumetric_lib.glsl */
@@ -909,27 +932,24 @@ void volumetric_resolve(vec2 frag_uvs,
void main()
{
Closure cl = nodetree_exec();
-# ifndef USE_ALPHA_BLEND
- /* Prevent alpha hash material writing into alpha channel. */
- cl.opacity = 1.0;
-# endif
-# if defined(USE_ALPHA_BLEND)
+# ifdef USE_ALPHA_BLEND
vec2 uvs = gl_FragCoord.xy * volCoordScale.zw;
- vec3 transmittance, scattering;
- volumetric_resolve(uvs, gl_FragCoord.z, transmittance, scattering);
- fragColor.rgb = cl.radiance * transmittance + scattering;
- fragColor.a = cl.opacity;
-# else
- fragColor = vec4(cl.radiance, cl.opacity);
-# endif
+ vec3 vol_transmit, vol_scatter;
+ volumetric_resolve(uvs, gl_FragCoord.z, vol_transmit, vol_scatter);
- ssrNormals = cl.ssr_normal.xyyy;
+ float transmit = saturate(avg(cl.transmittance));
+ outRadiance = vec4(cl.radiance * vol_transmit + vol_scatter, (1.0 - transmit));
+ outTransmittance = vec4(cl.transmittance, transmit);
+# else
+ outRadiance = vec4(cl.radiance, 1.0);
+ ssrNormals = cl.ssr_normal;
ssrData = cl.ssr_data;
-# ifdef USE_SSS
+# ifdef USE_SSS
sssData = cl.sss_data;
-# ifdef USE_SSS_ALBEDO
+# ifdef USE_SSS_ALBEDO
sssAlbedo = cl.sss_albedo.rgbb;
+# endif
# endif
# endif
@@ -945,9 +965,9 @@ void main()
# endif
# ifdef USE_SSS_ALBEDO
- fragColor.rgb += cl.sss_data.rgb * cl.sss_albedo.rgb * fac;
+ outRadiance.rgb += cl.sss_data.rgb * cl.sss_albedo.rgb * fac;
# else
- fragColor.rgb += cl.sss_data.rgb * fac;
+ outRadiance.rgb += cl.sss_data.rgb * fac;
# endif
# endif
}
@@ -955,18 +975,3 @@ void main()
# endif /* MESH_SHADER && !SHADOW_SHADER */
#endif /* VOLUMETRICS */
-
-Closure nodetree_exec(void); /* Prototype */
-
-/* TODO find a better place */
-#ifdef USE_MULTIPLY
-
-out vec4 fragColor;
-
-# define NODETREE_EXEC
-void main()
-{
- Closure cl = nodetree_exec();
- fragColor = vec4(mix(vec3(1.0), cl.radiance, cl.opacity), 1.0);
-}
-#endif
diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
index 64a1c725a6b..561f1335cb8 100644
--- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
@@ -33,15 +33,13 @@ Closure nodetree_exec(void)
vec3 out_diff, out_spec, ssr_spec;
eevee_closure_default(N, albedo, f0, f90, 1, roughness, 1.0, out_diff, out_spec, ssr_spec);
- Closure result = Closure(out_spec + out_diff * albedo,
- 1.0,
- vec4(ssr_spec, roughness),
- normal_encode(vN, viewCameraVec),
- 0);
+ Closure cl = CLOSURE_DEFAULT;
+ cl.radiance = out_spec + out_diff * albedo;
+ closure_load_ssr_data(ssr_spec, roughness, N, viewCameraVec, 0, cl);
#ifdef LOOKDEV
gl_FragDepth = 0.0;
#endif
- return result;
+ return cl;
}
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
index e7b31b94f81..dea6bc020ec 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
@@ -71,14 +71,16 @@ void main()
Closure cl = nodetree_exec();
+ float opacity = saturate(1.0 - avg(cl.transmittance));
+
# if defined(USE_ALPHA_HASH)
/* Hashed Alpha Testing */
- if (cl.opacity < hashed_alpha_threshold(worldPosition)) {
+ if (opacity < hashed_alpha_threshold(worldPosition)) {
discard;
}
# elif defined(USE_ALPHA_CLIP)
/* Alpha clip */
- if (cl.opacity <= alphaThreshold) {
+ if (opacity <= alphaThreshold) {
discard;
}
# endif