2017-03-17 00:00:46 +01:00
|
|
|
/*
|
|
|
|
|
* Copyright 2016, Blender Foundation.
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*
|
|
|
|
|
* Contributor(s): Blender Institute
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** \file eevee_lights.c
|
|
|
|
|
* \ingroup DNA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "DRW_render.h"
|
|
|
|
|
|
2017-04-26 17:42:39 +10:00
|
|
|
#include "eevee_engine.h"
|
2017-03-17 00:00:46 +01:00
|
|
|
#include "eevee_private.h"
|
|
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
typedef struct EEVEE_LightData {
|
|
|
|
|
short light_id, shadow_id;
|
|
|
|
|
} EEVEE_LightData;
|
2017-03-17 00:00:46 +01:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
typedef struct EEVEE_ShadowCubeData {
|
|
|
|
|
short light_id, shadow_id;
|
|
|
|
|
float viewprojmat[6][4][4];
|
|
|
|
|
} EEVEE_ShadowCubeData;
|
2017-03-17 00:00:46 +01:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
typedef struct EEVEE_ShadowMapData {
|
|
|
|
|
short light_id, shadow_id;
|
|
|
|
|
float viewprojmat[4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
|
|
|
|
|
} EEVEE_ShadowMapData;
|
|
|
|
|
|
|
|
|
|
typedef struct EEVEE_ShadowCascadeData {
|
|
|
|
|
short light_id, shadow_id;
|
|
|
|
|
float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
|
|
|
|
|
} EEVEE_ShadowCascadeData;
|
|
|
|
|
|
2017-05-20 13:16:14 +02:00
|
|
|
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[];
|
|
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
/* *********** FUNCTIONS *********** */
|
2017-03-17 00:00:46 +01:00
|
|
|
|
|
|
|
|
void EEVEE_lights_init(EEVEE_StorageList *stl)
|
|
|
|
|
{
|
2017-04-10 12:06:17 +02:00
|
|
|
const unsigned int shadow_ubo_size = sizeof(EEVEE_ShadowCube) * MAX_SHADOW_CUBE +
|
|
|
|
|
sizeof(EEVEE_ShadowMap) * MAX_SHADOW_MAP +
|
|
|
|
|
sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE;
|
|
|
|
|
|
2017-05-20 13:16:14 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
if (!stl->lamps) {
|
2017-04-19 22:07:53 +02:00
|
|
|
stl->lamps = MEM_callocN(sizeof(EEVEE_LampsInfo), "EEVEE_LampsInfo");
|
|
|
|
|
stl->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL);
|
|
|
|
|
stl->shadow_ubo = DRW_uniformbuffer_create(shadow_ubo_size, NULL);
|
|
|
|
|
stl->shadow_render_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_ShadowRender), NULL);
|
2017-04-10 12:06:17 +02:00
|
|
|
}
|
2017-03-17 00:00:46 +01:00
|
|
|
}
|
|
|
|
|
|
2017-05-20 13:16:14 +02:00
|
|
|
void EEVEE_lights_cache_init(EEVEE_StorageList *stl, EEVEE_PassList *psl, EEVEE_TextureList *txl)
|
2017-03-17 00:00:46 +01:00
|
|
|
{
|
2017-04-10 12:06:17 +02:00
|
|
|
EEVEE_LampsInfo *linfo = stl->lamps;
|
2017-03-17 00:00:46 +01:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
linfo->num_light = linfo->num_cube = linfo->num_map = linfo->num_cascade = 0;
|
|
|
|
|
memset(linfo->light_ref, 0, sizeof(linfo->light_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_cascade_ref, 0, sizeof(linfo->shadow_cascade_ref));
|
2017-05-20 13:16:14 +02:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
2017-03-17 00:00:46 +01:00
|
|
|
}
|
|
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
void EEVEE_lights_cache_add(EEVEE_StorageList *stl, Object *ob)
|
2017-03-17 00:00:46 +01:00
|
|
|
{
|
2017-04-10 12:06:17 +02:00
|
|
|
EEVEE_LampsInfo *linfo = stl->lamps;
|
2017-03-17 00:00:46 +01:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
/* Step 1 find all lamps in the scene and setup them */
|
|
|
|
|
if (linfo->num_light > MAX_LIGHT) {
|
2017-03-17 00:00:46 +01:00
|
|
|
printf("Too much lamps in the scene !!!\n");
|
2017-04-10 12:06:17 +02:00
|
|
|
linfo->num_light = MAX_LIGHT;
|
2017-03-17 00:00:46 +01:00
|
|
|
}
|
2017-04-10 12:06:17 +02:00
|
|
|
else {
|
|
|
|
|
Lamp *la = (Lamp *)ob->data;
|
2017-04-26 17:42:39 +10:00
|
|
|
EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &DRW_engine_viewport_eevee_type);
|
2017-03-17 00:00:46 +01:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
DRW_lamp_engine_data_free((void *)led);
|
|
|
|
|
|
2017-05-20 13:16:14 +02:00
|
|
|
#if 1 /* TODO Waiting for notified refresh. only on scene change. Else too much perf cost. */
|
2017-04-10 12:06:17 +02:00
|
|
|
if (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) {
|
2017-04-20 13:07:24 +02:00
|
|
|
if (la->type == LA_SUN && linfo->num_cascade < MAX_SHADOW_CASCADE) {
|
2017-05-23 15:12:24 +02:00
|
|
|
#if 0 /* TODO filter cascaded shadow map */
|
2017-04-20 13:07:24 +02:00
|
|
|
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++;
|
2017-05-23 15:12:24 +02:00
|
|
|
#endif
|
2017-04-10 12:06:17 +02:00
|
|
|
}
|
|
|
|
|
else if ((la->type == LA_SPOT || la->type == LA_LOCAL || la->type == LA_AREA)
|
|
|
|
|
&& linfo->num_cube < MAX_SHADOW_CUBE) {
|
|
|
|
|
led->sto = MEM_mallocN(sizeof(EEVEE_ShadowCubeData), "EEVEE_ShadowCubeData");
|
|
|
|
|
((EEVEE_ShadowCubeData *)led->sto)->shadow_id = linfo->num_cube;
|
|
|
|
|
linfo->shadow_cube_ref[linfo->num_cube] = ob;
|
|
|
|
|
linfo->num_cube++;
|
|
|
|
|
}
|
2017-03-17 00:00:46 +01:00
|
|
|
}
|
2017-04-26 11:25:43 +02:00
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(la);
|
2017-04-25 23:33:52 +02:00
|
|
|
#endif
|
2017-04-10 12:06:17 +02:00
|
|
|
if (!led->sto) {
|
|
|
|
|
led->sto = MEM_mallocN(sizeof(EEVEE_LightData), "EEVEE_LightData");
|
|
|
|
|
((EEVEE_LightData *)led->sto)->shadow_id = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
((EEVEE_LightData *)led->sto)->light_id = linfo->num_light;
|
|
|
|
|
linfo->light_ref[linfo->num_light] = ob;
|
|
|
|
|
linfo->num_light++;
|
2017-03-17 00:00:46 +01:00
|
|
|
}
|
2017-04-10 12:06:17 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-20 13:16:14 +02:00
|
|
|
/* 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);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, EEVEE_FramebufferList *fbl)
|
|
|
|
|
{
|
|
|
|
|
EEVEE_LampsInfo *linfo = stl->lamps;
|
2017-03-17 00:00:46 +01:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
/* Step 4 Update Lamp UBOs */
|
2017-03-17 00:00:46 +01:00
|
|
|
EEVEE_lights_update(stl);
|
2017-04-10 12:06:17 +02:00
|
|
|
|
|
|
|
|
/* Step 5 Setup enough layers */
|
|
|
|
|
/* Free textures if number mismatch */
|
|
|
|
|
if (linfo->num_cube != linfo->cache_num_cube) {
|
2017-04-13 13:30:53 +10:00
|
|
|
DRW_TEXTURE_FREE_SAFE(txl->shadow_depth_cube_pool);
|
2017-04-10 12:06:17 +02:00
|
|
|
linfo->cache_num_cube = linfo->num_cube;
|
|
|
|
|
}
|
|
|
|
|
if (linfo->num_map != linfo->cache_num_map) {
|
2017-04-13 13:30:53 +10:00
|
|
|
DRW_TEXTURE_FREE_SAFE(txl->shadow_depth_map_pool);
|
2017-04-10 12:06:17 +02:00
|
|
|
linfo->cache_num_map = linfo->num_map;
|
|
|
|
|
}
|
|
|
|
|
if (linfo->num_cascade != linfo->cache_num_cascade) {
|
2017-04-13 13:30:53 +10:00
|
|
|
DRW_TEXTURE_FREE_SAFE(txl->shadow_depth_cascade_pool);
|
2017-04-10 12:06:17 +02:00
|
|
|
linfo->cache_num_cascade = linfo->num_cascade;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-20 13:16:14 +02:00
|
|
|
/* 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);
|
2017-05-20 16:47:33 +02:00
|
|
|
txl->shadow_color_cube_target = DRW_texture_create_cube(512, DRW_TEX_R_32, DRW_TEX_FILTER, NULL);
|
2017-05-20 13:16:14 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-10 12:06:17 +02:00
|
|
|
if (!txl->shadow_depth_cube_pool) {
|
2017-05-20 13:16:14 +02:00
|
|
|
/* Cubemap / octahedra map pool */
|
|
|
|
|
/* TODO Cubemap array */
|
2017-04-22 16:11:12 +10:00
|
|
|
txl->shadow_depth_cube_pool = DRW_texture_create_2D_array(
|
2017-05-20 13:16:14 +02:00
|
|
|
512, 512, max_ff(1, linfo->num_cube), DRW_TEX_R_32,
|
2017-04-22 16:11:12 +10:00
|
|
|
DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
|
|
|
|
|
if (fbl->shadow_cube_fb) {
|
2017-04-18 11:28:11 +02:00
|
|
|
DRW_framebuffer_texture_attach(fbl->shadow_cube_fb, txl->shadow_depth_cube_pool, 0, 0);
|
2017-04-22 16:11:12 +10:00
|
|
|
}
|
2017-04-10 12:06:17 +02:00
|
|
|
}
|
|
|
|
|
if (!txl->shadow_depth_map_pool) {
|
2017-04-22 16:11:12 +10:00
|
|
|
txl->shadow_depth_map_pool = DRW_texture_create_2D_array(
|
2017-04-27 22:27:41 +02:00
|
|
|
512, 512, max_ff(1, linfo->num_map), DRW_TEX_DEPTH_24,
|
2017-04-22 16:11:12 +10:00
|
|
|
DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
|
|
|
|
|
if (fbl->shadow_map_fb) {
|
2017-04-18 11:28:11 +02:00
|
|
|
DRW_framebuffer_texture_attach(fbl->shadow_map_fb, txl->shadow_depth_map_pool, 0, 0);
|
2017-04-22 16:11:12 +10:00
|
|
|
}
|
2017-04-10 12:06:17 +02:00
|
|
|
}
|
|
|
|
|
if (!txl->shadow_depth_cascade_pool) {
|
2017-04-22 16:11:12 +10:00
|
|
|
txl->shadow_depth_cascade_pool = DRW_texture_create_2D_array(
|
2017-04-27 22:27:41 +02:00
|
|
|
512, 512, max_ff(1, linfo->num_cascade * MAX_CASCADE_NUM), DRW_TEX_DEPTH_24,
|
2017-04-22 16:11:12 +10:00
|
|
|
DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
|
|
|
|
|
if (fbl->shadow_cascade_fb) {
|
2017-04-18 11:28:11 +02:00
|
|
|
DRW_framebuffer_texture_attach(fbl->shadow_cascade_fb, txl->shadow_depth_map_pool, 0, 0);
|
2017-04-22 16:11:12 +10:00
|
|
|
}
|
2017-04-10 12:06:17 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-20 13:16:14 +02:00
|
|
|
DRWFboTexture tex_cube_target[2] = {
|
|
|
|
|
{&txl->shadow_depth_cube_target, DRW_TEX_DEPTH_24, 0},
|
2017-05-20 16:47:33 +02:00
|
|
|
{&txl->shadow_color_cube_target, DRW_TEX_R_32, DRW_TEX_FILTER}};
|
2017-05-20 13:16:14 +02:00
|
|
|
DRW_framebuffer_init(&fbl->shadow_cube_target_fb, &draw_engine_eevee_type, 512, 512, tex_cube_target, 2);
|
2017-04-10 12:06:17 +02:00
|
|
|
|
2017-05-20 13:16:14 +02:00
|
|
|
DRWFboTexture tex_cube = {&txl->shadow_depth_cube_pool, DRW_TEX_R_32, DRW_TEX_FILTER};
|
|
|
|
|
DRW_framebuffer_init(&fbl->shadow_cube_fb, &draw_engine_eevee_type, 512, 512, &tex_cube, 1);
|
2017-04-10 12:06:17 +02:00
|
|
|
|
2017-05-16 20:18:57 +02:00
|
|
|
DRWFboTexture tex_cascade = {&txl->shadow_depth_cascade_pool, DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE};
|
2017-05-16 03:03:58 +02:00
|
|
|
DRW_framebuffer_init(&fbl->shadow_cascade_fb, &draw_engine_eevee_type, 512, 512, &tex_cascade, 1);
|
2017-03-17 00:00:46 +01:00
|
|
|
}
|
|
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
/* Update buffer with lamp data */
|
|
|
|
|
static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
|
2017-03-17 00:00:46 +01:00
|
|
|
{
|
|
|
|
|
/* TODO only update if data changes */
|
2017-04-10 12:06:17 +02:00
|
|
|
EEVEE_LightData *evld = led->sto;
|
|
|
|
|
EEVEE_Light *evli = linfo->light_data + evld->light_id;
|
|
|
|
|
Lamp *la = (Lamp *)ob->data;
|
|
|
|
|
float mat[4][4], scale[3], power;
|
2017-03-17 00:00:46 +01:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
/* Position */
|
|
|
|
|
copy_v3_v3(evli->position, ob->obmat[3]);
|
2017-03-28 00:09:45 +02:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
/* Color */
|
2017-05-11 14:32:03 +02:00
|
|
|
srgb_to_linearrgb_v3_v3(evli->color, &la->r);
|
2017-03-28 00:09:45 +02:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
/* Influence Radius */
|
|
|
|
|
evli->dist = la->dist;
|
2017-03-28 00:09:45 +02:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
/* Vectors */
|
|
|
|
|
normalize_m4_m4_ex(mat, ob->obmat, scale);
|
|
|
|
|
copy_v3_v3(evli->forwardvec, mat[2]);
|
|
|
|
|
normalize_v3(evli->forwardvec);
|
|
|
|
|
negate_v3(evli->forwardvec);
|
2017-03-28 00:09:45 +02:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
copy_v3_v3(evli->rightvec, mat[0]);
|
|
|
|
|
normalize_v3(evli->rightvec);
|
2017-03-28 00:09:45 +02:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
copy_v3_v3(evli->upvec, mat[1]);
|
|
|
|
|
normalize_v3(evli->upvec);
|
2017-03-28 00:09:45 +02:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
/* Spot size & blend */
|
|
|
|
|
if (la->type == LA_SPOT) {
|
|
|
|
|
evli->sizex = scale[0] / scale[2];
|
|
|
|
|
evli->sizey = scale[1] / scale[2];
|
|
|
|
|
evli->spotsize = cosf(la->spotsize * 0.5f);
|
|
|
|
|
evli->spotblend = (1.0f - evli->spotsize) * la->spotblend;
|
2017-04-27 22:27:41 +02:00
|
|
|
evli->radius = max_ff(0.001f, la->area_size);
|
2017-04-10 12:06:17 +02:00
|
|
|
}
|
|
|
|
|
else if (la->type == LA_AREA) {
|
2017-04-27 22:27:41 +02:00
|
|
|
evli->sizex = max_ff(0.0001f, la->area_size * scale[0] * 0.5f);
|
2017-04-10 12:06:17 +02:00
|
|
|
if (la->area_shape == LA_AREA_RECT) {
|
2017-04-27 22:27:41 +02:00
|
|
|
evli->sizey = max_ff(0.0001f, la->area_sizey * scale[1] * 0.5f);
|
2017-03-29 23:45:07 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2017-04-27 22:27:41 +02:00
|
|
|
evli->sizey = max_ff(0.0001f, la->area_size * scale[1] * 0.5f);
|
2017-03-29 23:45:07 +02:00
|
|
|
}
|
2017-04-10 12:06:17 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2017-04-27 22:27:41 +02:00
|
|
|
evli->radius = max_ff(0.001f, la->area_size);
|
2017-04-10 12:06:17 +02:00
|
|
|
}
|
2017-03-28 00:09:45 +02:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
/* Make illumination power constant */
|
|
|
|
|
if (la->type == LA_AREA) {
|
|
|
|
|
power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) /* 1/(w*h*Pi) */
|
|
|
|
|
* 80.0f; /* XXX : Empirical, Fit cycles power */
|
|
|
|
|
}
|
|
|
|
|
else if (la->type == LA_SPOT || la->type == LA_LOCAL) {
|
|
|
|
|
power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) /* 1/(4*r²*Pi²) */
|
|
|
|
|
* M_PI * M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */
|
2017-03-31 01:07:30 +02:00
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
/* for point lights (a.k.a radius == 0.0) */
|
|
|
|
|
// power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
power = 1.0f;
|
|
|
|
|
}
|
2017-05-11 14:32:03 +02:00
|
|
|
mul_v3_fl(evli->color, power * la->energy);
|
2017-04-10 12:06:17 +02:00
|
|
|
|
|
|
|
|
/* Lamp Type */
|
|
|
|
|
evli->lamptype = (float)la->type;
|
|
|
|
|
|
|
|
|
|
/* No shadow by default */
|
|
|
|
|
evli->shadowid = -1.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
|
|
|
|
|
{
|
|
|
|
|
float projmat[4][4];
|
|
|
|
|
|
|
|
|
|
EEVEE_ShadowCubeData *evsmp = (EEVEE_ShadowCubeData *)led->sto;
|
|
|
|
|
EEVEE_Light *evli = linfo->light_data + evsmp->light_id;
|
|
|
|
|
EEVEE_ShadowCube *evsh = linfo->shadow_cube_data + evsmp->shadow_id;
|
|
|
|
|
Lamp *la = (Lamp *)ob->data;
|
|
|
|
|
|
|
|
|
|
perspective_m4(projmat, -la->clipsta, la->clipsta, -la->clipsta, la->clipsta, la->clipsta, la->clipend);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
|
|
|
float tmp[4][4];
|
|
|
|
|
unit_m4(tmp);
|
|
|
|
|
negate_v3_v3(tmp[3], ob->obmat[3]);
|
|
|
|
|
mul_m4_m4m4(tmp, cubefacemat[i], tmp);
|
|
|
|
|
mul_m4_m4m4(evsmp->viewprojmat[i], projmat, tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
evsh->bias = 0.05f * la->bias;
|
|
|
|
|
evsh->near = la->clipsta;
|
|
|
|
|
evsh->far = la->clipend;
|
|
|
|
|
|
|
|
|
|
evli->shadowid = (float)(evsmp->shadow_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void eevee_shadow_map_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
|
|
|
|
|
{
|
|
|
|
|
float viewmat[4][4], projmat[4][4];
|
|
|
|
|
|
|
|
|
|
EEVEE_ShadowMapData *evsmp = (EEVEE_ShadowMapData *)led->sto;
|
|
|
|
|
EEVEE_Light *evli = linfo->light_data + evsmp->light_id;
|
|
|
|
|
EEVEE_ShadowMap *evsh = linfo->shadow_map_data + evsmp->shadow_id;
|
|
|
|
|
Lamp *la = (Lamp *)ob->data;
|
|
|
|
|
|
|
|
|
|
invert_m4_m4(viewmat, ob->obmat);
|
|
|
|
|
normalize_v3(viewmat[0]);
|
|
|
|
|
normalize_v3(viewmat[1]);
|
|
|
|
|
normalize_v3(viewmat[2]);
|
|
|
|
|
|
|
|
|
|
float wsize = la->shadow_frustum_size;
|
|
|
|
|
orthographic_m4(projmat, -wsize, wsize, -wsize, wsize, la->clipsta, la->clipend);
|
|
|
|
|
|
|
|
|
|
mul_m4_m4m4(evsmp->viewprojmat, projmat, viewmat);
|
|
|
|
|
mul_m4_m4m4(evsh->shadowmat, texcomat, evsmp->viewprojmat);
|
|
|
|
|
|
|
|
|
|
evsh->bias = 0.005f * la->bias;
|
|
|
|
|
|
|
|
|
|
evli->shadowid = (float)(MAX_SHADOW_CUBE + evsmp->shadow_id);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-20 13:07:24 +02:00
|
|
|
#define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
|
|
|
|
|
|
2017-04-21 16:43:14 +02:00
|
|
|
static void frustum_min_bounding_sphere(const float corners[8][4], float r_center[3], float *r_radius)
|
|
|
|
|
{
|
|
|
|
|
#if 0 /* Simple solution but waist too much space. */
|
|
|
|
|
float minvec[3], maxvec[3];
|
|
|
|
|
|
|
|
|
|
/* compute the bounding box */
|
|
|
|
|
INIT_MINMAX(minvec, maxvec);
|
|
|
|
|
for (int i = 0; i < 8; ++i) {
|
|
|
|
|
minmax_v3v3_v3(minvec, maxvec, corners[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* compute the bounding sphere of this box */
|
|
|
|
|
r_radius = len_v3v3(minvec, maxvec) * 0.5f;
|
|
|
|
|
add_v3_v3v3(r_center, minvec, maxvec);
|
|
|
|
|
mul_v3_fl(r_center, 0.5f);
|
|
|
|
|
#else
|
|
|
|
|
/* Make the bouding sphere always centered on the front diagonal */
|
|
|
|
|
add_v3_v3v3(r_center, corners[4], corners[7]);
|
|
|
|
|
mul_v3_fl(r_center, 0.5f);
|
|
|
|
|
*r_radius = len_v3v3(corners[0], r_center);
|
|
|
|
|
|
|
|
|
|
/* Search the largest distance between the sphere center
|
|
|
|
|
* and the front plane corners. */
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
|
float rad = len_v3v3(corners[4+i], r_center);
|
|
|
|
|
if (rad > *r_radius) {
|
|
|
|
|
*r_radius = rad;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-20 13:07:24 +02:00
|
|
|
static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
|
|
|
|
|
{
|
|
|
|
|
/* Camera Matrices */
|
|
|
|
|
float persmat[4][4], persinv[4][4];
|
2017-04-21 16:43:14 +02:00
|
|
|
float viewprojmat[4][4], projinv[4][4];
|
|
|
|
|
float near, far;
|
|
|
|
|
float near_v[4] = {0.0f, 0.0f, -1.0f, 1.0f};
|
|
|
|
|
float far_v[4] = {0.0f, 0.0f, 1.0f, 1.0f};
|
|
|
|
|
bool is_persp = DRW_viewport_is_persp_get();
|
|
|
|
|
DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
|
|
|
|
|
invert_m4_m4(persinv, persmat);
|
|
|
|
|
/* FIXME : Get near / far from Draw manager? */
|
|
|
|
|
DRW_viewport_matrix_get(viewprojmat, DRW_MAT_WIN);
|
|
|
|
|
invert_m4_m4(projinv, viewprojmat);
|
|
|
|
|
mul_m4_v4(projinv, near_v);
|
|
|
|
|
mul_m4_v4(projinv, far_v);
|
|
|
|
|
near = near_v[2];
|
|
|
|
|
far = far_v[2]; /* TODO: Should be a shadow parameter */
|
|
|
|
|
if (is_persp) {
|
|
|
|
|
near /= near_v[3];
|
|
|
|
|
far /= far_v[3];
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-20 13:07:24 +02:00
|
|
|
/* Lamps Matrices */
|
|
|
|
|
float viewmat[4][4], projmat[4][4];
|
|
|
|
|
int cascade_ct = MAX_CASCADE_NUM;
|
2017-04-21 16:43:14 +02:00
|
|
|
float shadow_res = 512.0f; /* TODO parameter */
|
2017-04-20 13:07:24 +02:00
|
|
|
|
|
|
|
|
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 */
|
|
|
|
|
|
2017-04-21 16:43:14 +02:00
|
|
|
/* init near/far */
|
|
|
|
|
for (int c = 0; c < MAX_CASCADE_NUM; ++c) {
|
|
|
|
|
evsh->split[c] = far;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Compute split planes */
|
|
|
|
|
float splits_ndc[MAX_CASCADE_NUM + 1];
|
|
|
|
|
splits_ndc[0] = -1.0f;
|
|
|
|
|
splits_ndc[cascade_ct] = 1.0f;
|
|
|
|
|
for (int c = 1; c < cascade_ct; ++c) {
|
|
|
|
|
const float lambda = 0.8f; /* TODO : Parameter */
|
|
|
|
|
|
|
|
|
|
/* View Space */
|
|
|
|
|
float linear_split = LERP(((float)(c) / (float)cascade_ct), near, far);
|
|
|
|
|
float exp_split = near * powf(far / near, (float)(c) / (float)cascade_ct);
|
|
|
|
|
|
|
|
|
|
if (is_persp) {
|
|
|
|
|
evsh->split[c-1] = LERP(lambda, linear_split, exp_split);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
evsh->split[c-1] = linear_split;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* NDC Space */
|
|
|
|
|
float p[4] = {1.0f, 1.0f, evsh->split[c-1], 1.0f};
|
|
|
|
|
mul_m4_v4(viewprojmat, p);
|
|
|
|
|
splits_ndc[c] = p[2];
|
|
|
|
|
|
|
|
|
|
if (is_persp) {
|
|
|
|
|
splits_ndc[c] /= p[3];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-20 13:07:24 +02:00
|
|
|
/* For each cascade */
|
|
|
|
|
for (int c = 0; c < cascade_ct; ++c) {
|
|
|
|
|
/* Given 8 frustrum corners */
|
|
|
|
|
float corners[8][4] = {
|
|
|
|
|
/* Near Cap */
|
2017-04-21 16:43:14 +02:00
|
|
|
{-1.0f, -1.0f, splits_ndc[c], 1.0f},
|
|
|
|
|
{ 1.0f, -1.0f, splits_ndc[c], 1.0f},
|
|
|
|
|
{-1.0f, 1.0f, splits_ndc[c], 1.0f},
|
|
|
|
|
{ 1.0f, 1.0f, splits_ndc[c], 1.0f},
|
|
|
|
|
/* Far Cap */
|
|
|
|
|
{-1.0f, -1.0f, splits_ndc[c+1], 1.0f},
|
|
|
|
|
{ 1.0f, -1.0f, splits_ndc[c+1], 1.0f},
|
|
|
|
|
{-1.0f, 1.0f, splits_ndc[c+1], 1.0f},
|
|
|
|
|
{ 1.0f, 1.0f, splits_ndc[c+1], 1.0f}
|
2017-04-20 13:07:24 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Transform them into world space */
|
|
|
|
|
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]);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-21 16:43:14 +02:00
|
|
|
float center[3], radius;
|
|
|
|
|
frustum_min_bounding_sphere(corners, center, &radius);
|
|
|
|
|
|
|
|
|
|
/* Snap projection center to nearest texel to cancel shimering. */
|
|
|
|
|
float shadow_origin[2], shadow_texco[2];
|
|
|
|
|
mul_v2_v2fl(shadow_origin, center, shadow_res / (2.0f * radius)); /* Light to texture space. */
|
|
|
|
|
|
|
|
|
|
/* Find the nearest texel. */
|
|
|
|
|
shadow_texco[0] = round(shadow_origin[0]);
|
|
|
|
|
shadow_texco[1] = round(shadow_origin[1]);
|
|
|
|
|
|
|
|
|
|
/* Compute offset. */
|
|
|
|
|
sub_v2_v2(shadow_texco, shadow_origin);
|
|
|
|
|
mul_v2_fl(shadow_texco, (2.0f * radius) / shadow_res); /* Texture to light space. */
|
2017-04-20 13:07:24 +02:00
|
|
|
|
2017-04-21 16:43:14 +02:00
|
|
|
/* Apply offset. */
|
|
|
|
|
add_v2_v2(center, shadow_texco);
|
|
|
|
|
|
|
|
|
|
/* Expand the projection to cover frustum range */
|
|
|
|
|
orthographic_m4(projmat,
|
|
|
|
|
center[0] - radius,
|
|
|
|
|
center[0] + radius,
|
|
|
|
|
center[1] - radius,
|
|
|
|
|
center[1] + radius,
|
|
|
|
|
la->clipsta, la->clipend);
|
2017-04-20 13:07:24 +02:00
|
|
|
|
|
|
|
|
mul_m4_m4m4(evscp->viewprojmat[c], projmat, viewmat);
|
|
|
|
|
mul_m4_m4m4(evsh->shadowmat[c], texcomat, evscp->viewprojmat[c]);
|
|
|
|
|
|
2017-04-21 16:43:14 +02:00
|
|
|
/* TODO modify bias depending on the cascade radius */
|
|
|
|
|
evsh->bias[c] = 0.005f * la->bias;
|
|
|
|
|
}
|
2017-04-20 13:07:24 +02:00
|
|
|
|
|
|
|
|
evli->shadowid = (float)(MAX_SHADOW_CUBE + MAX_SHADOW_MAP + evscp->shadow_id);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 12:06:17 +02:00
|
|
|
void EEVEE_lights_update(EEVEE_StorageList *stl)
|
|
|
|
|
{
|
|
|
|
|
EEVEE_LampsInfo *linfo = stl->lamps;
|
|
|
|
|
Object *ob;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; (ob = linfo->light_ref[i]) && (i < MAX_LIGHT); i++) {
|
2017-04-26 17:42:39 +10:00
|
|
|
EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &DRW_engine_viewport_eevee_type);
|
2017-04-10 12:06:17 +02:00
|
|
|
eevee_light_setup(ob, linfo, led);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
|
2017-04-26 17:42:39 +10:00
|
|
|
EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &DRW_engine_viewport_eevee_type);
|
2017-04-10 12:06:17 +02:00
|
|
|
eevee_shadow_cube_setup(ob, linfo, led);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; (ob = linfo->shadow_map_ref[i]) && (i < MAX_SHADOW_MAP); i++) {
|
2017-04-26 17:42:39 +10:00
|
|
|
EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &DRW_engine_viewport_eevee_type);
|
2017-04-10 12:06:17 +02:00
|
|
|
eevee_shadow_map_setup(ob, linfo, led);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-20 13:07:24 +02:00
|
|
|
for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
|
2017-04-26 17:42:39 +10:00
|
|
|
EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &DRW_engine_viewport_eevee_type);
|
2017-04-20 13:07:24 +02:00
|
|
|
eevee_shadow_cascade_setup(ob, linfo, led);
|
|
|
|
|
}
|
2017-04-10 12:06:17 +02:00
|
|
|
|
|
|
|
|
DRW_uniformbuffer_update(stl->light_ubo, &linfo->light_data);
|
|
|
|
|
DRW_uniformbuffer_update(stl->shadow_ubo, &linfo->shadow_cube_data); /* Update all data at once */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* this refresh lamps shadow buffers */
|
|
|
|
|
void EEVEE_draw_shadows(EEVEE_Data *vedata)
|
|
|
|
|
{
|
2017-04-19 22:07:53 +02:00
|
|
|
EEVEE_PassList *psl = vedata->psl;
|
2017-04-10 12:06:17 +02:00
|
|
|
EEVEE_StorageList *stl = vedata->stl;
|
|
|
|
|
EEVEE_FramebufferList *fbl = vedata->fbl;
|
|
|
|
|
EEVEE_LampsInfo *linfo = stl->lamps;
|
|
|
|
|
Object *ob;
|
|
|
|
|
int i;
|
2017-05-20 13:16:14 +02:00
|
|
|
float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
2017-04-10 12:06:17 +02:00
|
|
|
|
|
|
|
|
/* Cube Shadow Maps */
|
|
|
|
|
/* Render each shadow to one layer of the array */
|
|
|
|
|
for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
|
2017-04-26 17:42:39 +10:00
|
|
|
EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &DRW_engine_viewport_eevee_type);
|
2017-04-10 12:06:17 +02:00
|
|
|
EEVEE_ShadowCubeData *evscd = (EEVEE_ShadowCubeData *)led->sto;
|
2017-04-19 22:07:53 +02:00
|
|
|
EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
|
2017-04-10 12:06:17 +02:00
|
|
|
|
2017-04-19 22:07:53 +02:00
|
|
|
srd->layer = i;
|
2017-05-20 13:16:14 +02:00
|
|
|
copy_v3_v3(srd->position, ob->obmat[3]);
|
2017-04-10 12:06:17 +02:00
|
|
|
for (int j = 0; j < 6; ++j) {
|
2017-04-19 22:07:53 +02:00
|
|
|
copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
|
2017-03-31 01:07:30 +02:00
|
|
|
}
|
2017-04-19 22:07:53 +02:00
|
|
|
DRW_uniformbuffer_update(stl->shadow_render_ubo, &linfo->shadow_render_data);
|
|
|
|
|
|
2017-05-20 13:16:14 +02:00
|
|
|
DRW_framebuffer_bind(fbl->shadow_cube_target_fb);
|
|
|
|
|
DRW_framebuffer_clear(true, true, false, clear_color, 1.0);
|
|
|
|
|
/* Render shadow cube */
|
2017-04-19 22:07:53 +02:00
|
|
|
DRW_draw_pass(psl->shadow_cube_pass);
|
2017-05-20 13:16:14 +02:00
|
|
|
|
|
|
|
|
/* Push it to shadowmap array */
|
|
|
|
|
DRW_framebuffer_bind(fbl->shadow_cube_fb);
|
|
|
|
|
DRW_draw_pass(psl->shadow_cube_store_pass);
|
2017-04-10 12:06:17 +02:00
|
|
|
}
|
|
|
|
|
|
2017-04-20 13:07:24 +02:00
|
|
|
#if 0
|
2017-04-10 12:06:17 +02:00
|
|
|
/* Standard Shadow Maps */
|
2017-04-20 13:07:24 +02:00
|
|
|
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++) {
|
2017-04-26 17:42:39 +10:00
|
|
|
EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &DRW_engine_viewport_eevee_type);
|
2017-04-20 13:07:24 +02:00
|
|
|
EEVEE_ShadowMapData *evsmd = (EEVEE_ShadowMapData *)led->sto;
|
2017-04-10 12:06:17 +02:00
|
|
|
|
2017-04-20 13:07:24 +02:00
|
|
|
linfo->layer = i;
|
|
|
|
|
copy_m4_m4(linfo->shadowmat, evsmd->viewprojmat);
|
|
|
|
|
DRW_draw_pass(vedata->psl->shadow_pass);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2017-03-31 01:07:30 +02:00
|
|
|
|
2017-04-20 13:07:24 +02:00
|
|
|
/* Cascaded Shadow Maps */
|
2017-05-20 13:16:14 +02:00
|
|
|
// 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, &DRW_engine_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);
|
|
|
|
|
// }
|
2017-03-17 00:00:46 +01:00
|
|
|
}
|
2017-05-20 13:16:14 +02:00
|
|
|
|
|
|
|
|
void EEVEE_lights_free(void)
|
|
|
|
|
{
|
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.shadow_sh);
|
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.shadow_store_sh);
|
|
|
|
|
}
|