Eevee: Polishing of Exponential Shadow mapping
Added exponent parameter to tweak light bleeding. Added depth bias to the shadow test. Added better blurring using 32 samples.
This commit is contained in:
@@ -69,6 +69,7 @@ void BKE_lamp_init(Lamp *la)
|
|||||||
la->bufsize = 512;
|
la->bufsize = 512;
|
||||||
la->clipsta = 0.5f;
|
la->clipsta = 0.5f;
|
||||||
la->clipend = 40.0f;
|
la->clipend = 40.0f;
|
||||||
|
la->bleedexp = 120.0f;
|
||||||
la->samp = 3;
|
la->samp = 3;
|
||||||
la->bias = 1.0f;
|
la->bias = 1.0f;
|
||||||
la->soft = 3.0f;
|
la->soft = 3.0f;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
#include "DNA_gpu_types.h"
|
#include "DNA_gpu_types.h"
|
||||||
|
#include "DNA_lamp_types.h"
|
||||||
#include "DNA_layer_types.h"
|
#include "DNA_layer_types.h"
|
||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
#include "DNA_mesh_types.h"
|
#include "DNA_mesh_types.h"
|
||||||
@@ -351,6 +352,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!MAIN_VERSION_ATLEAST(main, 280, 1)) {
|
if (!MAIN_VERSION_ATLEAST(main, 280, 1)) {
|
||||||
|
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "bleedexp")) {
|
||||||
|
for (Lamp *la = main->lamp.first; la; la = la->id.next) {
|
||||||
|
la->bleedexp = 120.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!DNA_struct_elem_find(fd->filesdna, "GPUDOFSettings", "float", "ratio")) {
|
if (!DNA_struct_elem_find(fd->filesdna, "GPUDOFSettings", "float", "ratio")) {
|
||||||
for (Camera *ca = main->camera.first; ca; ca = ca->id.next) {
|
for (Camera *ca = main->camera.first; ca; ca = ca->id.next) {
|
||||||
ca->gpu_dof.ratio = 1.0f;
|
ca->gpu_dof.ratio = 1.0f;
|
||||||
|
|||||||
@@ -382,6 +382,7 @@ static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_La
|
|||||||
evsh->bias = 0.05f * la->bias;
|
evsh->bias = 0.05f * la->bias;
|
||||||
evsh->near = la->clipsta;
|
evsh->near = la->clipsta;
|
||||||
evsh->far = la->clipend;
|
evsh->far = la->clipend;
|
||||||
|
evsh->exp = la->bleedexp;
|
||||||
|
|
||||||
evli->shadowid = (float)(evsmp->shadow_id);
|
evli->shadowid = (float)(evsmp->shadow_id);
|
||||||
}
|
}
|
||||||
@@ -732,12 +733,14 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
|||||||
/* Render each shadow to one layer of the array */
|
/* Render each shadow to one layer of the array */
|
||||||
for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
|
for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
|
||||||
EEVEE_LampEngineData *led = eevee_get_lamp_engine_data(ob);
|
EEVEE_LampEngineData *led = eevee_get_lamp_engine_data(ob);
|
||||||
|
Lamp *la = (Lamp *)ob->data;
|
||||||
|
|
||||||
if (led->need_update) {
|
if (led->need_update) {
|
||||||
EEVEE_ShadowCubeData *evscd = (EEVEE_ShadowCubeData *)led->storage;
|
EEVEE_ShadowCubeData *evscd = (EEVEE_ShadowCubeData *)led->storage;
|
||||||
EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
|
EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
|
||||||
|
|
||||||
srd->layer = i;
|
srd->layer = i;
|
||||||
|
srd->exponent = la->bleedexp;
|
||||||
copy_v3_v3(srd->position, ob->obmat[3]);
|
copy_v3_v3(srd->position, ob->obmat[3]);
|
||||||
for (int j = 0; j < 6; ++j) {
|
for (int j = 0; j < 6; ++j) {
|
||||||
copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
|
copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ typedef struct EEVEE_Light {
|
|||||||
} EEVEE_Light;
|
} EEVEE_Light;
|
||||||
|
|
||||||
typedef struct EEVEE_ShadowCube {
|
typedef struct EEVEE_ShadowCube {
|
||||||
float near, far, bias, pad;
|
float near, far, bias, exp;
|
||||||
} EEVEE_ShadowCube;
|
} EEVEE_ShadowCube;
|
||||||
|
|
||||||
typedef struct EEVEE_ShadowMap {
|
typedef struct EEVEE_ShadowMap {
|
||||||
@@ -133,6 +133,7 @@ typedef struct EEVEE_ShadowRender {
|
|||||||
float position[3];
|
float position[3];
|
||||||
float pad;
|
float pad;
|
||||||
int layer;
|
int layer;
|
||||||
|
float exponent;
|
||||||
} EEVEE_ShadowRender;
|
} EEVEE_ShadowRender;
|
||||||
|
|
||||||
/* ************ LIGHT DATA ************* */
|
/* ************ LIGHT DATA ************* */
|
||||||
|
|||||||
@@ -36,13 +36,14 @@ struct LightData {
|
|||||||
|
|
||||||
|
|
||||||
struct ShadowCubeData {
|
struct ShadowCubeData {
|
||||||
vec4 near_far_bias;
|
vec4 near_far_bias_exp;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* convenience aliases */
|
/* convenience aliases */
|
||||||
#define sh_cube_near near_far_bias.x
|
#define sh_cube_near near_far_bias_exp.x
|
||||||
#define sh_cube_far near_far_bias.y
|
#define sh_cube_far near_far_bias_exp.y
|
||||||
#define sh_cube_bias near_far_bias.z
|
#define sh_cube_bias near_far_bias_exp.z
|
||||||
|
#define sh_cube_exp near_far_bias_exp.w
|
||||||
|
|
||||||
|
|
||||||
struct ShadowMapData {
|
struct ShadowMapData {
|
||||||
|
|||||||
@@ -176,11 +176,11 @@ void light_visibility(LightData ld, ShadingData sd, out float vis)
|
|||||||
ShadowCubeData scd = shadows_cube_data[int(shid)];
|
ShadowCubeData scd = shadows_cube_data[int(shid)];
|
||||||
|
|
||||||
vec3 cubevec = sd.W - ld.l_position;
|
vec3 cubevec = sd.W - ld.l_position;
|
||||||
float dist = length(cubevec);
|
float dist = length(cubevec) - scd.sh_cube_bias;
|
||||||
|
|
||||||
float z = texture_octahedron(shadowCubes, vec4(cubevec, shid)).r;
|
float z = texture_octahedron(shadowCubes, vec4(cubevec, shid)).r;
|
||||||
|
|
||||||
float esm_test = min(1.0, exp(-5.0 * dist) * z);
|
float esm_test = saturate(exp(scd.sh_cube_exp * (z - dist)));
|
||||||
float sh_test = step(0, z - dist);
|
float sh_test = step(0, z - dist);
|
||||||
|
|
||||||
vis *= esm_test;
|
vis *= esm_test;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ layout(std140) uniform shadow_render_block {
|
|||||||
mat4 ShadowMatrix[6];
|
mat4 ShadowMatrix[6];
|
||||||
vec4 lampPosition;
|
vec4 lampPosition;
|
||||||
int layer;
|
int layer;
|
||||||
|
float exponent;
|
||||||
};
|
};
|
||||||
|
|
||||||
in vec3 worldPosition;
|
in vec3 worldPosition;
|
||||||
@@ -11,5 +12,5 @@ out vec4 FragColor;
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float dist = distance(lampPosition.xyz, worldPosition.xyz);
|
float dist = distance(lampPosition.xyz, worldPosition.xyz);
|
||||||
FragColor = vec4(exp(5.0 * dist), 0.0, 0.0, 1.0);
|
FragColor = vec4(dist, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ layout(std140) uniform shadow_render_block {
|
|||||||
mat4 ShadowMatrix[6];
|
mat4 ShadowMatrix[6];
|
||||||
vec4 lampPosition;
|
vec4 lampPosition;
|
||||||
int layer;
|
int layer;
|
||||||
|
float exponent;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(triangles) in;
|
layout(triangles) in;
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
|
|
||||||
|
layout(std140) uniform shadow_render_block {
|
||||||
|
mat4 ShadowMatrix[6];
|
||||||
|
vec4 lampPosition;
|
||||||
|
int layer;
|
||||||
|
float exponent;
|
||||||
|
};
|
||||||
|
|
||||||
uniform samplerCube shadowCube;
|
uniform samplerCube shadowCube;
|
||||||
|
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
@@ -24,6 +31,35 @@ void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B)
|
|||||||
B = cross(N, T);
|
B = cross(N, T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NUM_SAMPLE 32
|
||||||
|
vec2 poisson_disc[32] = vec2[32](
|
||||||
|
vec2( 0.476, 0.854), vec2(-0.659, -0.670),
|
||||||
|
vec2( 0.905, -0.270), vec2( 0.215, -0.133),
|
||||||
|
vec2(-0.595, 0.242), vec2(-0.146, 0.519),
|
||||||
|
vec2( 0.108, -0.930), vec2( 0.807, 0.449),
|
||||||
|
|
||||||
|
vec2(-0.476, -0.854), vec2( 0.659, 0.670),
|
||||||
|
vec2(-0.905, 0.270), vec2(-0.215, 0.133),
|
||||||
|
vec2( 0.595, -0.242), vec2( 0.146, -0.519),
|
||||||
|
vec2(-0.108, 0.930), vec2(-0.807, -0.449),
|
||||||
|
|
||||||
|
vec2(-0.854, 0.476), vec2( 0.670, -0.659),
|
||||||
|
vec2( 0.270, 0.905), vec2( 0.133, 0.215),
|
||||||
|
vec2(-0.242, -0.595), vec2(-0.519, -0.146),
|
||||||
|
vec2( 0.930, 0.108), vec2(-0.449, 0.807),
|
||||||
|
|
||||||
|
vec2( 0.854, -0.476), vec2(-0.670, 0.659),
|
||||||
|
vec2(-0.270, -0.905), vec2(-0.133, -0.215),
|
||||||
|
vec2( 0.242, 0.595), vec2( 0.519, 0.146),
|
||||||
|
vec2(-0.930, -0.108), vec2( 0.449, -0.807)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Marco Salvi's GDC 2008 presentation about shadow maps pre-filtering techniques slide 24 */
|
||||||
|
float ln_space_prefilter(float w0, float x, float w1, float y)
|
||||||
|
{
|
||||||
|
return x + log(w0 + w1 * exp(y - x));
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
const vec2 texelSize = vec2(1.0 / 512.0);
|
const vec2 texelSize = vec2(1.0 / 512.0);
|
||||||
|
|
||||||
@@ -52,13 +88,25 @@ void main() {
|
|||||||
vec3 T, B;
|
vec3 T, B;
|
||||||
make_orthonormal_basis(cubevec, T, B);
|
make_orthonormal_basis(cubevec, T, B);
|
||||||
|
|
||||||
vec2 offsetvec = texelSize.xy * vec2(-1.0, 1.0); /* Totally arbitrary */
|
|
||||||
|
|
||||||
/* get cubemap shadow value */
|
/* get cubemap shadow value */
|
||||||
FragColor = texture(shadowCube, cubevec + offsetvec.x * T + offsetvec.x * B).rrrr;
|
const float blur_radius = 5.0 / 512.0; /* Totally arbitrary */
|
||||||
FragColor += texture(shadowCube, cubevec + offsetvec.x * T + offsetvec.y * B).rrrr;
|
const float weight = 1.0 / float(NUM_SAMPLE);
|
||||||
FragColor += texture(shadowCube, cubevec + offsetvec.y * T + offsetvec.x * B).rrrr;
|
float accum = 0.0;
|
||||||
FragColor += texture(shadowCube, cubevec + offsetvec.y * T + offsetvec.y * B).rrrr;
|
|
||||||
|
|
||||||
FragColor /= 4.0;
|
/* Poisson disc blur in log space. */
|
||||||
|
vec2 offsetvec = poisson_disc[0].xy * blur_radius;
|
||||||
|
float depth1 = texture(shadowCube, cubevec + offsetvec.x * T + offsetvec.y * B).r;
|
||||||
|
|
||||||
|
offsetvec = poisson_disc[1].xy * blur_radius;
|
||||||
|
float depth2 = texture(shadowCube, cubevec + offsetvec.x * T + offsetvec.y * B).r;
|
||||||
|
|
||||||
|
accum = ln_space_prefilter(weight, depth1, weight, depth2);
|
||||||
|
|
||||||
|
for (int i = 2; i < NUM_SAMPLE; ++i) {
|
||||||
|
vec2 offsetvec = poisson_disc[i].xy * blur_radius;
|
||||||
|
depth1 = texture(shadowCube, cubevec + offsetvec.x * T + offsetvec.y * B).r;
|
||||||
|
accum = ln_space_prefilter(1.0, accum, weight, depth1);
|
||||||
|
}
|
||||||
|
|
||||||
|
FragColor = vec4(accum, accum, accum, 1.0);
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ layout(std140) uniform shadow_render_block {
|
|||||||
mat4 ShadowMatrix[6];
|
mat4 ShadowMatrix[6];
|
||||||
vec4 lampPosition;
|
vec4 lampPosition;
|
||||||
int layer;
|
int layer;
|
||||||
|
float exponent;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(triangles) in;
|
layout(triangles) in;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ typedef struct Lamp {
|
|||||||
short pad2;
|
short pad2;
|
||||||
|
|
||||||
float clipsta, clipend;
|
float clipsta, clipend;
|
||||||
float bias, soft, compressthresh, bleedbias, pad5;
|
float bias, soft, compressthresh, bleedbias, bleedexp;
|
||||||
short bufsize, samp, buffers, filtertype;
|
short bufsize, samp, buffers, filtertype;
|
||||||
char bufflag, buftype;
|
char bufflag, buftype;
|
||||||
|
|
||||||
|
|||||||
@@ -596,6 +596,12 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
|
|||||||
RNA_def_property_ui_text(prop, "Shadow Buffer Bleed Bias", "Bias for reducing light-bleed on variance shadow maps");
|
RNA_def_property_ui_text(prop, "Shadow Buffer Bleed Bias", "Bias for reducing light-bleed on variance shadow maps");
|
||||||
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "shadow_buffer_exp", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_float_sdna(prop, NULL, "bleedexp");
|
||||||
|
RNA_def_property_range(prop, 1.0f, 9999.0f);
|
||||||
|
RNA_def_property_ui_text(prop, "Shadow Buffer Exponent", "Bias for reducing light-bleed on exponential shadow maps");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "shadow_buffer_soft", PROP_FLOAT, PROP_NONE);
|
prop = RNA_def_property(srna, "shadow_buffer_soft", PROP_FLOAT, PROP_NONE);
|
||||||
RNA_def_property_float_sdna(prop, NULL, "soft");
|
RNA_def_property_float_sdna(prop, NULL, "soft");
|
||||||
RNA_def_property_range(prop, 0.0f, 100.0f);
|
RNA_def_property_range(prop, 0.0f, 100.0f);
|
||||||
|
|||||||
Reference in New Issue
Block a user