Eevee: Refactor Shadow System
- Use only one 2d texture array to store all shadowmaps. - Allow to change shadow maps resolution. - Do not output radial distance when rendering shadowmaps. This will allow fast rendering of shadowmaps when we will drop the use of geometry shaders.
This commit is contained in:
parent
5b026486e4
commit
8b7a83a868
|
@ -154,8 +154,6 @@ data_to_c_simple(engines/eevee/shaders/shadow_frag.glsl SRC)
|
|||
data_to_c_simple(engines/eevee/shaders/shadow_geom.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/shadow_vert.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/shadow_store_frag.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/shadow_store_geom.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/shadow_store_vert.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/bsdf_lut_frag.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/btdf_lut_frag.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/bsdf_direct_lib.glsl SRC)
|
||||
|
|
|
@ -39,15 +39,11 @@ static void eevee_scene_layer_data_free(void *storage)
|
|||
DRW_UBO_FREE_SAFE(sldata->light_ubo);
|
||||
DRW_UBO_FREE_SAFE(sldata->shadow_ubo);
|
||||
DRW_UBO_FREE_SAFE(sldata->shadow_render_ubo);
|
||||
DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cube_target_fb);
|
||||
DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cube_fb);
|
||||
DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_map_fb);
|
||||
DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cascade_fb);
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_cube_target);
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_color_cube_target);
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_cube_pool);
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_map_pool);
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_cascade_pool);
|
||||
DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_target_fb);
|
||||
DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_store_fb);
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target);
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target);
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool);
|
||||
BLI_freelistN(&sldata->shadow_casters);
|
||||
|
||||
/* Probes */
|
||||
|
|
|
@ -811,7 +811,7 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
|
|||
|
||||
if (grp != NULL) {
|
||||
DRW_shgroup_uniform_buffer(grp, "depthFull", &e_data.depth_src);
|
||||
DRW_shgroup_uniform_buffer(grp, "shadowCubes", &sldata->shadow_depth_cube_pool);
|
||||
DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_pool);
|
||||
DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool);
|
||||
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
|
||||
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
|
||||
|
|
|
@ -309,6 +309,9 @@ static void EEVEE_scene_layer_settings_create(RenderEngine *UNUSED(engine), IDPr
|
|||
BKE_collection_engine_property_add_bool(props, "motion_blur_enable", false);
|
||||
BKE_collection_engine_property_add_int(props, "motion_blur_samples", 8);
|
||||
BKE_collection_engine_property_add_float(props, "motion_blur_shutter", 1.0f);
|
||||
|
||||
BKE_collection_engine_property_add_int(props, "shadow_method", SHADOW_ESM);
|
||||
BKE_collection_engine_property_add_int(props, "shadow_size", 512);
|
||||
}
|
||||
|
||||
static const DrawEngineDataSize EEVEE_data_size = DRW_VIEWPORT_DATA_SIZE(EEVEE_Data);
|
||||
|
|
|
@ -42,11 +42,6 @@ typedef struct EEVEE_ShadowCubeData {
|
|||
float viewprojmat[6][4][4];
|
||||
} EEVEE_ShadowCubeData;
|
||||
|
||||
typedef struct EEVEE_ShadowMapData {
|
||||
short light_id, shadow_id;
|
||||
float viewprojmat[4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
|
||||
} EEVEE_ShadowMapData;
|
||||
|
||||
typedef struct EEVEE_ShadowCascadeData {
|
||||
short light_id, shadow_id;
|
||||
float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
|
||||
|
@ -60,14 +55,13 @@ typedef struct ShadowCaster {
|
|||
|
||||
static struct {
|
||||
struct GPUShader *shadow_sh;
|
||||
struct GPUShader *shadow_store_sh;
|
||||
struct GPUShader *shadow_store_cube_sh;
|
||||
struct GPUShader *shadow_store_cascade_sh;
|
||||
} e_data = {NULL}; /* Engine data */
|
||||
|
||||
extern char datatoc_shadow_vert_glsl[];
|
||||
extern char datatoc_shadow_geom_glsl[];
|
||||
extern char datatoc_shadow_frag_glsl[];
|
||||
extern char datatoc_shadow_store_vert_glsl[];
|
||||
extern char datatoc_shadow_store_geom_glsl[];
|
||||
extern char datatoc_shadow_store_frag_glsl[];
|
||||
|
||||
/* *********** FUNCTIONS *********** */
|
||||
|
@ -75,15 +69,18 @@ extern char datatoc_shadow_store_frag_glsl[];
|
|||
void EEVEE_lights_init(EEVEE_SceneLayerData *sldata)
|
||||
{
|
||||
const unsigned int shadow_ubo_size = sizeof(EEVEE_ShadowCube) * MAX_SHADOW_CUBE +
|
||||
sizeof(EEVEE_ShadowMap) * MAX_SHADOW_MAP +
|
||||
sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE;
|
||||
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
SceneLayer *scene_layer = draw_ctx->scene_layer;
|
||||
IDProperty *props = BKE_scene_layer_engine_evaluated_get(scene_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
|
||||
|
||||
if (!e_data.shadow_sh) {
|
||||
e_data.shadow_sh = DRW_shader_create(
|
||||
datatoc_shadow_vert_glsl, datatoc_shadow_geom_glsl, datatoc_shadow_frag_glsl, NULL);
|
||||
|
||||
e_data.shadow_store_sh = DRW_shader_create(
|
||||
datatoc_shadow_store_vert_glsl, datatoc_shadow_store_geom_glsl, datatoc_shadow_store_frag_glsl, NULL);
|
||||
e_data.shadow_store_cube_sh = DRW_shader_create_fullscreen(datatoc_shadow_store_frag_glsl, NULL);
|
||||
e_data.shadow_store_cascade_sh = DRW_shader_create_fullscreen(datatoc_shadow_store_frag_glsl, "#define CSM");
|
||||
}
|
||||
|
||||
if (!sldata->lamps) {
|
||||
|
@ -92,23 +89,58 @@ void EEVEE_lights_init(EEVEE_SceneLayerData *sldata)
|
|||
sldata->shadow_ubo = DRW_uniformbuffer_create(shadow_ubo_size, NULL);
|
||||
sldata->shadow_render_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_ShadowRender), NULL);
|
||||
}
|
||||
|
||||
int sh_method = BKE_collection_engine_property_value_get_int(props, "shadow_method");
|
||||
int sh_size = BKE_collection_engine_property_value_get_int(props, "shadow_size");
|
||||
UNUSED_VARS(sh_method);
|
||||
|
||||
EEVEE_LampsInfo *linfo = sldata->lamps;
|
||||
if (linfo->shadow_size != sh_size) {
|
||||
BLI_assert((sh_size > 0) && (sh_size <= 8192));
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool);
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target);
|
||||
|
||||
linfo->shadow_size = sh_size;
|
||||
linfo->shadow_render_data.stored_texel_size = 1.0 / (float)linfo->shadow_size;
|
||||
|
||||
/* Compute adequate size for the cubemap render target.
|
||||
* The 3.0f factor is here to make sure there is no under sampling between
|
||||
* the octahedron mapping and the cubemap. */
|
||||
int new_cube_target_size = (int)ceil(sqrt((float)(sh_size * sh_size) / 6.0f) * 3.0f);
|
||||
|
||||
CLAMP(new_cube_target_size, 1, 4096);
|
||||
|
||||
if (linfo->shadow_cube_target_size != new_cube_target_size) {
|
||||
linfo->shadow_cube_target_size = new_cube_target_size;
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target);
|
||||
linfo->shadow_render_data.cube_texel_size = 1.0 / (float)linfo->shadow_cube_target_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EEVEE_lights_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
||||
{
|
||||
EEVEE_LampsInfo *linfo = sldata->lamps;
|
||||
|
||||
linfo->num_light = linfo->num_cube = linfo->num_map = linfo->num_cascade = 0;
|
||||
linfo->num_light = linfo->num_cube = linfo->num_cascade = linfo->num_shadow = 0;
|
||||
memset(linfo->light_ref, 0, sizeof(linfo->light_ref));
|
||||
memset(linfo->shadow_cube_ref, 0, sizeof(linfo->shadow_cube_ref));
|
||||
memset(linfo->shadow_map_ref, 0, sizeof(linfo->shadow_map_ref));
|
||||
memset(linfo->shadow_cascade_ref, 0, sizeof(linfo->shadow_cascade_ref));
|
||||
|
||||
{
|
||||
psl->shadow_cube_store_pass = DRW_pass_create("Shadow Storage Pass", DRW_STATE_WRITE_COLOR);
|
||||
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_store_sh, psl->shadow_cube_store_pass);
|
||||
DRW_shgroup_uniform_buffer(grp, "shadowCube", &sldata->shadow_color_cube_target);
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_store_cube_sh, psl->shadow_cube_store_pass);
|
||||
DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cube_target);
|
||||
DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
|
||||
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
|
||||
}
|
||||
|
||||
{
|
||||
psl->shadow_cascade_store_pass = DRW_pass_create("Shadow Cascade Storage Pass", DRW_STATE_WRITE_COLOR);
|
||||
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_store_cascade_sh, psl->shadow_cascade_store_pass);
|
||||
DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cascade_target);
|
||||
DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
|
||||
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
|
||||
}
|
||||
|
@ -118,7 +150,7 @@ void EEVEE_lights_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
|||
}
|
||||
|
||||
{
|
||||
psl->shadow_cascade_pass = DRW_pass_create("Shadow Cascade Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
|
||||
psl->shadow_cascade_pass = DRW_pass_create("Shadow Cascade Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
|
||||
}
|
||||
|
||||
/* Reset shadow casters list */
|
||||
|
@ -147,19 +179,19 @@ void EEVEE_lights_cache_add(EEVEE_SceneLayerData *sldata, Object *ob)
|
|||
#if 1 /* TODO Waiting for notified refresh. only on scene change. Else too much perf cost. */
|
||||
if (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) {
|
||||
if (la->type == LA_SUN && linfo->num_cascade < MAX_SHADOW_CASCADE) {
|
||||
#if 0 /* TODO filter cascaded shadow map */
|
||||
led->storage = MEM_mallocN(sizeof(EEVEE_ShadowCascadeData), "EEVEE_ShadowCascadeData");
|
||||
((EEVEE_ShadowCascadeData *)led->storage)->shadow_id = linfo->num_cascade;
|
||||
((EEVEE_ShadowCascadeData *)led->storage)->shadow_id = linfo->num_shadow;
|
||||
linfo->shadow_cascade_ref[linfo->num_cascade] = ob;
|
||||
linfo->num_cascade++;
|
||||
#endif
|
||||
linfo->num_shadow += MAX_CASCADE_NUM;
|
||||
}
|
||||
else if ((la->type == LA_SPOT || la->type == LA_LOCAL || la->type == LA_AREA)
|
||||
&& linfo->num_cube < MAX_SHADOW_CUBE) {
|
||||
led->storage = MEM_mallocN(sizeof(EEVEE_ShadowCubeData), "EEVEE_ShadowCubeData");
|
||||
((EEVEE_ShadowCubeData *)led->storage)->shadow_id = linfo->num_cube;
|
||||
((EEVEE_ShadowCubeData *)led->storage)->shadow_id = linfo->num_shadow;
|
||||
linfo->shadow_cube_ref[linfo->num_cube] = ob;
|
||||
linfo->num_cube++;
|
||||
linfo->num_shadow += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -226,70 +258,58 @@ void EEVEE_lights_cache_shcaster_material_add(
|
|||
void EEVEE_lights_cache_finish(EEVEE_SceneLayerData *sldata)
|
||||
{
|
||||
EEVEE_LampsInfo *linfo = sldata->lamps;
|
||||
DRWTextureFormat shadow_pool_format;
|
||||
|
||||
/* Setup enough layers. */
|
||||
/* Free textures if number mismatch. */
|
||||
if (linfo->num_cube != linfo->cache_num_cube) {
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_cube_pool);
|
||||
if ((linfo->num_shadow != linfo->cache_num_shadow) ||
|
||||
(linfo->num_cube != linfo->cache_num_cube) ||
|
||||
(linfo->num_cascade != linfo->cache_num_cascade))
|
||||
{
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool);
|
||||
linfo->cache_num_cube = linfo->num_cube;
|
||||
linfo->cache_num_cascade = linfo->num_cascade;
|
||||
linfo->cache_num_shadow = linfo->num_shadow;
|
||||
linfo->update_flag |= LIGHT_UPDATE_SHADOW_CUBE;
|
||||
}
|
||||
if (linfo->num_map != linfo->cache_num_map) {
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_map_pool);
|
||||
linfo->cache_num_map = linfo->num_map;
|
||||
}
|
||||
if (linfo->num_cascade != linfo->cache_num_cascade) {
|
||||
DRW_TEXTURE_FREE_SAFE(sldata->shadow_depth_cascade_pool);
|
||||
linfo->cache_num_cascade = linfo->num_cascade;
|
||||
|
||||
/* TODO Variance Shadow Map */
|
||||
shadow_pool_format = DRW_TEX_R_32;
|
||||
|
||||
if (!sldata->shadow_cube_target) {
|
||||
/* TODO render everything on the same 2d render target using clip planes and no Geom Shader. */
|
||||
/* Cubemaps */
|
||||
sldata->shadow_cube_target = DRW_texture_create_cube(linfo->shadow_cube_target_size, DRW_TEX_DEPTH_24, 0, NULL);
|
||||
}
|
||||
|
||||
/* Initialize Textures Arrays first so DRW_framebuffer_init just bind them. */
|
||||
if (!sldata->shadow_depth_cube_target) {
|
||||
/* Render Cubemap */
|
||||
sldata->shadow_depth_cube_target = DRW_texture_create_cube(512, DRW_TEX_DEPTH_24, 0, NULL);
|
||||
sldata->shadow_color_cube_target = DRW_texture_create_cube(512, DRW_TEX_R_32, DRW_TEX_FILTER, NULL);
|
||||
if (sldata->shadow_cube_fb) {
|
||||
DRW_framebuffer_texture_attach(sldata->shadow_cube_fb, sldata->shadow_depth_cube_target, 0, 0);
|
||||
DRW_framebuffer_texture_attach(sldata->shadow_cube_fb, sldata->shadow_color_cube_target, 0, 0);
|
||||
}
|
||||
}
|
||||
if (!sldata->shadow_depth_cube_pool) {
|
||||
/* Cubemap / octahedral map pool */
|
||||
/* TODO Cubemap array */
|
||||
sldata->shadow_depth_cube_pool = DRW_texture_create_2D_array(
|
||||
512, 512, max_ff(1, linfo->num_cube), DRW_TEX_R_16,
|
||||
DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
|
||||
if (sldata->shadow_cube_fb) {
|
||||
DRW_framebuffer_texture_attach(sldata->shadow_cube_fb, sldata->shadow_depth_cube_pool, 0, 0);
|
||||
}
|
||||
}
|
||||
if (!sldata->shadow_depth_map_pool) {
|
||||
sldata->shadow_depth_map_pool = DRW_texture_create_2D_array(
|
||||
512, 512, max_ff(1, linfo->num_map), DRW_TEX_DEPTH_24,
|
||||
DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
|
||||
if (sldata->shadow_map_fb) {
|
||||
DRW_framebuffer_texture_attach(sldata->shadow_map_fb, sldata->shadow_depth_map_pool, 0, 0);
|
||||
}
|
||||
}
|
||||
if (!sldata->shadow_depth_cascade_pool) {
|
||||
sldata->shadow_depth_cascade_pool = DRW_texture_create_2D_array(
|
||||
512, 512, max_ff(1, linfo->num_cascade * MAX_CASCADE_NUM), DRW_TEX_DEPTH_24,
|
||||
DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
|
||||
if (sldata->shadow_cascade_fb) {
|
||||
DRW_framebuffer_texture_attach(sldata->shadow_cascade_fb, sldata->shadow_depth_map_pool, 0, 0);
|
||||
}
|
||||
if (!sldata->shadow_cascade_target) {
|
||||
/* CSM */
|
||||
sldata->shadow_cascade_target = DRW_texture_create_2D_array(
|
||||
linfo->shadow_size, linfo->shadow_size, MAX_CASCADE_NUM, DRW_TEX_DEPTH_24, 0, NULL);
|
||||
}
|
||||
|
||||
DRWFboTexture tex_cube_target[2] = {
|
||||
{&sldata->shadow_depth_cube_target, DRW_TEX_DEPTH_24, 0},
|
||||
{&sldata->shadow_color_cube_target, DRW_TEX_R_16, DRW_TEX_FILTER}};
|
||||
DRW_framebuffer_init(&sldata->shadow_cube_target_fb, &draw_engine_eevee_type, 512, 512, tex_cube_target, 2);
|
||||
/* Initialize Textures Array first so DRW_framebuffer_init just bind them. */
|
||||
if (!sldata->shadow_pool) {
|
||||
/* All shadows fit in this array */
|
||||
sldata->shadow_pool = DRW_texture_create_2D_array(
|
||||
linfo->shadow_size, linfo->shadow_size, max_ff(1, linfo->num_cube + linfo->num_cascade),
|
||||
shadow_pool_format, DRW_TEX_FILTER, NULL);
|
||||
}
|
||||
|
||||
DRWFboTexture tex_cube = {&sldata->shadow_depth_cube_pool, DRW_TEX_R_16, DRW_TEX_FILTER};
|
||||
DRW_framebuffer_init(&sldata->shadow_cube_fb, &draw_engine_eevee_type, 512, 512, &tex_cube, 1);
|
||||
/* Render FB */
|
||||
DRWFboTexture tex_cascade = {&sldata->shadow_cube_target, DRW_TEX_DEPTH_24, 0};
|
||||
DRW_framebuffer_init(&sldata->shadow_target_fb, &draw_engine_eevee_type,
|
||||
linfo->shadow_size, linfo->shadow_size,
|
||||
&tex_cascade, 1);
|
||||
|
||||
DRWFboTexture tex_cascade = {&sldata->shadow_depth_cascade_pool, DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE};
|
||||
DRW_framebuffer_init(&sldata->shadow_cascade_fb, &draw_engine_eevee_type, 512, 512, &tex_cascade, 1);
|
||||
/* Storage FB */
|
||||
DRWFboTexture tex_pool = {&sldata->shadow_pool, shadow_pool_format, DRW_TEX_FILTER};
|
||||
DRW_framebuffer_init(&sldata->shadow_store_fb, &draw_engine_eevee_type,
|
||||
linfo->shadow_size, linfo->shadow_size,
|
||||
&tex_pool, 1);
|
||||
|
||||
/* Restore */
|
||||
DRW_framebuffer_texture_detach(sldata->shadow_cube_target);
|
||||
|
||||
/* Update Lamps UBOs. */
|
||||
EEVEE_lights_update(sldata);
|
||||
|
@ -397,31 +417,6 @@ static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_La
|
|||
evli->shadowid = (float)(evsmp->shadow_id);
|
||||
}
|
||||
|
||||
static void eevee_shadow_map_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
|
||||
{
|
||||
float viewmat[4][4], projmat[4][4];
|
||||
|
||||
EEVEE_ShadowMapData *evsmp = (EEVEE_ShadowMapData *)led->storage;
|
||||
EEVEE_Light *evli = linfo->light_data + evsmp->light_id;
|
||||
EEVEE_ShadowMap *evsh = linfo->shadow_map_data + evsmp->shadow_id;
|
||||
Lamp *la = (Lamp *)ob->data;
|
||||
|
||||
invert_m4_m4(viewmat, ob->obmat);
|
||||
normalize_v3(viewmat[0]);
|
||||
normalize_v3(viewmat[1]);
|
||||
normalize_v3(viewmat[2]);
|
||||
|
||||
float wsize = la->shadow_frustum_size;
|
||||
orthographic_m4(projmat, -wsize, wsize, -wsize, wsize, la->clipsta, la->clipend);
|
||||
|
||||
mul_m4_m4m4(evsmp->viewprojmat, projmat, viewmat);
|
||||
mul_m4_m4m4(evsh->shadowmat, texcomat, evsmp->viewprojmat);
|
||||
|
||||
evsh->bias = 0.005f * la->bias;
|
||||
|
||||
evli->shadowid = (float)(MAX_SHADOW_CUBE + evsmp->shadow_id);
|
||||
}
|
||||
|
||||
#define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
|
||||
|
||||
static void frustum_min_bounding_sphere(const float corners[8][4], float r_center[3], float *r_radius)
|
||||
|
@ -589,10 +584,10 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
|
|||
mul_m4_m4m4(evsh->shadowmat[c], texcomat, evscp->viewprojmat[c]);
|
||||
|
||||
/* TODO modify bias depending on the cascade radius */
|
||||
evsh->bias[c] = 0.005f * la->bias;
|
||||
evsh->bias = 0.005f * la->bias;
|
||||
}
|
||||
|
||||
evli->shadowid = (float)(MAX_SHADOW_CUBE + MAX_SHADOW_MAP + evscp->shadow_id);
|
||||
evli->shadowid = (float)(MAX_SHADOW_CUBE + evscp->shadow_id);
|
||||
}
|
||||
|
||||
/* Used for checking if object is inside the shadow volume. */
|
||||
|
@ -718,11 +713,6 @@ void EEVEE_lights_update(EEVEE_SceneLayerData *sldata)
|
|||
delete_pruned_shadowcaster(led);
|
||||
}
|
||||
|
||||
for (i = 0; (ob = linfo->shadow_map_ref[i]) && (i < MAX_SHADOW_MAP); i++) {
|
||||
EEVEE_LampEngineData *led = EEVEE_lamp_data_get(ob);
|
||||
eevee_shadow_map_setup(ob, linfo, led);
|
||||
}
|
||||
|
||||
for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
|
||||
EEVEE_LampEngineData *led = EEVEE_lamp_data_get(ob);
|
||||
eevee_shadow_cascade_setup(ob, linfo, led);
|
||||
|
@ -738,7 +728,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
|||
EEVEE_LampsInfo *linfo = sldata->lamps;
|
||||
Object *ob;
|
||||
int i;
|
||||
float clear_color[4] = {FLT_MAX, FLT_MAX, FLT_MAX, 0.0f};
|
||||
float clear_col[4] = {FLT_MAX};
|
||||
|
||||
/* Cube Shadow Maps */
|
||||
/* Render each shadow to one layer of the array */
|
||||
|
@ -750,8 +740,10 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
|||
EEVEE_ShadowCubeData *evscd = (EEVEE_ShadowCubeData *)led->storage;
|
||||
EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
|
||||
|
||||
srd->layer = i;
|
||||
srd->exponent = la->bleedexp;
|
||||
srd->shadow_samples_ct = 32.0f;
|
||||
srd->shadow_inv_samples_ct = 1.0f / srd->shadow_samples_ct;
|
||||
srd->clip_near = la->clipsta;
|
||||
srd->clip_far = la->clipend;
|
||||
copy_v3_v3(srd->position, ob->obmat[3]);
|
||||
for (int j = 0; j < 6; j++) {
|
||||
float tmp[4][4];
|
||||
|
@ -762,15 +754,17 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
|||
|
||||
copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
|
||||
}
|
||||
DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
|
||||
DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
|
||||
|
||||
DRW_framebuffer_bind(sldata->shadow_cube_target_fb);
|
||||
DRW_framebuffer_clear(true, true, false, clear_color, 1.0f);
|
||||
DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cube_target, 0, 0);
|
||||
DRW_framebuffer_bind(sldata->shadow_target_fb);
|
||||
DRW_framebuffer_clear(true, true, false, clear_col, 1.0f);
|
||||
/* Render shadow cube */
|
||||
DRW_draw_pass(psl->shadow_cube_pass);
|
||||
|
||||
/* Push it to shadowmap array */
|
||||
DRW_framebuffer_bind(sldata->shadow_cube_fb);
|
||||
DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, i, 0);
|
||||
DRW_framebuffer_bind(sldata->shadow_store_fb);
|
||||
DRW_draw_pass(psl->shadow_cube_store_pass);
|
||||
|
||||
led->need_update = false;
|
||||
|
@ -778,21 +772,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
|||
}
|
||||
linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE;
|
||||
|
||||
#if 0
|
||||
/* Standard Shadow Maps */
|
||||
DRW_framebuffer_bind(fbl->shadow_map_fb);
|
||||
DRW_framebuffer_clear(false, true, false, NULL, 1.0);
|
||||
|
||||
/* Render each shadow to one layer of the array */
|
||||
for (i = 0; (ob = linfo->shadow_map_ref[i]) && (i < MAX_SHADOW_MAP); i++) {
|
||||
EEVEE_LampEngineData *led = EEVEE_lamp_data_get(ob);
|
||||
EEVEE_ShadowMapData *evsmd = (EEVEE_ShadowMapData *)led->storage;
|
||||
|
||||
linfo->layer = i;
|
||||
copy_m4_m4(linfo->shadowmat, evsmd->viewprojmat);
|
||||
DRW_draw_pass(vedata->psl->shadow_pass);
|
||||
}
|
||||
#endif
|
||||
DRW_framebuffer_texture_detach(sldata->shadow_cube_target);
|
||||
|
||||
/* Cascaded Shadow Maps */
|
||||
// DRW_framebuffer_bind(fbl->shadow_cascade_fb);
|
||||
|
@ -817,5 +797,6 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
|||
void EEVEE_lights_free(void)
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(e_data.shadow_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.shadow_store_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.shadow_store_cube_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.shadow_store_cascade_sh);
|
||||
}
|
|
@ -58,7 +58,6 @@
|
|||
"#define MAX_PLANAR " STRINGIFY(MAX_PLANAR) "\n" \
|
||||
"#define MAX_LIGHT " STRINGIFY(MAX_LIGHT) "\n" \
|
||||
"#define MAX_SHADOW_CUBE " STRINGIFY(MAX_SHADOW_CUBE) "\n" \
|
||||
"#define MAX_SHADOW_MAP " STRINGIFY(MAX_SHADOW_MAP) "\n" \
|
||||
"#define MAX_SHADOW_CASCADE " STRINGIFY(MAX_SHADOW_CASCADE) "\n" \
|
||||
"#define MAX_CASCADE_NUM " STRINGIFY(MAX_CASCADE_NUM) "\n" \
|
||||
SHADER_IRRADIANCE
|
||||
|
@ -370,8 +369,7 @@ static void add_standard_uniforms(
|
|||
DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool);
|
||||
DRW_shgroup_uniform_buffer(shgrp, "probePlanars", &vedata->txl->planar_pool);
|
||||
DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool);
|
||||
DRW_shgroup_uniform_buffer(shgrp, "shadowCubes", &sldata->shadow_depth_cube_pool);
|
||||
DRW_shgroup_uniform_buffer(shgrp, "shadowCascades", &sldata->shadow_depth_cascade_pool);
|
||||
DRW_shgroup_uniform_buffer(shgrp, "shadowTexture", &sldata->shadow_pool);
|
||||
DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1);
|
||||
DRW_shgroup_uniform_vec4(shgrp, "aoParameters[0]", &vedata->stl->effects->ao_dist, 2);
|
||||
if (refract_depth != NULL) {
|
||||
|
|
|
@ -36,7 +36,6 @@ extern struct DrawEngineType draw_engine_eevee_type;
|
|||
#define MAX_PLANAR 16 /* TODO : find size by dividing UBO max size by grid data size */
|
||||
#define MAX_LIGHT 128 /* TODO : find size by dividing UBO max size by light data size */
|
||||
#define MAX_SHADOW_CUBE 42 /* TODO : Make this depends on GL_MAX_ARRAY_TEXTURE_LAYERS */
|
||||
#define MAX_SHADOW_MAP 64
|
||||
#define MAX_SHADOW_CASCADE 8
|
||||
#define MAX_CASCADE_NUM 4
|
||||
#define MAX_BLOOM_STEP 16
|
||||
|
@ -78,12 +77,19 @@ enum {
|
|||
VAR_MAT_REFRACT = (1 << 12),
|
||||
};
|
||||
|
||||
/* Shadow Technique */
|
||||
enum {
|
||||
SHADOW_ESM = 1,
|
||||
SHADOW_VSM = 2,
|
||||
};
|
||||
|
||||
typedef struct EEVEE_PassList {
|
||||
/* Shadows */
|
||||
struct DRWPass *shadow_pass;
|
||||
struct DRWPass *shadow_cube_pass;
|
||||
struct DRWPass *shadow_cube_store_pass;
|
||||
struct DRWPass *shadow_cascade_pass;
|
||||
struct DRWPass *shadow_cascade_store_pass;
|
||||
|
||||
/* Probes */
|
||||
struct DRWPass *probe_background;
|
||||
|
@ -206,24 +212,22 @@ typedef struct EEVEE_ShadowCube {
|
|||
float near, far, bias, exp;
|
||||
} EEVEE_ShadowCube;
|
||||
|
||||
typedef struct EEVEE_ShadowMap {
|
||||
float shadowmat[4][4]; /* World->Lamp->NDC->Tex : used for sampling the shadow map. */
|
||||
float near, far, bias, pad;
|
||||
} EEVEE_ShadowMap;
|
||||
|
||||
typedef struct EEVEE_ShadowCascade {
|
||||
float shadowmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC->Tex : used for sampling the shadow map. */
|
||||
float split[4];
|
||||
float bias[4];
|
||||
float near, far, bias, pad;
|
||||
} EEVEE_ShadowCascade;
|
||||
|
||||
typedef struct EEVEE_ShadowRender {
|
||||
float shadowmat[6][4][4]; /* World->Lamp->NDC : used to render the shadow map. 6 frustrum for cubemap shadow */
|
||||
float shadowmat[6][4][4]; /* World->Lamp->NDC : used to render the shadow map. 6 frustum for cubemap shadow */
|
||||
float viewmat[6][4][4]; /* World->Lamp : used to render the shadow map. 6 viewmat for cubemap shadow */
|
||||
float position[3];
|
||||
float pad;
|
||||
int layer;
|
||||
float exponent;
|
||||
float position[3], pad;
|
||||
float cube_texel_size;
|
||||
float stored_texel_size;
|
||||
float clip_near;
|
||||
float clip_far;
|
||||
float shadow_samples_ct;
|
||||
float shadow_inv_samples_ct;
|
||||
} EEVEE_ShadowRender;
|
||||
|
||||
/* ************ VOLUME DATA ************ */
|
||||
|
@ -237,20 +241,20 @@ typedef struct EEVEE_VolumetricsInfo {
|
|||
typedef struct EEVEE_LampsInfo {
|
||||
int num_light, cache_num_light;
|
||||
int num_cube, cache_num_cube;
|
||||
int num_map, cache_num_map;
|
||||
int num_cascade, cache_num_cascade;
|
||||
int num_shadow, cache_num_shadow;
|
||||
int update_flag;
|
||||
int shadow_size, shadow_method;
|
||||
int shadow_cube_target_size;
|
||||
/* List of lights in the scene. */
|
||||
/* XXX This is fragile, can get out of sync quickly. */
|
||||
struct Object *light_ref[MAX_LIGHT];
|
||||
struct Object *shadow_cube_ref[MAX_SHADOW_CUBE];
|
||||
struct Object *shadow_map_ref[MAX_SHADOW_MAP];
|
||||
struct Object *shadow_cascade_ref[MAX_SHADOW_CASCADE];
|
||||
/* UBO Storage : data used by UBO */
|
||||
struct EEVEE_Light light_data[MAX_LIGHT];
|
||||
struct EEVEE_ShadowRender shadow_render_data;
|
||||
struct EEVEE_ShadowCube shadow_cube_data[MAX_SHADOW_CUBE];
|
||||
struct EEVEE_ShadowMap shadow_map_data[MAX_SHADOW_MAP];
|
||||
struct EEVEE_ShadowCascade shadow_cascade_data[MAX_SHADOW_CASCADE];
|
||||
} EEVEE_LampsInfo;
|
||||
|
||||
|
@ -401,17 +405,14 @@ typedef struct EEVEE_SceneLayerData {
|
|||
struct GPUUniformBuffer *light_ubo;
|
||||
struct GPUUniformBuffer *shadow_ubo;
|
||||
struct GPUUniformBuffer *shadow_render_ubo;
|
||||
struct GPUUniformBuffer *shadow_samples_ubo;
|
||||
|
||||
struct GPUFrameBuffer *shadow_cube_target_fb;
|
||||
struct GPUFrameBuffer *shadow_cube_fb;
|
||||
struct GPUFrameBuffer *shadow_map_fb;
|
||||
struct GPUFrameBuffer *shadow_cascade_fb;
|
||||
struct GPUFrameBuffer *shadow_target_fb;
|
||||
struct GPUFrameBuffer *shadow_store_fb;
|
||||
|
||||
struct GPUTexture *shadow_depth_cube_target;
|
||||
struct GPUTexture *shadow_color_cube_target;
|
||||
struct GPUTexture *shadow_depth_cube_pool;
|
||||
struct GPUTexture *shadow_depth_map_pool;
|
||||
struct GPUTexture *shadow_depth_cascade_pool;
|
||||
struct GPUTexture *shadow_cube_target;
|
||||
struct GPUTexture *shadow_cascade_target;
|
||||
struct GPUTexture *shadow_pool;
|
||||
|
||||
struct ListBase shadow_casters; /* Shadow casters gathered during cache iteration */
|
||||
|
||||
|
|
|
@ -19,8 +19,12 @@ layout(std140) uniform shadow_render_block {
|
|||
mat4 ShadowMatrix[6];
|
||||
mat4 FaceViewMatrix[6];
|
||||
vec4 lampPosition;
|
||||
int layer;
|
||||
float exponent;
|
||||
float cubeTexelSize;
|
||||
float storedTexelSize;
|
||||
float nearClip;
|
||||
float farClip;
|
||||
float shadowSampleCount;
|
||||
float shadowInvSampleCount;
|
||||
};
|
||||
|
||||
flat in int shFace; /* Shadow layer we are rendering to. */
|
||||
|
@ -72,23 +76,6 @@ struct ShadowCubeData {
|
|||
vec4 near_far_bias_exp;
|
||||
};
|
||||
|
||||
/* convenience aliases */
|
||||
#define sh_cube_near near_far_bias_exp.x
|
||||
#define sh_cube_far near_far_bias_exp.y
|
||||
#define sh_cube_bias near_far_bias_exp.z
|
||||
#define sh_cube_exp near_far_bias_exp.w
|
||||
|
||||
|
||||
struct ShadowMapData {
|
||||
mat4 shadowmat;
|
||||
vec4 near_far_bias;
|
||||
};
|
||||
|
||||
/* convenience aliases */
|
||||
#define sh_map_near near_far_bias.x
|
||||
#define sh_map_far near_far_bias.y
|
||||
#define sh_map_bias near_far_bias.z
|
||||
|
||||
#ifndef MAX_CASCADE_NUM
|
||||
#define MAX_CASCADE_NUM 4
|
||||
#endif
|
||||
|
@ -97,9 +84,15 @@ struct ShadowCascadeData {
|
|||
mat4 shadowmat[MAX_CASCADE_NUM];
|
||||
/* arrays of float are not aligned so use vec4 */
|
||||
vec4 split_distances;
|
||||
vec4 bias;
|
||||
vec4 near_far_bias_exp;
|
||||
};
|
||||
|
||||
/* convenience aliases */
|
||||
#define sh_cube_near near_far_bias_exp.x
|
||||
#define sh_cube_far near_far_bias_exp.y
|
||||
#define sh_cube_bias near_far_bias_exp.z
|
||||
#define sh_cube_exp near_far_bias_exp.w
|
||||
|
||||
/* ------- Convenience functions --------- */
|
||||
|
||||
vec3 mul(mat3 m, vec3 v) { return m * v; }
|
||||
|
@ -114,6 +107,7 @@ vec3 project_point(mat4 m, vec3 v) {
|
|||
float min_v2(vec2 v) { return min(v.x, v.y); }
|
||||
float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); }
|
||||
float max_v2(vec2 v) { return max(v.x, v.y); }
|
||||
float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); }
|
||||
|
||||
float saturate(float a) { return clamp(a, 0.0, 1.0); }
|
||||
vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); }
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
|
||||
uniform sampler2DArray shadowCubes;
|
||||
uniform sampler2DArrayShadow shadowCascades;
|
||||
uniform sampler2DArray shadowTexture;
|
||||
|
||||
layout(std140) uniform shadow_block {
|
||||
ShadowCubeData shadows_cube_data[MAX_SHADOW_CUBE];
|
||||
ShadowMapData shadows_map_data[MAX_SHADOW_MAP];
|
||||
ShadowCascadeData shadows_cascade_data[MAX_SHADOW_CASCADE];
|
||||
};
|
||||
|
||||
|
@ -26,23 +24,25 @@ float shadow_cubemap(float shid, vec4 l_vector)
|
|||
vec3 cubevec = -l_vector.xyz / l_vector.w;
|
||||
float dist = l_vector.w - scd.sh_cube_bias;
|
||||
|
||||
float z = texture_octahedron(shadowCubes, vec4(cubevec, shid)).r;
|
||||
float z = texture_octahedron(shadowTexture, vec4(cubevec, shid)).r;
|
||||
|
||||
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);
|
||||
|
||||
return esm_test;
|
||||
}
|
||||
|
||||
float shadow_cascade(float shid, vec3 W)
|
||||
{
|
||||
return 1.0;
|
||||
#if 0
|
||||
/* Shadow Cascade */
|
||||
shid -= (MAX_SHADOW_CUBE + MAX_SHADOW_MAP);
|
||||
shid -= MAX_SHADOW_CUBE;
|
||||
ShadowCascadeData smd = shadows_cascade_data[int(shid)];
|
||||
|
||||
/* Finding Cascade index */
|
||||
vec4 z = vec4(-dot(cameraPos - W, cameraForward));
|
||||
vec4 comp = step(z, smd.split_distances);
|
||||
vec4 view_z = vec4(-dot(cameraPos - W, cameraForward));
|
||||
vec4 comp = step(view_z, smd.split_distances);
|
||||
float cascade = dot(comp, comp);
|
||||
mat4 shadowmat;
|
||||
float bias;
|
||||
|
@ -68,10 +68,15 @@ float shadow_cascade(float shid, vec3 W)
|
|||
}
|
||||
|
||||
vec4 shpos = shadowmat * vec4(W, 1.0);
|
||||
shpos.z -= bias * shpos.w;
|
||||
float dist = shpos.z - bias * shpos.w;
|
||||
shpos.xyz /= shpos.w;
|
||||
|
||||
return texture(shadowCascades, vec4(shpos.xy, shid * float(MAX_CASCADE_NUM) + cascade, shpos.z));
|
||||
float z = texture(shadowTexture, vec4(shpos.xy, shid * float(MAX_CASCADE_NUM) + cascade, shpos.z)).r;
|
||||
|
||||
float esm_test = saturate(exp(smd.sh_cube_exp * (z - dist)));
|
||||
|
||||
return esm_test;
|
||||
#endif
|
||||
}
|
||||
|
||||
float light_visibility(LightData ld, vec3 W, vec4 l_vector)
|
||||
|
@ -97,7 +102,7 @@ float light_visibility(LightData ld, vec3 W, vec4 l_vector)
|
|||
|
||||
#if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW)
|
||||
/* shadowing */
|
||||
if (ld.l_shadowid >= (MAX_SHADOW_MAP + MAX_SHADOW_CUBE)) {
|
||||
if (ld.l_shadowid >= MAX_SHADOW_CUBE) {
|
||||
vis *= shadow_cascade(ld.l_shadowid, W);
|
||||
}
|
||||
else if (ld.l_shadowid >= 0.0) {
|
||||
|
|
|
@ -62,10 +62,6 @@ float hashed_alpha_threshold(vec3 co)
|
|||
uniform float alphaThreshold;
|
||||
#endif
|
||||
|
||||
#ifdef SHADOW_SHADER
|
||||
out vec4 FragColor;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
/* For now do nothing.
|
||||
|
@ -86,9 +82,4 @@ void main()
|
|||
discard;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SHADOW_SHADER
|
||||
float dist = distance(lampPosition.xyz, worldPosition.xyz);
|
||||
FragColor = vec4(dist, 0.0, 0.0, 1.0);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,17 +1,4 @@
|
|||
|
||||
layout(std140) uniform shadow_render_block {
|
||||
mat4 ShadowMatrix[6];
|
||||
mat4 FaceViewMatrix[6];
|
||||
vec4 lampPosition;
|
||||
int layer;
|
||||
float exponent;
|
||||
};
|
||||
|
||||
in vec3 worldPosition;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
float dist = distance(lampPosition.xyz, worldPosition.xyz);
|
||||
FragColor = vec4(dist, 0.0, 0.0, 1.0);
|
||||
/* Do nothing */
|
||||
}
|
||||
|
|
|
@ -3,8 +3,12 @@ layout(std140) uniform shadow_render_block {
|
|||
mat4 ShadowMatrix[6];
|
||||
mat4 FaceViewMatrix[6];
|
||||
vec4 lampPosition;
|
||||
int layer;
|
||||
float exponent;
|
||||
float cubeTexelSize;
|
||||
float storedTexelSize;
|
||||
float nearClip;
|
||||
float farClip;
|
||||
float shadowSampleCount;
|
||||
float shadowInvSampleCount;
|
||||
};
|
||||
|
||||
layout(triangles) in;
|
||||
|
|
|
@ -3,11 +3,19 @@ layout(std140) uniform shadow_render_block {
|
|||
mat4 ShadowMatrix[6];
|
||||
mat4 FaceViewMatrix[6];
|
||||
vec4 lampPosition;
|
||||
int layer;
|
||||
float exponent;
|
||||
float cubeTexelSize;
|
||||
float storedTexelSize;
|
||||
float nearClip;
|
||||
float farClip;
|
||||
float shadowSampleCount;
|
||||
float shadowInvSampleCount;
|
||||
};
|
||||
|
||||
uniform samplerCube shadowCube;
|
||||
#ifdef CSM
|
||||
uniform sampler2DArray shadowTexture;
|
||||
#else
|
||||
uniform samplerCube shadowTexture;
|
||||
#endif
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
|
@ -25,35 +33,31 @@ vec3 octahedral_to_cubemap_proj(vec2 co)
|
|||
return v;
|
||||
}
|
||||
|
||||
void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B)
|
||||
void make_orthonormal_basis(vec3 N, float rot, out vec3 T, out vec3 B)
|
||||
{
|
||||
vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0,0.0,1.0) : vec3(1.0,0.0,0.0);
|
||||
T = normalize( cross(UpVector, N) );
|
||||
B = cross(N, T);
|
||||
vec3 UpVector = (abs(N.z) < max(abs(N.x), abs(N.y))) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 nT = normalize(cross(UpVector, N));
|
||||
vec3 nB = cross(N, nT);
|
||||
|
||||
/* Rotate tangent space */
|
||||
vec2 dir = vec2(cos(rot * 3.1415 * 2.0), sin(rot * 3.1415 * 2.0));
|
||||
T = dir.x * nT + dir.y * nB;
|
||||
B = -dir.y * nT + dir.x * nB;
|
||||
}
|
||||
|
||||
#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),
|
||||
float linear_depth(float z)
|
||||
{
|
||||
return (nearClip * farClip) / (z * (nearClip - farClip) + farClip);
|
||||
}
|
||||
|
||||
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)
|
||||
);
|
||||
float get_cube_radial_distance(vec3 cubevec)
|
||||
{
|
||||
float zdepth = texture(shadowTexture, cubevec).r;
|
||||
float linear_zdepth = linear_depth(zdepth);
|
||||
cubevec = normalize(abs(cubevec));
|
||||
float cos_vec = max(cubevec.x, max(cubevec.y, cubevec.z));
|
||||
return linear_zdepth / cos_vec;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
@ -61,14 +65,66 @@ float ln_space_prefilter(float w0, float x, float w1, float y)
|
|||
return x + log(w0 + w1 * exp(y - x));
|
||||
}
|
||||
|
||||
void main() {
|
||||
const vec2 texelSize = vec2(1.0 / 512.0);
|
||||
const int SAMPLE_NUM = 32;
|
||||
const float INV_SAMPLE_NUM = 1.0 / float(SAMPLE_NUM);
|
||||
const vec2 poisson[32] = vec2[32](
|
||||
vec2(-0.31889129888, 0.945170187163),
|
||||
vec2(0.0291070069348, 0.993645382622),
|
||||
vec2(0.453968568675, 0.882119488776),
|
||||
vec2(-0.59142811398, 0.775098624552),
|
||||
vec2(0.0672147039953, 0.677233646792),
|
||||
vec2(0.632546991242, 0.60080388224),
|
||||
vec2(-0.846282545004, 0.478266943968),
|
||||
vec2(-0.304563967348, 0.550414788876),
|
||||
vec2(0.343951542639, 0.482122717676),
|
||||
vec2(0.903371461134, 0.419225918868),
|
||||
vec2(-0.566433506581, 0.326544955645),
|
||||
vec2(-0.0174468029403, 0.345927250589),
|
||||
vec2(-0.970838848328, 0.131541221423),
|
||||
vec2(-0.317404956404, 0.102175571059),
|
||||
vec2(0.309107085158, 0.136502232088),
|
||||
vec2(0.67009683403, 0.198922062526),
|
||||
vec2(-0.62544683989, -0.0237682928336),
|
||||
vec2(0.0, 0.0),
|
||||
vec2(0.260779995092, -0.192490308513),
|
||||
vec2(0.555635503398, -0.0918935341973),
|
||||
vec2(0.989587880961, -0.03629312269),
|
||||
vec2(-0.93440130633, -0.213478602005),
|
||||
vec2(-0.615716455579, -0.335329659339),
|
||||
vec2(0.813589336772, -0.292544036149),
|
||||
vec2(-0.821106257666, -0.568279197395),
|
||||
vec2(-0.298092257627, -0.457929494012),
|
||||
vec2(0.263233114326, -0.515552889911),
|
||||
vec2(-0.0311374378304, -0.643310533036),
|
||||
vec2(0.785838482787, -0.615972502555),
|
||||
vec2(-0.444079211316, -0.836548440017),
|
||||
vec2(-0.0253421088433, -0.96112294526),
|
||||
vec2(0.350411908643, -0.89783206142)
|
||||
);
|
||||
|
||||
vec2 uvs = gl_FragCoord.xy * texelSize;
|
||||
float wang_hash_noise(uint s)
|
||||
{
|
||||
uint seed = (uint(gl_FragCoord.x) * 1664525u + uint(gl_FragCoord.y)) + s;
|
||||
|
||||
seed = (seed ^ 61u) ^ (seed >> 16u);
|
||||
seed *= 9u;
|
||||
seed = seed ^ (seed >> 4u);
|
||||
seed *= 0x27d4eb2du;
|
||||
seed = seed ^ (seed >> 15u);
|
||||
|
||||
float value = float(seed);
|
||||
value *= 1.0 / 4294967296.0;
|
||||
return fract(value);
|
||||
}
|
||||
|
||||
#define ESM
|
||||
|
||||
void main() {
|
||||
vec2 uvs = gl_FragCoord.xy * storedTexelSize;
|
||||
|
||||
/* add a 2 pixel border to ensure filtering is correct */
|
||||
uvs.xy *= 1.0 + texelSize * 2.0;
|
||||
uvs.xy -= texelSize;
|
||||
uvs.xy *= 1.0 + storedTexelSize * 2.0;
|
||||
uvs.xy -= storedTexelSize;
|
||||
|
||||
float pattern = 1.0;
|
||||
|
||||
|
@ -86,28 +142,30 @@ void main() {
|
|||
/* get cubemap vector */
|
||||
vec3 cubevec = octahedral_to_cubemap_proj(uvs.xy);
|
||||
|
||||
/* TODO Can be optimized by groupping fetches
|
||||
* and by converting to radial distance beforehand. */
|
||||
#if defined(ESM)
|
||||
vec3 T, B;
|
||||
make_orthonormal_basis(cubevec, T, B);
|
||||
make_orthonormal_basis(cubevec, wang_hash_noise(0u), T, B);
|
||||
|
||||
T *= 0.01;
|
||||
B *= 0.01;
|
||||
|
||||
/* get cubemap shadow value */
|
||||
const float blur_radius = 5.0 / 512.0; /* Totally arbitrary */
|
||||
const float weight = 1.0 / float(NUM_SAMPLE);
|
||||
float accum = 0.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;
|
||||
float depth1 = get_cube_radial_distance(cubevec + poisson[0].x * T + poisson[0].y * B);
|
||||
float depth2 = get_cube_radial_distance(cubevec + poisson[1].x * T + poisson[1].y * B);
|
||||
accum = ln_space_prefilter(INV_SAMPLE_NUM, depth1, INV_SAMPLE_NUM, depth2);
|
||||
|
||||
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);
|
||||
for (int i = 2; i < SAMPLE_NUM; ++i) {
|
||||
depth1 = get_cube_radial_distance(cubevec + poisson[i].x * T + poisson[i].y * B);
|
||||
accum = ln_space_prefilter(1.0, accum, INV_SAMPLE_NUM, depth1);
|
||||
}
|
||||
|
||||
FragColor = vec4(accum, accum, accum, 1.0);
|
||||
FragColor = vec4(accum);
|
||||
|
||||
#else /* PCF (no prefilter) */
|
||||
FragColor = vec4(get_cube_radial_distance(cubevec));
|
||||
#endif
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
|
||||
layout(std140) uniform shadow_render_block {
|
||||
mat4 ShadowMatrix[6];
|
||||
mat4 FaceViewMatrix[6];
|
||||
vec4 lampPosition;
|
||||
int layer;
|
||||
float exponent;
|
||||
};
|
||||
|
||||
layout(triangles) in;
|
||||
layout(triangle_strip, max_vertices=3) out;
|
||||
|
||||
in vec4 vPos[];
|
||||
|
||||
void main() {
|
||||
gl_Layer = layer;
|
||||
|
||||
for (int v = 0; v < 3; ++v) {
|
||||
gl_Position = vPos[v];
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
EndPrimitive();
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
in vec3 pos;
|
||||
|
||||
out vec4 vPos;
|
||||
|
||||
void main() {
|
||||
vPos = vec4(pos, 1.0);
|
||||
}
|
|
@ -2222,7 +2222,9 @@ static GPUTextureFormat convert_tex_format(
|
|||
case DRW_TEX_RGBA_8: *r_channels = 4; return GPU_RGBA8;
|
||||
case DRW_TEX_RGBA_16: *r_channels = 4; return GPU_RGBA16F;
|
||||
case DRW_TEX_RGBA_32: *r_channels = 4; return GPU_RGBA32F;
|
||||
case DRW_TEX_DEPTH_16: *r_channels = 1; return GPU_DEPTH_COMPONENT16;
|
||||
case DRW_TEX_DEPTH_24: *r_channels = 1; return GPU_DEPTH_COMPONENT24;
|
||||
case DRW_TEX_DEPTH_32: *r_channels = 1; return GPU_DEPTH_COMPONENT32F;
|
||||
case DRW_TEX_RGB_11_11_10: *r_channels = 3; return GPU_R11F_G11F_B10F;
|
||||
default:
|
||||
BLI_assert(false && "Texture format unsupported as render target!");
|
||||
|
|
Loading…
Reference in New Issue