Eevee: Start Implementation of Cascaded Shadow Maps
This commit is contained in:
parent
b386828671
commit
3d17ece539
|
@ -316,6 +316,18 @@ static DRWShadingGroup *eevee_cube_shadow_shgroup(EEVEE_PassList *psl, EEVEE_Sto
|
|||
return grp;
|
||||
}
|
||||
|
||||
static DRWShadingGroup *eevee_cascade_shadow_shgroup(EEVEE_PassList *psl, EEVEE_StorageList *stl, struct Batch *geom, float (*obmat)[4])
|
||||
{
|
||||
DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cascade_pass, geom);
|
||||
DRW_shgroup_uniform_block(grp, "shadow_render_block", stl->shadow_render_ubo, 0);
|
||||
DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
|
||||
|
||||
for (int i = 0; i < MAX_CASCADE_NUM; ++i)
|
||||
DRW_shgroup_dynamic_call_add_empty(grp);
|
||||
|
||||
return grp;
|
||||
}
|
||||
|
||||
static void EEVEE_cache_init(void *vedata)
|
||||
{
|
||||
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
|
||||
|
@ -331,6 +343,10 @@ static void EEVEE_cache_init(void *vedata)
|
|||
psl->shadow_cube_pass = DRW_pass_create("Shadow Cube Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
|
||||
}
|
||||
|
||||
{
|
||||
psl->shadow_cascade_pass = DRW_pass_create("Shadow Cascade Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
|
||||
}
|
||||
|
||||
{
|
||||
// psl->shadow_pass = DRW_pass_create("Shadow Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
|
||||
// stl->g_data->shadow_shgrp = DRW_shgroup_create(e_data.shadow_sh, psl->shadow_pass);
|
||||
|
@ -430,6 +446,7 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
|
|||
|
||||
DRW_shgroup_call_add(stl->g_data->default_lit_grp, geom, ob->obmat);
|
||||
// DRW_shgroup_call_add(stl->g_data->shadow_shgrp, geom, ob->obmat);
|
||||
eevee_cascade_shadow_shgroup(psl, stl, geom, ob->obmat);
|
||||
eevee_cube_shadow_shgroup(psl, stl, geom, ob->obmat);
|
||||
}
|
||||
else if (ob->type == OB_LAMP) {
|
||||
|
@ -448,6 +465,7 @@ static void EEVEE_cache_finish(void *vedata)
|
|||
/* Shadows binding */
|
||||
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "shadowMaps", txl->shadow_depth_map_pool, 4);
|
||||
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "shadowCubes", txl->shadow_depth_cube_pool, 5);
|
||||
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "shadowCascades", txl->shadow_depth_cascade_pool, 6);
|
||||
}
|
||||
|
||||
static void EEVEE_draw_scene(void *vedata)
|
||||
|
|
|
@ -90,11 +90,11 @@ void EEVEE_lights_cache_add(EEVEE_StorageList *stl, Object *ob)
|
|||
DRW_lamp_engine_data_free((void *)led);
|
||||
|
||||
if (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) {
|
||||
if (la->type == LA_SUN && linfo->num_map < MAX_SHADOW_MAP) {
|
||||
led->sto = MEM_mallocN(sizeof(EEVEE_ShadowMapData), "EEVEE_ShadowMapData");
|
||||
((EEVEE_ShadowMapData *)led->sto)->shadow_id = linfo->num_map;
|
||||
linfo->shadow_map_ref[linfo->num_map] = ob;
|
||||
linfo->num_map++;
|
||||
if (la->type == LA_SUN && linfo->num_cascade < MAX_SHADOW_CASCADE) {
|
||||
led->sto = MEM_mallocN(sizeof(EEVEE_ShadowCascadeData), "EEVEE_ShadowCascadeData");
|
||||
((EEVEE_ShadowCascadeData *)led->sto)->shadow_id = linfo->num_cascade;
|
||||
linfo->shadow_cascade_ref[linfo->num_cascade] = ob;
|
||||
linfo->num_cascade++;
|
||||
}
|
||||
else if ((la->type == LA_SPOT || la->type == LA_LOCAL || la->type == LA_AREA)
|
||||
&& linfo->num_cube < MAX_SHADOW_CUBE) {
|
||||
|
@ -150,7 +150,7 @@ void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, E
|
|||
DRW_framebuffer_texture_attach(fbl->shadow_map_fb, txl->shadow_depth_map_pool, 0, 0);
|
||||
}
|
||||
if (!txl->shadow_depth_cascade_pool) {
|
||||
txl->shadow_depth_cascade_pool = DRW_texture_create_2D_array(512, 512, MAX2(1, linfo->num_cascade), DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
|
||||
txl->shadow_depth_cascade_pool = DRW_texture_create_2D_array(512, 512, MAX2(1, linfo->num_cascade * MAX_CASCADE_NUM), DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
|
||||
if (fbl->shadow_cascade_fb)
|
||||
DRW_framebuffer_texture_attach(fbl->shadow_cascade_fb, txl->shadow_depth_map_pool, 0, 0);
|
||||
}
|
||||
|
@ -293,6 +293,83 @@ static void eevee_shadow_map_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_Lam
|
|||
evli->shadowid = (float)(MAX_SHADOW_CUBE + evsmp->shadow_id);
|
||||
}
|
||||
|
||||
#define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
|
||||
|
||||
static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
|
||||
{
|
||||
/* Camera Matrices */
|
||||
float persmat[4][4], persinv[4][4];
|
||||
/* Lamps Matrices */
|
||||
float viewmat[4][4], projmat[4][4];
|
||||
float minvec[3], maxvec[3];
|
||||
int cascade_ct = MAX_CASCADE_NUM;
|
||||
|
||||
EEVEE_ShadowCascadeData *evscp = (EEVEE_ShadowCascadeData *)led->sto;
|
||||
EEVEE_Light *evli = linfo->light_data + evscp->light_id;
|
||||
EEVEE_ShadowCascade *evsh = linfo->shadow_cascade_data + evscp->shadow_id;
|
||||
Lamp *la = (Lamp *)ob->data;
|
||||
|
||||
/* The technique consists into splitting
|
||||
* the view frustum into several sub-frustum
|
||||
* that are individually receiving one shadow map */
|
||||
|
||||
/* For each cascade */
|
||||
for (int c = 0; c < cascade_ct; ++c) {
|
||||
float splitnear = LERP(((float)(c) / cascade_ct), -1.0f, 1.0f);
|
||||
float splitfar = LERP(((float)(c + 1) / cascade_ct), -1.0f, 1.0f);
|
||||
|
||||
/* Given 8 frustrum corners */
|
||||
float corners[8][4] = {
|
||||
/* Far Cap */
|
||||
{-1.0f, -1.0f, splitfar, 1.0f},
|
||||
{ 1.0f, -1.0f, splitfar, 1.0f},
|
||||
{-1.0f, 1.0f, splitfar, 1.0f},
|
||||
{ 1.0f, 1.0f, splitfar, 1.0f},
|
||||
/* Near Cap */
|
||||
{-1.0f, -1.0f, splitnear, 1.0f},
|
||||
{ 1.0f, -1.0f, splitnear, 1.0f},
|
||||
{-1.0f, 1.0f, splitnear, 1.0f},
|
||||
{ 1.0f, 1.0f, splitnear, 1.0f}
|
||||
};
|
||||
|
||||
/* Transform them into world space */
|
||||
DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
|
||||
invert_m4_m4(persinv, persmat);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
mul_m4_v4(persinv, corners[i]);
|
||||
mul_v3_fl(corners[i], 1.0f / corners[i][3]);
|
||||
corners[i][3] = 1.0f;
|
||||
}
|
||||
|
||||
/* Project them into light space */
|
||||
invert_m4_m4(viewmat, ob->obmat);
|
||||
normalize_v3(viewmat[0]);
|
||||
normalize_v3(viewmat[1]);
|
||||
normalize_v3(viewmat[2]);
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
mul_m4_v4(viewmat, corners[i]);
|
||||
}
|
||||
|
||||
/* compute the minimum bounding box */
|
||||
INIT_MINMAX(minvec, maxvec);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
minmax_v3v3_v3(minvec, maxvec, corners[i]);
|
||||
}
|
||||
|
||||
/* expand the bounding box to cover light range */
|
||||
orthographic_m4(projmat, minvec[0], maxvec[0], minvec[1], maxvec[1], la->clipsta, la->clipend);
|
||||
|
||||
mul_m4_m4m4(evscp->viewprojmat[c], projmat, viewmat);
|
||||
mul_m4_m4m4(evsh->shadowmat[c], texcomat, evscp->viewprojmat[c]);
|
||||
}
|
||||
|
||||
evsh->bias = 0.005f * la->bias;
|
||||
evsh->count = (float)cascade_ct;
|
||||
|
||||
evli->shadowid = (float)(MAX_SHADOW_CUBE + MAX_SHADOW_MAP + evscp->shadow_id);
|
||||
}
|
||||
|
||||
void EEVEE_lights_update(EEVEE_StorageList *stl)
|
||||
{
|
||||
EEVEE_LampsInfo *linfo = stl->lamps;
|
||||
|
@ -314,10 +391,10 @@ void EEVEE_lights_update(EEVEE_StorageList *stl)
|
|||
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_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
|
||||
// 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_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
|
||||
eevee_shadow_cascade_setup(ob, linfo, led);
|
||||
}
|
||||
|
||||
DRW_uniformbuffer_update(stl->light_ubo, &linfo->light_data);
|
||||
DRW_uniformbuffer_update(stl->shadow_ubo, &linfo->shadow_cube_data); /* Update all data at once */
|
||||
|
@ -355,19 +432,38 @@ void EEVEE_draw_shadows(EEVEE_Data *vedata)
|
|||
DRW_draw_pass(psl->shadow_cube_pass);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Standard Shadow Maps */
|
||||
// DRW_framebuffer_bind(fbl->shadow_map_fb);
|
||||
// DRW_framebuffer_clear(false, true, false, NULL, 1.0);
|
||||
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_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
|
||||
// EEVEE_ShadowMapData *evsmd = (EEVEE_ShadowMapData *)led->sto;
|
||||
/* 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_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
|
||||
EEVEE_ShadowMapData *evsmd = (EEVEE_ShadowMapData *)led->sto;
|
||||
|
||||
// linfo->layer = i;
|
||||
// copy_m4_m4(linfo->shadowmat, evsmd->viewprojmat);
|
||||
// DRW_draw_pass(vedata->psl->shadow_pass);
|
||||
// }
|
||||
linfo->layer = i;
|
||||
copy_m4_m4(linfo->shadowmat, evsmd->viewprojmat);
|
||||
DRW_draw_pass(vedata->psl->shadow_pass);
|
||||
}
|
||||
#endif
|
||||
|
||||
// DRW_framebuffer_bind(e_data.shadow_cascade_fb);
|
||||
/* Cascaded Shadow Maps */
|
||||
DRW_framebuffer_bind(fbl->shadow_cascade_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_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
|
||||
EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
|
||||
EEVEE_ShadowCascadeData *evscd = (EEVEE_ShadowCascadeData *)led->sto;
|
||||
EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
|
||||
|
||||
srd->layer = i;
|
||||
for (int j = 0; j < MAX_CASCADE_NUM; ++j) {
|
||||
copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
|
||||
}
|
||||
DRW_uniformbuffer_update(stl->shadow_render_ubo, &linfo->shadow_render_data);
|
||||
|
||||
DRW_draw_pass(psl->shadow_cascade_pass);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ typedef struct EEVEE_PassList {
|
|||
/* Shadows */
|
||||
struct DRWPass *shadow_pass;
|
||||
struct DRWPass *shadow_cube_pass;
|
||||
struct DRWPass *shadow_cascade_pass;
|
||||
|
||||
/* Probes */
|
||||
struct DRWPass *probe_background;
|
||||
|
|
|
@ -13,7 +13,7 @@ uniform sampler2D brdfLut;
|
|||
#endif
|
||||
uniform sampler2DArrayShadow shadowCubes;
|
||||
uniform sampler2DArrayShadow shadowMaps;
|
||||
// uniform sampler2DArrayShadow shadowCascades;
|
||||
uniform sampler2DArrayShadow shadowCascades;
|
||||
|
||||
layout(std140) uniform light_block {
|
||||
LightData lights_data[MAX_LIGHT];
|
||||
|
@ -88,6 +88,20 @@ float light_visibility(LightData ld, ShadingData sd)
|
|||
/* shadowing */
|
||||
if (ld.l_shadowid >= (MAX_SHADOW_MAP + MAX_SHADOW_CUBE)) {
|
||||
/* Shadow Cascade */
|
||||
float shid = ld.l_shadowid - (MAX_SHADOW_CUBE + MAX_SHADOW_MAP);
|
||||
ShadowCascadeData smd = shadows_cascade_data[int(shid)];
|
||||
|
||||
for (int i = 0; i < int(smd.sh_cascade_count); i++) {
|
||||
vec4 shpos = smd.shadowmat[i] * vec4(sd.W, 1.0);
|
||||
shpos.z -= smd.sh_cascade_bias * shpos.w;
|
||||
shpos.xyz /= shpos.w;
|
||||
|
||||
if (shpos.w > 0.0 && min(shpos.x, shpos.y) > 0.0 && max(shpos.x, shpos.y) < 1.0) {
|
||||
vis *= texture(shadowCascades, vec4(shpos.xy, shid * float(MAX_CASCADE_NUM) + float(i), shpos.z));
|
||||
// vis = float(i) / float(MAX_CASCADE_NUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ld.l_shadowid >= MAX_SHADOW_CUBE) {
|
||||
/* Shadow Map */
|
||||
|
|
|
@ -1889,7 +1889,6 @@ void DRW_draw_view(const bContext *C)
|
|||
DRW_engines_draw_background();
|
||||
|
||||
DRW_draw_callbacks_pre_scene();
|
||||
// DRW_draw_grid();
|
||||
DRW_engines_draw_scene();
|
||||
DRW_draw_callbacks_post_scene();
|
||||
|
||||
|
|
Loading…
Reference in New Issue