Cleanup: replace attrib w/ attr
[blender.git] / source / blender / draw / engines / eevee / eevee_lightprobes.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * Copyright 2016, Blender Foundation.
19  * Contributor(s): Blender Institute
20  *
21  * ***** END GPL LICENSE BLOCK *****
22  *
23  */
24
25 /** \file eevee_lightprobes.c
26  *  \ingroup draw_engine
27  */
28
29 #include "DRW_render.h"
30
31 #include "BLI_utildefines.h"
32 #include "BLI_rand.h"
33
34 #include "DNA_world_types.h"
35 #include "DNA_texture_types.h"
36 #include "DNA_image_types.h"
37 #include "DNA_lightprobe_types.h"
38 #include "DNA_view3d_types.h"
39
40 #include "BKE_collection.h"
41 #include "BKE_object.h"
42 #include "MEM_guardedalloc.h"
43
44 #include "GPU_material.h"
45 #include "GPU_texture.h"
46
47 #include "DEG_depsgraph_query.h"
48
49 #include "eevee_lightcache.h"
50 #include "eevee_private.h"
51
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 static struct {
57         struct GPUTexture *hammersley;
58         struct GPUTexture *planar_pool_placeholder;
59         struct GPUTexture *depth_placeholder;
60         struct GPUTexture *depth_array_placeholder;
61         struct GPUTexture *cube_face_minmaxz;
62
63         struct GPUVertFormat *format_probe_display_cube;
64         struct GPUVertFormat *format_probe_display_planar;
65 } e_data = {NULL}; /* Engine data */
66
67
68 /* *********** FUNCTIONS *********** */
69
70 /* TODO find a better way than this. This does not support dupli objects if
71  * the original object is hidden. */
72 bool EEVEE_lightprobes_obj_visibility_cb(bool vis_in, void *user_data)
73 {
74         EEVEE_ObjectEngineData *oed = (EEVEE_ObjectEngineData *)user_data;
75
76         /* test disabled if group is NULL */
77         if (oed->test_data->collection == NULL) {
78                 return vis_in;
79         }
80
81         if (oed->test_data->cached == false) {
82                 oed->ob_vis_dirty = true;
83         }
84
85         /* early out, don't need to compute ob_vis yet. */
86         if (vis_in == false) {
87                 return vis_in;
88         }
89
90         if (oed->ob_vis_dirty) {
91                 oed->ob_vis_dirty = false;
92                 oed->ob_vis = BKE_collection_has_object_recursive(oed->test_data->collection, oed->ob);
93                 oed->ob_vis = (oed->test_data->invert) ? !oed->ob_vis : oed->ob_vis;
94         }
95
96         return vis_in && oed->ob_vis;
97 }
98
99 static struct GPUTexture *create_hammersley_sample_texture(int samples)
100 {
101         struct GPUTexture *tex;
102         float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * samples, "hammersley_tex");
103         int i;
104
105         for (i = 0; i < samples; i++) {
106                 double dphi;
107                 BLI_hammersley_1D(i, &dphi);
108                 float phi = (float)dphi * 2.0f * M_PI;
109                 texels[i][0] = cosf(phi);
110                 texels[i][1] = sinf(phi);
111         }
112
113         tex = DRW_texture_create_1D(samples, GPU_RG16F, DRW_TEX_WRAP, (float *)texels);
114         MEM_freeN(texels);
115         return tex;
116 }
117
118 static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
119 {
120         EEVEE_TextureList *txl = vedata->txl;
121
122         /* XXX TODO OPTIMISATION : This is a complete waist of texture memory.
123          * Instead of allocating each planar probe for each viewport,
124          * only alloc them once using the biggest viewport resolution. */
125         const float *viewport_size = DRW_viewport_size_get();
126
127         /* TODO get screen percentage from layer setting */
128         // const DRWContextState *draw_ctx = DRW_context_state_get();
129         // ViewLayer *view_layer = draw_ctx->view_layer;
130         float screen_percentage = 1.0f;
131
132         int width = (int)(viewport_size[0] * screen_percentage);
133         int height = (int)(viewport_size[1] * screen_percentage);
134
135         /* We need an Array texture so allocate it ourself */
136         if (!txl->planar_pool) {
137                 if (num_planar_ref > 0) {
138                         txl->planar_pool = DRW_texture_create_2D_array(width, height, max_ff(1, num_planar_ref),
139                                                                          GPU_R11F_G11F_B10F, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
140                         txl->planar_depth = DRW_texture_create_2D_array(width, height, max_ff(1, num_planar_ref),
141                                                                         GPU_DEPTH_COMPONENT24, 0, NULL);
142                 }
143                 else if (num_planar_ref == 0) {
144                         /* Makes Opengl Happy : Create a placeholder texture that will never be sampled but still bound to shader. */
145                         txl->planar_pool = DRW_texture_create_2D_array(1, 1, 1, GPU_RGBA8, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
146                         txl->planar_depth = DRW_texture_create_2D_array(1, 1, 1, GPU_DEPTH_COMPONENT24, 0, NULL);
147                 }
148         }
149 }
150
151 void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
152 {
153         EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
154         EEVEE_StorageList *stl = vedata->stl;
155
156         const DRWContextState *draw_ctx = DRW_context_state_get();
157         const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
158
159         if (!e_data.hammersley) {
160                 EEVEE_shaders_lightprobe_shaders_init();
161                 e_data.hammersley = create_hammersley_sample_texture(HAMMERSLEY_SIZE);
162         }
163
164         /* Use fallback if we don't have gpu texture allocated an we cannot restore them. */
165         bool use_fallback_lightcache = (scene_eval->eevee.light_cache == NULL) ||
166                                        ((scene_eval->eevee.light_cache->grid_tx.tex == NULL) &&
167                                         (scene_eval->eevee.light_cache->grid_tx.data == NULL)) ||
168                                        ((scene_eval->eevee.light_cache->cube_tx.tex == NULL) &&
169                                         (scene_eval->eevee.light_cache->cube_tx.data == NULL));
170
171         if (use_fallback_lightcache && (sldata->fallback_lightcache == NULL)) {
172 #if defined(IRRADIANCE_SH_L2)
173                 int grid_res = 4;
174 #elif defined(IRRADIANCE_CUBEMAP)
175                 int grid_res = 8;
176 #elif defined(IRRADIANCE_HL2)
177                 int grid_res = 4;
178 #endif
179                 int cube_res = OCTAHEDRAL_SIZE_FROM_CUBESIZE(scene_eval->eevee.gi_cubemap_resolution);
180                 int vis_res = scene_eval->eevee.gi_visibility_resolution;
181                 sldata->fallback_lightcache = EEVEE_lightcache_create(1, 1, cube_res, vis_res, (int[3]){grid_res, grid_res, 1});
182         }
183
184         stl->g_data->light_cache = (use_fallback_lightcache) ? sldata->fallback_lightcache : scene_eval->eevee.light_cache;
185
186         EEVEE_lightcache_load(stl->g_data->light_cache);
187
188         if (!sldata->probes) {
189                 sldata->probes = MEM_callocN(sizeof(EEVEE_LightProbesInfo), "EEVEE_LightProbesInfo");
190                 sldata->probe_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightProbe) * MAX_PROBE, NULL);
191                 sldata->grid_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightGrid) * MAX_GRID, NULL);
192                 sldata->planar_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_PlanarReflection) * MAX_PLANAR, NULL);
193         }
194
195         common_data->prb_num_planar = 0;
196         common_data->prb_num_render_cube = 1;
197         common_data->prb_num_render_grid = 1;
198
199         common_data->spec_toggle = true;
200         common_data->ssr_toggle = true;
201         common_data->sss_toggle = true;
202
203         /* Placeholder planar pool: used when rendering planar reflections (avoid dependency loop). */
204         if (!e_data.planar_pool_placeholder) {
205                 e_data.planar_pool_placeholder = DRW_texture_create_2D_array(1, 1, 1, GPU_RGBA8, DRW_TEX_FILTER, NULL);
206         }
207 }
208
209 /* Only init the passes useful for rendering the light cache. */
210 void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, GPUTexture *rt_color, GPUTexture *rt_depth)
211 {
212         EEVEE_PassList *psl = vedata->psl;
213         LightCache *light_cache = vedata->stl->g_data->light_cache;
214         EEVEE_LightProbesInfo *pinfo = sldata->probes;
215
216         {
217                 psl->probe_glossy_compute = DRW_pass_create("LightProbe Glossy Compute", DRW_STATE_WRITE_COLOR);
218
219                 DRWShadingGroup *grp = DRW_shgroup_create(
220                         EEVEE_shaders_probe_filter_glossy_sh_get(), psl->probe_glossy_compute);
221
222                 DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
223                 DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_len, 1);
224                 DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->samples_len_inv, 1);
225                 DRW_shgroup_uniform_float(grp, "roughnessSquared", &pinfo->roughness, 1);
226                 DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1);
227                 DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1);
228                 DRW_shgroup_uniform_float(grp, "texelSize", &pinfo->texel_size, 1);
229                 DRW_shgroup_uniform_float(grp, "paddingSize", &pinfo->padding_size, 1);
230                 DRW_shgroup_uniform_float(grp, "fireflyFactor", &pinfo->firefly_fac, 1);
231                 DRW_shgroup_uniform_int(grp, "Layer", &pinfo->layer, 1);
232                 DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
233                 // DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
234                 DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
235                 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
236
237                 struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
238                 DRW_shgroup_call_add(grp, geom, NULL);
239         }
240
241         {
242                 psl->probe_diffuse_compute = DRW_pass_create("LightProbe Diffuse Compute", DRW_STATE_WRITE_COLOR);
243
244                 DRWShadingGroup *grp = DRW_shgroup_create(
245                         EEVEE_shaders_probe_filter_diffuse_sh_get(), psl->probe_diffuse_compute);
246 #ifdef IRRADIANCE_SH_L2
247                 DRW_shgroup_uniform_int(grp, "probeSize", &pinfo->shres, 1);
248 #else
249                 DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_len, 1);
250                 DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->samples_len_inv, 1);
251                 DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1);
252                 DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1);
253                 DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
254 #endif
255                 DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
256                 DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
257                 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
258
259                 struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
260                 DRW_shgroup_call_add(grp, geom, NULL);
261         }
262
263         {
264                 psl->probe_visibility_compute = DRW_pass_create("LightProbe Visibility Compute", DRW_STATE_WRITE_COLOR);
265
266                 DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_filter_visibility_sh_get(), psl->probe_visibility_compute);
267                 DRW_shgroup_uniform_int(grp, "outputSize", &pinfo->shres, 1);
268                 DRW_shgroup_uniform_float(grp, "visibilityRange", &pinfo->visibility_range, 1);
269                 DRW_shgroup_uniform_float(grp, "visibilityBlur", &pinfo->visibility_blur, 1);
270                 DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_len, 1);
271                 DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->samples_len_inv, 1);
272                 DRW_shgroup_uniform_float(grp, "storedTexelSize", &pinfo->texel_size, 1);
273                 DRW_shgroup_uniform_float(grp, "nearClip", &pinfo->near_clip, 1);
274                 DRW_shgroup_uniform_float(grp, "farClip", &pinfo->far_clip, 1);
275                 DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
276                 DRW_shgroup_uniform_texture(grp, "probeDepth", rt_depth);
277                 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
278
279                 struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
280                 DRW_shgroup_call_add(grp, geom, NULL);
281         }
282
283         {
284                 psl->probe_grid_fill = DRW_pass_create("LightProbe Grid Floodfill", DRW_STATE_WRITE_COLOR);
285
286                 DRWShadingGroup *grp = DRW_shgroup_create(
287                         EEVEE_shaders_probe_grid_fill_sh_get(), psl->probe_grid_fill);
288
289                 DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &light_cache->grid_tx.tex);
290
291                 struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
292                 DRW_shgroup_call_add(grp, geom, NULL);
293         }
294 }
295
296 void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
297 {
298         EEVEE_TextureList *txl = vedata->txl;
299         EEVEE_PassList *psl = vedata->psl;
300         EEVEE_StorageList *stl = vedata->stl;
301         EEVEE_LightProbesInfo *pinfo = sldata->probes;
302         LightCache *lcache = stl->g_data->light_cache;
303         const DRWContextState *draw_ctx = DRW_context_state_get();
304         const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
305
306         pinfo->num_planar = 0;
307         pinfo->vis_data.collection = NULL;
308         pinfo->do_grid_update = false;
309         pinfo->do_cube_update = false;
310
311         {
312                 psl->probe_background = DRW_pass_create("World Probe Background Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
313
314                 struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
315                 DRWShadingGroup *grp = NULL;
316
317                 Scene *scene = draw_ctx->scene;
318                 World *wo = scene->world;
319
320                 const float *col = G_draw.block.colorBackground;
321
322                 /* LookDev */
323                 EEVEE_lookdev_cache_init(vedata, &grp, psl->probe_background, wo, pinfo);
324                 /* END */
325                 if (!grp && wo) {
326                         col = &wo->horr;
327
328                         if (wo->use_nodes && wo->nodetree) {
329                                 static float error_col[3] = {1.0f, 0.0f, 1.0f};
330                                 struct GPUMaterial *gpumat = EEVEE_material_world_lightprobe_get(scene, wo);
331
332                                 eGPUMaterialStatus status = GPU_material_status(gpumat);
333
334                                 switch (status) {
335                                         case GPU_MAT_SUCCESS:
336                                                 grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
337                                                 DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
338                                                 /* TODO (fclem): remove those (need to clean the GLSL files). */
339                                                 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
340                                                 DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
341                                                 DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
342                                                 DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
343                                                 DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
344                                                 DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
345                                                 DRW_shgroup_call_add(grp, geom, NULL);
346                                                 break;
347                                         default:
348                                                 col = error_col;
349                                                 break;
350                                 }
351                         }
352                 }
353
354                 /* Fallback if shader fails or if not using nodetree. */
355                 if (grp == NULL) {
356                         grp = DRW_shgroup_create(EEVEE_shaders_probe_default_sh_get(), psl->probe_background);
357                         DRW_shgroup_uniform_vec3(grp, "color", col, 1);
358                         DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
359                         DRW_shgroup_call_add(grp, geom, NULL);
360                 }
361         }
362
363         if (DRW_state_draw_support() && !LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
364                 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
365                 psl->probe_display = DRW_pass_create("LightProbe Display", state);
366
367                 /* Cube Display */
368                 if (scene_eval->eevee.flag & SCE_EEVEE_SHOW_CUBEMAPS && lcache->cube_len > 1) {
369                         int cube_len = lcache->cube_len - 1; /* don't count the world. */
370                         DRWShadingGroup *grp = DRW_shgroup_empty_tri_batch_create(
371                                 EEVEE_shaders_probe_cube_display_sh_get(), psl->probe_display, cube_len * 2);
372
373                         DRW_shgroup_uniform_texture_ref(grp, "probeCubes", &lcache->cube_tx.tex);
374                         DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
375                         DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
376                         DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
377                         DRW_shgroup_uniform_float_copy(grp, "sphere_size", scene_eval->eevee.gi_cubemap_draw_size * 0.5f);
378                         /* TODO (fclem) get rid of those UBO. */
379                         DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
380                         DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
381                 }
382
383                 /* Grid Display */
384                 if (scene_eval->eevee.flag & SCE_EEVEE_SHOW_IRRADIANCE) {
385                         EEVEE_LightGrid *egrid = lcache->grid_data + 1;
386                         for (int p = 1; p < lcache->grid_len; ++p, egrid++) {
387                                 DRWShadingGroup *shgrp = DRW_shgroup_create(
388                                         EEVEE_shaders_probe_grid_display_sh_get(), psl->probe_display);
389
390                                 DRW_shgroup_uniform_int(shgrp, "offset", &egrid->offset, 1);
391                                 DRW_shgroup_uniform_ivec3(shgrp, "grid_resolution", egrid->resolution, 1);
392                                 DRW_shgroup_uniform_vec3(shgrp, "corner", egrid->corner, 1);
393                                 DRW_shgroup_uniform_vec3(shgrp, "increment_x", egrid->increment_x, 1);
394                                 DRW_shgroup_uniform_vec3(shgrp, "increment_y", egrid->increment_y, 1);
395                                 DRW_shgroup_uniform_vec3(shgrp, "increment_z", egrid->increment_z, 1);
396                                 DRW_shgroup_uniform_vec3(shgrp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
397                                 DRW_shgroup_uniform_texture_ref(shgrp, "irradianceGrid", &lcache->grid_tx.tex);
398                                 DRW_shgroup_uniform_float_copy(shgrp, "sphere_size", scene_eval->eevee.gi_irradiance_draw_size * 0.5f);
399                                 /* TODO (fclem) get rid of those UBO. */
400                                 DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
401                                 DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
402                                 DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
403                                 DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
404                                 int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2;
405                                 DRW_shgroup_call_procedural_triangles_add(shgrp, tri_count, NULL);
406                         }
407                 }
408
409                 /* Planar Display */
410                 DRW_shgroup_instance_format(e_data.format_probe_display_planar, {
411                     {"probe_id", DRW_ATTR_INT, 1},
412                     {"probe_mat", DRW_ATTR_FLOAT, 16},
413                 });
414
415                 DRWShadingGroup *grp = DRW_shgroup_instance_create(
416                         EEVEE_shaders_probe_planar_display_sh_get(),
417                         psl->probe_display,
418                         DRW_cache_quad_get(),
419                         e_data.format_probe_display_planar);
420                 stl->g_data->planar_display_shgrp = grp;
421                 DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool);
422         }
423         else {
424                 stl->g_data->planar_display_shgrp = NULL;
425         }
426
427         {
428                 psl->probe_planar_downsample_ps = DRW_pass_create("LightProbe Planar Downsample", DRW_STATE_WRITE_COLOR);
429
430                 DRWShadingGroup *grp = DRW_shgroup_create(
431                         EEVEE_shaders_probe_planar_downsample_sh_get(), psl->probe_planar_downsample_ps);
432
433                 DRW_shgroup_uniform_texture_ref(grp, "source", &txl->planar_pool);
434                 DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
435                 DRW_shgroup_call_instances_add(grp, DRW_cache_fullscreen_quad_get(), NULL, (uint *)&pinfo->num_planar);
436         }
437 }
438
439 static bool eevee_lightprobes_culling_test(Object *ob)
440 {
441         LightProbe *probe = (LightProbe *)ob->data;
442
443         switch (probe->type) {
444                 case LIGHTPROBE_TYPE_PLANAR:
445                 {
446                         /* See if this planar probe is inside the view frustum. If not, no need to update it. */
447                         /* NOTE: this could be bypassed if we want feedback loop mirrors for rendering. */
448                         BoundBox bbox; float tmp[4][4];
449                         const float min[3] = {-1.0f, -1.0f, -1.0f};
450                         const float max[3] = { 1.0f,  1.0f,  1.0f};
451                         BKE_boundbox_init_from_minmax(&bbox, min, max);
452
453                         copy_m4_m4(tmp, ob->obmat);
454                         normalize_v3(tmp[2]);
455                         mul_v3_fl(tmp[2], probe->distinf);
456
457                         for (int v = 0; v < 8; ++v) {
458                                 mul_m4_v3(tmp, bbox.vec[v]);
459                         }
460                         return DRW_culling_box_test(&bbox);
461                 }
462                 case LIGHTPROBE_TYPE_CUBE:
463                         return true; /* TODO */
464                 case LIGHTPROBE_TYPE_GRID:
465                         return true; /* TODO */
466         }
467         BLI_assert(0);
468         return true;
469 }
470
471 void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *ob)
472 {
473         EEVEE_LightProbesInfo *pinfo = sldata->probes;
474         LightProbe *probe = (LightProbe *)ob->data;
475
476         if ((probe->type == LIGHTPROBE_TYPE_CUBE && pinfo->num_cube >= MAX_PROBE) ||
477             (probe->type == LIGHTPROBE_TYPE_GRID && pinfo->num_grid >= MAX_PROBE) ||
478             (probe->type == LIGHTPROBE_TYPE_PLANAR && pinfo->num_planar >= MAX_PLANAR))
479         {
480                 printf("Too many probes in the view !!!\n");
481                 return;
482         }
483
484         if (probe->type == LIGHTPROBE_TYPE_PLANAR) {
485                 if (!eevee_lightprobes_culling_test(ob)) {
486                         return; /* Culled */
487                 }
488                 EEVEE_lightprobes_planar_data_from_object(ob,
489                                                           &pinfo->planar_data[pinfo->num_planar],
490                                                           &pinfo->planar_vis_tests[pinfo->num_planar]);
491                 /* Debug Display */
492                 DRWShadingGroup *grp = vedata->stl->g_data->planar_display_shgrp;
493                 if (grp && (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) {
494                         DRW_shgroup_call_dynamic_add(grp, &pinfo->num_planar, ob->obmat);
495                 }
496
497                 pinfo->num_planar++;
498         }
499         else {
500                 EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
501                 if (ped->need_update) {
502                         if (probe->type == LIGHTPROBE_TYPE_GRID) {
503                                 pinfo->do_grid_update = true;
504                         }
505                         else {
506                                 pinfo->do_cube_update = true;
507                         }
508                         ped->need_update = false;
509                 }
510         }
511 }
512
513 void EEVEE_lightprobes_grid_data_from_object(Object *ob, EEVEE_LightGrid *egrid, int *offset)
514 {
515         LightProbe *probe = (LightProbe *)ob->data;
516
517         copy_v3_v3_int(egrid->resolution, &probe->grid_resolution_x);
518
519         /* Save current offset and advance it for the next grid. */
520         egrid->offset = *offset;
521         *offset += egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2];
522
523         /* Add one for level 0 */
524         float fac = 1.0f / max_ff(1e-8f, probe->falloff);
525         egrid->attenuation_scale = fac / max_ff(1e-8f, probe->distinf);
526         egrid->attenuation_bias = fac;
527
528         /* Update transforms */
529         float cell_dim[3], half_cell_dim[3];
530         cell_dim[0] = 2.0f / egrid->resolution[0];
531         cell_dim[1] = 2.0f / egrid->resolution[1];
532         cell_dim[2] = 2.0f / egrid->resolution[2];
533
534         mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f);
535
536         /* Matrix converting world space to cell ranges. */
537         invert_m4_m4(egrid->mat, ob->obmat);
538
539         /* First cell. */
540         copy_v3_fl(egrid->corner, -1.0f);
541         add_v3_v3(egrid->corner, half_cell_dim);
542         mul_m4_v3(ob->obmat, egrid->corner);
543
544         /* Opposite neighbor cell. */
545         copy_v3_fl3(egrid->increment_x, cell_dim[0], 0.0f, 0.0f);
546         add_v3_v3(egrid->increment_x, half_cell_dim);
547         add_v3_fl(egrid->increment_x, -1.0f);
548         mul_m4_v3(ob->obmat, egrid->increment_x);
549         sub_v3_v3(egrid->increment_x, egrid->corner);
550
551         copy_v3_fl3(egrid->increment_y, 0.0f, cell_dim[1], 0.0f);
552         add_v3_v3(egrid->increment_y, half_cell_dim);
553         add_v3_fl(egrid->increment_y, -1.0f);
554         mul_m4_v3(ob->obmat, egrid->increment_y);
555         sub_v3_v3(egrid->increment_y, egrid->corner);
556
557         copy_v3_fl3(egrid->increment_z, 0.0f, 0.0f, cell_dim[2]);
558         add_v3_v3(egrid->increment_z, half_cell_dim);
559         add_v3_fl(egrid->increment_z, -1.0f);
560         mul_m4_v3(ob->obmat, egrid->increment_z);
561         sub_v3_v3(egrid->increment_z, egrid->corner);
562
563         /* Visibility bias */
564         egrid->visibility_bias = 0.05f * probe->vis_bias;
565         egrid->visibility_bleed = probe->vis_bleedbias;
566         egrid->visibility_range = 1.0f + sqrtf(max_fff(len_squared_v3(egrid->increment_x),
567                                                        len_squared_v3(egrid->increment_y),
568                                                        len_squared_v3(egrid->increment_z)));
569 }
570
571 void EEVEE_lightprobes_cube_data_from_object(Object *ob, EEVEE_LightProbe *eprobe)
572 {
573         LightProbe *probe = (LightProbe *)ob->data;
574
575         /* Update transforms */
576         copy_v3_v3(eprobe->position, ob->obmat[3]);
577
578         /* Attenuation */
579         eprobe->attenuation_type = probe->attenuation_type;
580         eprobe->attenuation_fac = 1.0f / max_ff(1e-8f, probe->falloff);
581
582         unit_m4(eprobe->attenuationmat);
583         scale_m4_fl(eprobe->attenuationmat, probe->distinf);
584         mul_m4_m4m4(eprobe->attenuationmat, ob->obmat, eprobe->attenuationmat);
585         invert_m4(eprobe->attenuationmat);
586
587         /* Parallax */
588         unit_m4(eprobe->parallaxmat);
589
590         if ((probe->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) {
591                 eprobe->parallax_type = probe->parallax_type;
592                 scale_m4_fl(eprobe->parallaxmat, probe->distpar);
593         }
594         else {
595                 eprobe->parallax_type = probe->attenuation_type;
596                 scale_m4_fl(eprobe->parallaxmat, probe->distinf);
597         }
598
599         mul_m4_m4m4(eprobe->parallaxmat, ob->obmat, eprobe->parallaxmat);
600         invert_m4(eprobe->parallaxmat);
601 }
602
603 void EEVEE_lightprobes_planar_data_from_object(Object *ob, EEVEE_PlanarReflection *eplanar, EEVEE_LightProbeVisTest *vis_test)
604 {
605         LightProbe *probe = (LightProbe *)ob->data;
606         float normat[4][4], imat[4][4];
607
608         vis_test->collection = probe->visibility_grp;
609         vis_test->invert = probe->flag & LIGHTPROBE_FLAG_INVERT_GROUP;
610         vis_test->cached = false;
611
612         /* Computing mtx : matrix that mirror position around object's XY plane. */
613         normalize_m4_m4(normat, ob->obmat);  /* object > world */
614         invert_m4_m4(imat, normat); /* world > object */
615         /* XY reflection plane */
616         imat[0][2] = -imat[0][2];
617         imat[1][2] = -imat[1][2];
618         imat[2][2] = -imat[2][2];
619         imat[3][2] = -imat[3][2]; /* world > object > mirrored obj */
620         mul_m4_m4m4(eplanar->mtx, normat, imat); /* world > object > mirrored obj > world */
621
622         /* Compute clip plane equation / normal. */
623         copy_v3_v3(eplanar->plane_equation, ob->obmat[2]);
624         normalize_v3(eplanar->plane_equation); /* plane normal */
625         eplanar->plane_equation[3] = -dot_v3v3(eplanar->plane_equation, ob->obmat[3]);
626         eplanar->clipsta = probe->clipsta;
627
628         /* Compute XY clip planes. */
629         normalize_v3_v3(eplanar->clip_vec_x, ob->obmat[0]);
630         normalize_v3_v3(eplanar->clip_vec_y, ob->obmat[1]);
631
632         float vec[3] = {0.0f, 0.0f, 0.0f};
633         vec[0] = 1.0f; vec[1] = 0.0f; vec[2] = 0.0f;
634         mul_m4_v3(ob->obmat, vec); /* Point on the edge */
635         eplanar->clip_edge_x_pos = dot_v3v3(eplanar->clip_vec_x, vec);
636
637         vec[0] = 0.0f; vec[1] = 1.0f; vec[2] = 0.0f;
638         mul_m4_v3(ob->obmat, vec); /* Point on the edge */
639         eplanar->clip_edge_y_pos = dot_v3v3(eplanar->clip_vec_y, vec);
640
641         vec[0] = -1.0f; vec[1] = 0.0f; vec[2] = 0.0f;
642         mul_m4_v3(ob->obmat, vec); /* Point on the edge */
643         eplanar->clip_edge_x_neg = dot_v3v3(eplanar->clip_vec_x, vec);
644
645         vec[0] = 0.0f; vec[1] = -1.0f; vec[2] = 0.0f;
646         mul_m4_v3(ob->obmat, vec); /* Point on the edge */
647         eplanar->clip_edge_y_neg = dot_v3v3(eplanar->clip_vec_y, vec);
648
649         /* Facing factors */
650         float max_angle = max_ff(1e-2f, 1.0f - probe->falloff) * M_PI * 0.5f;
651         float min_angle = 0.0f;
652         eplanar->facing_scale = 1.0f / max_ff(1e-8f, cosf(min_angle) - cosf(max_angle));
653         eplanar->facing_bias = -min_ff(1.0f - 1e-8f, cosf(max_angle)) * eplanar->facing_scale;
654
655         /* Distance factors */
656         float max_dist = probe->distinf;
657         float min_dist = min_ff(1.0f - 1e-8f, 1.0f - probe->falloff) * probe->distinf;
658         eplanar->attenuation_scale = -1.0f / max_ff(1e-8f, max_dist - min_dist);
659         eplanar->attenuation_bias = max_dist * -eplanar->attenuation_scale;
660 }
661
662 static void lightbake_planar_compute_render_matrices(
663         EEVEE_PlanarReflection *eplanar, DRWMatrixState *r_matstate, const float viewmat[4][4])
664 {
665         /* Reflect Camera Matrix. */
666         mul_m4_m4m4(r_matstate->viewmat, viewmat, eplanar->mtx);
667         /* TODO FOV margin */
668         /* Temporal sampling jitter should be already applied to the DRW_MAT_WIN. */
669         DRW_viewport_matrix_get(r_matstate->winmat, DRW_MAT_WIN);
670         /* Apply Projection Matrix. */
671         mul_m4_m4m4(r_matstate->persmat, r_matstate->winmat, r_matstate->viewmat);
672
673         /* This is the matrix used to reconstruct texture coordinates.
674          * We use the original view matrix because it does not create
675          * visual artifacts if receiver is not perfectly aligned with
676          * the planar reflection probe. */
677         mul_m4_m4m4(eplanar->reflectionmat, r_matstate->winmat, viewmat); /* TODO FOV margin */
678         /* Convert from [-1, 1] to [0, 1] (NDC to Texture coord). */
679         mul_m4_m4m4(eplanar->reflectionmat, texcomat, eplanar->reflectionmat);
680 }
681
682 static void eevee_lightprobes_extract_from_cache(EEVEE_LightProbesInfo *pinfo, LightCache *lcache)
683 {
684         /* copy the entire cache for now (up to MAX_PROBE) */
685         /* TODO Frutum cull to only add visible probes. */
686         memcpy(pinfo->probe_data, lcache->cube_data, sizeof(EEVEE_LightProbe) * max_ii(1, min_ii(lcache->cube_len, MAX_PROBE)));
687         /* TODO compute the max number of grid based on sample count. */
688         memcpy(pinfo->grid_data, lcache->grid_data, sizeof(EEVEE_LightGrid) * max_ii(1, min_ii(lcache->grid_len, MAX_GRID)));
689 }
690
691 void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
692 {
693         EEVEE_StorageList *stl = vedata->stl;
694         LightCache *light_cache = stl->g_data->light_cache;
695         EEVEE_LightProbesInfo *pinfo = sldata->probes;
696         const DRWContextState *draw_ctx = DRW_context_state_get();
697         const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
698
699         eevee_lightprobes_extract_from_cache(sldata->probes, light_cache);
700
701         DRW_uniformbuffer_update(sldata->probe_ubo, &sldata->probes->probe_data);
702         DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data);
703
704         /* For shading, save max level of the octahedron map */
705         sldata->common_data.prb_lod_cube_max = (float)light_cache->mips_len - 1.0f;
706         sldata->common_data.prb_lod_planar_max = (float)MAX_PLANAR_LOD_LEVEL;
707         sldata->common_data.prb_irradiance_vis_size = light_cache->vis_res;
708         sldata->common_data.prb_irradiance_smooth = SQUARE(scene_eval->eevee.gi_irradiance_smoothing);
709         sldata->common_data.prb_num_render_cube = max_ii(1, light_cache->cube_len);
710         sldata->common_data.prb_num_render_grid = max_ii(1, light_cache->grid_len);
711         sldata->common_data.prb_num_planar = pinfo->num_planar;
712
713         if (pinfo->num_planar != pinfo->cache_num_planar) {
714                 DRW_TEXTURE_FREE_SAFE(vedata->txl->planar_pool);
715                 DRW_TEXTURE_FREE_SAFE(vedata->txl->planar_depth);
716                 pinfo->cache_num_planar = pinfo->num_planar;
717         }
718         planar_pool_ensure_alloc(vedata, pinfo->num_planar);
719
720         /* If lightcache auto-update is enable we tag the relevant part
721          * of the cache to update and fire up a baking job. */
722         if (!DRW_state_is_image_render() && !DRW_state_is_opengl_render() &&
723             (pinfo->do_grid_update || pinfo->do_cube_update))
724         {
725                 BLI_assert(draw_ctx->evil_C);
726
727                 if (draw_ctx->scene->eevee.flag & SCE_EEVEE_GI_AUTOBAKE) {
728                         Scene *scene_orig = DEG_get_input_scene(draw_ctx->depsgraph);
729                         if (scene_orig->eevee.light_cache != NULL) {
730                                 if (pinfo->do_grid_update) {
731                                         scene_orig->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_GRID;
732                                 }
733                                 /* If we update grid we need to update the cubemaps too.
734                                  * So always refresh cubemaps. */
735                                 scene_orig->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE;
736                                 /* Tag the lightcache to auto update. */
737                                 scene_orig->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_AUTO;
738                                 /* Use a notifier to trigger the operator after drawing. */
739                                 WM_event_add_notifier(draw_ctx->evil_C, NC_LIGHTPROBE, scene_orig);
740                         }
741                 }
742         }
743 }
744
745 /* -------------------------------------------------------------------- */
746 /** \name Rendering
747  * \{ */
748
749 typedef struct EEVEE_BakeRenderData {
750         EEVEE_Data *vedata;
751         EEVEE_ViewLayerData *sldata;
752         struct GPUFrameBuffer **face_fb; /* should contain 6 framebuffer */
753 } EEVEE_BakeRenderData;
754
755 static void render_cubemap(
756         void (*callback)(int face, EEVEE_BakeRenderData *user_data), EEVEE_BakeRenderData *user_data,
757         const float pos[3], float clipsta, float clipend)
758 {
759         DRWMatrixState matstate;
760
761         /* Move to capture position */
762         float posmat[4][4];
763         unit_m4(posmat);
764         negate_v3_v3(posmat[3], pos);
765
766         perspective_m4(matstate.winmat, -clipsta, clipsta, -clipsta, clipsta, clipsta, clipend);
767         invert_m4_m4(matstate.wininv, matstate.winmat);
768
769         /* 1 - Render to each cubeface individually.
770          * We do this instead of using geometry shader because a) it's faster,
771          * b) it's easier than fixing the nodetree shaders (for view dependent effects). */
772         for (int i = 0; i < 6; ++i) {
773                 /* Setup custom matrices */
774                 mul_m4_m4m4(matstate.viewmat, cubefacemat[i], posmat);
775                 mul_m4_m4m4(matstate.persmat, matstate.winmat, matstate.viewmat);
776                 invert_m4_m4(matstate.persinv, matstate.persmat);
777                 invert_m4_m4(matstate.viewinv, matstate.viewmat);
778                 invert_m4_m4(matstate.wininv, matstate.winmat);
779
780                 DRW_viewport_matrix_override_set_all(&matstate);
781
782                 callback(i, user_data);
783         }
784 }
785
786 static void render_reflections(
787         void (*callback)(int face, EEVEE_BakeRenderData *user_data), EEVEE_BakeRenderData *user_data,
788         EEVEE_PlanarReflection *planar_data, int ref_count)
789 {
790         DRWMatrixState matstate;
791
792         float original_viewmat[4][4];
793         DRW_viewport_matrix_get(original_viewmat, DRW_MAT_VIEW);
794
795         for (int i = 0; i < ref_count; ++i) {
796                 /* Setup custom matrices */
797                 lightbake_planar_compute_render_matrices(planar_data + i, &matstate, original_viewmat);
798                 invert_m4_m4(matstate.persinv, matstate.persmat);
799                 invert_m4_m4(matstate.viewinv, matstate.viewmat);
800                 invert_m4_m4(matstate.wininv, matstate.winmat);
801                 DRW_viewport_matrix_override_set_all(&matstate);
802
803                 callback(i, user_data);
804         }
805 }
806
807 static void lightbake_render_world_face(int face, EEVEE_BakeRenderData *user_data)
808 {
809         EEVEE_PassList *psl = user_data->vedata->psl;
810         struct GPUFrameBuffer **face_fb = user_data->face_fb;
811
812         /* For world probe, we don't need to clear the color buffer
813          * since we render the background directly. */
814         GPU_framebuffer_bind(face_fb[face]);
815         GPU_framebuffer_clear_depth(face_fb[face], 1.0f);
816         DRW_draw_pass(psl->probe_background);
817 }
818
819 void EEVEE_lightbake_render_world(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, struct GPUFrameBuffer *face_fb[6])
820 {
821         EEVEE_BakeRenderData brdata = {
822                 .vedata = vedata,
823                 .face_fb = face_fb,
824         };
825
826         render_cubemap(lightbake_render_world_face, &brdata, (float[3]){0.0f}, 1.0f, 10.0f);
827 }
828
829 static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_data)
830 {
831         EEVEE_ViewLayerData *sldata = user_data->sldata;
832         EEVEE_PassList *psl = user_data->vedata->psl;
833         struct GPUFrameBuffer **face_fb = user_data->face_fb;
834
835         /* Be sure that cascaded shadow maps are updated. */
836         EEVEE_draw_shadows(sldata, user_data->vedata);
837
838         GPU_framebuffer_bind(face_fb[face]);
839         GPU_framebuffer_clear_depth(face_fb[face], 1.0f);
840
841         DRW_draw_pass(psl->depth_pass);
842         DRW_draw_pass(psl->depth_pass_cull);
843         DRW_draw_pass(psl->probe_background);
844         DRW_draw_pass(psl->material_pass);
845         DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
846         EEVEE_draw_default_passes(psl);
847 }
848
849 /* Render the scene to the probe_rt texture. */
850 void EEVEE_lightbake_render_scene(
851         EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct GPUFrameBuffer *face_fb[6],
852         const float pos[3], float near_clip, float far_clip)
853 {
854         EEVEE_BakeRenderData brdata = {
855                 .vedata = vedata,
856                 .sldata = sldata,
857                 .face_fb = face_fb,
858         };
859
860         render_cubemap(lightbake_render_scene_face, &brdata, pos, near_clip, far_clip);
861 }
862
863 static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *user_data)
864 {
865         EEVEE_Data *vedata = user_data->vedata;
866         EEVEE_ViewLayerData *sldata = user_data->sldata;
867         EEVEE_PassList *psl = vedata->psl;
868         EEVEE_TextureList *txl = vedata->txl;
869         EEVEE_FramebufferList *fbl = vedata->fbl;
870         EEVEE_LightProbesInfo *pinfo = sldata->probes;
871         EEVEE_PlanarReflection *eplanar = pinfo->planar_data + layer;
872
873         GPU_framebuffer_ensure_config(&fbl->planarref_fb, {
874                 GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_depth, layer),
875                 GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_pool, layer)
876         });
877
878         /* Use visibility info for this planar reflection. */
879         pinfo->vis_data = pinfo->planar_vis_tests[layer];
880
881         /* Avoid using the texture attached to framebuffer when rendering. */
882         /* XXX */
883         GPUTexture *tmp_planar_pool = txl->planar_pool;
884         GPUTexture *tmp_planar_depth = txl->planar_depth;
885         txl->planar_pool = e_data.planar_pool_placeholder;
886         txl->planar_depth = e_data.depth_array_placeholder;
887
888         /* Be sure that cascaded shadow maps are updated. */
889         DRW_stats_group_start("Planar Reflection");
890
891         /* Be sure that cascaded shadow maps are updated. */
892         EEVEE_draw_shadows(sldata, vedata);
893         /* Since we are rendering with an inverted view matrix, we need
894          * to invert the facing for backface culling to be the same. */
895         DRW_state_invert_facing();
896         /* Compute offset plane equation (fix missing texels near reflection plane). */
897         copy_v4_v4(sldata->clip_data.clip_planes[0], eplanar->plane_equation);
898         sldata->clip_data.clip_planes[0][3] += eplanar->clipsta;
899         /* Set clipping plane */
900         DRW_uniformbuffer_update(sldata->clip_ubo, &sldata->clip_data);
901         DRW_state_clip_planes_len_set(1);
902
903         GPU_framebuffer_bind(fbl->planarref_fb);
904         GPU_framebuffer_clear_depth(fbl->planarref_fb, 1.0);
905
906         /* Slight modification: we handle refraction as normal
907          * shading and don't do SSRefraction. */
908
909         DRW_draw_pass(psl->depth_pass_clip);
910         DRW_draw_pass(psl->depth_pass_clip_cull);
911         DRW_draw_pass(psl->refract_depth_pass);
912         DRW_draw_pass(psl->refract_depth_pass_cull);
913
914         DRW_draw_pass(psl->probe_background);
915         EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer);
916         EEVEE_occlusion_compute(sldata, vedata, tmp_planar_depth, layer);
917
918         GPU_framebuffer_bind(fbl->planarref_fb);
919
920         /* Shading pass */
921         EEVEE_draw_default_passes(psl);
922         DRW_draw_pass(psl->material_pass);
923         DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
924         DRW_draw_pass(psl->refract_pass);
925
926         /* Transparent */
927         if (DRW_state_is_image_render()) {
928                 /* Do the reordering only for offline because it can be costly. */
929                 DRW_pass_sort_shgroup_z(psl->transparent_pass);
930         }
931         DRW_draw_pass(psl->transparent_pass);
932
933         DRW_state_invert_facing();
934         DRW_state_clip_planes_reset();
935
936         DRW_stats_group_end();
937
938         /* Restore */
939         txl->planar_pool = tmp_planar_pool;
940         txl->planar_depth = tmp_planar_depth;
941 }
942
943 static void eevee_lightbake_render_scene_to_planars(
944         EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
945 {
946         EEVEE_BakeRenderData brdata = {
947                 .vedata = vedata,
948                 .sldata = sldata,
949         };
950
951         render_reflections(lightbake_render_scene_reflected, &brdata, sldata->probes->planar_data, sldata->probes->num_planar);
952 }
953 /** \} */
954
955 /* -------------------------------------------------------------------- */
956 /** \name Filtering
957  * \{ */
958
959 /* Glossy filter rt_color to light_cache->cube_tx.tex at index probe_idx */
960 void EEVEE_lightbake_filter_glossy(
961         EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
962         struct GPUTexture *rt_color, struct GPUFrameBuffer *fb,
963         int probe_idx, float intensity, int maxlevel, float filter_quality, float firefly_fac)
964 {
965         EEVEE_PassList *psl = vedata->psl;
966         EEVEE_LightProbesInfo *pinfo = sldata->probes;
967         LightCache *light_cache = vedata->stl->g_data->light_cache;
968
969         float target_size = (float)GPU_texture_width(rt_color);
970
971         /* Max lod used from the render target probe */
972         pinfo->lod_rt_max = floorf(log2f(target_size)) - 2.0f;
973         pinfo->intensity_fac = intensity;
974
975         /* Start fresh */
976         GPU_framebuffer_ensure_config(&fb, {
977                 GPU_ATTACHMENT_NONE,
978                 GPU_ATTACHMENT_NONE
979         });
980
981         /* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */
982         /* Bind next framebuffer to be able to gen. mips for probe_rt. */
983         EEVEE_downsample_cube_buffer(vedata, rt_color, (int)(pinfo->lod_rt_max));
984
985         /* 3 - Render to probe array to the specified layer, do prefiltering. */
986         int mipsize = GPU_texture_width(light_cache->cube_tx.tex);
987         for (int i = 0; i < maxlevel + 1; i++) {
988                 float bias = (i == 0) ? -1.0f : 1.0f;
989                 pinfo->texel_size = 1.0f / (float)mipsize;
990                 pinfo->padding_size = (i == maxlevel) ? 0 : (float)(1 << (maxlevel - i - 1));
991                 pinfo->padding_size *= pinfo->texel_size;
992                 pinfo->layer = probe_idx;
993                 pinfo->roughness = i / (float)maxlevel;
994                 pinfo->roughness *= pinfo->roughness; /* Disney Roughness */
995                 pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */
996                 CLAMP(pinfo->roughness, 1e-8f, 0.99999f); /* Avoid artifacts */
997
998 #if 1 /* Variable Sample count (fast) */
999                 switch (i) {
1000                         case 0: pinfo->samples_len = 1.0f; break;
1001                         case 1: pinfo->samples_len = 16.0f; break;
1002                         case 2: pinfo->samples_len = 32.0f; break;
1003                         case 3: pinfo->samples_len = 64.0f; break;
1004                         default: pinfo->samples_len = 128.0f; break;
1005                 }
1006 #else /* Constant Sample count (slow) */
1007                 pinfo->samples_len = 1024.0f;
1008 #endif
1009                 /* Cannot go higher than HAMMERSLEY_SIZE */
1010                 CLAMP(filter_quality, 1.0f, 8.0f);
1011                 pinfo->samples_len *= filter_quality;
1012
1013                 pinfo->samples_len_inv = 1.0f / pinfo->samples_len;
1014                 pinfo->lodfactor = bias + 0.5f * log((float)(target_size * target_size) * pinfo->samples_len_inv) / log(2);
1015                 pinfo->firefly_fac = (firefly_fac > 0.0) ? firefly_fac : 1e16;
1016
1017                 GPU_framebuffer_ensure_config(&fb, {
1018                         GPU_ATTACHMENT_NONE,
1019                         GPU_ATTACHMENT_TEXTURE_MIP(light_cache->cube_tx.tex, i)
1020                 });
1021                 GPU_framebuffer_bind(fb);
1022                 GPU_framebuffer_viewport_set(fb, 0, 0, mipsize, mipsize);
1023                 DRW_draw_pass(psl->probe_glossy_compute);
1024
1025                 mipsize /= 2;
1026                 CLAMP_MIN(mipsize, 1);
1027         }
1028 }
1029
1030 /* Diffuse filter rt_color to light_cache->grid_tx.tex at index grid_offset */
1031 void EEVEE_lightbake_filter_diffuse(
1032         EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
1033         struct GPUTexture *rt_color, struct GPUFrameBuffer *fb,
1034         int grid_offset, float intensity)
1035 {
1036         EEVEE_PassList *psl = vedata->psl;
1037         EEVEE_LightProbesInfo *pinfo = sldata->probes;
1038         LightCache *light_cache = vedata->stl->g_data->light_cache;
1039
1040         float target_size = (float)GPU_texture_width(rt_color);
1041
1042         pinfo->intensity_fac = intensity;
1043
1044         /* find cell position on the virtual 3D texture */
1045         /* NOTE : Keep in sync with load_irradiance_cell() */
1046 #if defined(IRRADIANCE_SH_L2)
1047         int size[2] = {3, 3};
1048 #elif defined(IRRADIANCE_CUBEMAP)
1049         int size[2] = {8, 8};
1050         pinfo->samples_len = 1024.0f;
1051 #elif defined(IRRADIANCE_HL2)
1052         int size[2] = {3, 2};
1053         pinfo->samples_len = 1024.0f;
1054 #endif
1055
1056         int cell_per_row = GPU_texture_width(light_cache->grid_tx.tex) / size[0];
1057         int x = size[0] * (grid_offset % cell_per_row);
1058         int y = size[1] * (grid_offset / cell_per_row);
1059
1060 #ifndef IRRADIANCE_SH_L2
1061         /* Tweaking parameters to balance perf. vs precision */
1062         const float bias = 0.0f;
1063         pinfo->samples_len_inv = 1.0f / pinfo->samples_len;
1064         pinfo->lodfactor = bias + 0.5f * log((float)(target_size * target_size) * pinfo->samples_len_inv) / log(2);
1065         pinfo->lod_rt_max = floorf(log2f(target_size)) - 2.0f;
1066 #else
1067         pinfo->shres = 32; /* Less texture fetches & reduce branches */
1068         pinfo->lod_rt_max = 2.0f; /* Improve cache reuse */
1069 #endif
1070
1071         /* Start fresh */
1072         GPU_framebuffer_ensure_config(&fb, {
1073                 GPU_ATTACHMENT_NONE,
1074                 GPU_ATTACHMENT_NONE
1075         });
1076
1077         /* 4 - Compute diffuse irradiance */
1078         EEVEE_downsample_cube_buffer(vedata, rt_color, (int)(pinfo->lod_rt_max));
1079
1080         GPU_framebuffer_ensure_config(&fb, {
1081                 GPU_ATTACHMENT_NONE,
1082                 GPU_ATTACHMENT_TEXTURE_LAYER(light_cache->grid_tx.tex, 0)
1083         });
1084         GPU_framebuffer_bind(fb);
1085         GPU_framebuffer_viewport_set(fb, x, y, size[0], size[1]);
1086         DRW_draw_pass(psl->probe_diffuse_compute);
1087 }
1088
1089 /* Filter rt_depth to light_cache->grid_tx.tex at index grid_offset */
1090 void EEVEE_lightbake_filter_visibility(
1091         EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
1092         struct GPUTexture *UNUSED(rt_depth), struct GPUFrameBuffer *fb,
1093         int grid_offset, float clipsta, float clipend,
1094         float vis_range, float vis_blur, int vis_size)
1095 {
1096         EEVEE_PassList *psl = vedata->psl;
1097         EEVEE_LightProbesInfo *pinfo = sldata->probes;
1098         LightCache *light_cache = vedata->stl->g_data->light_cache;
1099
1100         pinfo->samples_len = 512.0f; /* TODO refine */
1101         pinfo->samples_len_inv = 1.0f / pinfo->samples_len;
1102         pinfo->shres = vis_size;
1103         pinfo->visibility_range = vis_range;
1104         pinfo->visibility_blur = vis_blur;
1105         pinfo->near_clip = -clipsta;
1106         pinfo->far_clip = -clipend;
1107         pinfo->texel_size = 1.0f / (float)vis_size;
1108
1109         int cell_per_col = GPU_texture_height(light_cache->grid_tx.tex) / vis_size;
1110         int cell_per_row = GPU_texture_width(light_cache->grid_tx.tex) / vis_size;
1111         int x = vis_size * (grid_offset % cell_per_row);
1112         int y = vis_size * ((grid_offset / cell_per_row) % cell_per_col);
1113         int layer = 1 + ((grid_offset / cell_per_row) / cell_per_col);
1114
1115         GPU_framebuffer_ensure_config(&fb, {
1116                 GPU_ATTACHMENT_NONE,
1117                 GPU_ATTACHMENT_TEXTURE_LAYER(light_cache->grid_tx.tex, layer)
1118         });
1119         GPU_framebuffer_bind(fb);
1120         GPU_framebuffer_viewport_set(fb, x, y, vis_size, vis_size);
1121         DRW_draw_pass(psl->probe_visibility_compute);
1122 }
1123
1124 /* Actually a simple downsampling */
1125 static void downsample_planar(void *vedata, int level)
1126 {
1127         EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
1128         EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
1129
1130         const float *size = DRW_viewport_size_get();
1131         copy_v2_v2(stl->g_data->planar_texel_size, size);
1132         for (int i = 0; i < level - 1; ++i) {
1133                 stl->g_data->planar_texel_size[0] /= 2.0f;
1134                 stl->g_data->planar_texel_size[1] /= 2.0f;
1135                 min_ff(floorf(stl->g_data->planar_texel_size[0]), 1.0f);
1136                 min_ff(floorf(stl->g_data->planar_texel_size[1]), 1.0f);
1137         }
1138         invert_v2(stl->g_data->planar_texel_size);
1139
1140         DRW_draw_pass(psl->probe_planar_downsample_ps);
1141 }
1142
1143 static void EEVEE_lightbake_filter_planar(EEVEE_Data *vedata)
1144 {
1145         EEVEE_TextureList *txl = vedata->txl;
1146         EEVEE_FramebufferList  *fbl = vedata->fbl;
1147
1148         DRW_stats_group_start("Planar Probe Downsample");
1149
1150         GPU_framebuffer_ensure_config(&fbl->planar_downsample_fb, {
1151                 GPU_ATTACHMENT_NONE,
1152                 GPU_ATTACHMENT_TEXTURE(txl->planar_pool)
1153         });
1154
1155         GPU_framebuffer_recursive_downsample(fbl->planar_downsample_fb, MAX_PLANAR_LOD_LEVEL, &downsample_planar, vedata);
1156         DRW_stats_group_end();
1157 }
1158
1159 /** \} */
1160
1161 void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
1162 {
1163         EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
1164         EEVEE_LightProbesInfo *pinfo = sldata->probes;
1165         DRWMatrixState saved_mats;
1166
1167         if (pinfo->num_planar == 0) {
1168                 /* Disable SSR if we cannot read previous frame */
1169                 common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer;
1170                 common_data->prb_num_planar = 0;
1171                 return;
1172         }
1173
1174         /* We need to save the Matrices before overidding them */
1175         DRW_viewport_matrix_get_all(&saved_mats);
1176
1177         /* Temporary Remove all planar reflections (avoid lag effect). */
1178         common_data->prb_num_planar = 0;
1179         /* Turn off ssr to avoid black specular */
1180         common_data->ssr_toggle = false;
1181         common_data->sss_toggle = false;
1182
1183         common_data->ray_type = EEVEE_RAY_GLOSSY;
1184         common_data->ray_depth = 1.0f;
1185         DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
1186
1187         /* Rendering happens here! */
1188         eevee_lightbake_render_scene_to_planars(sldata, vedata);
1189
1190         /* Make sure no aditionnal visibility check runs after this. */
1191         pinfo->vis_data.collection = NULL;
1192
1193         DRW_uniformbuffer_update(sldata->planar_ubo, &sldata->probes->planar_data);
1194
1195         /* Restore */
1196         common_data->prb_num_planar = pinfo->num_planar;
1197         common_data->ssr_toggle = true;
1198         common_data->sss_toggle = true;
1199
1200         /* Prefilter for SSR */
1201         if ((vedata->stl->effects->enabled_effects & EFFECT_SSR) != 0) {
1202                 EEVEE_lightbake_filter_planar(vedata);
1203         }
1204
1205         DRW_viewport_matrix_override_set_all(&saved_mats);
1206
1207         if (DRW_state_is_image_render()) {
1208                 /* Sort transparents because planar reflections could have re-sorted them. */
1209                 DRW_pass_sort_shgroup_z(vedata->psl->transparent_pass);
1210         }
1211
1212         /* Disable SSR if we cannot read previous frame */
1213         common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer;
1214 }
1215
1216 void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
1217 {
1218         const DRWContextState *draw_ctx = DRW_context_state_get();
1219         const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
1220         LightCache *light_cache = vedata->stl->g_data->light_cache;
1221
1222         if (light_cache->flag & LIGHTCACHE_UPDATE_WORLD) {
1223                 DRWMatrixState saved_mats;
1224                 DRW_viewport_matrix_get_all(&saved_mats);
1225                 EEVEE_lightbake_update_world_quick(sldata, vedata, scene_eval);
1226                 DRW_viewport_matrix_override_set_all(&saved_mats);
1227         }
1228 }
1229
1230 void EEVEE_lightprobes_free(void)
1231 {
1232         MEM_SAFE_FREE(e_data.format_probe_display_cube);
1233         MEM_SAFE_FREE(e_data.format_probe_display_planar);
1234         DRW_TEXTURE_FREE_SAFE(e_data.hammersley);
1235         DRW_TEXTURE_FREE_SAFE(e_data.planar_pool_placeholder);
1236         DRW_TEXTURE_FREE_SAFE(e_data.depth_placeholder);
1237         DRW_TEXTURE_FREE_SAFE(e_data.depth_array_placeholder);
1238 }