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:
authorClément Foucault <foucault.clem@gmail.com>2017-04-20 14:07:24 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-04-20 14:07:51 +0300
commit3d17ece53924aae7289d279bf139ca444dd5bf82 (patch)
tree9512cb1b80c3c463ae0ea9748177eea12391a0ca /source/blender/draw/engines/eevee/eevee_lights.c
parentb386828671a40feea026ccefae17560e58e0d440 (diff)
Eevee: Start Implementation of Cascaded Shadow Maps
Diffstat (limited to 'source/blender/draw/engines/eevee/eevee_lights.c')
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c138
1 files changed, 117 insertions, 21 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 6c694b05e6a..7c4a5523ecd 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -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);
+ }
+#endif
- // linfo->layer = i;
- // copy_m4_m4(linfo->shadowmat, evsmd->viewprojmat);
- // DRW_draw_pass(vedata->psl->shadow_pass);
- // }
+ /* Cascaded Shadow Maps */
+ DRW_framebuffer_bind(fbl->shadow_cascade_fb);
+ DRW_framebuffer_clear(false, true, false, NULL, 1.0);
- // DRW_framebuffer_bind(e_data.shadow_cascade_fb);
+ /* 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);
+ }
}