2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * Copyright 2016, Blender Foundation.
20 * \ingroup draw_engine
23 #include "DRW_render.h"
25 #include "BLI_utildefines.h"
28 #include "DNA_world_types.h"
29 #include "DNA_texture_types.h"
30 #include "DNA_image_types.h"
31 #include "DNA_lightprobe_types.h"
32 #include "DNA_view3d_types.h"
34 #include "BKE_collection.h"
35 #include "BKE_object.h"
36 #include "MEM_guardedalloc.h"
38 #include "GPU_material.h"
39 #include "GPU_texture.h"
41 #include "DEG_depsgraph_query.h"
43 #include "eevee_lightcache.h"
44 #include "eevee_private.h"
51 struct GPUTexture *hammersley;
52 struct GPUTexture *planar_pool_placeholder;
53 struct GPUTexture *depth_placeholder;
54 struct GPUTexture *depth_array_placeholder;
55 struct GPUTexture *cube_face_minmaxz;
57 struct GPUVertFormat *format_probe_display_cube;
58 struct GPUVertFormat *format_probe_display_planar;
59 } e_data = {NULL}; /* Engine data */
62 /* *********** FUNCTIONS *********** */
64 /* TODO find a better way than this. This does not support dupli objects if
65 * the original object is hidden. */
66 bool EEVEE_lightprobes_obj_visibility_cb(bool vis_in, void *user_data)
68 EEVEE_ObjectEngineData *oed = (EEVEE_ObjectEngineData *)user_data;
70 /* test disabled if group is NULL */
71 if (oed->test_data->collection == NULL) {
75 if (oed->test_data->cached == false) {
76 oed->ob_vis_dirty = true;
79 /* early out, don't need to compute ob_vis yet. */
80 if (vis_in == false) {
84 if (oed->ob_vis_dirty) {
85 oed->ob_vis_dirty = false;
86 oed->ob_vis = BKE_collection_has_object_recursive(oed->test_data->collection, oed->ob);
87 oed->ob_vis = (oed->test_data->invert) ? !oed->ob_vis : oed->ob_vis;
90 return vis_in && oed->ob_vis;
93 static struct GPUTexture *create_hammersley_sample_texture(int samples)
95 struct GPUTexture *tex;
96 float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * samples, "hammersley_tex");
99 for (i = 0; i < samples; i++) {
101 BLI_hammersley_1D(i, &dphi);
102 float phi = (float)dphi * 2.0f * M_PI;
103 texels[i][0] = cosf(phi);
104 texels[i][1] = sinf(phi);
107 tex = DRW_texture_create_1D(samples, GPU_RG16F, DRW_TEX_WRAP, (float *)texels);
112 static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
114 EEVEE_TextureList *txl = vedata->txl;
116 /* XXX TODO OPTIMISATION : This is a complete waist of texture memory.
117 * Instead of allocating each planar probe for each viewport,
118 * only alloc them once using the biggest viewport resolution. */
119 const float *viewport_size = DRW_viewport_size_get();
121 /* TODO get screen percentage from layer setting */
122 // const DRWContextState *draw_ctx = DRW_context_state_get();
123 // ViewLayer *view_layer = draw_ctx->view_layer;
124 float screen_percentage = 1.0f;
126 int width = (int)(viewport_size[0] * screen_percentage);
127 int height = (int)(viewport_size[1] * screen_percentage);
129 /* We need an Array texture so allocate it ourself */
130 if (!txl->planar_pool) {
131 if (num_planar_ref > 0) {
132 txl->planar_pool = DRW_texture_create_2D_array(width, height, max_ff(1, num_planar_ref),
133 GPU_R11F_G11F_B10F, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
134 txl->planar_depth = DRW_texture_create_2D_array(width, height, max_ff(1, num_planar_ref),
135 GPU_DEPTH_COMPONENT24, 0, NULL);
137 else if (num_planar_ref == 0) {
138 /* Makes Opengl Happy : Create a placeholder texture that will never be sampled but still bound to shader. */
139 txl->planar_pool = DRW_texture_create_2D_array(1, 1, 1, GPU_RGBA8, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
140 txl->planar_depth = DRW_texture_create_2D_array(1, 1, 1, GPU_DEPTH_COMPONENT24, 0, NULL);
145 void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
147 EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
148 EEVEE_StorageList *stl = vedata->stl;
150 const DRWContextState *draw_ctx = DRW_context_state_get();
151 const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
153 if (!e_data.hammersley) {
154 EEVEE_shaders_lightprobe_shaders_init();
155 e_data.hammersley = create_hammersley_sample_texture(HAMMERSLEY_SIZE);
158 /* Use fallback if we don't have gpu texture allocated an we cannot restore them. */
159 bool use_fallback_lightcache = (scene_eval->eevee.light_cache == NULL) ||
160 ((scene_eval->eevee.light_cache->grid_tx.tex == NULL) &&
161 (scene_eval->eevee.light_cache->grid_tx.data == NULL)) ||
162 ((scene_eval->eevee.light_cache->cube_tx.tex == NULL) &&
163 (scene_eval->eevee.light_cache->cube_tx.data == NULL));
165 if (use_fallback_lightcache && (sldata->fallback_lightcache == NULL)) {
166 #if defined(IRRADIANCE_SH_L2)
168 #elif defined(IRRADIANCE_CUBEMAP)
170 #elif defined(IRRADIANCE_HL2)
173 int cube_res = OCTAHEDRAL_SIZE_FROM_CUBESIZE(scene_eval->eevee.gi_cubemap_resolution);
174 int vis_res = scene_eval->eevee.gi_visibility_resolution;
175 sldata->fallback_lightcache = EEVEE_lightcache_create(1, 1, cube_res, vis_res, (int[3]){grid_res, grid_res, 1});
178 stl->g_data->light_cache = (use_fallback_lightcache) ? sldata->fallback_lightcache : scene_eval->eevee.light_cache;
180 EEVEE_lightcache_load(stl->g_data->light_cache);
182 if (!sldata->probes) {
183 sldata->probes = MEM_callocN(sizeof(EEVEE_LightProbesInfo), "EEVEE_LightProbesInfo");
184 sldata->probe_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightProbe) * MAX_PROBE, NULL);
185 sldata->grid_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightGrid) * MAX_GRID, NULL);
186 sldata->planar_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_PlanarReflection) * MAX_PLANAR, NULL);
189 common_data->prb_num_planar = 0;
190 common_data->prb_num_render_cube = 1;
191 common_data->prb_num_render_grid = 1;
193 common_data->spec_toggle = true;
194 common_data->ssr_toggle = true;
195 common_data->sss_toggle = true;
197 /* Placeholder planar pool: used when rendering planar reflections (avoid dependency loop). */
198 if (!e_data.planar_pool_placeholder) {
199 e_data.planar_pool_placeholder = DRW_texture_create_2D_array(1, 1, 1, GPU_RGBA8, DRW_TEX_FILTER, NULL);
203 /* Only init the passes useful for rendering the light cache. */
204 void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, GPUTexture *rt_color, GPUTexture *rt_depth)
206 EEVEE_PassList *psl = vedata->psl;
207 LightCache *light_cache = vedata->stl->g_data->light_cache;
208 EEVEE_LightProbesInfo *pinfo = sldata->probes;
211 psl->probe_glossy_compute = DRW_pass_create("LightProbe Glossy Compute", DRW_STATE_WRITE_COLOR);
213 DRWShadingGroup *grp = DRW_shgroup_create(
214 EEVEE_shaders_probe_filter_glossy_sh_get(), psl->probe_glossy_compute);
216 DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
217 DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_len, 1);
218 DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->samples_len_inv, 1);
219 DRW_shgroup_uniform_float(grp, "roughnessSquared", &pinfo->roughness, 1);
220 DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1);
221 DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1);
222 DRW_shgroup_uniform_float(grp, "texelSize", &pinfo->texel_size, 1);
223 DRW_shgroup_uniform_float(grp, "paddingSize", &pinfo->padding_size, 1);
224 DRW_shgroup_uniform_float(grp, "fireflyFactor", &pinfo->firefly_fac, 1);
225 DRW_shgroup_uniform_int(grp, "Layer", &pinfo->layer, 1);
226 DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
227 // DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
228 DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
229 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
231 struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
232 DRW_shgroup_call_add(grp, geom, NULL);
236 psl->probe_diffuse_compute = DRW_pass_create("LightProbe Diffuse Compute", DRW_STATE_WRITE_COLOR);
238 DRWShadingGroup *grp = DRW_shgroup_create(
239 EEVEE_shaders_probe_filter_diffuse_sh_get(), psl->probe_diffuse_compute);
240 #ifdef IRRADIANCE_SH_L2
241 DRW_shgroup_uniform_int(grp, "probeSize", &pinfo->shres, 1);
243 DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_len, 1);
244 DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->samples_len_inv, 1);
245 DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1);
246 DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1);
247 DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
249 DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
250 DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
251 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
253 struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
254 DRW_shgroup_call_add(grp, geom, NULL);
258 psl->probe_visibility_compute = DRW_pass_create("LightProbe Visibility Compute", DRW_STATE_WRITE_COLOR);
260 DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_filter_visibility_sh_get(), psl->probe_visibility_compute);
261 DRW_shgroup_uniform_int(grp, "outputSize", &pinfo->shres, 1);
262 DRW_shgroup_uniform_float(grp, "visibilityRange", &pinfo->visibility_range, 1);
263 DRW_shgroup_uniform_float(grp, "visibilityBlur", &pinfo->visibility_blur, 1);
264 DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_len, 1);
265 DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->samples_len_inv, 1);
266 DRW_shgroup_uniform_float(grp, "storedTexelSize", &pinfo->texel_size, 1);
267 DRW_shgroup_uniform_float(grp, "nearClip", &pinfo->near_clip, 1);
268 DRW_shgroup_uniform_float(grp, "farClip", &pinfo->far_clip, 1);
269 DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
270 DRW_shgroup_uniform_texture(grp, "probeDepth", rt_depth);
271 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
273 struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
274 DRW_shgroup_call_add(grp, geom, NULL);
278 psl->probe_grid_fill = DRW_pass_create("LightProbe Grid Floodfill", DRW_STATE_WRITE_COLOR);
280 DRWShadingGroup *grp = DRW_shgroup_create(
281 EEVEE_shaders_probe_grid_fill_sh_get(), psl->probe_grid_fill);
283 DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &light_cache->grid_tx.tex);
285 struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
286 DRW_shgroup_call_add(grp, geom, NULL);
290 void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
292 EEVEE_TextureList *txl = vedata->txl;
293 EEVEE_PassList *psl = vedata->psl;
294 EEVEE_StorageList *stl = vedata->stl;
295 EEVEE_LightProbesInfo *pinfo = sldata->probes;
296 LightCache *lcache = stl->g_data->light_cache;
297 const DRWContextState *draw_ctx = DRW_context_state_get();
298 const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
300 pinfo->num_planar = 0;
301 pinfo->vis_data.collection = NULL;
302 pinfo->do_grid_update = false;
303 pinfo->do_cube_update = false;
306 psl->probe_background = DRW_pass_create("World Probe Background Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
308 struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
309 DRWShadingGroup *grp = NULL;
311 Scene *scene = draw_ctx->scene;
312 World *wo = scene->world;
314 const float *col = G_draw.block.colorBackground;
317 EEVEE_lookdev_cache_init(vedata, &grp, psl->probe_background, wo, pinfo);
322 if (wo->use_nodes && wo->nodetree) {
323 static float error_col[3] = {1.0f, 0.0f, 1.0f};
324 struct GPUMaterial *gpumat = EEVEE_material_world_lightprobe_get(scene, wo);
326 eGPUMaterialStatus status = GPU_material_status(gpumat);
329 case GPU_MAT_SUCCESS:
330 grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
331 DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
332 /* TODO (fclem): remove those (need to clean the GLSL files). */
333 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
334 DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
335 DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
336 DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
337 DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
338 DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
339 DRW_shgroup_call_add(grp, geom, NULL);
348 /* Fallback if shader fails or if not using nodetree. */
350 grp = DRW_shgroup_create(EEVEE_shaders_probe_default_sh_get(), psl->probe_background);
351 DRW_shgroup_uniform_vec3(grp, "color", col, 1);
352 DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
353 DRW_shgroup_call_add(grp, geom, NULL);
357 if (DRW_state_draw_support() && !LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
358 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
359 psl->probe_display = DRW_pass_create("LightProbe Display", state);
362 if (scene_eval->eevee.flag & SCE_EEVEE_SHOW_CUBEMAPS && lcache->cube_len > 1) {
363 int cube_len = lcache->cube_len - 1; /* don't count the world. */
364 DRWShadingGroup *grp = DRW_shgroup_empty_tri_batch_create(
365 EEVEE_shaders_probe_cube_display_sh_get(), psl->probe_display, cube_len * 2);
367 DRW_shgroup_uniform_texture_ref(grp, "probeCubes", &lcache->cube_tx.tex);
368 DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
369 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
370 DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
371 DRW_shgroup_uniform_float_copy(grp, "sphere_size", scene_eval->eevee.gi_cubemap_draw_size * 0.5f);
372 /* TODO (fclem) get rid of those UBO. */
373 DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
374 DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
378 if (scene_eval->eevee.flag & SCE_EEVEE_SHOW_IRRADIANCE) {
379 EEVEE_LightGrid *egrid = lcache->grid_data + 1;
380 for (int p = 1; p < lcache->grid_len; ++p, egrid++) {
381 DRWShadingGroup *shgrp = DRW_shgroup_create(
382 EEVEE_shaders_probe_grid_display_sh_get(), psl->probe_display);
384 DRW_shgroup_uniform_int(shgrp, "offset", &egrid->offset, 1);
385 DRW_shgroup_uniform_ivec3(shgrp, "grid_resolution", egrid->resolution, 1);
386 DRW_shgroup_uniform_vec3(shgrp, "corner", egrid->corner, 1);
387 DRW_shgroup_uniform_vec3(shgrp, "increment_x", egrid->increment_x, 1);
388 DRW_shgroup_uniform_vec3(shgrp, "increment_y", egrid->increment_y, 1);
389 DRW_shgroup_uniform_vec3(shgrp, "increment_z", egrid->increment_z, 1);
390 DRW_shgroup_uniform_vec3(shgrp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
391 DRW_shgroup_uniform_texture_ref(shgrp, "irradianceGrid", &lcache->grid_tx.tex);
392 DRW_shgroup_uniform_float_copy(shgrp, "sphere_size", scene_eval->eevee.gi_irradiance_draw_size * 0.5f);
393 /* TODO (fclem) get rid of those UBO. */
394 DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
395 DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
396 DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
397 DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
398 int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2;
399 DRW_shgroup_call_procedural_triangles_add(shgrp, tri_count, NULL);
404 DRW_shgroup_instance_format(e_data.format_probe_display_planar, {
405 {"probe_id", DRW_ATTR_INT, 1},
406 {"probe_mat", DRW_ATTR_FLOAT, 16},
409 DRWShadingGroup *grp = DRW_shgroup_instance_create(
410 EEVEE_shaders_probe_planar_display_sh_get(),
412 DRW_cache_quad_get(),
413 e_data.format_probe_display_planar);
414 stl->g_data->planar_display_shgrp = grp;
415 DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool);
418 stl->g_data->planar_display_shgrp = NULL;
422 psl->probe_planar_downsample_ps = DRW_pass_create("LightProbe Planar Downsample", DRW_STATE_WRITE_COLOR);
424 DRWShadingGroup *grp = DRW_shgroup_create(
425 EEVEE_shaders_probe_planar_downsample_sh_get(), psl->probe_planar_downsample_ps);
427 DRW_shgroup_uniform_texture_ref(grp, "source", &txl->planar_pool);
428 DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
429 DRW_shgroup_call_instances_add(grp, DRW_cache_fullscreen_quad_get(), NULL, (uint *)&pinfo->num_planar);
433 static bool eevee_lightprobes_culling_test(Object *ob)
435 LightProbe *probe = (LightProbe *)ob->data;
437 switch (probe->type) {
438 case LIGHTPROBE_TYPE_PLANAR:
440 /* See if this planar probe is inside the view frustum. If not, no need to update it. */
441 /* NOTE: this could be bypassed if we want feedback loop mirrors for rendering. */
442 BoundBox bbox; float tmp[4][4];
443 const float min[3] = {-1.0f, -1.0f, -1.0f};
444 const float max[3] = { 1.0f, 1.0f, 1.0f};
445 BKE_boundbox_init_from_minmax(&bbox, min, max);
447 copy_m4_m4(tmp, ob->obmat);
448 normalize_v3(tmp[2]);
449 mul_v3_fl(tmp[2], probe->distinf);
451 for (int v = 0; v < 8; ++v) {
452 mul_m4_v3(tmp, bbox.vec[v]);
454 return DRW_culling_box_test(&bbox);
456 case LIGHTPROBE_TYPE_CUBE:
457 return true; /* TODO */
458 case LIGHTPROBE_TYPE_GRID:
459 return true; /* TODO */
465 void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *ob)
467 EEVEE_LightProbesInfo *pinfo = sldata->probes;
468 LightProbe *probe = (LightProbe *)ob->data;
470 if ((probe->type == LIGHTPROBE_TYPE_CUBE && pinfo->num_cube >= MAX_PROBE) ||
471 (probe->type == LIGHTPROBE_TYPE_GRID && pinfo->num_grid >= MAX_PROBE) ||
472 (probe->type == LIGHTPROBE_TYPE_PLANAR && pinfo->num_planar >= MAX_PLANAR))
474 printf("Too many probes in the view !!!\n");
478 if (probe->type == LIGHTPROBE_TYPE_PLANAR) {
479 if (!eevee_lightprobes_culling_test(ob)) {
482 EEVEE_lightprobes_planar_data_from_object(ob,
483 &pinfo->planar_data[pinfo->num_planar],
484 &pinfo->planar_vis_tests[pinfo->num_planar]);
486 DRWShadingGroup *grp = vedata->stl->g_data->planar_display_shgrp;
487 if (grp && (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) {
488 DRW_shgroup_call_dynamic_add(grp, &pinfo->num_planar, ob->obmat);
494 EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
495 if (ped->need_update) {
496 if (probe->type == LIGHTPROBE_TYPE_GRID) {
497 pinfo->do_grid_update = true;
500 pinfo->do_cube_update = true;
502 ped->need_update = false;
507 void EEVEE_lightprobes_grid_data_from_object(Object *ob, EEVEE_LightGrid *egrid, int *offset)
509 LightProbe *probe = (LightProbe *)ob->data;
511 copy_v3_v3_int(egrid->resolution, &probe->grid_resolution_x);
513 /* Save current offset and advance it for the next grid. */
514 egrid->offset = *offset;
515 *offset += egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2];
517 /* Add one for level 0 */
518 float fac = 1.0f / max_ff(1e-8f, probe->falloff);
519 egrid->attenuation_scale = fac / max_ff(1e-8f, probe->distinf);
520 egrid->attenuation_bias = fac;
522 /* Update transforms */
523 float cell_dim[3], half_cell_dim[3];
524 cell_dim[0] = 2.0f / egrid->resolution[0];
525 cell_dim[1] = 2.0f / egrid->resolution[1];
526 cell_dim[2] = 2.0f / egrid->resolution[2];
528 mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f);
530 /* Matrix converting world space to cell ranges. */
531 invert_m4_m4(egrid->mat, ob->obmat);
534 copy_v3_fl(egrid->corner, -1.0f);
535 add_v3_v3(egrid->corner, half_cell_dim);
536 mul_m4_v3(ob->obmat, egrid->corner);
538 /* Opposite neighbor cell. */
539 copy_v3_fl3(egrid->increment_x, cell_dim[0], 0.0f, 0.0f);
540 add_v3_v3(egrid->increment_x, half_cell_dim);
541 add_v3_fl(egrid->increment_x, -1.0f);
542 mul_m4_v3(ob->obmat, egrid->increment_x);
543 sub_v3_v3(egrid->increment_x, egrid->corner);
545 copy_v3_fl3(egrid->increment_y, 0.0f, cell_dim[1], 0.0f);
546 add_v3_v3(egrid->increment_y, half_cell_dim);
547 add_v3_fl(egrid->increment_y, -1.0f);
548 mul_m4_v3(ob->obmat, egrid->increment_y);
549 sub_v3_v3(egrid->increment_y, egrid->corner);
551 copy_v3_fl3(egrid->increment_z, 0.0f, 0.0f, cell_dim[2]);
552 add_v3_v3(egrid->increment_z, half_cell_dim);
553 add_v3_fl(egrid->increment_z, -1.0f);
554 mul_m4_v3(ob->obmat, egrid->increment_z);
555 sub_v3_v3(egrid->increment_z, egrid->corner);
557 /* Visibility bias */
558 egrid->visibility_bias = 0.05f * probe->vis_bias;
559 egrid->visibility_bleed = probe->vis_bleedbias;
560 egrid->visibility_range = 1.0f + sqrtf(max_fff(len_squared_v3(egrid->increment_x),
561 len_squared_v3(egrid->increment_y),
562 len_squared_v3(egrid->increment_z)));
565 void EEVEE_lightprobes_cube_data_from_object(Object *ob, EEVEE_LightProbe *eprobe)
567 LightProbe *probe = (LightProbe *)ob->data;
569 /* Update transforms */
570 copy_v3_v3(eprobe->position, ob->obmat[3]);
573 eprobe->attenuation_type = probe->attenuation_type;
574 eprobe->attenuation_fac = 1.0f / max_ff(1e-8f, probe->falloff);
576 unit_m4(eprobe->attenuationmat);
577 scale_m4_fl(eprobe->attenuationmat, probe->distinf);
578 mul_m4_m4m4(eprobe->attenuationmat, ob->obmat, eprobe->attenuationmat);
579 invert_m4(eprobe->attenuationmat);
582 unit_m4(eprobe->parallaxmat);
584 if ((probe->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) {
585 eprobe->parallax_type = probe->parallax_type;
586 scale_m4_fl(eprobe->parallaxmat, probe->distpar);
589 eprobe->parallax_type = probe->attenuation_type;
590 scale_m4_fl(eprobe->parallaxmat, probe->distinf);
593 mul_m4_m4m4(eprobe->parallaxmat, ob->obmat, eprobe->parallaxmat);
594 invert_m4(eprobe->parallaxmat);
597 void EEVEE_lightprobes_planar_data_from_object(Object *ob, EEVEE_PlanarReflection *eplanar, EEVEE_LightProbeVisTest *vis_test)
599 LightProbe *probe = (LightProbe *)ob->data;
600 float normat[4][4], imat[4][4];
602 vis_test->collection = probe->visibility_grp;
603 vis_test->invert = probe->flag & LIGHTPROBE_FLAG_INVERT_GROUP;
604 vis_test->cached = false;
606 /* Computing mtx : matrix that mirror position around object's XY plane. */
607 normalize_m4_m4(normat, ob->obmat); /* object > world */
608 invert_m4_m4(imat, normat); /* world > object */
609 /* XY reflection plane */
610 imat[0][2] = -imat[0][2];
611 imat[1][2] = -imat[1][2];
612 imat[2][2] = -imat[2][2];
613 imat[3][2] = -imat[3][2]; /* world > object > mirrored obj */
614 mul_m4_m4m4(eplanar->mtx, normat, imat); /* world > object > mirrored obj > world */
616 /* Compute clip plane equation / normal. */
617 copy_v3_v3(eplanar->plane_equation, ob->obmat[2]);
618 normalize_v3(eplanar->plane_equation); /* plane normal */
619 eplanar->plane_equation[3] = -dot_v3v3(eplanar->plane_equation, ob->obmat[3]);
620 eplanar->clipsta = probe->clipsta;
622 /* Compute XY clip planes. */
623 normalize_v3_v3(eplanar->clip_vec_x, ob->obmat[0]);
624 normalize_v3_v3(eplanar->clip_vec_y, ob->obmat[1]);
626 float vec[3] = {0.0f, 0.0f, 0.0f};
627 vec[0] = 1.0f; vec[1] = 0.0f; vec[2] = 0.0f;
628 mul_m4_v3(ob->obmat, vec); /* Point on the edge */
629 eplanar->clip_edge_x_pos = dot_v3v3(eplanar->clip_vec_x, vec);
631 vec[0] = 0.0f; vec[1] = 1.0f; vec[2] = 0.0f;
632 mul_m4_v3(ob->obmat, vec); /* Point on the edge */
633 eplanar->clip_edge_y_pos = dot_v3v3(eplanar->clip_vec_y, vec);
635 vec[0] = -1.0f; vec[1] = 0.0f; vec[2] = 0.0f;
636 mul_m4_v3(ob->obmat, vec); /* Point on the edge */
637 eplanar->clip_edge_x_neg = dot_v3v3(eplanar->clip_vec_x, vec);
639 vec[0] = 0.0f; vec[1] = -1.0f; vec[2] = 0.0f;
640 mul_m4_v3(ob->obmat, vec); /* Point on the edge */
641 eplanar->clip_edge_y_neg = dot_v3v3(eplanar->clip_vec_y, vec);
644 float max_angle = max_ff(1e-2f, 1.0f - probe->falloff) * M_PI * 0.5f;
645 float min_angle = 0.0f;
646 eplanar->facing_scale = 1.0f / max_ff(1e-8f, cosf(min_angle) - cosf(max_angle));
647 eplanar->facing_bias = -min_ff(1.0f - 1e-8f, cosf(max_angle)) * eplanar->facing_scale;
649 /* Distance factors */
650 float max_dist = probe->distinf;
651 float min_dist = min_ff(1.0f - 1e-8f, 1.0f - probe->falloff) * probe->distinf;
652 eplanar->attenuation_scale = -1.0f / max_ff(1e-8f, max_dist - min_dist);
653 eplanar->attenuation_bias = max_dist * -eplanar->attenuation_scale;
656 static void lightbake_planar_compute_render_matrices(
657 EEVEE_PlanarReflection *eplanar, DRWMatrixState *r_matstate, const float viewmat[4][4])
659 /* Reflect Camera Matrix. */
660 mul_m4_m4m4(r_matstate->viewmat, viewmat, eplanar->mtx);
661 /* TODO FOV margin */
662 /* Temporal sampling jitter should be already applied to the DRW_MAT_WIN. */
663 DRW_viewport_matrix_get(r_matstate->winmat, DRW_MAT_WIN);
664 /* Apply Projection Matrix. */
665 mul_m4_m4m4(r_matstate->persmat, r_matstate->winmat, r_matstate->viewmat);
667 /* This is the matrix used to reconstruct texture coordinates.
668 * We use the original view matrix because it does not create
669 * visual artifacts if receiver is not perfectly aligned with
670 * the planar reflection probe. */
671 mul_m4_m4m4(eplanar->reflectionmat, r_matstate->winmat, viewmat); /* TODO FOV margin */
672 /* Convert from [-1, 1] to [0, 1] (NDC to Texture coord). */
673 mul_m4_m4m4(eplanar->reflectionmat, texcomat, eplanar->reflectionmat);
676 static void eevee_lightprobes_extract_from_cache(EEVEE_LightProbesInfo *pinfo, LightCache *lcache)
678 /* copy the entire cache for now (up to MAX_PROBE) */
679 /* TODO Frutum cull to only add visible probes. */
680 memcpy(pinfo->probe_data, lcache->cube_data, sizeof(EEVEE_LightProbe) * max_ii(1, min_ii(lcache->cube_len, MAX_PROBE)));
681 /* TODO compute the max number of grid based on sample count. */
682 memcpy(pinfo->grid_data, lcache->grid_data, sizeof(EEVEE_LightGrid) * max_ii(1, min_ii(lcache->grid_len, MAX_GRID)));
685 void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
687 EEVEE_StorageList *stl = vedata->stl;
688 LightCache *light_cache = stl->g_data->light_cache;
689 EEVEE_LightProbesInfo *pinfo = sldata->probes;
690 const DRWContextState *draw_ctx = DRW_context_state_get();
691 const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
693 eevee_lightprobes_extract_from_cache(sldata->probes, light_cache);
695 DRW_uniformbuffer_update(sldata->probe_ubo, &sldata->probes->probe_data);
696 DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data);
698 /* For shading, save max level of the octahedron map */
699 sldata->common_data.prb_lod_cube_max = (float)light_cache->mips_len - 1.0f;
700 sldata->common_data.prb_lod_planar_max = (float)MAX_PLANAR_LOD_LEVEL;
701 sldata->common_data.prb_irradiance_vis_size = light_cache->vis_res;
702 sldata->common_data.prb_irradiance_smooth = SQUARE(scene_eval->eevee.gi_irradiance_smoothing);
703 sldata->common_data.prb_num_render_cube = max_ii(1, light_cache->cube_len);
704 sldata->common_data.prb_num_render_grid = max_ii(1, light_cache->grid_len);
705 sldata->common_data.prb_num_planar = pinfo->num_planar;
707 if (pinfo->num_planar != pinfo->cache_num_planar) {
708 DRW_TEXTURE_FREE_SAFE(vedata->txl->planar_pool);
709 DRW_TEXTURE_FREE_SAFE(vedata->txl->planar_depth);
710 pinfo->cache_num_planar = pinfo->num_planar;
712 planar_pool_ensure_alloc(vedata, pinfo->num_planar);
714 /* If lightcache auto-update is enable we tag the relevant part
715 * of the cache to update and fire up a baking job. */
716 if (!DRW_state_is_image_render() && !DRW_state_is_opengl_render() &&
717 (pinfo->do_grid_update || pinfo->do_cube_update))
719 BLI_assert(draw_ctx->evil_C);
721 if (draw_ctx->scene->eevee.flag & SCE_EEVEE_GI_AUTOBAKE) {
722 Scene *scene_orig = DEG_get_input_scene(draw_ctx->depsgraph);
723 if (scene_orig->eevee.light_cache != NULL) {
724 if (pinfo->do_grid_update) {
725 scene_orig->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_GRID;
727 /* If we update grid we need to update the cubemaps too.
728 * So always refresh cubemaps. */
729 scene_orig->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE;
730 /* Tag the lightcache to auto update. */
731 scene_orig->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_AUTO;
732 /* Use a notifier to trigger the operator after drawing. */
733 WM_event_add_notifier(draw_ctx->evil_C, NC_LIGHTPROBE, scene_orig);
739 /* -------------------------------------------------------------------- */
743 typedef struct EEVEE_BakeRenderData {
745 EEVEE_ViewLayerData *sldata;
746 struct GPUFrameBuffer **face_fb; /* should contain 6 framebuffer */
747 } EEVEE_BakeRenderData;
749 static void render_cubemap(
750 void (*callback)(int face, EEVEE_BakeRenderData *user_data), EEVEE_BakeRenderData *user_data,
751 const float pos[3], float clipsta, float clipend)
753 DRWMatrixState matstate;
755 /* Move to capture position */
758 negate_v3_v3(posmat[3], pos);
760 perspective_m4(matstate.winmat, -clipsta, clipsta, -clipsta, clipsta, clipsta, clipend);
761 invert_m4_m4(matstate.wininv, matstate.winmat);
763 /* 1 - Render to each cubeface individually.
764 * We do this instead of using geometry shader because a) it's faster,
765 * b) it's easier than fixing the nodetree shaders (for view dependent effects). */
766 for (int i = 0; i < 6; ++i) {
767 /* Setup custom matrices */
768 mul_m4_m4m4(matstate.viewmat, cubefacemat[i], posmat);
769 mul_m4_m4m4(matstate.persmat, matstate.winmat, matstate.viewmat);
770 invert_m4_m4(matstate.persinv, matstate.persmat);
771 invert_m4_m4(matstate.viewinv, matstate.viewmat);
772 invert_m4_m4(matstate.wininv, matstate.winmat);
774 DRW_viewport_matrix_override_set_all(&matstate);
776 callback(i, user_data);
780 static void render_reflections(
781 void (*callback)(int face, EEVEE_BakeRenderData *user_data), EEVEE_BakeRenderData *user_data,
782 EEVEE_PlanarReflection *planar_data, int ref_count)
784 DRWMatrixState matstate;
786 float original_viewmat[4][4];
787 DRW_viewport_matrix_get(original_viewmat, DRW_MAT_VIEW);
789 for (int i = 0; i < ref_count; ++i) {
790 /* Setup custom matrices */
791 lightbake_planar_compute_render_matrices(planar_data + i, &matstate, original_viewmat);
792 invert_m4_m4(matstate.persinv, matstate.persmat);
793 invert_m4_m4(matstate.viewinv, matstate.viewmat);
794 invert_m4_m4(matstate.wininv, matstate.winmat);
795 DRW_viewport_matrix_override_set_all(&matstate);
797 callback(i, user_data);
801 static void lightbake_render_world_face(int face, EEVEE_BakeRenderData *user_data)
803 EEVEE_PassList *psl = user_data->vedata->psl;
804 struct GPUFrameBuffer **face_fb = user_data->face_fb;
806 /* For world probe, we don't need to clear the color buffer
807 * since we render the background directly. */
808 GPU_framebuffer_bind(face_fb[face]);
809 GPU_framebuffer_clear_depth(face_fb[face], 1.0f);
810 DRW_draw_pass(psl->probe_background);
813 void EEVEE_lightbake_render_world(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, struct GPUFrameBuffer *face_fb[6])
815 EEVEE_BakeRenderData brdata = {
820 render_cubemap(lightbake_render_world_face, &brdata, (float[3]){0.0f}, 1.0f, 10.0f);
823 static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_data)
825 EEVEE_ViewLayerData *sldata = user_data->sldata;
826 EEVEE_PassList *psl = user_data->vedata->psl;
827 struct GPUFrameBuffer **face_fb = user_data->face_fb;
829 /* Be sure that cascaded shadow maps are updated. */
830 EEVEE_draw_shadows(sldata, user_data->vedata);
832 GPU_framebuffer_bind(face_fb[face]);
833 GPU_framebuffer_clear_depth(face_fb[face], 1.0f);
835 DRW_draw_pass(psl->depth_pass);
836 DRW_draw_pass(psl->depth_pass_cull);
837 DRW_draw_pass(psl->probe_background);
838 DRW_draw_pass(psl->material_pass);
839 DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
840 EEVEE_draw_default_passes(psl);
843 /* Render the scene to the probe_rt texture. */
844 void EEVEE_lightbake_render_scene(
845 EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct GPUFrameBuffer *face_fb[6],
846 const float pos[3], float near_clip, float far_clip)
848 EEVEE_BakeRenderData brdata = {
854 render_cubemap(lightbake_render_scene_face, &brdata, pos, near_clip, far_clip);
857 static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *user_data)
859 EEVEE_Data *vedata = user_data->vedata;
860 EEVEE_ViewLayerData *sldata = user_data->sldata;
861 EEVEE_PassList *psl = vedata->psl;
862 EEVEE_TextureList *txl = vedata->txl;
863 EEVEE_FramebufferList *fbl = vedata->fbl;
864 EEVEE_LightProbesInfo *pinfo = sldata->probes;
865 EEVEE_PlanarReflection *eplanar = pinfo->planar_data + layer;
867 GPU_framebuffer_ensure_config(&fbl->planarref_fb, {
868 GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_depth, layer),
869 GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_pool, layer)
872 /* Use visibility info for this planar reflection. */
873 pinfo->vis_data = pinfo->planar_vis_tests[layer];
875 /* Avoid using the texture attached to framebuffer when rendering. */
877 GPUTexture *tmp_planar_pool = txl->planar_pool;
878 GPUTexture *tmp_planar_depth = txl->planar_depth;
879 txl->planar_pool = e_data.planar_pool_placeholder;
880 txl->planar_depth = e_data.depth_array_placeholder;
882 /* Be sure that cascaded shadow maps are updated. */
883 DRW_stats_group_start("Planar Reflection");
885 /* Be sure that cascaded shadow maps are updated. */
886 EEVEE_draw_shadows(sldata, vedata);
887 /* Since we are rendering with an inverted view matrix, we need
888 * to invert the facing for backface culling to be the same. */
889 DRW_state_invert_facing();
890 /* Compute offset plane equation (fix missing texels near reflection plane). */
891 copy_v4_v4(sldata->clip_data.clip_planes[0], eplanar->plane_equation);
892 sldata->clip_data.clip_planes[0][3] += eplanar->clipsta;
893 /* Set clipping plane */
894 DRW_uniformbuffer_update(sldata->clip_ubo, &sldata->clip_data);
895 DRW_state_clip_planes_len_set(1);
897 GPU_framebuffer_bind(fbl->planarref_fb);
898 GPU_framebuffer_clear_depth(fbl->planarref_fb, 1.0);
900 /* Slight modification: we handle refraction as normal
901 * shading and don't do SSRefraction. */
903 DRW_draw_pass(psl->depth_pass_clip);
904 DRW_draw_pass(psl->depth_pass_clip_cull);
905 DRW_draw_pass(psl->refract_depth_pass);
906 DRW_draw_pass(psl->refract_depth_pass_cull);
908 DRW_draw_pass(psl->probe_background);
909 EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer);
910 EEVEE_occlusion_compute(sldata, vedata, tmp_planar_depth, layer);
912 GPU_framebuffer_bind(fbl->planarref_fb);
915 EEVEE_draw_default_passes(psl);
916 DRW_draw_pass(psl->material_pass);
917 DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
918 DRW_draw_pass(psl->refract_pass);
921 if (DRW_state_is_image_render()) {
922 /* Do the reordering only for offline because it can be costly. */
923 DRW_pass_sort_shgroup_z(psl->transparent_pass);
925 DRW_draw_pass(psl->transparent_pass);
927 DRW_state_invert_facing();
928 DRW_state_clip_planes_reset();
930 DRW_stats_group_end();
933 txl->planar_pool = tmp_planar_pool;
934 txl->planar_depth = tmp_planar_depth;
937 static void eevee_lightbake_render_scene_to_planars(
938 EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
940 EEVEE_BakeRenderData brdata = {
945 render_reflections(lightbake_render_scene_reflected, &brdata, sldata->probes->planar_data, sldata->probes->num_planar);
949 /* -------------------------------------------------------------------- */
953 /* Glossy filter rt_color to light_cache->cube_tx.tex at index probe_idx */
954 void EEVEE_lightbake_filter_glossy(
955 EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
956 struct GPUTexture *rt_color, struct GPUFrameBuffer *fb,
957 int probe_idx, float intensity, int maxlevel, float filter_quality, float firefly_fac)
959 EEVEE_PassList *psl = vedata->psl;
960 EEVEE_LightProbesInfo *pinfo = sldata->probes;
961 LightCache *light_cache = vedata->stl->g_data->light_cache;
963 float target_size = (float)GPU_texture_width(rt_color);
965 /* Max lod used from the render target probe */
966 pinfo->lod_rt_max = floorf(log2f(target_size)) - 2.0f;
967 pinfo->intensity_fac = intensity;
970 GPU_framebuffer_ensure_config(&fb, {
975 /* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */
976 /* Bind next framebuffer to be able to gen. mips for probe_rt. */
977 EEVEE_downsample_cube_buffer(vedata, rt_color, (int)(pinfo->lod_rt_max));
979 /* 3 - Render to probe array to the specified layer, do prefiltering. */
980 int mipsize = GPU_texture_width(light_cache->cube_tx.tex);
981 for (int i = 0; i < maxlevel + 1; i++) {
982 float bias = (i == 0) ? -1.0f : 1.0f;
983 pinfo->texel_size = 1.0f / (float)mipsize;
984 pinfo->padding_size = (i == maxlevel) ? 0 : (float)(1 << (maxlevel - i - 1));
985 pinfo->padding_size *= pinfo->texel_size;
986 pinfo->layer = probe_idx;
987 pinfo->roughness = i / (float)maxlevel;
988 pinfo->roughness *= pinfo->roughness; /* Disney Roughness */
989 pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */
990 CLAMP(pinfo->roughness, 1e-8f, 0.99999f); /* Avoid artifacts */
992 #if 1 /* Variable Sample count (fast) */
994 case 0: pinfo->samples_len = 1.0f; break;
995 case 1: pinfo->samples_len = 16.0f; break;
996 case 2: pinfo->samples_len = 32.0f; break;
997 case 3: pinfo->samples_len = 64.0f; break;
998 default: pinfo->samples_len = 128.0f; break;
1000 #else /* Constant Sample count (slow) */
1001 pinfo->samples_len = 1024.0f;
1003 /* Cannot go higher than HAMMERSLEY_SIZE */
1004 CLAMP(filter_quality, 1.0f, 8.0f);
1005 pinfo->samples_len *= filter_quality;
1007 pinfo->samples_len_inv = 1.0f / pinfo->samples_len;
1008 pinfo->lodfactor = bias + 0.5f * log((float)(target_size * target_size) * pinfo->samples_len_inv) / log(2);
1009 pinfo->firefly_fac = (firefly_fac > 0.0) ? firefly_fac : 1e16;
1011 GPU_framebuffer_ensure_config(&fb, {
1012 GPU_ATTACHMENT_NONE,
1013 GPU_ATTACHMENT_TEXTURE_MIP(light_cache->cube_tx.tex, i)
1015 GPU_framebuffer_bind(fb);
1016 GPU_framebuffer_viewport_set(fb, 0, 0, mipsize, mipsize);
1017 DRW_draw_pass(psl->probe_glossy_compute);
1020 CLAMP_MIN(mipsize, 1);
1024 /* Diffuse filter rt_color to light_cache->grid_tx.tex at index grid_offset */
1025 void EEVEE_lightbake_filter_diffuse(
1026 EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
1027 struct GPUTexture *rt_color, struct GPUFrameBuffer *fb,
1028 int grid_offset, float intensity)
1030 EEVEE_PassList *psl = vedata->psl;
1031 EEVEE_LightProbesInfo *pinfo = sldata->probes;
1032 LightCache *light_cache = vedata->stl->g_data->light_cache;
1034 float target_size = (float)GPU_texture_width(rt_color);
1036 pinfo->intensity_fac = intensity;
1038 /* find cell position on the virtual 3D texture */
1039 /* NOTE : Keep in sync with load_irradiance_cell() */
1040 #if defined(IRRADIANCE_SH_L2)
1041 int size[2] = {3, 3};
1042 #elif defined(IRRADIANCE_CUBEMAP)
1043 int size[2] = {8, 8};
1044 pinfo->samples_len = 1024.0f;
1045 #elif defined(IRRADIANCE_HL2)
1046 int size[2] = {3, 2};
1047 pinfo->samples_len = 1024.0f;
1050 int cell_per_row = GPU_texture_width(light_cache->grid_tx.tex) / size[0];
1051 int x = size[0] * (grid_offset % cell_per_row);
1052 int y = size[1] * (grid_offset / cell_per_row);
1054 #ifndef IRRADIANCE_SH_L2
1055 /* Tweaking parameters to balance perf. vs precision */
1056 const float bias = 0.0f;
1057 pinfo->samples_len_inv = 1.0f / pinfo->samples_len;
1058 pinfo->lodfactor = bias + 0.5f * log((float)(target_size * target_size) * pinfo->samples_len_inv) / log(2);
1059 pinfo->lod_rt_max = floorf(log2f(target_size)) - 2.0f;
1061 pinfo->shres = 32; /* Less texture fetches & reduce branches */
1062 pinfo->lod_rt_max = 2.0f; /* Improve cache reuse */
1066 GPU_framebuffer_ensure_config(&fb, {
1067 GPU_ATTACHMENT_NONE,
1071 /* 4 - Compute diffuse irradiance */
1072 EEVEE_downsample_cube_buffer(vedata, rt_color, (int)(pinfo->lod_rt_max));
1074 GPU_framebuffer_ensure_config(&fb, {
1075 GPU_ATTACHMENT_NONE,
1076 GPU_ATTACHMENT_TEXTURE_LAYER(light_cache->grid_tx.tex, 0)
1078 GPU_framebuffer_bind(fb);
1079 GPU_framebuffer_viewport_set(fb, x, y, size[0], size[1]);
1080 DRW_draw_pass(psl->probe_diffuse_compute);
1083 /* Filter rt_depth to light_cache->grid_tx.tex at index grid_offset */
1084 void EEVEE_lightbake_filter_visibility(
1085 EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
1086 struct GPUTexture *UNUSED(rt_depth), struct GPUFrameBuffer *fb,
1087 int grid_offset, float clipsta, float clipend,
1088 float vis_range, float vis_blur, int vis_size)
1090 EEVEE_PassList *psl = vedata->psl;
1091 EEVEE_LightProbesInfo *pinfo = sldata->probes;
1092 LightCache *light_cache = vedata->stl->g_data->light_cache;
1094 pinfo->samples_len = 512.0f; /* TODO refine */
1095 pinfo->samples_len_inv = 1.0f / pinfo->samples_len;
1096 pinfo->shres = vis_size;
1097 pinfo->visibility_range = vis_range;
1098 pinfo->visibility_blur = vis_blur;
1099 pinfo->near_clip = -clipsta;
1100 pinfo->far_clip = -clipend;
1101 pinfo->texel_size = 1.0f / (float)vis_size;
1103 int cell_per_col = GPU_texture_height(light_cache->grid_tx.tex) / vis_size;
1104 int cell_per_row = GPU_texture_width(light_cache->grid_tx.tex) / vis_size;
1105 int x = vis_size * (grid_offset % cell_per_row);
1106 int y = vis_size * ((grid_offset / cell_per_row) % cell_per_col);
1107 int layer = 1 + ((grid_offset / cell_per_row) / cell_per_col);
1109 GPU_framebuffer_ensure_config(&fb, {
1110 GPU_ATTACHMENT_NONE,
1111 GPU_ATTACHMENT_TEXTURE_LAYER(light_cache->grid_tx.tex, layer)
1113 GPU_framebuffer_bind(fb);
1114 GPU_framebuffer_viewport_set(fb, x, y, vis_size, vis_size);
1115 DRW_draw_pass(psl->probe_visibility_compute);
1118 /* Actually a simple downsampling */
1119 static void downsample_planar(void *vedata, int level)
1121 EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
1122 EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
1124 const float *size = DRW_viewport_size_get();
1125 copy_v2_v2(stl->g_data->planar_texel_size, size);
1126 for (int i = 0; i < level - 1; ++i) {
1127 stl->g_data->planar_texel_size[0] /= 2.0f;
1128 stl->g_data->planar_texel_size[1] /= 2.0f;
1129 min_ff(floorf(stl->g_data->planar_texel_size[0]), 1.0f);
1130 min_ff(floorf(stl->g_data->planar_texel_size[1]), 1.0f);
1132 invert_v2(stl->g_data->planar_texel_size);
1134 DRW_draw_pass(psl->probe_planar_downsample_ps);
1137 static void EEVEE_lightbake_filter_planar(EEVEE_Data *vedata)
1139 EEVEE_TextureList *txl = vedata->txl;
1140 EEVEE_FramebufferList *fbl = vedata->fbl;
1142 DRW_stats_group_start("Planar Probe Downsample");
1144 GPU_framebuffer_ensure_config(&fbl->planar_downsample_fb, {
1145 GPU_ATTACHMENT_NONE,
1146 GPU_ATTACHMENT_TEXTURE(txl->planar_pool)
1149 GPU_framebuffer_recursive_downsample(fbl->planar_downsample_fb, MAX_PLANAR_LOD_LEVEL, &downsample_planar, vedata);
1150 DRW_stats_group_end();
1155 void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
1157 EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
1158 EEVEE_LightProbesInfo *pinfo = sldata->probes;
1159 DRWMatrixState saved_mats;
1161 if (pinfo->num_planar == 0) {
1162 /* Disable SSR if we cannot read previous frame */
1163 common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer;
1164 common_data->prb_num_planar = 0;
1168 /* We need to save the Matrices before overidding them */
1169 DRW_viewport_matrix_get_all(&saved_mats);
1171 /* Temporary Remove all planar reflections (avoid lag effect). */
1172 common_data->prb_num_planar = 0;
1173 /* Turn off ssr to avoid black specular */
1174 common_data->ssr_toggle = false;
1175 common_data->sss_toggle = false;
1177 common_data->ray_type = EEVEE_RAY_GLOSSY;
1178 common_data->ray_depth = 1.0f;
1179 DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
1181 /* Rendering happens here! */
1182 eevee_lightbake_render_scene_to_planars(sldata, vedata);
1184 /* Make sure no aditionnal visibility check runs after this. */
1185 pinfo->vis_data.collection = NULL;
1187 DRW_uniformbuffer_update(sldata->planar_ubo, &sldata->probes->planar_data);
1190 common_data->prb_num_planar = pinfo->num_planar;
1191 common_data->ssr_toggle = true;
1192 common_data->sss_toggle = true;
1194 /* Prefilter for SSR */
1195 if ((vedata->stl->effects->enabled_effects & EFFECT_SSR) != 0) {
1196 EEVEE_lightbake_filter_planar(vedata);
1199 DRW_viewport_matrix_override_set_all(&saved_mats);
1201 if (DRW_state_is_image_render()) {
1202 /* Sort transparents because planar reflections could have re-sorted them. */
1203 DRW_pass_sort_shgroup_z(vedata->psl->transparent_pass);
1206 /* Disable SSR if we cannot read previous frame */
1207 common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer;
1210 void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
1212 const DRWContextState *draw_ctx = DRW_context_state_get();
1213 const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
1214 LightCache *light_cache = vedata->stl->g_data->light_cache;
1216 if (light_cache->flag & LIGHTCACHE_UPDATE_WORLD) {
1217 DRWMatrixState saved_mats;
1218 DRW_viewport_matrix_get_all(&saved_mats);
1219 EEVEE_lightbake_update_world_quick(sldata, vedata, scene_eval);
1220 DRW_viewport_matrix_override_set_all(&saved_mats);
1224 void EEVEE_lightprobes_free(void)
1226 MEM_SAFE_FREE(e_data.format_probe_display_cube);
1227 MEM_SAFE_FREE(e_data.format_probe_display_planar);
1228 DRW_TEXTURE_FREE_SAFE(e_data.hammersley);
1229 DRW_TEXTURE_FREE_SAFE(e_data.planar_pool_placeholder);
1230 DRW_TEXTURE_FREE_SAFE(e_data.depth_placeholder);
1231 DRW_TEXTURE_FREE_SAFE(e_data.depth_array_placeholder);