2 * Copyright 2016, Blender Foundation.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Contributor(s): Blender Institute
22 /** \file eevee_lights.c
26 #include "DRW_render.h"
28 #include "BLI_dynstr.h"
30 #include "BKE_object.h"
32 #include "eevee_engine.h"
33 #include "eevee_private.h"
35 #define SHADOW_CASTER_ALLOC_CHUNK 16
38 struct GPUShader *shadow_sh;
39 struct GPUShader *shadow_store_cube_sh[SHADOW_METHOD_MAX];
40 struct GPUShader *shadow_store_cascade_sh[SHADOW_METHOD_MAX];
41 struct GPUShader *shadow_copy_cube_sh[SHADOW_METHOD_MAX];
42 struct GPUShader *shadow_copy_cascade_sh[SHADOW_METHOD_MAX];
43 } e_data = {NULL}; /* Engine data */
45 extern char datatoc_shadow_vert_glsl[];
46 extern char datatoc_shadow_geom_glsl[];
47 extern char datatoc_shadow_frag_glsl[];
48 extern char datatoc_shadow_store_frag_glsl[];
49 extern char datatoc_shadow_copy_frag_glsl[];
50 extern char datatoc_concentric_samples_lib_glsl[];
53 static void eevee_light_setup(Object *ob, EEVEE_Light *evli);
55 /* *********** LIGHT BITS *********** */
56 static void lightbits_set_single(EEVEE_LightBits *bitf, unsigned int idx, bool val)
59 bitf->fields[idx / 8] |= (1 << (idx % 8));
62 bitf->fields[idx / 8] &= ~(1 << (idx % 8));
66 static void lightbits_set_all(EEVEE_LightBits *bitf, bool val)
68 memset(bitf, (val) ? 0xFF : 0x00, sizeof(EEVEE_LightBits));
71 static void lightbits_or(EEVEE_LightBits *r, const EEVEE_LightBits *v)
73 for (int i = 0; i < MAX_LIGHTBITS_FIELDS; ++i) {
74 r->fields[i] |= v->fields[i];
78 static bool lightbits_get(const EEVEE_LightBits *r, unsigned int idx)
80 return r->fields[idx / 8] & (1 << (idx % 8));
83 static void lightbits_convert(EEVEE_LightBits *r, const EEVEE_LightBits *bitf, const int *light_bit_conv_table, unsigned int table_length)
85 for (int i = 0; i < table_length; ++i) {
86 if (lightbits_get(bitf, i) != 0) {
87 if (light_bit_conv_table[i] >= 0) {
88 r->fields[i / 8] |= (1 << (i % 8));
94 /* *********** FUNCTIONS *********** */
96 void EEVEE_lights_init(EEVEE_ViewLayerData *sldata)
98 const unsigned int shadow_ubo_size = sizeof(EEVEE_Shadow) * MAX_SHADOW +
99 sizeof(EEVEE_ShadowCube) * MAX_SHADOW_CUBE +
100 sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE;
102 const DRWContextState *draw_ctx = DRW_context_state_get();
103 ViewLayer *view_layer = draw_ctx->view_layer;
104 IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
106 if (!e_data.shadow_sh) {
107 e_data.shadow_sh = DRW_shader_create(
108 datatoc_shadow_vert_glsl, datatoc_shadow_geom_glsl, datatoc_shadow_frag_glsl, NULL);
110 DynStr *ds_frag = BLI_dynstr_new();
111 BLI_dynstr_append(ds_frag, datatoc_concentric_samples_lib_glsl);
112 BLI_dynstr_append(ds_frag, datatoc_shadow_store_frag_glsl);
113 char *store_shadow_shader_str = BLI_dynstr_get_cstring(ds_frag);
114 BLI_dynstr_free(ds_frag);
116 e_data.shadow_store_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
117 store_shadow_shader_str,
119 e_data.shadow_store_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
120 store_shadow_shader_str,
124 e_data.shadow_store_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
125 store_shadow_shader_str,
127 e_data.shadow_store_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
128 store_shadow_shader_str,
132 MEM_freeN(store_shadow_shader_str);
134 e_data.shadow_copy_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
135 datatoc_shadow_copy_frag_glsl,
138 e_data.shadow_copy_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
139 datatoc_shadow_copy_frag_glsl,
144 e_data.shadow_copy_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
145 datatoc_shadow_copy_frag_glsl,
148 e_data.shadow_copy_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
149 datatoc_shadow_copy_frag_glsl,
155 if (!sldata->lamps) {
156 sldata->lamps = MEM_callocN(sizeof(EEVEE_LampsInfo), "EEVEE_LampsInfo");
157 sldata->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL);
158 sldata->shadow_ubo = DRW_uniformbuffer_create(shadow_ubo_size, NULL);
159 sldata->shadow_render_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_ShadowRender), NULL);
161 for (int i = 0; i < 2; ++i) {
162 sldata->shcasters_buffers[i].shadow_casters = MEM_callocN(sizeof(EEVEE_ShadowCaster) * SHADOW_CASTER_ALLOC_CHUNK, "EEVEE_ShadowCaster buf");
163 sldata->shcasters_buffers[i].flags = MEM_callocN(sizeof(sldata->shcasters_buffers[0].flags) * SHADOW_CASTER_ALLOC_CHUNK, "EEVEE_shcast_buffer flags buf");
164 sldata->shcasters_buffers[i].alloc_count = SHADOW_CASTER_ALLOC_CHUNK;
165 sldata->shcasters_buffers[i].count = 0;
168 sldata->lamps->shcaster_frontbuffer = &sldata->shcasters_buffers[0];
169 sldata->lamps->shcaster_backbuffer = &sldata->shcasters_buffers[1];
173 SWAP(EEVEE_ShadowCasterBuffer *, sldata->lamps->shcaster_frontbuffer, sldata->lamps->shcaster_backbuffer);
175 int sh_method = BKE_collection_engine_property_value_get_int(props, "shadow_method");
176 int sh_size = BKE_collection_engine_property_value_get_int(props, "shadow_size");
177 int sh_high_bitdepth = BKE_collection_engine_property_value_get_int(props, "shadow_high_bitdepth");
179 EEVEE_LampsInfo *linfo = sldata->lamps;
180 if ((linfo->shadow_size != sh_size) ||
181 (linfo->shadow_method != sh_method) ||
182 (linfo->shadow_high_bitdepth != sh_high_bitdepth))
184 BLI_assert((sh_size > 0) && (sh_size <= 8192));
185 DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool);
186 DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target);
187 DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target);
188 DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_blur);
189 DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_blur);
191 linfo->shadow_high_bitdepth = sh_high_bitdepth;
192 linfo->shadow_method = sh_method;
193 linfo->shadow_size = sh_size;
194 linfo->shadow_render_data.stored_texel_size = 1.0 / (float)linfo->shadow_size;
196 /* Compute adequate size for the cubemap render target.
197 * The 3.0f factor is here to make sure there is no under sampling between
198 * the octahedron mapping and the cubemap. */
199 int new_cube_target_size = (int)ceil(sqrt((float)(sh_size * sh_size) / 6.0f) * 3.0f);
201 CLAMP(new_cube_target_size, 1, 4096);
203 linfo->shadow_cube_target_size = new_cube_target_size;
204 linfo->shadow_render_data.cube_texel_size = 1.0 / (float)linfo->shadow_cube_target_size;
208 void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
210 EEVEE_LampsInfo *linfo = sldata->lamps;
212 linfo->shcaster_frontbuffer->count = 0;
213 linfo->num_light = 0;
214 linfo->num_layer = 0;
215 linfo->gpu_cube_ct = linfo->gpu_cascade_ct = linfo->gpu_shadow_ct = 0;
216 linfo->cpu_cube_ct = linfo->cpu_cascade_ct = 0;
217 memset(linfo->light_ref, 0, sizeof(linfo->light_ref));
218 memset(linfo->shadow_cube_ref, 0, sizeof(linfo->shadow_cube_ref));
219 memset(linfo->shadow_cascade_ref, 0, sizeof(linfo->shadow_cascade_ref));
220 memset(linfo->new_shadow_id, -1, sizeof(linfo->new_shadow_id));
222 /* Shadow Casters: Reset flags. */
223 memset(linfo->shcaster_backbuffer->flags, (char)SHADOW_CASTER_PRUNED, linfo->shcaster_backbuffer->alloc_count);
224 memset(linfo->shcaster_frontbuffer->flags, 0x00, linfo->shcaster_frontbuffer->alloc_count);
227 psl->shadow_cube_store_pass = DRW_pass_create("Shadow Storage Pass", DRW_STATE_WRITE_COLOR);
229 DRWShadingGroup *grp = DRW_shgroup_create(
230 e_data.shadow_store_cube_sh[linfo->shadow_method], psl->shadow_cube_store_pass);
231 DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cube_blur);
232 DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
233 DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
234 DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
238 psl->shadow_cascade_store_pass = DRW_pass_create("Shadow Cascade Storage Pass", DRW_STATE_WRITE_COLOR);
240 DRWShadingGroup *grp = DRW_shgroup_create(
241 e_data.shadow_store_cascade_sh[linfo->shadow_method], psl->shadow_cascade_store_pass);
242 DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cascade_blur);
243 DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
244 DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1);
245 DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
246 DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
250 psl->shadow_cube_copy_pass = DRW_pass_create("Shadow Copy Pass", DRW_STATE_WRITE_COLOR);
252 DRWShadingGroup *grp = DRW_shgroup_create(
253 e_data.shadow_copy_cube_sh[linfo->shadow_method], psl->shadow_cube_copy_pass);
254 DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cube_target);
255 DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
256 DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
257 DRW_shgroup_uniform_int(grp, "faceId", &linfo->current_shadow_face, 1);
258 DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
262 psl->shadow_cascade_copy_pass = DRW_pass_create("Shadow Cascade Copy Pass", DRW_STATE_WRITE_COLOR);
264 DRWShadingGroup *grp = DRW_shgroup_create(
265 e_data.shadow_copy_cascade_sh[linfo->shadow_method], psl->shadow_cascade_copy_pass);
266 DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cascade_target);
267 DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
268 DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
269 DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1);
270 DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
274 psl->shadow_cube_pass = DRW_pass_create(
276 DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
280 psl->shadow_cascade_pass = DRW_pass_create(
281 "Shadow Cascade Pass",
282 DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
286 void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
288 EEVEE_LampsInfo *linfo = sldata->lamps;
290 /* Step 1 find all lamps in the scene and setup them */
291 if (linfo->num_light >= MAX_LIGHT) {
292 printf("Too many lamps in the scene !!!\n");
295 Lamp *la = (Lamp *)ob->data;
296 EEVEE_Light *evli = linfo->light_data + linfo->num_light;
297 eevee_light_setup(ob, evli);
299 /* We do not support shadowmaps for dupli lamps. */
300 if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
305 EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
307 /* Save previous shadow id. */
308 int prev_cube_sh_id = led->prev_cube_shadow_id;
310 /* Default light without shadows */
311 led->data.ld.shadow_id = -1;
312 led->prev_cube_shadow_id = -1;
314 if (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) {
315 if (la->type == LA_SUN) {
316 int sh_nbr = 1; /* TODO : MSM */
317 int cascade_nbr = MAX_CASCADE_NUM; /* TODO : Custom cascade number */
319 if ((linfo->gpu_cascade_ct + sh_nbr) <= MAX_SHADOW_CASCADE) {
320 /* Save Light object. */
321 linfo->shadow_cascade_ref[linfo->cpu_cascade_ct] = ob;
324 EEVEE_ShadowCascadeData *data = &led->data.scad;
325 data->shadow_id = linfo->gpu_shadow_ct;
326 data->cascade_id = linfo->gpu_cascade_ct;
327 data->layer_id = linfo->num_layer;
329 /* Increment indices. */
330 linfo->gpu_shadow_ct += 1;
331 linfo->gpu_cascade_ct += sh_nbr;
332 linfo->num_layer += sh_nbr * cascade_nbr;
334 linfo->cpu_cascade_ct += 1;
337 else if (la->type == LA_SPOT || la->type == LA_LOCAL || la->type == LA_AREA) {
338 int sh_nbr = 1; /* TODO : MSM */
340 if ((linfo->gpu_cube_ct + sh_nbr) <= MAX_SHADOW_CUBE) {
341 /* Save Light object. */
342 linfo->shadow_cube_ref[linfo->cpu_cube_ct] = ob;
344 /* For light update tracking. */
345 if ((prev_cube_sh_id >= 0) &&
346 (prev_cube_sh_id < linfo->shcaster_backbuffer->count))
348 linfo->new_shadow_id[prev_cube_sh_id] = linfo->cpu_cube_ct;
350 led->prev_cube_shadow_id = linfo->cpu_cube_ct;
352 /* Saving lamp bounds for later. */
353 BLI_assert(linfo->cpu_cube_ct >= 0 && linfo->cpu_cube_ct < MAX_LIGHT);
354 copy_v3_v3(linfo->shadow_bounds[linfo->cpu_cube_ct].center, ob->obmat[3]);
355 linfo->shadow_bounds[linfo->cpu_cube_ct].radius = la->clipend;
357 EEVEE_ShadowCubeData *data = &led->data.scd;
359 data->shadow_id = linfo->gpu_shadow_ct;
360 data->cube_id = linfo->gpu_cube_ct;
361 data->layer_id = linfo->num_layer;
363 /* Increment indices. */
364 linfo->gpu_shadow_ct += 1;
365 linfo->gpu_cube_ct += sh_nbr;
366 linfo->num_layer += sh_nbr;
368 linfo->cpu_cube_ct += 1;
373 led->data.ld.light_id = linfo->num_light;
374 linfo->light_ref[linfo->num_light] = ob;
379 /* Add a shadow caster to the shadowpasses */
380 void EEVEE_lights_cache_shcaster_add(
381 EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, struct Gwn_Batch *geom, float (*obmat)[4])
383 DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cube_pass, geom, NULL);
384 DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
385 DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
386 DRW_shgroup_set_instance_count(grp, 6);
388 grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cascade_pass, geom, NULL);
389 DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
390 DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
391 DRW_shgroup_set_instance_count(grp, MAX_CASCADE_NUM);
394 void EEVEE_lights_cache_shcaster_material_add(
395 EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, struct GPUMaterial *gpumat,
396 struct Gwn_Batch *geom, struct Object *ob, float (*obmat)[4], float *alpha_threshold)
398 DRWShadingGroup *grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cube_pass, geom, ob, NULL);
400 if (grp == NULL) return;
402 DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
403 DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
405 if (alpha_threshold != NULL)
406 DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
408 DRW_shgroup_set_instance_count(grp, 6);
410 grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cascade_pass, geom, ob, NULL);
411 DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
412 DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
414 if (alpha_threshold != NULL)
415 DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
417 DRW_shgroup_set_instance_count(grp, MAX_CASCADE_NUM);
420 /* Make that object update shadow casting lamps inside its influence bounding box. */
421 void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, Object *ob)
423 if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
424 /* TODO: Special case for dupli objects because we cannot save the object pointer. */
428 EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob);
429 EEVEE_LampsInfo *linfo = sldata->lamps;
430 EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer;
431 EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer;
432 int past_id = oedata->shadow_caster_id;
434 /* Update flags in backbuffer. */
435 if (past_id > -1 && past_id < backbuffer->count) {
436 backbuffer->flags[past_id] &= ~SHADOW_CASTER_PRUNED;
438 if (oedata->need_update) {
439 backbuffer->flags[past_id] |= SHADOW_CASTER_UPDATED;
444 oedata->shadow_caster_id = frontbuffer->count++;
446 /* Make sure shadow_casters is big enough. */
447 if (oedata->shadow_caster_id >= frontbuffer->alloc_count) {
448 frontbuffer->alloc_count += SHADOW_CASTER_ALLOC_CHUNK;
449 frontbuffer->shadow_casters = MEM_reallocN(frontbuffer->shadow_casters, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
450 frontbuffer->flags = MEM_reallocN(frontbuffer->flags, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
453 EEVEE_ShadowCaster *shcaster = frontbuffer->shadow_casters + oedata->shadow_caster_id;
455 if (oedata->need_update) {
456 frontbuffer->flags[oedata->shadow_caster_id] = SHADOW_CASTER_UPDATED;
459 /* Update World AABB in frontbuffer. */
460 BoundBox *bb = BKE_object_boundbox_get(ob);
461 float min[3], max[3];
462 INIT_MINMAX(min, max);
463 for (int i = 0; i < 8; ++i) {
465 copy_v3_v3(vec, bb->vec[i]);
466 mul_m4_v3(ob->obmat, vec);
467 minmax_v3v3_v3(min, max, vec);
470 EEVEE_BoundBox *aabb = &shcaster->bbox;
471 add_v3_v3v3(aabb->center, min, max);
472 mul_v3_fl(aabb->center, 0.5f);
473 sub_v3_v3v3(aabb->halfdim, aabb->center, max);
475 aabb->halfdim[0] = fabsf(aabb->halfdim[0]);
476 aabb->halfdim[1] = fabsf(aabb->halfdim[1]);
477 aabb->halfdim[2] = fabsf(aabb->halfdim[2]);
479 oedata->need_update = false;
482 void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata)
484 EEVEE_LampsInfo *linfo = sldata->lamps;
485 DRWTextureFormat shadow_pool_format = DRW_TEX_R_32;
487 sldata->common_data.la_num_light = linfo->num_light;
489 /* Setup enough layers. */
490 /* Free textures if number mismatch. */
491 if (linfo->num_layer != linfo->cache_num_layer) {
492 DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool);
493 linfo->cache_num_layer = linfo->num_layer;
494 linfo->update_flag |= LIGHT_UPDATE_SHADOW_CUBE;
497 switch (linfo->shadow_method) {
498 case SHADOW_ESM: shadow_pool_format = ((linfo->shadow_high_bitdepth) ? DRW_TEX_R_32 : DRW_TEX_R_16); break;
499 case SHADOW_VSM: shadow_pool_format = ((linfo->shadow_high_bitdepth) ? DRW_TEX_RG_32 : DRW_TEX_RG_16); break;
501 BLI_assert(!"Incorrect Shadow Method");
505 if (!sldata->shadow_cube_target) {
506 /* TODO render everything on the same 2d render target using clip planes and no Geom Shader. */
508 sldata->shadow_cube_target = DRW_texture_create_cube(
509 linfo->shadow_cube_target_size, DRW_TEX_DEPTH_24, 0, NULL);
510 sldata->shadow_cube_blur = DRW_texture_create_cube(
511 linfo->shadow_cube_target_size, shadow_pool_format, DRW_TEX_FILTER, NULL);
514 if (!sldata->shadow_cascade_target) {
516 sldata->shadow_cascade_target = DRW_texture_create_2D_array(
517 linfo->shadow_size, linfo->shadow_size, MAX_CASCADE_NUM, DRW_TEX_DEPTH_24, 0, NULL);
518 sldata->shadow_cascade_blur = DRW_texture_create_2D_array(
519 linfo->shadow_size, linfo->shadow_size, MAX_CASCADE_NUM, shadow_pool_format, DRW_TEX_FILTER, NULL);
522 /* Initialize Textures Array first so DRW_framebuffer_init just bind them. */
523 if (!sldata->shadow_pool) {
524 /* All shadows fit in this array */
525 sldata->shadow_pool = DRW_texture_create_2D_array(
526 linfo->shadow_size, linfo->shadow_size, max_ff(1, linfo->num_layer),
527 shadow_pool_format, DRW_TEX_FILTER, NULL);
531 DRWFboTexture tex_cascade = {&sldata->shadow_cube_target, DRW_TEX_DEPTH_24, 0};
532 DRW_framebuffer_init(&sldata->shadow_target_fb, &draw_engine_eevee_type,
533 linfo->shadow_size, linfo->shadow_size,
537 DRWFboTexture tex_pool = {&sldata->shadow_pool, shadow_pool_format, DRW_TEX_FILTER};
538 DRW_framebuffer_init(&sldata->shadow_store_fb, &draw_engine_eevee_type,
539 linfo->shadow_size, linfo->shadow_size,
543 DRW_framebuffer_texture_detach(sldata->shadow_cube_target);
545 /* Update Lamps UBOs. */
546 EEVEE_lights_update(sldata);
549 /* Update buffer with lamp data */
550 static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
552 Lamp *la = (Lamp *)ob->data;
553 float mat[4][4], scale[3], power;
556 copy_v3_v3(evli->position, ob->obmat[3]);
559 copy_v3_v3(evli->color, &la->r);
561 /* Influence Radius */
562 evli->dist = la->dist;
565 normalize_m4_m4_ex(mat, ob->obmat, scale);
566 copy_v3_v3(evli->forwardvec, mat[2]);
567 normalize_v3(evli->forwardvec);
568 negate_v3(evli->forwardvec);
570 copy_v3_v3(evli->rightvec, mat[0]);
571 normalize_v3(evli->rightvec);
573 copy_v3_v3(evli->upvec, mat[1]);
574 normalize_v3(evli->upvec);
576 /* Spot size & blend */
577 if (la->type == LA_SPOT) {
578 evli->sizex = scale[0] / scale[2];
579 evli->sizey = scale[1] / scale[2];
580 evli->spotsize = cosf(la->spotsize * 0.5f);
581 evli->spotblend = (1.0f - evli->spotsize) * la->spotblend;
582 evli->radius = max_ff(0.001f, la->area_size);
584 else if (la->type == LA_AREA) {
585 evli->sizex = max_ff(0.0001f, la->area_size * scale[0] * 0.5f);
586 if (la->area_shape == LA_AREA_RECT) {
587 evli->sizey = max_ff(0.0001f, la->area_sizey * scale[1] * 0.5f);
590 evli->sizey = max_ff(0.0001f, la->area_size * scale[1] * 0.5f);
594 evli->radius = max_ff(0.001f, la->area_size);
597 /* Make illumination power constant */
598 if (la->type == LA_AREA) {
599 power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) * /* 1/(w*h*Pi) */
600 80.0f; /* XXX : Empirical, Fit cycles power */
602 else if (la->type == LA_SPOT || la->type == LA_LOCAL) {
603 power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(4*r²*Pi²) */
604 M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */
606 /* for point lights (a.k.a radius == 0.0) */
607 // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
610 power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(r²*Pi) */
611 12.5f; /* XXX : Empirical, Fit cycles power */
613 mul_v3_fl(evli->color, power * la->energy);
616 evli->lamptype = (float)la->type;
618 /* No shadow by default */
619 evli->shadowid = -1.0f;
622 static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
624 EEVEE_ShadowCubeData *sh_data = &led->data.scd;
625 EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
626 EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
627 EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + sh_data->cube_id;
628 Lamp *la = (Lamp *)ob->data;
630 int sh_nbr = 1; /* TODO: MSM */
632 for (int i = 0; i < sh_nbr; ++i) {
633 /* TODO : choose MSM sample point here. */
634 copy_v3_v3(cube_data->position, ob->obmat[3]);
637 ubo_data->bias = 0.05f * la->bias;
638 ubo_data->near = la->clipsta;
639 ubo_data->far = la->clipend;
640 ubo_data->exp = (linfo->shadow_method == SHADOW_VSM) ? la->bleedbias : la->bleedexp;
642 evli->shadowid = (float)(sh_data->shadow_id);
643 ubo_data->shadow_start = (float)(sh_data->layer_id);
644 ubo_data->data_start = (float)(sh_data->cube_id);
645 ubo_data->multi_shadow_count = (float)(sh_nbr);
646 ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */
648 ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
649 ubo_data->contact_bias = 0.05f * la->contact_bias;
650 ubo_data->contact_spread = la->contact_spread;
651 ubo_data->contact_thickness = la->contact_thickness;
654 #define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
656 static double round_to_digits(double value, int digits)
658 double factor = pow(10.0, digits - ceil(log10(fabs(value))));
659 return round(value * factor) / factor;
662 static void frustum_min_bounding_sphere(const float corners[8][3], float r_center[3], float *r_radius)
664 #if 0 /* Simple solution but waste too much space. */
665 float minvec[3], maxvec[3];
667 /* compute the bounding box */
668 INIT_MINMAX(minvec, maxvec);
669 for (int i = 0; i < 8; ++i) {
670 minmax_v3v3_v3(minvec, maxvec, corners[i]);
673 /* compute the bounding sphere of this box */
674 r_radius = len_v3v3(minvec, maxvec) * 0.5f;
675 add_v3_v3v3(r_center, minvec, maxvec);
676 mul_v3_fl(r_center, 0.5f);
678 /* Find averaged center. */
680 for (int i = 0; i < 8; ++i) {
681 add_v3_v3(r_center, corners[i]);
683 mul_v3_fl(r_center, 1.0f / 8.0f);
685 /* Search the largest distance from the sphere center. */
687 for (int i = 0; i < 8; ++i) {
688 float rad = len_squared_v3v3(corners[i], r_center);
689 if (rad > *r_radius) {
694 /* TODO try to reduce the radius further by moving the center.
695 * Remember we need a __stable__ solution! */
697 /* Try to reduce float imprecision leading to shimmering. */
698 *r_radius = (float)round_to_digits(sqrtf(*r_radius), 3);
702 static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
704 Lamp *la = (Lamp *)ob->data;
706 /* Camera Matrices */
707 float persmat[4][4], persinv[4][4];
708 float viewprojmat[4][4], projinv[4][4];
709 float view_near, view_far;
710 float near_v[4] = {0.0f, 0.0f, -1.0f, 1.0f};
711 float far_v[4] = {0.0f, 0.0f, 1.0f, 1.0f};
712 bool is_persp = DRW_viewport_is_persp_get();
713 DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
714 invert_m4_m4(persinv, persmat);
715 /* FIXME : Get near / far from Draw manager? */
716 DRW_viewport_matrix_get(viewprojmat, DRW_MAT_WIN);
717 invert_m4_m4(projinv, viewprojmat);
718 mul_m4_v4(projinv, near_v);
719 mul_m4_v4(projinv, far_v);
720 view_near = near_v[2];
721 view_far = far_v[2]; /* TODO: Should be a shadow parameter */
723 view_near /= near_v[3];
724 view_far /= far_v[3];
728 float viewmat[4][4], projmat[4][4];
729 int sh_nbr = 1; /* TODO : MSM */
730 int cascade_nbr = la->cascade_count;
732 EEVEE_ShadowCascadeData *sh_data = &led->data.scad;
733 EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
734 EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
735 EEVEE_ShadowCascade *cascade_data = linfo->shadow_cascade_data + sh_data->cascade_id;
737 /* The technique consists into splitting
738 * the view frustum into several sub-frustum
739 * that are individually receiving one shadow map */
741 float csm_start, csm_end;
744 csm_start = view_near;
745 csm_end = max_ff(view_far, -la->cascade_max_dist);
746 /* Avoid artifacts */
747 csm_end = min_ff(view_near, csm_end);
750 csm_start = -view_far;
755 for (int c = 0; c < MAX_CASCADE_NUM; ++c) {
756 cascade_data->split_start[c] = csm_end;
757 cascade_data->split_end[c] = csm_end;
760 /* Compute split planes */
761 float splits_start_ndc[MAX_CASCADE_NUM];
762 float splits_end_ndc[MAX_CASCADE_NUM];
766 float p[4] = {1.0f, 1.0f, csm_start, 1.0f};
767 /* TODO: we don't need full m4 multiply here */
768 mul_m4_v4(viewprojmat, p);
769 splits_start_ndc[0] = p[2];
771 splits_start_ndc[0] /= p[3];
777 float p[4] = {1.0f, 1.0f, csm_end, 1.0f};
778 /* TODO: we don't need full m4 multiply here */
779 mul_m4_v4(viewprojmat, p);
780 splits_end_ndc[cascade_nbr - 1] = p[2];
782 splits_end_ndc[cascade_nbr - 1] /= p[3];
786 cascade_data->split_start[0] = csm_start;
787 cascade_data->split_end[cascade_nbr - 1] = csm_end;
789 for (int c = 1; c < cascade_nbr; ++c) {
791 float linear_split = LERP(((float)(c) / (float)cascade_nbr), csm_start, csm_end);
792 float exp_split = csm_start * powf(csm_end / csm_start, (float)(c) / (float)cascade_nbr);
795 cascade_data->split_start[c] = LERP(la->cascade_exponent, linear_split, exp_split);
798 cascade_data->split_start[c] = linear_split;
800 cascade_data->split_end[c - 1] = cascade_data->split_start[c];
802 /* Add some overlap for smooth transition */
803 cascade_data->split_start[c] = LERP(la->cascade_fade, cascade_data->split_end[c - 1],
804 (c > 1) ? cascade_data->split_end[c - 2] : cascade_data->split_start[0]);
808 float p[4] = {1.0f, 1.0f, cascade_data->split_start[c], 1.0f};
809 /* TODO: we don't need full m4 multiply here */
810 mul_m4_v4(viewprojmat, p);
811 splits_start_ndc[c] = p[2];
814 splits_start_ndc[c] /= p[3];
819 float p[4] = {1.0f, 1.0f, cascade_data->split_end[c - 1], 1.0f};
820 /* TODO: we don't need full m4 multiply here */
821 mul_m4_v4(viewprojmat, p);
822 splits_end_ndc[c - 1] = p[2];
825 splits_end_ndc[c - 1] /= p[3];
830 /* Set last cascade split fade distance into the first split_start. */
831 float prev_split = (cascade_nbr > 1) ? cascade_data->split_end[cascade_nbr - 2] : cascade_data->split_start[0];
832 cascade_data->split_start[0] = LERP(la->cascade_fade, cascade_data->split_end[cascade_nbr - 1], prev_split);
834 /* For each cascade */
835 for (int c = 0; c < cascade_nbr; ++c) {
836 /* Given 8 frustum corners */
837 float corners[8][3] = {
839 {-1.0f, -1.0f, splits_start_ndc[c]},
840 { 1.0f, -1.0f, splits_start_ndc[c]},
841 {-1.0f, 1.0f, splits_start_ndc[c]},
842 { 1.0f, 1.0f, splits_start_ndc[c]},
844 {-1.0f, -1.0f, splits_end_ndc[c]},
845 { 1.0f, -1.0f, splits_end_ndc[c]},
846 {-1.0f, 1.0f, splits_end_ndc[c]},
847 { 1.0f, 1.0f, splits_end_ndc[c]}
850 /* Transform them into world space */
851 for (int i = 0; i < 8; ++i) {
852 mul_project_m4_v3(persinv, corners[i]);
856 frustum_min_bounding_sphere(corners, center, &(sh_data->radius[c]));
858 /* Project into lightspace */
859 invert_m4_m4(viewmat, ob->obmat);
860 normalize_v3(viewmat[0]);
861 normalize_v3(viewmat[1]);
862 normalize_v3(viewmat[2]);
864 mul_mat3_m4_v3(viewmat, center);
866 /* Snap projection center to nearest texel to cancel shimmering. */
867 float shadow_origin[2], shadow_texco[2];
868 /* Light to texture space. */
869 mul_v2_v2fl(shadow_origin, center, linfo->shadow_size / (2.0f * sh_data->radius[c]));
871 /* Find the nearest texel. */
872 shadow_texco[0] = roundf(shadow_origin[0]);
873 shadow_texco[1] = roundf(shadow_origin[1]);
875 /* Compute offset. */
876 sub_v2_v2(shadow_texco, shadow_origin);
877 mul_v2_fl(shadow_texco, (2.0f * sh_data->radius[c]) / linfo->shadow_size); /* Texture to light space. */
880 add_v2_v2(center, shadow_texco);
882 /* Expand the projection to cover frustum range */
883 orthographic_m4(projmat,
884 center[0] - sh_data->radius[c],
885 center[0] + sh_data->radius[c],
886 center[1] - sh_data->radius[c],
887 center[1] + sh_data->radius[c],
888 la->clipsta, la->clipend);
890 mul_m4_m4m4(sh_data->viewprojmat[c], projmat, viewmat);
891 mul_m4_m4m4(cascade_data->shadowmat[c], texcomat, sh_data->viewprojmat[c]);
894 ubo_data->bias = 0.05f * la->bias;
895 ubo_data->near = la->clipsta;
896 ubo_data->far = la->clipend;
897 ubo_data->exp = (linfo->shadow_method == SHADOW_VSM) ? la->bleedbias : la->bleedexp;
899 evli->shadowid = (float)(sh_data->shadow_id);
900 ubo_data->shadow_start = (float)(sh_data->layer_id);
901 ubo_data->data_start = (float)(sh_data->cascade_id);
902 ubo_data->multi_shadow_count = (float)(sh_nbr);
903 ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */
905 ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
906 ubo_data->contact_bias = 0.05f * la->contact_bias;
907 ubo_data->contact_spread = la->contact_spread;
908 ubo_data->contact_thickness = la->contact_thickness;
911 /* Used for checking if object is inside the shadow volume. */
912 static bool sphere_bbox_intersect(const EEVEE_BoundSphere *bs, const EEVEE_BoundBox *bb)
914 /* We are testing using a rougher AABB vs AABB test instead of full AABB vs Sphere. */
915 /* TODO test speed with AABB vs Sphere. */
916 bool x = fabsf(bb->center[0] - bs->center[0]) <= (bb->halfdim[0] + bs->radius);
917 bool y = fabsf(bb->center[1] - bs->center[1]) <= (bb->halfdim[1] + bs->radius);
918 bool z = fabsf(bb->center[2] - bs->center[2]) <= (bb->halfdim[2] + bs->radius);
923 void EEVEE_lights_update(EEVEE_ViewLayerData *sldata)
925 EEVEE_LampsInfo *linfo = sldata->lamps;
929 EEVEE_ShadowCaster *shcaster;
930 EEVEE_BoundSphere *bsphere;
931 EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer;
932 EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer;
934 EEVEE_LightBits update_bits = {{0}};
935 if ((linfo->update_flag & LIGHT_UPDATE_SHADOW_CUBE) != 0) {
936 /* Update all lights. */
937 lightbits_set_all(&update_bits, true);
940 /* Search for deleted shadow casters and if shcaster WAS in shadow radius. */
941 /* No need to run this if we already update all lamps. */
942 EEVEE_LightBits past_bits = {{0}};
943 EEVEE_LightBits curr_bits = {{0}};
944 shcaster = backbuffer->shadow_casters;
945 flag = backbuffer->flags;
946 for (i = 0; i < backbuffer->count; ++i, ++flag, ++shcaster) {
947 /* If the shadowcaster has been deleted or updated. */
949 /* Add the lamps that were intersecting with its BBox. */
950 lightbits_or(&past_bits, &shcaster->bits);
953 /* Convert old bits to new bits and add result to final update bits. */
954 /* NOTE: This might be overkill since all lights are tagged to refresh if
955 * the light count changes. */
956 lightbits_convert(&curr_bits, &past_bits, linfo->new_shadow_id, MAX_LIGHT);
957 lightbits_or(&update_bits, &curr_bits);
960 /* Search for updates in current shadow casters. */
961 shcaster = frontbuffer->shadow_casters;
962 flag = frontbuffer->flags;
963 for (i = 0; i < frontbuffer->count; i++, flag++, shcaster++) {
964 /* Run intersection checks to fill the bitfields. */
965 bsphere = linfo->shadow_bounds;
966 for (int j = 0; j < linfo->cpu_cube_ct; j++, bsphere++) {
967 bool iter = sphere_bbox_intersect(bsphere, &shcaster->bbox);
968 lightbits_set_single(&shcaster->bits, j, iter);
970 /* Only add to final bits if objects has been updated. */
972 lightbits_or(&update_bits, &shcaster->bits);
976 /* Setup shadow cube in UBO and tag for update if necessary. */
977 for (i = 0; (i < MAX_SHADOW_CUBE) && (ob = linfo->shadow_cube_ref[i]); i++) {
978 EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
980 eevee_shadow_cube_setup(ob, linfo, led);
981 if (lightbits_get(&update_bits, i) != 0) {
982 led->need_update = true;
986 /* Resize shcasters buffers if too big. */
987 if (frontbuffer->alloc_count - frontbuffer->count > SHADOW_CASTER_ALLOC_CHUNK) {
988 frontbuffer->alloc_count = (frontbuffer->count / SHADOW_CASTER_ALLOC_CHUNK) * SHADOW_CASTER_ALLOC_CHUNK;
989 frontbuffer->alloc_count += (frontbuffer->count % SHADOW_CASTER_ALLOC_CHUNK != 0) ? SHADOW_CASTER_ALLOC_CHUNK : 0;
990 frontbuffer->shadow_casters = MEM_reallocN(frontbuffer->shadow_casters, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
991 frontbuffer->flags = MEM_reallocN(frontbuffer->flags, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
995 /* this refresh lamps shadow buffers */
996 void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
998 EEVEE_LampsInfo *linfo = sldata->lamps;
1001 float clear_col[4] = {FLT_MAX};
1003 /* Cube Shadow Maps */
1004 DRW_stats_group_start("Cube Shadow Maps");
1005 DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cube_target, 0, 0);
1006 /* Render each shadow to one layer of the array */
1007 for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
1008 EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
1009 Lamp *la = (Lamp *)ob->data;
1011 float cube_projmat[4][4];
1012 perspective_m4(cube_projmat, -la->clipsta, la->clipsta, -la->clipsta, la->clipsta, la->clipsta, la->clipend);
1014 if (!led->need_update) {
1018 EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
1019 EEVEE_ShadowCubeData *evscd = &led->data.scd;
1021 srd->clip_near = la->clipsta;
1022 srd->clip_far = la->clipend;
1023 copy_v3_v3(srd->position, ob->obmat[3]);
1024 for (int j = 0; j < 6; j++) {
1028 negate_v3_v3(tmp[3], ob->obmat[3]);
1029 mul_m4_m4m4(srd->viewmat[j], cubefacemat[j], tmp);
1031 mul_m4_m4m4(srd->shadowmat[j], cube_projmat, srd->viewmat[j]);
1033 DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
1035 DRW_framebuffer_bind(sldata->shadow_target_fb);
1036 DRW_framebuffer_clear(true, true, false, clear_col, 1.0f);
1038 /* Render shadow cube */
1039 DRW_draw_pass(psl->shadow_cube_pass);
1041 /* 0.001f is arbitrary, but it should be relatively small so that filter size is not too big. */
1042 float filter_texture_size = la->soft * 0.001f;
1043 float filter_pixel_size = ceil(filter_texture_size / linfo->shadow_render_data.cube_texel_size);
1044 linfo->filter_size = linfo->shadow_render_data.cube_texel_size * ((filter_pixel_size > 1.0f) ? 1.5f : 0.0f);
1046 /* TODO: OPTI: Filter all faces in one/two draw call */
1047 for (linfo->current_shadow_face = 0;
1048 linfo->current_shadow_face < 6;
1049 linfo->current_shadow_face++)
1051 /* Copy using a small 3x3 box filter */
1052 DRW_framebuffer_cubeface_attach(sldata->shadow_store_fb, sldata->shadow_cube_blur, 0, linfo->current_shadow_face, 0);
1053 DRW_framebuffer_bind(sldata->shadow_store_fb);
1054 DRW_draw_pass(psl->shadow_cube_copy_pass);
1055 DRW_framebuffer_texture_detach(sldata->shadow_cube_blur);
1058 /* Push it to shadowmap array */
1060 /* Adjust constants if concentric samples change. */
1061 const float max_filter_size = 7.5f;
1062 const float previous_box_filter_size = 9.0f; /* Dunno why but that works. */
1063 const int max_sample = 256;
1065 if (filter_pixel_size > 2.0f) {
1066 linfo->filter_size = linfo->shadow_render_data.cube_texel_size * max_filter_size * previous_box_filter_size;
1067 filter_pixel_size = max_ff(0.0f, filter_pixel_size - 3.0f);
1068 /* Compute number of concentric samples. Depends directly on filter size. */
1069 float pix_size_sqr = filter_pixel_size * filter_pixel_size;
1070 srd->shadow_samples_ct = min_ii(max_sample, 4 + 8 * (int)filter_pixel_size + 4 * (int)(pix_size_sqr));
1073 linfo->filter_size = 0.0f;
1074 srd->shadow_samples_ct = 4;
1076 srd->shadow_inv_samples_ct = 1.0f / (float)srd->shadow_samples_ct;
1077 DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
1079 DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, evscd->layer_id, 0);
1080 DRW_framebuffer_bind(sldata->shadow_store_fb);
1081 DRW_draw_pass(psl->shadow_cube_store_pass);
1083 led->need_update = false;
1085 linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE;
1087 DRW_framebuffer_texture_detach(sldata->shadow_cube_target);
1088 DRW_stats_group_end();
1090 /* Cascaded Shadow Maps */
1091 DRW_stats_group_start("Cascaded Shadow Maps");
1092 DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cascade_target, 0, 0);
1093 for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
1094 EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
1095 Lamp *la = (Lamp *)ob->data;
1097 EEVEE_ShadowCascadeData *evscd = &led->data.scad;
1098 EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
1100 eevee_shadow_cascade_setup(ob, linfo, led);
1102 srd->clip_near = la->clipsta;
1103 srd->clip_far = la->clipend;
1104 for (int j = 0; j < la->cascade_count; ++j) {
1105 copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
1107 DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
1109 DRW_framebuffer_bind(sldata->shadow_target_fb);
1110 DRW_framebuffer_clear(false, true, false, NULL, 1.0);
1112 /* Render shadow cascades */
1113 DRW_draw_pass(psl->shadow_cascade_pass);
1115 /* TODO: OPTI: Filter all cascade in one/two draw call */
1116 for (linfo->current_shadow_cascade = 0;
1117 linfo->current_shadow_cascade < la->cascade_count;
1118 ++linfo->current_shadow_cascade)
1120 /* 0.01f factor to convert to percentage */
1121 float filter_texture_size = la->soft * 0.01f / evscd->radius[linfo->current_shadow_cascade];
1122 float filter_pixel_size = ceil(linfo->shadow_size * filter_texture_size);
1124 /* Copy using a small 3x3 box filter */
1125 linfo->filter_size = linfo->shadow_render_data.stored_texel_size * ((filter_pixel_size > 1.0f) ? 1.0f : 0.0f);
1126 DRW_framebuffer_texture_layer_attach(
1127 sldata->shadow_store_fb, sldata->shadow_cascade_blur, 0, linfo->current_shadow_cascade, 0);
1128 DRW_framebuffer_bind(sldata->shadow_store_fb);
1129 DRW_draw_pass(psl->shadow_cascade_copy_pass);
1130 DRW_framebuffer_texture_detach(sldata->shadow_cascade_blur);
1132 /* Push it to shadowmap array and blur more */
1134 /* Adjust constants if concentric samples change. */
1135 const float max_filter_size = 7.5f;
1136 const float previous_box_filter_size = 3.2f; /* Arbitrary: less banding */
1137 const int max_sample = 256;
1139 if (filter_pixel_size > 2.0f) {
1140 linfo->filter_size = linfo->shadow_render_data.stored_texel_size * max_filter_size * previous_box_filter_size;
1141 filter_pixel_size = max_ff(0.0f, filter_pixel_size - 3.0f);
1142 /* Compute number of concentric samples. Depends directly on filter size. */
1143 float pix_size_sqr = filter_pixel_size * filter_pixel_size;
1144 srd->shadow_samples_ct = min_ii(max_sample, 4 + 8 * (int)filter_pixel_size + 4 * (int)(pix_size_sqr));
1147 linfo->filter_size = 0.0f;
1148 srd->shadow_samples_ct = 4;
1150 srd->shadow_inv_samples_ct = 1.0f / (float)srd->shadow_samples_ct;
1151 DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
1153 int layer = evscd->layer_id + linfo->current_shadow_cascade;
1154 DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, layer, 0);
1155 DRW_framebuffer_bind(sldata->shadow_store_fb);
1156 DRW_draw_pass(psl->shadow_cascade_store_pass);
1160 DRW_framebuffer_texture_detach(sldata->shadow_cascade_target);
1161 DRW_stats_group_end();
1163 DRW_uniformbuffer_update(sldata->light_ubo, &linfo->light_data);
1164 DRW_uniformbuffer_update(sldata->shadow_ubo, &linfo->shadow_data); /* Update all data at once */
1167 void EEVEE_lights_free(void)
1169 DRW_SHADER_FREE_SAFE(e_data.shadow_sh);
1170 for (int i = 0; i < SHADOW_METHOD_MAX; ++i) {
1171 DRW_SHADER_FREE_SAFE(e_data.shadow_store_cube_sh[i]);
1172 DRW_SHADER_FREE_SAFE(e_data.shadow_store_cascade_sh[i]);
1173 DRW_SHADER_FREE_SAFE(e_data.shadow_copy_cube_sh[i]);
1174 DRW_SHADER_FREE_SAFE(e_data.shadow_copy_cascade_sh[i]);