From c43d51c1c2c7c811a30a26ebc1fcdf7af6c0c0c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 2 Mar 2018 18:35:25 +0100 Subject: Eevee: Make use of culling when rendering the shadowmaps. --- .../blender/draw/engines/eevee/eevee_lightprobes.c | 6 +- source/blender/draw/engines/eevee/eevee_lights.c | 98 +++++++++++++++++----- source/blender/draw/engines/eevee/eevee_private.h | 1 + 3 files changed, 83 insertions(+), 22 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index b69823b60c3..11eebb517e2 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -1246,13 +1246,13 @@ static void render_scene_to_planar( DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW); DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV); + /* Be sure that cascaded shadow maps are updated. */ + EEVEE_draw_shadows(sldata, psl); + /* Since we are rendering with an inverted view matrix, we need * to invert the facing for backface culling to be the same. */ DRW_state_invert_facing(); - /* Be sure that cascaded shadow maps are updated. */ - EEVEE_draw_shadows(sldata, psl); - DRW_state_clip_planes_add(clip_plane); /* Attach depth here since it's a DRW_TEX_TEMP */ diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 9eb6a761e1d..622c7bc95d5 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -26,6 +26,7 @@ #include "DRW_render.h" #include "BLI_dynstr.h" +#include "BLI_rect.h" #include "BKE_object.h" @@ -710,7 +711,7 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE } /* Lamps Matrices */ - float viewmat[4][4], projmat[4][4]; + float (*viewmat)[4], projmat[4][4]; int sh_nbr = 1; /* TODO : MSM */ int cascade_nbr = la->cascade_count; @@ -719,6 +720,13 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id; EEVEE_ShadowCascade *cascade_data = linfo->shadow_cascade_data + sh_data->cascade_id; + /* obmat = Object Space > World Space */ + /* viewmat = World Space > View Space */ + invert_m4_m4(sh_data->clipmat[DRW_MAT_VIEW], ob->obmat); + viewmat = sh_data->clipmat[DRW_MAT_VIEW]; + normalize_m4(viewmat); + invert_m4_m4(sh_data->clipmat[DRW_MAT_VIEWINV], viewmat); + /* The technique consists into splitting * the view frustum into several sub-frustum * that are individually receiving one shadow map */ @@ -817,6 +825,7 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE cascade_data->split_start[0] = LERP(la->cascade_fade, cascade_data->split_end[cascade_nbr - 1], prev_split); /* For each cascade */ + rctf rect_clip, rect_cascade; for (int c = 0; c < cascade_nbr; ++c) { /* Given 8 frustum corners */ float corners[8][3] = { @@ -841,11 +850,6 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE frustum_min_bounding_sphere(corners, center, &(sh_data->radius[c])); /* Project into lightspace */ - invert_m4_m4(viewmat, ob->obmat); - normalize_v3(viewmat[0]); - normalize_v3(viewmat[1]); - normalize_v3(viewmat[2]); - mul_mat3_m4_v3(viewmat, center); /* Snap projection center to nearest texel to cancel shimmering. */ @@ -865,17 +869,32 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE add_v2_v2(center, shadow_texco); /* Expand the projection to cover frustum range */ + BLI_rctf_init_pt_radius(&rect_cascade, center, sh_data->radius[c]); orthographic_m4(projmat, - center[0] - sh_data->radius[c], - center[0] + sh_data->radius[c], - center[1] - sh_data->radius[c], - center[1] + sh_data->radius[c], + rect_cascade.xmin, rect_cascade.xmax, + rect_cascade.ymin, rect_cascade.ymax, la->clipsta, la->clipend); + if (c == 0) { + memcpy(&rect_clip, &rect_cascade, sizeof(rect_clip)); + } + else { + BLI_rctf_union(&rect_clip, &rect_cascade); + } + mul_m4_m4m4(sh_data->viewprojmat[c], projmat, viewmat); mul_m4_m4m4(cascade_data->shadowmat[c], texcomat, sh_data->viewprojmat[c]); } + /* Clipping mats */ + orthographic_m4(sh_data->clipmat[DRW_MAT_WIN], + rect_clip.xmin, rect_clip.xmax, + rect_clip.ymin, rect_clip.ymax, + la->clipsta, la->clipend); + mul_m4_m4m4(sh_data->clipmat[DRW_MAT_PERS], sh_data->clipmat[DRW_MAT_WIN], viewmat); + invert_m4_m4(sh_data->clipmat[DRW_MAT_WININV], sh_data->clipmat[DRW_MAT_WIN]); + invert_m4_m4(sh_data->clipmat[DRW_MAT_PERSINV], sh_data->clipmat[DRW_MAT_PERS]); + ubo_data->bias = 0.05f * la->bias; ubo_data->near = la->clipsta; ubo_data->far = la->clipend; @@ -977,6 +996,37 @@ void EEVEE_lights_update(EEVEE_ViewLayerData *sldata) } } +static void eevee_shadows_cube_culling_frustum(EEVEE_ShadowRender *srd) +{ + float persmat[4][4], persinv[4][4]; + float viewmat[4][4], viewinv[4][4]; + float winmat[4][4], wininv[4][4]; + orthographic_m4(winmat, -srd->clip_far, srd->clip_far, -srd->clip_far, srd->clip_far, -srd->clip_far, srd->clip_far); + DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN); + + invert_m4_m4(wininv, winmat); + DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV); + + unit_m4(viewmat); + negate_v3_v3(viewmat[3], srd->position); + DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW); + + unit_m4(viewinv); + copy_v3_v3(viewinv[3], srd->position); + DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV); + + mul_m4_m4m4(persmat, winmat, viewmat); + DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS); + + invert_m4_m4(persinv, persmat); + DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV); +} + +static void eevee_shadows_cascade_culling_frustum(EEVEE_ShadowCascadeData *evscd) +{ + DRW_viewport_matrix_override_set_all((DRWMatrixState *)evscd->clipmat); +} + /* this refresh lamps shadow buffers */ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) { @@ -985,6 +1035,11 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) int i; float clear_col[4] = {FLT_MAX}; + DRWMatrixState saved_mats; + + /* We need to save the Matrices before overidding them */ + DRW_viewport_matrix_get_all(&saved_mats); + /* Cube Shadow Maps */ DRW_stats_group_start("Cube Shadow Maps"); DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cube_target, 0, 0); @@ -993,9 +1048,6 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob); Lamp *la = (Lamp *)ob->data; - float cube_projmat[4][4]; - perspective_m4(cube_projmat, -la->clipsta, la->clipsta, -la->clipsta, la->clipsta, la->clipsta, la->clipend); - if (!led->need_update) { continue; } @@ -1003,20 +1055,24 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) EEVEE_ShadowRender *srd = &linfo->shadow_render_data; EEVEE_ShadowCubeData *evscd = &led->data.scd; + float cube_projmat[4][4]; + float cube_viewmat[4][4]; + perspective_m4(cube_projmat, -la->clipsta, la->clipsta, -la->clipsta, la->clipsta, la->clipsta, la->clipend); + unit_m4(cube_viewmat); + 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]; - - unit_m4(tmp); - negate_v3_v3(tmp[3], ob->obmat[3]); - mul_m4_m4m4(srd->viewmat[j], cubefacemat[j], tmp); + negate_v3_v3(cube_viewmat[3], srd->position); + for (int j = 0; j < 6; j++) { + mul_m4_m4m4(srd->viewmat[j], cubefacemat[j], cube_viewmat); mul_m4_m4m4(srd->shadowmat[j], cube_projmat, srd->viewmat[j]); } DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd); + eevee_shadows_cube_culling_frustum(srd); + DRW_framebuffer_bind(sldata->shadow_target_fb); DRW_framebuffer_clear(true, true, false, clear_col, 1.0f); @@ -1095,6 +1151,8 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) DRW_framebuffer_bind(sldata->shadow_target_fb); DRW_framebuffer_clear(false, true, false, NULL, 1.0); + eevee_shadows_cascade_culling_frustum(evscd); + /* Render shadow cascades */ linfo->shadow_instance_count = la->cascade_count; DRW_draw_pass(psl->shadow_pass); @@ -1147,6 +1205,8 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) DRW_framebuffer_texture_detach(sldata->shadow_cascade_target); DRW_stats_group_end(); + DRW_viewport_matrix_override_set_all(&saved_mats); + DRW_uniformbuffer_update(sldata->light_ubo, &linfo->light_data); DRW_uniformbuffer_update(sldata->shadow_ubo, &linfo->shadow_data); /* Update all data at once */ } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index fa23d6f72ef..8b035e97bf4 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -655,6 +655,7 @@ typedef struct EEVEE_ShadowCubeData { typedef struct EEVEE_ShadowCascadeData { short light_id, shadow_id, cascade_id, layer_id; float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */ + float clipmat[DRW_MAT_COUNT][4][4]; /* Override matrices used for clipping. */ float radius[MAX_CASCADE_NUM]; } EEVEE_ShadowCascadeData; -- cgit v1.2.3