Commit: 3d17ece53924aae7289d279bf139ca444dd5bf82
Author: Clément Foucault
Date:   Thu Apr 20 13:07:24 2017 +0200
Branches: blender2.8
https://developer.blender.org/rB3d17ece53924aae7289d279bf139ca444dd5bf82

Eevee: Start Implementation of Cascaded Shadow Maps

===================================================================

M       source/blender/draw/engines/eevee/eevee.c
M       source/blender/draw/engines/eevee/eevee_lights.c
M       source/blender/draw/engines/eevee/eevee_private.h
M       source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
M       source/blender/draw/intern/draw_manager.c

===================================================================

diff --git a/source/blender/draw/engines/eevee/eevee.c 
b/source/blender/draw/engines/eevee/eevee.c
index fca7feb2f65..0c3802b37ad 100644
--- a/source/blender/draw/engines/eevee/eevee.c
+++ b/source/blender/draw/engines/eevee/eevee.c
@@ -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;
@@ -332,6 +344,10 @@ static void EEVEE_cache_init(void *vedata)
        }
 
        {
+               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);
                // DRW_shgroup_uniform_mat4(stl->g_data->shadow_shgrp, 
"ShadowMatrix", (float *)stl->lamps->shadowmat);
@@ -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)
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);
+       }
 }
diff --git a/source/blender/draw/engines/eevee/eevee_private.h 
b/source/blender/draw/engines/eevee/eevee_private.h
index 97d78a7ce84..6f249ea888d 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -36,6 +36,7 @@ typedef struct EEVEE_PassList {
        /* Shadows */
        struct DRWPass *shadow_pass;
        struct DRWPass *shadow_cube_pass;
+       struct DRWPass *shadow_cascade_pass;
 
        /* Probes */

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to