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/draw')
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c24
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h5
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c2
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl1
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/lamps_lib.glsl136
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl58
8 files changed, 221 insertions, 11 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 09a090955c2..17295713001 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -530,6 +530,7 @@ static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_La
ubo_data->shadow_start = (float)(sh_data->layer_id);
ubo_data->data_start = (float)(sh_data->cube_id);
ubo_data->multi_shadow_count = (float)(sh_nbr);
+ ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */
ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
ubo_data->contact_bias = 0.05f * la->contact_bias;
@@ -777,6 +778,7 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
ubo_data->shadow_start = (float)(sh_data->layer_id);
ubo_data->data_start = (float)(sh_data->cascade_id);
ubo_data->multi_shadow_count = (float)(sh_nbr);
+ ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */
ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
ubo_data->contact_bias = 0.05f * la->contact_bias;
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index dbd953553cd..4a9633b4f44 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -307,6 +307,9 @@ static char *eevee_get_defines(int options)
if ((options & VAR_MAT_SSS) != 0) {
BLI_dynstr_appendf(ds, "#define USE_SSS\n");
}
+ if ((options & VAR_MAT_TRANSLUC) != 0) {
+ BLI_dynstr_appendf(ds, "#define USE_TRANSLUCENCY\n");
+ }
if ((options & VAR_MAT_VSM) != 0) {
BLI_dynstr_appendf(ds, "#define SHADOW_VSM\n");
}
@@ -636,7 +639,7 @@ struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *
struct GPUMaterial *EEVEE_material_mesh_get(
struct Scene *scene, Material *ma, EEVEE_Data *vedata,
- bool use_blend, bool use_multiply, bool use_refract, bool use_sss, int shadow_method)
+ bool use_blend, bool use_multiply, bool use_refract, bool use_sss, bool use_translucency, int shadow_method)
{
const void *engine = &DRW_engine_viewport_eevee_type;
int options = VAR_MAT_MESH;
@@ -645,6 +648,7 @@ struct GPUMaterial *EEVEE_material_mesh_get(
if (use_multiply) options |= VAR_MAT_MULT;
if (use_refract) options |= VAR_MAT_REFRACT;
if (use_sss) options |= VAR_MAT_SSS;
+ if (use_translucency) options |= VAR_MAT_TRANSLUC;
if (vedata->stl->effects->use_volumetrics && use_blend) options |= VAR_MAT_VOLUME;
options |= eevee_material_shadow_option(shadow_method);
@@ -977,6 +981,7 @@ static void material_opaque(
const bool use_gpumat = (ma->use_nodes && ma->nodetree);
const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0);
const bool use_sss = ((ma->blend_flag & MA_BL_SS_SUBSURFACE) != 0) && ((stl->effects->enabled_effects & EFFECT_SSS) != 0);
+ const bool use_translucency = ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0) && ((stl->effects->enabled_effects & EFFECT_SSS) != 0);
EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma);
@@ -987,7 +992,7 @@ static void material_opaque(
/* This will have been created already, just perform a lookup. */
*gpumat = (use_gpumat) ? EEVEE_material_mesh_get(
- scene, ma, vedata, false, false, use_refract, use_sss, linfo->shadow_method) : NULL;
+ scene, ma, vedata, false, false, use_refract, use_sss, use_translucency, linfo->shadow_method) : NULL;
*gpumat_depth = (use_gpumat) ? EEVEE_material_mesh_depth_get(
scene, ma, (ma->blend_method == MA_BM_HASHED), false) : NULL;
return;
@@ -995,7 +1000,8 @@ static void material_opaque(
if (use_gpumat) {
/* Shading */
- *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, false, use_refract, use_sss, linfo->shadow_method);
+ *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, false, use_refract,
+ use_sss, use_translucency, linfo->shadow_method);
*shgrp = DRW_shgroup_material_create(*gpumat,
(use_refract) ? psl->refract_pass :
@@ -1007,9 +1013,17 @@ static void material_opaque(
add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false);
if (use_sss) {
+ struct GPUTexture *sss_tex_profile = NULL;
struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(*gpumat,
- stl->effects->sss_sample_count);
+ stl->effects->sss_sample_count,
+ &sss_tex_profile);
+
if (sss_profile) {
+ if (use_translucency) {
+ DRW_shgroup_uniform_block(*shgrp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_texture(*shgrp, "sssTexProfile", sss_tex_profile);
+ }
+
DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1);
EEVEE_subsurface_add_pass(vedata, e_data.sss_count + 1, sss_profile);
e_data.sss_count++;
@@ -1099,7 +1113,7 @@ static void material_transparent(
if (ma->use_nodes && ma->nodetree) {
/* Shading */
*gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, (ma->blend_method == MA_BM_MULTIPLY), use_refract,
- false, linfo->shadow_method);
+ false, false, linfo->shadow_method);
*shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass);
if (*shgrp) {
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index b1ed108bad0..6a3adb36a7c 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -116,6 +116,7 @@ enum {
VAR_MAT_REFRACT = (1 << 12),
VAR_MAT_VOLUME = (1 << 13),
VAR_MAT_SSS = (1 << 14),
+ VAR_MAT_TRANSLUC = (1 << 15),
};
/* Shadow Technique */
@@ -280,7 +281,7 @@ typedef struct EEVEE_Light {
typedef struct EEVEE_Shadow {
float near, far, bias, exp;
- float shadow_start, data_start, multi_shadow_count, pad;
+ float shadow_start, data_start, multi_shadow_count, shadow_blur;
float contact_dist, contact_bias, contact_spread, contact_thickness;
} EEVEE_Shadow;
@@ -639,7 +640,7 @@ struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, str
struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo);
struct GPUMaterial *EEVEE_material_mesh_get(
struct Scene *scene, Material *ma, EEVEE_Data *vedata,
- bool use_blend, bool use_multiply, bool use_refract, bool use_sss, int shadow_method);
+ bool use_blend, bool use_multiply, bool use_refract, bool use_sss, bool use_translucency, int shadow_method);
struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma);
struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material *ma, bool use_hashed_alpha, bool is_shadow);
struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, int shadow_method);
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 6827d44aea4..fe6e77ddf29 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -123,7 +123,6 @@ void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct G
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_data);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_int(grp, "sampleCount", &effects->sss_sample_count, 1);
DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1);
DRW_shgroup_stencil_mask(grp, sss_id);
DRW_shgroup_call_add(grp, quad, NULL);
@@ -134,7 +133,6 @@ void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct G
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_blur);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_int(grp, "sampleCount", &effects->sss_sample_count, 1);
DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1);
DRW_shgroup_stencil_mask(grp, sss_id);
DRW_shgroup_call_add(grp, quad, NULL);
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 bd6c1923bfe..32d27838da3 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -103,6 +103,7 @@ struct ShadowCascadeData {
#define sh_tex_start shadow_data_start_end.x
#define sh_data_start shadow_data_start_end.y
#define sh_multi_nbr shadow_data_start_end.z
+#define sh_blur shadow_data_start_end.w
#define sh_contact_dist contact_shadow_data.x
#define sh_contact_offset contact_shadow_data.y
#define sh_contact_spread contact_shadow_data.z
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 9ee713ab483..ea9711a6cad 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -5,9 +5,9 @@
layout(std140) uniform sssProfile {
vec4 kernel[MAX_SSS_SAMPLES];
vec4 radii_max_radius;
+ int sss_samples;
};
-uniform int sampleCount;
uniform float jitterThreshold;
uniform sampler2D depthBuffer;
uniform sampler2D sssData;
@@ -59,7 +59,7 @@ void main(void)
/* Center sample */
vec3 accum = sss_data.rgb * kernel[0].rgb;
- for (int i = 1; i < sampleCount && i < MAX_SSS_SAMPLES; i++) {
+ for (int i = 1; i < sss_samples && i < MAX_SSS_SAMPLES; i++) {
vec2 sample_uv = uvs + kernel[i].a * finalStep * ((abs(kernel[i].a) > jitterThreshold) ? dir : dir_rand);
vec3 color = texture(sssData, sample_uv).rgb;
float sample_depth = texture(depthBuffer, sample_uv).r;
diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
index 5ca40cd06a2..c2e3f81aefd 100644
--- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
@@ -277,6 +277,142 @@ vec3 light_specular(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness
#endif
}
+#define MAX_SSS_SAMPLES 65
+#define SSS_LUT_SIZE 64.0
+#define SSS_LUT_SCALE ((SSS_LUT_SIZE - 1.0) / float(SSS_LUT_SIZE))
+#define SSS_LUT_BIAS (0.5 / float(SSS_LUT_SIZE))
+layout(std140) uniform sssProfile {
+ vec4 kernel[MAX_SSS_SAMPLES];
+ vec4 radii_max_radius;
+ int sss_samples;
+};
+
+uniform sampler1D sssTexProfile;
+
+vec3 sss_profile(float s) {
+ s /= radii_max_radius.w;
+ return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb;
+}
+
+vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale)
+{
+ vec3 vis = vec3(1.0);
+
+ /* Only shadowed light can produce translucency */
+ if (ld.l_shadowid >= 0.0) {
+ ShadowData data = shadows_data[int(ld.l_shadowid)];
+ float delta;
+
+ vec4 L = (ld.l_type != SUN) ? l_vector : vec4(-ld.l_forward, 1.0);
+
+ vec3 T, B;
+ make_orthonormal_basis(L.xyz / L.w, T, B);
+
+ vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw;
+ /* XXX This is a hack to not have noise correlation artifacts.
+ * A better solution to have better noise is welcome. */
+ rand.yz *= fast_sqrt(fract(rand.x * 7919.0)) * data.sh_blur;
+
+ /* We use the full l_vector.xyz so that the spread is minimize
+ * if the shading point is further away from the light source */
+ W = W + T * rand.y + B * rand.z;
+
+ if (ld.l_type == SUN) {
+ ShadowCascadeData scd = shadows_cascade_data[int(data.sh_data_start)];
+ vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
+
+ vec4 weights = step(scd.split_end_distances, view_z);
+ float id = abs(4.0 - dot(weights, weights));
+
+ if (id > 3.0) {
+ return vec3(0.0);
+ }
+
+ float range = abs(data.sh_far - data.sh_near); /* Same factor as in get_cascade_world_distance(). */
+
+ vec4 shpos = scd.shadowmat[int(id)] * vec4(W, 1.0);
+ float dist = shpos.z * range;
+
+ if (shpos.z > 1.0 || shpos.z < 0.0) {
+ return vec3(0.0);
+ }
+
+#if defined(SHADOW_VSM)
+ vec2 moments = texture(shadowTexture, vec3(shpos.xy, data.sh_tex_start + id)).rg;
+ delta = dist - moments.x;
+#else
+ float z = texture(shadowTexture, vec3(shpos.xy, data.sh_tex_start + id)).r;
+ delta = dist - z;
+#endif
+ }
+ else {
+ vec3 cubevec = W - shadows_cube_data[int(data.sh_data_start)].position.xyz;
+ float dist = length(cubevec);
+
+ /* If fragment is out of shadowmap range, do not occlude */
+ /* XXX : we check radial distance against a cubeface distance.
+ * We loose quite a bit of valid area. */
+ if (dist < data.sh_far) {
+ cubevec /= dist;
+
+#if defined(SHADOW_VSM)
+ vec2 moments = texture_octahedron(shadowTexture, vec4(cubevec, data.sh_tex_start)).rg;
+ delta = dist - moments.x;
+#else
+ float z = texture_octahedron(shadowTexture, vec4(cubevec, data.sh_tex_start)).r;
+ delta = dist - z;
+#endif
+ }
+ }
+
+ /* XXX : Removing Area Power. */
+ /* TODO : put this out of the shader. */
+ float falloff;
+ if (ld.l_type == AREA) {
+ vis *= 0.0962 * (ld.l_sizex * ld.l_sizey * 4.0 * M_PI);
+ vis /= (l_vector.w * l_vector.w);
+ falloff = dot(N, l_vector.xyz / l_vector.w);
+ }
+ else if (ld.l_type == SUN) {
+ falloff = dot(N, -ld.l_forward);
+ }
+ else {
+ vis *= 0.0248 * (4.0 * ld.l_radius * ld.l_radius * M_PI * M_PI);
+ vis /= (l_vector.w * l_vector.w);
+ falloff = dot(N, l_vector.xyz / l_vector.w);
+ }
+ vis *= M_1_PI; /* Normalize */
+
+ /* Applying profile */
+ vis *= sss_profile(abs(delta) / scale);
+
+ /* No transmittance at grazing angle (hide artifacts) */
+ vis *= saturate(falloff * 2.0);
+
+ if (ld.l_type == SPOT) {
+ float z = dot(ld.l_forward, l_vector.xyz);
+ vec3 lL = l_vector.xyz / z;
+ float x = dot(ld.l_right, lL) / ld.l_sizex;
+ float y = dot(ld.l_up, lL) / ld.l_sizey;
+
+ float ellipse = 1.0 / sqrt(1.0 + x * x + y * y);
+
+ float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend);
+
+ vis *= spotmask;
+ vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
+ }
+ else if (ld.l_type == AREA) {
+ vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
+ }
+ }
+ else {
+ vis = vec3(0.0);
+ }
+
+ return vis;
+}
+
#ifdef HAIR_SHADER
void light_hair_common(
LightData ld, vec3 N, vec3 V, vec4 l_vector, vec3 norm_view,
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index f63a9665810..44410be700b 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -810,3 +810,61 @@ vec3 eevee_surface_glass(vec3 N, vec3 transmission_col, float roughness, float i
return out_light;
}
+
+/* ----------- Translucency ----------- */
+
+vec3 eevee_surface_translucent_lit(vec3 N, vec3 albedo, float sss_scale)
+{
+#ifndef USE_TRANSLUCENCY
+ return vec3(0.0);
+#endif
+
+ vec3 V = cameraVec;
+
+ /* Zero length vectors cause issues, see: T51979. */
+#if 0
+ N = normalize(N);
+#else
+ {
+ float len = length(N);
+ if (isnan(len)) {
+ return vec3(0.0);
+ }
+ N /= len;
+ }
+#endif
+
+ /* We only enlit the backfaces */
+ N = -N;
+
+ /* ---------------- SCENE LAMPS LIGHTING ----------------- */
+
+#ifdef HAIR_SHADER
+ vec3 norm_view = cross(V, N);
+ norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
+#endif
+
+ vec3 diff = vec3(0.0);
+ for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
+ LightData ld = lights_data[i];
+
+ vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
+ l_vector.xyz = ld.l_position - worldPosition;
+ l_vector.w = length(l_vector.xyz);
+
+#ifdef HAIR_SHADER
+ vec3 norm_lamp, view_vec;
+ float occlu_trans, occlu;
+ light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
+
+ diff += ld.l_color * light_translucent(ld, worldPosition, norm_lamp, l_vector, sss_scale) * occlu_trans;
+#else
+ diff += ld.l_color * light_translucent(ld, worldPosition, N, l_vector, sss_scale);
+#endif
+ }
+
+ /* Accumulate outgoing radiance */
+ vec3 out_light = diff * albedo;
+
+ return out_light;
+}