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:
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c9
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c11
-rw-r--r--source/blender/draw/engines/eevee/shaders/lights_lib.glsl222
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c3
5 files changed, 56 insertions, 193 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 10da80ece54..1cf5650205d 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -428,7 +428,7 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
linfo->shadow_cube_size,
max_ii(1, linfo->num_cube_layer * 6),
shadow_pool_format,
- DRW_TEX_FILTER,
+ DRW_TEX_FILTER | DRW_TEX_COMPARE,
NULL);
}
@@ -437,7 +437,7 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
linfo->shadow_cascade_size,
max_ii(1, linfo->num_cascade_layer),
shadow_pool_format,
- DRW_TEX_FILTER,
+ DRW_TEX_FILTER | DRW_TEX_COMPARE,
NULL);
}
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index af9e2bc67f4..41df16ab22d 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -1753,6 +1753,15 @@ void EEVEE_materials_free(void)
void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
{
+ /* We sample the shadowmaps using shadow sampler. We need to enable Comparison mode.
+ * TODO(fclem) avoid this by using sampler objects.*/
+ GPU_texture_bind(sldata->shadow_cube_pool, 0);
+ GPU_texture_compare_mode(sldata->shadow_cube_pool, true);
+ GPU_texture_unbind(sldata->shadow_cube_pool);
+ GPU_texture_bind(sldata->shadow_cascade_pool, 0);
+ GPU_texture_compare_mode(sldata->shadow_cascade_pool, true);
+ GPU_texture_unbind(sldata->shadow_cascade_pool);
+
for (int i = 0; i < VAR_MAT_MAX; ++i) {
if (psl->default_pass[i]) {
DRW_draw_pass(psl->default_pass[i]);
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index b31925e8eff..4d29e597dae 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -333,7 +333,7 @@ void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
}
}
-void EEVEE_subsurface_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
@@ -356,6 +356,15 @@ void EEVEE_subsurface_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
}
if (!DRW_pass_is_empty(psl->sss_translucency_ps)) {
+ /* We sample the shadowmaps using normal sampler. We need to disable Comparison mode.
+ * TODO(fclem) avoid this by using sampler objects.*/
+ GPU_texture_bind(sldata->shadow_cube_pool, 0);
+ GPU_texture_compare_mode(sldata->shadow_cube_pool, false);
+ GPU_texture_unbind(sldata->shadow_cube_pool);
+ GPU_texture_bind(sldata->shadow_cascade_pool, 0);
+ GPU_texture_compare_mode(sldata->shadow_cascade_pool, false);
+ GPU_texture_unbind(sldata->shadow_cascade_pool);
+
GPU_framebuffer_bind(fbl->sss_translucency_fb);
DRW_draw_pass(psl->sss_translucency_ps);
}
diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
index 5558e2ef074..23bf8b59648 100644
--- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
@@ -1,6 +1,6 @@
-uniform sampler2DArray shadowCubeTexture;
-uniform sampler2DArray shadowCascadeTexture;
+uniform sampler2DArrayShadow shadowCubeTexture;
+uniform sampler2DArrayShadow shadowCascadeTexture;
#define LAMPS_LIB
@@ -51,19 +51,6 @@ vec2 cubeFaceCoordEEVEE(vec3 P, float face)
}
}
-float cubeFaceDepthEEVEE(vec3 P, float face)
-{
- if (face < 2.0) {
- return abs(P.x);
- }
- else if (face < 4.0) {
- return abs(P.y);
- }
- else {
- return abs(P.z);
- }
-}
-
vec4 sample_cube(sampler2DArray tex, vec3 cubevec, float cube)
{
/* Manual Shadow Cube Layer indexing. */
@@ -78,168 +65,25 @@ vec4 sample_cascade(sampler2DArray tex, vec2 co, float cascade_id)
return texture(tex, vec3(co, cascade_id));
}
-/** Convert screenspace derivatives to texture space derivatives.
- * As described by John R. Isidoro in GDC 2006 presentation "Shadow Mapping: GPU-based Tips and
- *Techniques". https://developer.amd.com/wordpress/media/2012/10/Isidoro-ShadowMapping.pdf
- **/
-vec2 texture_space_derivatives(vec3 duvfdx, vec3 duvfdy)
-{
- /* Invert texture Jacobian and use chain rule to compute ddist/du and ddist/dv
- * |ddist/du| = |du/dx du/dy|-T * |ddist/dx|
- * |ddist/dv| |dv/dx dv/dy| |ddist/dy| */
-
- /* // Multiply ddist/dx and ddist/dy by inverse transpose of Jacobian
- * float invDet = 1 / ((duvdist_dx.x * duvdist_dy.y) - (duvdist_dx.y * duvdist_dy.x));
- * // Top row of 2x2
- * ddist_duv.x = duvdist_dy.y * duvdist_dx.w; // invJtrans[0][0] * ddist_dx
- * ddist_duv.x -= duvdist_dx.y * duvdist_dy.w; // invJtrans[0][1] * ddist_dy
- * // Bottom row of 2x2
- * ddist_duv.y = duvdist_dx.x * duvdist_dy.w; // invJtrans[1][1] * ddist_dy
- * ddist_duv.y -= duvdist_dy.x * duvdist_dx.w; // invJtrans[1][0] * ddist_dx
- * ddist_duv *= invDet;
- **/
-
- /* Optimized version. */
- vec2 a = duvfdx.xy * duvfdy.yx;
- vec4 b = duvfdy.yzzx * duvfdx.zyxz;
- return (b.xz - b.yw) / (a.x - a.y);
-}
-
-/** Returns Receiver Plane Depth Bias
- * As described by John R. Isidoro in GDC 2006 presentation "Shadow Mapping: GPU-based Tips and
- * Techniques". https://developer.amd.com/wordpress/media/2012/10/Isidoro-ShadowMapping.pdf
- */
-float shadowmap_bias(vec2 co, vec2 tap_co, vec2 dwduv)
-{
- return dot(tap_co - co, dwduv);
-}
-
-/**
- * Parameters:
- * shadow_tx : shadowmap to sample.
- * co : the original sample position.
- * ref : the original depth to test (Depth of the surface in shadowmap space).
- * co_ofs : the actual offseted sample position.
- * dwduv : result of texture_space_derivatives().
- **/
-float filtered_and_biased_shadow_test(sampler2DArray shadow_tx,
- vec2 co,
- float layer,
- float ref,
- float max_bias,
- vec2 co_ofs,
- vec2 dwduv)
-{
- vec4 biases, depths;
- vec2 texture_size = vec2(textureSize(shadow_tx, 0).xy);
- vec3 texel_size = vec3(1.0 / texture_size, 0.0);
- /* Center texel coordinate to match hardware filtering */
- vec2 texel_uv = co_ofs * texture_size.xy - 0.5;
- vec2 texel_fract = fract(texel_uv);
- vec2 texel_floor = (floor(texel_uv) + 0.5) * texel_size.xy;
- /* Calc bias for each sample */
- biases.x = shadowmap_bias(co, texel_floor + texel_size.zy, dwduv);
- biases.y = shadowmap_bias(co, texel_floor + texel_size.xy, dwduv);
- biases.z = shadowmap_bias(co, texel_floor + texel_size.xz, dwduv);
- biases.w = shadowmap_bias(co, texel_floor + texel_size.zz, dwduv);
- /* Gather samples */
-#ifdef GPU_ARB_texture_gather
- /* Note: To make sure that we get the exact same result we use texel center.
- * This is because Anisotropic filtering is offsetting the coordinate. */
- depths = textureGather(shadow_tx, vec3(texel_floor + texel_size.xy * 0.5, layer));
-#else
- depths.x = texture(shadow_tx, vec3(texel_floor + texel_size.zy, layer)).x;
- depths.y = texture(shadow_tx, vec3(texel_floor + texel_size.xy, layer)).x;
- depths.z = texture(shadow_tx, vec3(texel_floor + texel_size.xz, layer)).x;
- depths.w = texture(shadow_tx, vec3(texel_floor + texel_size.zz, layer)).x;
-#endif
- /* Take absolute of bias to avoid overshadowing in proximity area.
- * Also limit the bias in case the geom is almost perpendicular to the shadow source
- * to avoid light leaking. */
- vec4 refs = saturate(ref - min(vec4(max_bias), abs(biases)));
- /* Bilinear PCF. */
- vec4 tests = step(refs, depths);
- tests.xy = mix(tests.wz, tests.xy, texel_fract.y);
- return saturate(mix(tests.x, tests.y, texel_fract.x));
-}
-
-float shadow_cubemap(ShadowData sd, ShadowCubeData scd, float texid, vec3 W)
+float sample_cube_shadow(ShadowData sd, ShadowCubeData scd, float texid, vec3 W)
{
vec3 cubevec = W - scd.position.xyz;
-#ifndef VOLUMETRICS
- vec3 rand = texelfetch_noise_tex(gl_FragCoord.xy).zwy;
- float ofs_len = fast_sqrt(rand.z) * sd.sh_blur * 0.1;
- vec3 cubevec_nor = normalize(cubevec);
- vec3 T, B;
- make_orthonormal_basis(cubevec_nor, T, B);
- vec3 cubevec_ofs = cubevec_nor + (T * rand.x + B * rand.y) * ofs_len;
- /* Use face of the offseted cubevec. */
- float face_id = cubeFaceIndexEEVEE(cubevec_ofs);
- vec2 uv_ofs = cubeFaceCoordEEVEE(cubevec_ofs, face_id);
-
- /* To avoid derivatives discontinuity, we compute derivatives
- * on a smooth linear function (unormalized cubevec),
- * and manually do the derivative of the uv coords. */
- vec3 duvwdx, duvwdy;
- vec3 dPdx = cubevec + dFdx(cubevec);
- vec3 dPdy = cubevec + dFdy(cubevec);
- vec2 uv = cubeFaceCoordEEVEE(cubevec, face_id);
- duvwdx.xy = cubeFaceCoordEEVEE(dPdx, face_id) - uv;
- duvwdy.xy = cubeFaceCoordEEVEE(dPdy, face_id) - uv;
-
- float dist = cubeFaceDepthEEVEE(cubevec, face_id);
- duvwdx.z = cubeFaceDepthEEVEE(dPdx, face_id);
- duvwdy.z = cubeFaceDepthEEVEE(dPdy, face_id);
-
- dist = buffer_depth(true, dist, sd.sh_far, sd.sh_near);
- duvwdx.z = buffer_depth(true, duvwdx.z, sd.sh_far, sd.sh_near) - dist;
- duvwdy.z = buffer_depth(true, duvwdy.z, sd.sh_far, sd.sh_near) - dist;
-
- vec2 dwduv = texture_space_derivatives(duvwdx, duvwdy);
-
- float layer = texid * 6.0 + face_id;
- return filtered_and_biased_shadow_test(
- shadowCubeTexture, uv, layer, dist, sd.sh_bias * 0.15, uv_ofs, dwduv);
-#else
float dist = max_v3(abs(cubevec));
dist = buffer_depth(true, dist, sd.sh_far, sd.sh_near);
- float face_id = cubeFaceIndexEEVEE(cubevec);
- vec2 uv = cubeFaceCoordEEVEE(cubevec, face_id);
- float layer = texid * 6.0 + face_id;
- return filtered_and_biased_shadow_test(shadowCubeTexture, uv, layer, dist, 0.0, uv, vec2(0.0));
-#endif
+ /* Manual Shadow Cube Layer indexing. */
+ /* TODO Shadow Cube Array. */
+ float face = cubeFaceIndexEEVEE(cubevec);
+ vec2 coord = cubeFaceCoordEEVEE(cubevec, face);
+
+ return texture(shadowCubeTexture, vec4(coord, texid * 6.0 + face, dist));
}
-float evaluate_cascade(ShadowData sd, mat4 shadowmat, mat4 shadowmat0, vec3 W, float texid)
+float sample_cascade_shadow(ShadowData sd, mat4 shadowmat, mat4 shadowmat0, vec3 W, float texid)
{
- vec4 shpos = shadowmat * vec4(W, 1.0);
-
-#ifndef VOLUMETRICS
- float fac = length(shadowmat0[0].xyz) / length(shadowmat[0].xyz);
- vec3 rand = texelfetch_noise_tex(gl_FragCoord.xy).zwy;
- float ofs_len = fast_sqrt(rand.z) * sd.sh_blur * 0.05 / fac;
- /* This assumes that shadowmap is a square (w == h)
- * and that all cascades are the same dimensions. */
- vec2 uv_ofs = shpos.xy + rand.xy * ofs_len;
-
- vec2 dwduv = texture_space_derivatives(dFdx(shpos.xyz), dFdy(shpos.xyz));
-
- float vis = filtered_and_biased_shadow_test(
- shadowCascadeTexture, shpos.xy, texid, shpos.z, sd.sh_bias * 0.75, uv_ofs, dwduv);
-#else
- float vis = filtered_and_biased_shadow_test(
- shadowCascadeTexture, shpos.xy, texid, shpos.z, 0.0, shpos.xy, vec2(0.0));
-#endif
-
- /* If fragment is out of shadowmap range, do not occlude */
- if (shpos.z < 1.0 && shpos.z > 0.0) {
- return vis;
- }
- else {
- return 1.0;
- }
+ vec4 coord = shadowmat * vec4(W, 1.0);
+ return texture(shadowCascadeTexture, vec4(coord.xy, texid, coord.z));
}
float shadow_cascade(ShadowData sd, int scd_id, float texid, vec3 W)
@@ -255,26 +99,26 @@ float shadow_cascade(ShadowData sd, int scd_id, float texid, vec3 W)
/* Branching using (weights > 0.0) is reaally slooow on intel so avoid it for now. */
/* TODO OPTI: Only do 2 samples and blend. */
- vis.x = evaluate_cascade(sd,
- shadows_cascade_data[scd_id].shadowmat[0],
- shadows_cascade_data[scd_id].shadowmat[0],
- W,
- texid + 0);
- vis.y = evaluate_cascade(sd,
- shadows_cascade_data[scd_id].shadowmat[1],
- shadows_cascade_data[scd_id].shadowmat[0],
- W,
- texid + 1);
- vis.z = evaluate_cascade(sd,
- shadows_cascade_data[scd_id].shadowmat[2],
- shadows_cascade_data[scd_id].shadowmat[0],
- W,
- texid + 2);
- vis.w = evaluate_cascade(sd,
- shadows_cascade_data[scd_id].shadowmat[3],
- shadows_cascade_data[scd_id].shadowmat[0],
- W,
- texid + 3);
+ vis.x = sample_cascade_shadow(sd,
+ shadows_cascade_data[scd_id].shadowmat[0],
+ shadows_cascade_data[scd_id].shadowmat[0],
+ W,
+ texid + 0);
+ vis.y = sample_cascade_shadow(sd,
+ shadows_cascade_data[scd_id].shadowmat[1],
+ shadows_cascade_data[scd_id].shadowmat[0],
+ W,
+ texid + 1);
+ vis.z = sample_cascade_shadow(sd,
+ shadows_cascade_data[scd_id].shadowmat[2],
+ shadows_cascade_data[scd_id].shadowmat[0],
+ W,
+ texid + 2);
+ vis.w = sample_cascade_shadow(sd,
+ shadows_cascade_data[scd_id].shadowmat[3],
+ shadows_cascade_data[scd_id].shadowmat[0],
+ W,
+ texid + 3);
float weight_sum = dot(vec4(1.0), weights);
if (weight_sum > 0.9999) {
@@ -346,7 +190,7 @@ float light_visibility(LightData ld,
vis *= shadow_cascade(data, int(data.sh_data_start), data.sh_tex_start, W);
}
else {
- vis *= shadow_cubemap(
+ vis *= sample_cube_shadow(
data, shadows_cube_data[int(data.sh_data_start)], data.sh_tex_start, W);
}
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 54c874241ac..1274b41c407 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -285,7 +285,8 @@ void drw_state_set(DRWState state)
if ((test = CHANGED_TO(DRW_STATE_SHADOW_OFFSET))) {
if (test == 1) {
glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(1.0f, 1.0f);
+ /* 2.0 Seems to be the lowest possible slope bias that works in every case. */
+ glPolygonOffset(2.0f, 1.0f);
}
else {
glDisable(GL_POLYGON_OFFSET_FILL);