Eevee: Move cube shadows to octahedron shadowmaps.

We render linear distance to the light in a R32 texture and store it into an octahedron projection inside a 2D texture array.

This render the sampling function much more simpler and without edge artifacts.
This commit is contained in:
Clément Foucault 2017-05-20 13:16:14 +02:00
parent 4c3382d55f
commit d9d65a06d3
11 changed files with 245 additions and 148 deletions

View File

@ -131,6 +131,9 @@ data_to_c_simple(engines/eevee/shaders/probe_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/shadow_frag.glsl SRC) 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_geom.glsl SRC)
data_to_c_simple(engines/eevee/shaders/shadow_vert.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/bsdf_lut_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/bsdf_direct_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/bsdf_direct_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/bsdf_common_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/bsdf_common_lib.glsl SRC)

View File

@ -56,8 +56,6 @@ static struct {
struct GPUShader *default_world; struct GPUShader *default_world;
struct GPUShader *default_background; struct GPUShader *default_background;
struct GPUShader *depth_sh; struct GPUShader *depth_sh;
struct GPUShader *tonemap;
struct GPUShader *shadow_sh;
struct GPUShader *probe_filter_sh; struct GPUShader *probe_filter_sh;
struct GPUShader *probe_spherical_harmonic_sh; struct GPUShader *probe_spherical_harmonic_sh;
@ -263,11 +261,6 @@ static void EEVEE_engine_init(void *ved)
MEM_freeN(frag_str); MEM_freeN(frag_str);
} }
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);
}
if (!e_data.default_world) { if (!e_data.default_world) {
e_data.default_world = DRW_shader_create( e_data.default_world = DRW_shader_create(
datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, datatoc_default_world_frag_glsl, NULL); datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, datatoc_default_world_frag_glsl, NULL);
@ -341,32 +334,6 @@ static DRWShadingGroup *eevee_cube_shgroup(struct GPUShader *sh, DRWPass *pass,
return grp; return grp;
} }
static DRWShadingGroup *eevee_cube_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_cube_pass, geom);
DRW_shgroup_uniform_block(grp, "shadow_render_block", stl->shadow_render_ubo);
DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
for (int i = 0; i < 6; ++i)
DRW_shgroup_call_dynamic_add_empty(grp);
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);
DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
for (int i = 0; i < MAX_CASCADE_NUM; ++i)
DRW_shgroup_call_dynamic_add_empty(grp);
return grp;
}
static void EEVEE_cache_init(void *vedata) static void EEVEE_cache_init(void *vedata)
{ {
static int zero = 0; static int zero = 0;
@ -380,14 +347,6 @@ static void EEVEE_cache_init(void *vedata)
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
} }
{
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); // 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); // stl->g_data->shadow_shgrp = DRW_shgroup_create(e_data.shadow_sh, psl->shadow_pass);
@ -556,7 +515,7 @@ static void EEVEE_cache_init(void *vedata)
} }
EEVEE_lights_cache_init(stl); EEVEE_lights_cache_init(stl, psl, txl);
EEVEE_effects_cache_init(vedata); EEVEE_effects_cache_init(vedata);
} }
@ -683,8 +642,11 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
// GPUMaterial *gpumat = GPU_material_from_nodetree(struct bNodeTree *ntree, ListBase *gpumaterials, void *engine_type, int options) // GPUMaterial *gpumat = GPU_material_from_nodetree(struct bNodeTree *ntree, ListBase *gpumaterials, void *engine_type, int options)
// DRW_shgroup_call_add(stl->g_data->shadow_shgrp, geom, ob->obmat); // DRW_shgroup_call_add(stl->g_data->shadow_shgrp, geom, ob->obmat);
eevee_cascade_shadow_shgroup(psl, stl, geom, ob->obmat); const bool cast_shadow = true;
eevee_cube_shadow_shgroup(psl, stl, geom, ob->obmat);
if (cast_shadow) {
EEVEE_lights_cache_shcaster_add(psl, stl, geom, ob->obmat);
}
} }
else if (ob->type == OB_LAMP) { else if (ob->type == OB_LAMP) {
EEVEE_lights_cache_add(stl, ob); EEVEE_lights_cache_add(stl, ob);
@ -692,7 +654,6 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
} }
typedef struct eevee_bind_shadow_data { typedef struct eevee_bind_shadow_data {
struct GPUTexture *shadow_depth_map_pool;
struct GPUTexture *shadow_depth_cube_pool; struct GPUTexture *shadow_depth_cube_pool;
struct GPUTexture *shadow_depth_cascade_pool; struct GPUTexture *shadow_depth_cascade_pool;
} eevee_bind_shadow_data; } eevee_bind_shadow_data;
@ -700,7 +661,6 @@ typedef struct eevee_bind_shadow_data {
static void eevee_bind_shadow(void *data, DRWShadingGroup *shgrp) static void eevee_bind_shadow(void *data, DRWShadingGroup *shgrp)
{ {
eevee_bind_shadow_data *shdw_data = data; eevee_bind_shadow_data *shdw_data = data;
DRW_shgroup_uniform_texture(shgrp, "shadowMaps", shdw_data->shadow_depth_map_pool);
DRW_shgroup_uniform_texture(shgrp, "shadowCubes", shdw_data->shadow_depth_cube_pool); DRW_shgroup_uniform_texture(shgrp, "shadowCubes", shdw_data->shadow_depth_cube_pool);
DRW_shgroup_uniform_texture(shgrp, "shadowCascades", shdw_data->shadow_depth_cascade_pool); DRW_shgroup_uniform_texture(shgrp, "shadowCascades", shdw_data->shadow_depth_cascade_pool);
} }
@ -717,7 +677,6 @@ static void EEVEE_cache_finish(void *vedata)
/* Shadows binding */ /* Shadows binding */
eevee_bind_shadow_data data; eevee_bind_shadow_data data;
data.shadow_depth_map_pool = txl->shadow_depth_map_pool;
data.shadow_depth_cube_pool = txl->shadow_depth_cube_pool; data.shadow_depth_cube_pool = txl->shadow_depth_cube_pool;
data.shadow_depth_cascade_pool = txl->shadow_depth_cascade_pool; data.shadow_depth_cascade_pool = txl->shadow_depth_cascade_pool;
@ -757,11 +716,11 @@ static void EEVEE_draw_scene(void *vedata)
static void EEVEE_engine_free(void) static void EEVEE_engine_free(void)
{ {
EEVEE_effects_free(); EEVEE_effects_free();
EEVEE_lights_free();
MEM_SAFE_FREE(e_data.frag_shader_lib); MEM_SAFE_FREE(e_data.frag_shader_lib);
DRW_SHADER_FREE_SAFE(e_data.default_lit); DRW_SHADER_FREE_SAFE(e_data.default_lit);
DRW_SHADER_FREE_SAFE(e_data.default_lit_flat); DRW_SHADER_FREE_SAFE(e_data.default_lit_flat);
DRW_SHADER_FREE_SAFE(e_data.shadow_sh);
DRW_SHADER_FREE_SAFE(e_data.default_world); DRW_SHADER_FREE_SAFE(e_data.default_world);
DRW_SHADER_FREE_SAFE(e_data.default_background); DRW_SHADER_FREE_SAFE(e_data.default_background);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_sh);

View File

@ -47,6 +47,18 @@ typedef struct EEVEE_ShadowCascadeData {
float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */ float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
} EEVEE_ShadowCascadeData; } EEVEE_ShadowCascadeData;
static struct {
struct GPUShader *shadow_sh;
struct GPUShader *shadow_store_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 *********** */ /* *********** FUNCTIONS *********** */
void EEVEE_lights_init(EEVEE_StorageList *stl) void EEVEE_lights_init(EEVEE_StorageList *stl)
@ -55,6 +67,14 @@ void EEVEE_lights_init(EEVEE_StorageList *stl)
sizeof(EEVEE_ShadowMap) * MAX_SHADOW_MAP + sizeof(EEVEE_ShadowMap) * MAX_SHADOW_MAP +
sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE; sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE;
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);
}
if (!stl->lamps) { if (!stl->lamps) {
stl->lamps = MEM_callocN(sizeof(EEVEE_LampsInfo), "EEVEE_LampsInfo"); stl->lamps = MEM_callocN(sizeof(EEVEE_LampsInfo), "EEVEE_LampsInfo");
stl->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL); stl->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL);
@ -63,7 +83,7 @@ void EEVEE_lights_init(EEVEE_StorageList *stl)
} }
} }
void EEVEE_lights_cache_init(EEVEE_StorageList *stl) void EEVEE_lights_cache_init(EEVEE_StorageList *stl, EEVEE_PassList *psl, EEVEE_TextureList *txl)
{ {
EEVEE_LampsInfo *linfo = stl->lamps; EEVEE_LampsInfo *linfo = stl->lamps;
@ -72,6 +92,23 @@ void EEVEE_lights_cache_init(EEVEE_StorageList *stl)
memset(linfo->shadow_cube_ref, 0, sizeof(linfo->shadow_cube_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_map_ref, 0, sizeof(linfo->shadow_map_ref));
memset(linfo->shadow_cascade_ref, 0, sizeof(linfo->shadow_cascade_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", &txl->shadow_color_cube_target);
DRW_shgroup_uniform_block(grp, "shadow_render_block", stl->shadow_render_ubo);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
{
psl->shadow_cube_pass = DRW_pass_create("Shadow Cube Pass", DRW_STATE_WRITE_COLOR | 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);
}
} }
void EEVEE_lights_cache_add(EEVEE_StorageList *stl, Object *ob) void EEVEE_lights_cache_add(EEVEE_StorageList *stl, Object *ob)
@ -89,7 +126,7 @@ void EEVEE_lights_cache_add(EEVEE_StorageList *stl, Object *ob)
DRW_lamp_engine_data_free((void *)led); DRW_lamp_engine_data_free((void *)led);
#if 0 /* TODO Waiting for notified refresh. only on scene change. Else too much perf cost. */ #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->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) {
if (la->type == LA_SUN && linfo->num_cascade < MAX_SHADOW_CASCADE) { if (la->type == LA_SUN && linfo->num_cascade < MAX_SHADOW_CASCADE) {
led->sto = MEM_mallocN(sizeof(EEVEE_ShadowCascadeData), "EEVEE_ShadowCascadeData"); led->sto = MEM_mallocN(sizeof(EEVEE_ShadowCascadeData), "EEVEE_ShadowCascadeData");
@ -119,6 +156,24 @@ void EEVEE_lights_cache_add(EEVEE_StorageList *stl, Object *ob)
} }
} }
/* Add a shadow caster to the shadowpasses */
void EEVEE_lights_cache_shcaster_add(EEVEE_PassList *psl, EEVEE_StorageList *stl, struct Batch *geom, float (*obmat)[4])
{
DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cube_pass, geom);
DRW_shgroup_uniform_block(grp, "shadow_render_block", stl->shadow_render_ubo);
DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
for (int i = 0; i < 6; ++i)
DRW_shgroup_call_dynamic_add_empty(grp);
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);
DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
for (int i = 0; i < MAX_CASCADE_NUM; ++i)
DRW_shgroup_call_dynamic_add_empty(grp);
}
void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, EEVEE_FramebufferList *fbl) void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, EEVEE_FramebufferList *fbl)
{ {
EEVEE_LampsInfo *linfo = stl->lamps; EEVEE_LampsInfo *linfo = stl->lamps;
@ -141,10 +196,21 @@ void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, E
linfo->cache_num_cascade = linfo->num_cascade; linfo->cache_num_cascade = linfo->num_cascade;
} }
/* Initialize Textures Arrays first so DRW_framebuffer_init just bind them */ /* Initialize Textures Arrays first so DRW_framebuffer_init just bind them. */
if (!txl->shadow_depth_cube_target) {
/* Render Cubemap */
txl->shadow_depth_cube_target = DRW_texture_create_cube(512, DRW_TEX_DEPTH_24, 0, NULL);
txl->shadow_color_cube_target = DRW_texture_create_cube(512, DRW_TEX_R_32, 0, NULL);
if (fbl->shadow_cube_fb) {
DRW_framebuffer_texture_attach(fbl->shadow_cube_fb, txl->shadow_depth_cube_target, 0, 0);
DRW_framebuffer_texture_attach(fbl->shadow_cube_fb, txl->shadow_color_cube_target, 0, 0);
}
}
if (!txl->shadow_depth_cube_pool) { if (!txl->shadow_depth_cube_pool) {
/* Cubemap / octahedra map pool */
/* TODO Cubemap array */
txl->shadow_depth_cube_pool = DRW_texture_create_2D_array( txl->shadow_depth_cube_pool = DRW_texture_create_2D_array(
512, 512, max_ff(1, linfo->num_cube * 6), DRW_TEX_DEPTH_24, 512, 512, max_ff(1, linfo->num_cube), DRW_TEX_R_32,
DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL); DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
if (fbl->shadow_cube_fb) { if (fbl->shadow_cube_fb) {
DRW_framebuffer_texture_attach(fbl->shadow_cube_fb, txl->shadow_depth_cube_pool, 0, 0); DRW_framebuffer_texture_attach(fbl->shadow_cube_fb, txl->shadow_depth_cube_pool, 0, 0);
@ -167,11 +233,13 @@ void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, E
} }
} }
DRWFboTexture tex_cube = {&txl->shadow_depth_cube_pool, DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE}; DRWFboTexture tex_cube_target[2] = {
DRW_framebuffer_init(&fbl->shadow_cube_fb, &draw_engine_eevee_type, 512, 512, &tex_cube, 1); {&txl->shadow_depth_cube_target, DRW_TEX_DEPTH_24, 0},
{&txl->shadow_color_cube_target, DRW_TEX_R_32, 0}};
DRW_framebuffer_init(&fbl->shadow_cube_target_fb, &draw_engine_eevee_type, 512, 512, tex_cube_target, 2);
DRWFboTexture tex_map = {&txl->shadow_depth_map_pool, DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE}; DRWFboTexture tex_cube = {&txl->shadow_depth_cube_pool, DRW_TEX_R_32, DRW_TEX_FILTER};
DRW_framebuffer_init(&fbl->shadow_map_fb, &draw_engine_eevee_type, 512, 512, &tex_map, 1); DRW_framebuffer_init(&fbl->shadow_cube_fb, &draw_engine_eevee_type, 512, 512, &tex_cube, 1);
DRWFboTexture tex_cascade = {&txl->shadow_depth_cascade_pool, DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE}; DRWFboTexture tex_cascade = {&txl->shadow_depth_cascade_pool, DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE};
DRW_framebuffer_init(&fbl->shadow_cascade_fb, &draw_engine_eevee_type, 512, 512, &tex_cascade, 1); DRW_framebuffer_init(&fbl->shadow_cascade_fb, &draw_engine_eevee_type, 512, 512, &tex_cascade, 1);
@ -515,14 +583,9 @@ void EEVEE_draw_shadows(EEVEE_Data *vedata)
EEVEE_LampsInfo *linfo = stl->lamps; EEVEE_LampsInfo *linfo = stl->lamps;
Object *ob; Object *ob;
int i; int i;
float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
/* Cube Shadow Maps */ /* Cube Shadow Maps */
/* For old hardware support, we render each face of the shadow map
* onto 6 layer of a big 2D texture array and sample manualy the right layer
* in the fragment shader. */
DRW_framebuffer_bind(fbl->shadow_cube_fb);
DRW_framebuffer_clear(false, true, false, NULL, 1.0);
/* Render each shadow to one layer of the array */ /* Render each shadow to one layer of the array */
for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) { for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &DRW_engine_viewport_eevee_type); EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &DRW_engine_viewport_eevee_type);
@ -530,12 +593,20 @@ void EEVEE_draw_shadows(EEVEE_Data *vedata)
EEVEE_ShadowRender *srd = &linfo->shadow_render_data; EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
srd->layer = i; srd->layer = i;
copy_v3_v3(srd->position, ob->obmat[3]);
for (int j = 0; j < 6; ++j) { for (int j = 0; j < 6; ++j) {
copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]); copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
} }
DRW_uniformbuffer_update(stl->shadow_render_ubo, &linfo->shadow_render_data); DRW_uniformbuffer_update(stl->shadow_render_ubo, &linfo->shadow_render_data);
DRW_framebuffer_bind(fbl->shadow_cube_target_fb);
DRW_framebuffer_clear(true, true, false, clear_color, 1.0);
/* Render shadow cube */
DRW_draw_pass(psl->shadow_cube_pass); DRW_draw_pass(psl->shadow_cube_pass);
/* Push it to shadowmap array */
DRW_framebuffer_bind(fbl->shadow_cube_fb);
DRW_draw_pass(psl->shadow_cube_store_pass);
} }
#if 0 #if 0
@ -555,21 +626,27 @@ void EEVEE_draw_shadows(EEVEE_Data *vedata)
#endif #endif
/* Cascaded Shadow Maps */ /* Cascaded Shadow Maps */
DRW_framebuffer_bind(fbl->shadow_cascade_fb); // DRW_framebuffer_bind(fbl->shadow_cascade_fb);
DRW_framebuffer_clear(false, true, false, NULL, 1.0); // DRW_framebuffer_clear(false, true, false, NULL, 1.0);
/* Render each shadow to one layer of the array */ // /* Render each shadow to one layer of the array */
for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) { // 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, &DRW_engine_viewport_eevee_type); // EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &DRW_engine_viewport_eevee_type);
EEVEE_ShadowCascadeData *evscd = (EEVEE_ShadowCascadeData *)led->sto; // EEVEE_ShadowCascadeData *evscd = (EEVEE_ShadowCascadeData *)led->sto;
EEVEE_ShadowRender *srd = &linfo->shadow_render_data; // EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
srd->layer = i; // srd->layer = i;
for (int j = 0; j < MAX_CASCADE_NUM; ++j) { // for (int j = 0; j < MAX_CASCADE_NUM; ++j) {
copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]); // copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
} // }
DRW_uniformbuffer_update(stl->shadow_render_ubo, &linfo->shadow_render_data); // DRW_uniformbuffer_update(stl->shadow_render_ubo, &linfo->shadow_render_data);
DRW_draw_pass(psl->shadow_cascade_pass); // DRW_draw_pass(psl->shadow_cascade_pass);
} // }
} }
void EEVEE_lights_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.shadow_sh);
DRW_SHADER_FREE_SAFE(e_data.shadow_store_sh);
}

View File

@ -42,6 +42,7 @@ typedef struct EEVEE_PassList {
/* Shadows */ /* Shadows */
struct DRWPass *shadow_pass; struct DRWPass *shadow_pass;
struct DRWPass *shadow_cube_pass; struct DRWPass *shadow_cube_pass;
struct DRWPass *shadow_cube_store_pass;
struct DRWPass *shadow_cascade_pass; struct DRWPass *shadow_cascade_pass;
/* Probes */ /* Probes */
@ -69,6 +70,7 @@ typedef struct EEVEE_PassList {
typedef struct EEVEE_FramebufferList { typedef struct EEVEE_FramebufferList {
/* Shadows */ /* Shadows */
struct GPUFrameBuffer *shadow_cube_target_fb;
struct GPUFrameBuffer *shadow_cube_fb; struct GPUFrameBuffer *shadow_cube_fb;
struct GPUFrameBuffer *shadow_map_fb; struct GPUFrameBuffer *shadow_map_fb;
struct GPUFrameBuffer *shadow_cascade_fb; struct GPUFrameBuffer *shadow_cascade_fb;
@ -90,6 +92,8 @@ typedef struct EEVEE_FramebufferList {
typedef struct EEVEE_TextureList { typedef struct EEVEE_TextureList {
/* Shadows */ /* Shadows */
struct GPUTexture *shadow_depth_cube_target;
struct GPUTexture *shadow_color_cube_target;
struct GPUTexture *shadow_depth_cube_pool; struct GPUTexture *shadow_depth_cube_pool;
struct GPUTexture *shadow_depth_map_pool; struct GPUTexture *shadow_depth_map_pool;
struct GPUTexture *shadow_depth_cascade_pool; struct GPUTexture *shadow_depth_cascade_pool;
@ -157,6 +161,8 @@ typedef struct EEVEE_ShadowCascade {
typedef struct EEVEE_ShadowRender { 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 frustrum for cubemap shadow */
float position[3];
float pad;
int layer; int layer;
} EEVEE_ShadowRender; } EEVEE_ShadowRender;
@ -263,11 +269,13 @@ typedef struct EEVEE_PrivateData {
/* eevee_lights.c */ /* eevee_lights.c */
void EEVEE_lights_init(EEVEE_StorageList *stl); void EEVEE_lights_init(EEVEE_StorageList *stl);
void EEVEE_lights_cache_init(EEVEE_StorageList *stl); void EEVEE_lights_cache_init(EEVEE_StorageList *stl, EEVEE_PassList *psl, EEVEE_TextureList *txl);
void EEVEE_lights_cache_add(EEVEE_StorageList *stl, struct Object *ob); void EEVEE_lights_cache_add(EEVEE_StorageList *stl, struct Object *ob);
void EEVEE_lights_cache_shcaster_add(EEVEE_PassList *psl, EEVEE_StorageList *stl, struct Batch *geom, float (*obmat)[4]);
void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, EEVEE_FramebufferList *fbl); void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, EEVEE_FramebufferList *fbl);
void EEVEE_lights_update(EEVEE_StorageList *stl); void EEVEE_lights_update(EEVEE_StorageList *stl);
void EEVEE_draw_shadows(EEVEE_Data *vedata); void EEVEE_draw_shadows(EEVEE_Data *vedata);
void EEVEE_lights_free(void);
/* eevee_probes.c */ /* eevee_probes.c */
void EEVEE_probes_init(EEVEE_Data *vedata); void EEVEE_probes_init(EEVEE_Data *vedata);
@ -305,13 +313,13 @@ static const float cubefacemat[6][4][4] = {
{0.0, 0.0, 0.0, 1.0}}, {0.0, 0.0, 0.0, 1.0}},
/* Pos Y */ /* Pos Y */
{{1.0, 0.0, 0.0, 0.0}, {{1.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, -1.0, 0.0},
{0.0, -1.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 1.0}}, {0.0, 0.0, 0.0, 1.0}},
/* Neg Y */ /* Neg Y */
{{1.0, 0.0, 0.0, 0.0}, {{1.0, 0.0, 0.0, 0.0},
{0.0, 0.0, -1.0, 0.0}, {0.0, 0.0, 1.0, 0.0},
{0.0, 1.0, 0.0, 0.0}, {0.0, -1.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 1.0}}, {0.0, 0.0, 0.0, 1.0}},
/* Pos Z */ /* Pos Z */
{{1.0, 0.0, 0.0, 0.0}, {{1.0, 0.0, 0.0, 0.0},

View File

@ -11,8 +11,7 @@ uniform vec3 shCoefs[9];
#ifndef USE_LTC #ifndef USE_LTC
uniform sampler2D brdfLut; uniform sampler2D brdfLut;
#endif #endif
uniform sampler2DArrayShadow shadowCubes; uniform sampler2DArray shadowCubes;
uniform sampler2DArrayShadow shadowMaps;
uniform sampler2DArrayShadow shadowCascades; uniform sampler2DArrayShadow shadowCascades;
layout(std140) uniform light_block { layout(std140) uniform light_block {
@ -130,75 +129,30 @@ float light_visibility(LightData ld, ShadingData sd)
vis *= texture(shadowCascades, vec4(shpos.xy, shid * float(MAX_CASCADE_NUM) + cascade, shpos.z)); vis *= texture(shadowCascades, vec4(shpos.xy, shid * float(MAX_CASCADE_NUM) + cascade, shpos.z));
} }
else if (ld.l_shadowid >= MAX_SHADOW_CUBE) {
/* Shadow Map */
float shid = ld.l_shadowid - MAX_SHADOW_CUBE;
ShadowMapData smd = shadows_map_data[int(shid)];
vec4 shpos = smd.shadowmat * vec4(sd.W, 1.0);
shpos.z -= smd.sh_map_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(shadowMaps, vec4(shpos.xy, shid, shpos.z));
}
}
else { else {
/* Shadow Cube */ /* Shadow Cube */
float shid = ld.l_shadowid; float shid = ld.l_shadowid;
ShadowCubeData scd = shadows_cube_data[int(shid)]; ShadowCubeData scd = shadows_cube_data[int(shid)];
float face; vec3 cubevec = sd.W - ld.l_position;
vec2 uvs; float dist = length(cubevec);
vec3 Linv = sd.L;
vec3 Labs = abs(Linv);
vec3 maj_axis;
if (max(Labs.y, Labs.z) < Labs.x) { /* projection onto octahedron */
if (Linv.x > 0.0) { cubevec /= dot( vec3(1), abs(cubevec) );
face = 1.0;
uvs = vec2(1.0, -1.0) * Linv.zy / -Linv.x; /* out-folding of the downward faces */
maj_axis = vec3(1.0, 0.0, 0.0); if ( cubevec.z < 0.0 ) {
} cubevec.xy = (1.0 - abs(cubevec.yx)) * sign(cubevec.xy);
else {
face = 0.0;
uvs = -Linv.zy / Linv.x;
maj_axis = vec3(-1.0, 0.0, 0.0);
}
}
else if (max(Labs.x, Labs.z) < Labs.y) {
if (Linv.y > 0.0) {
face = 2.0;
uvs = vec2(-1.0, 1.0) * Linv.xz / Linv.y;
maj_axis = vec3(0.0, 1.0, 0.0);
}
else {
face = 3.0;
uvs = -Linv.xz / -Linv.y;
maj_axis = vec3(0.0, -1.0, 0.0);
}
}
else {
if (Linv.z > 0.0) {
face = 5.0;
uvs = Linv.xy / Linv.z;
maj_axis = vec3(0.0, 0.0, 1.0);
}
else {
face = 4.0;
uvs = vec2(-1.0, 1.0) * Linv.xy / -Linv.z;
maj_axis = vec3(0.0, 0.0, -1.0);
}
} }
vec2 texelSize = vec2(1.0 / 512.0);
uvs = uvs * 0.5 + 0.5; /* mapping to [0;1]ˆ2 texture space */
vec2 uvs = cubevec.xy * (0.5) + 0.5;
uvs = uvs * (1.0 - 2.0 * texelSize) + 1.0 * texelSize; /* edge filtering fix */
/* Depth in lightspace to compare against shadow map */ float sh_test = step(0, texture(shadowCubes, vec3(uvs, shid)).r - dist);
float w = dot(maj_axis, sd.l_vector);
w -= scd.sh_map_bias * w;
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
float shdepth = buffer_depth(is_persp, w, scd.sh_cube_far, scd.sh_cube_near);
vis *= texture(shadowCubes, vec4(uvs, shid * 6.0 + face, shdepth)); vis *= sh_test;
} }
return vis; return vis;

View File

@ -1,3 +1,8 @@
in float linearDistance;
out vec4 FragColor;
void main() { void main() {
FragColor = vec4(linearDistance, 0.0, 0.0, 1.0);
} }

View File

@ -1,21 +1,26 @@
layout(std140) uniform shadow_render_block {
mat4 ShadowMatrix[6];
vec4 lampPosition;
int layer;
};
layout(triangles) in; layout(triangles) in;
layout(triangle_strip, max_vertices=3) out; layout(triangle_strip, max_vertices=3) out;
layout(std140) uniform shadow_render_block {
mat4 ShadowMatrix[6];
int Layer;
};
in vec4 vPos[]; in vec4 vPos[];
in float lDist[];
flat in int face[]; flat in int face[];
out float linearDistance;
void main() { void main() {
int f = face[0]; int f = face[0];
gl_Layer = Layer + f; gl_Layer = f;
for (int v = 0; v < 3; ++v) { for (int v = 0; v < 3; ++v) {
gl_Position = ShadowMatrix[f] * vPos[v]; gl_Position = ShadowMatrix[f] * vPos[v];
linearDistance = lDist[v];
EmitVertex(); EmitVertex();
} }

View File

@ -0,0 +1,47 @@
uniform samplerCube shadowCube;
out vec4 FragColor;
vec3 octahedral_to_cubemap_proj(vec2 co)
{
co = co * 2.0 - 1.0;
vec2 abs_co = abs(co);
vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y));
if ( abs_co.x + abs_co.y > 1.0 ) {
v.xy = (abs(co.yx) - 1.0) * -sign(co.xy);
}
return v;
}
void main() {
const vec2 texelSize = vec2(1.0 / 512.0);
vec2 uvs = gl_FragCoord.xy * texelSize;
/* add a 2 pixel border to ensure filtering is correct */
uvs.xy *= 1.0 + texelSize * 2.0;
uvs.xy -= texelSize;
float pattern = 1.0;
/* edge mirroring : only mirror if directly adjacent
* (not diagonally adjacent) */
vec2 m = abs(uvs - 0.5) + 0.5;
vec2 f = floor(m);
if (f.x - f.y != 0.0) {
uvs.xy = 1.0 - uvs.xy;
}
/* clamp to [0-1] */
uvs.xy = fract(uvs.xy);
/* get cubemap vector */
vec3 cubevec = octahedral_to_cubemap_proj(uvs.xy);
/* get cubemap vector */
FragColor = texture(shadowCube, cubevec).rrrr;
}

View File

@ -0,0 +1,22 @@
layout(std140) uniform shadow_render_block {
mat4 ShadowMatrix[6];
vec4 lampPosition;
int layer;
};
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();
}

View File

@ -0,0 +1,8 @@
in vec3 pos;
out vec4 vPos;
void main() {
vPos = vec4(pos, 1.0);
}

View File

@ -1,12 +1,21 @@
layout(std140) uniform shadow_render_block {
mat4 ShadowMatrix[6];
vec4 lampPosition;
int layer;
};
uniform mat4 ShadowModelMatrix; uniform mat4 ShadowModelMatrix;
in vec3 pos; in vec3 pos;
out vec4 vPos; out vec4 vPos;
out float lDist;
flat out int face; flat out int face;
void main() { void main() {
vPos = ShadowModelMatrix * vec4(pos, 1.0); vPos = ShadowModelMatrix * vec4(pos, 1.0);
lDist = distance(lampPosition.xyz, vPos.xyz);
face = gl_InstanceID; face = gl_InstanceID;
} }