2018-07-10 15:02:25 +02:00
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
2019-01-23 11:29:18 +11:00
|
|
|
* Copyright 2016, Blender Foundation.
|
2018-07-10 15:02:25 +02:00
|
|
|
*/
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup draw_engine
|
2018-07-10 15:02:25 +02:00
|
|
|
*
|
|
|
|
* Eevee's indirect lighting cache.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "DRW_render.h"
|
|
|
|
|
|
|
|
#include "BKE_global.h"
|
|
|
|
|
2020-11-06 13:35:19 +01:00
|
|
|
#include "BLI_endian_switch.h"
|
2018-07-10 15:02:25 +02:00
|
|
|
#include "BLI_threads.h"
|
|
|
|
|
|
|
|
#include "DEG_depsgraph_build.h"
|
|
|
|
#include "DEG_depsgraph_query.h"
|
|
|
|
|
|
|
|
#include "BKE_object.h"
|
|
|
|
|
2018-08-29 15:32:50 +02:00
|
|
|
#include "DNA_collection_types.h"
|
2018-07-10 15:02:25 +02:00
|
|
|
#include "DNA_lightprobe_types.h"
|
|
|
|
|
|
|
|
#include "PIL_time.h"
|
|
|
|
|
|
|
|
#include "eevee_lightcache.h"
|
|
|
|
#include "eevee_private.h"
|
|
|
|
|
2020-09-07 19:35:56 +02:00
|
|
|
#include "GPU_capabilities.h"
|
2018-07-17 21:11:23 +02:00
|
|
|
#include "GPU_context.h"
|
2018-07-10 15:02:25 +02:00
|
|
|
|
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
2020-11-06 13:35:19 +01:00
|
|
|
#include "BLO_read_write.h"
|
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
#include "wm_window.h"
|
|
|
|
|
|
|
|
/* Rounded to nearest PowerOfTwo */
|
|
|
|
#if defined(IRRADIANCE_SH_L2)
|
|
|
|
# define IRRADIANCE_SAMPLE_SIZE_X 4 /* 3 in reality */
|
|
|
|
# define IRRADIANCE_SAMPLE_SIZE_Y 4 /* 3 in reality */
|
|
|
|
#elif defined(IRRADIANCE_HL2)
|
|
|
|
# define IRRADIANCE_SAMPLE_SIZE_X 4 /* 3 in reality */
|
|
|
|
# define IRRADIANCE_SAMPLE_SIZE_Y 2
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef IRRADIANCE_SH_L2
|
|
|
|
/* we need a signed format for Spherical Harmonics */
|
|
|
|
# define IRRADIANCE_FORMAT GPU_RGBA16F
|
|
|
|
#else
|
|
|
|
# define IRRADIANCE_FORMAT GPU_RGBA8
|
|
|
|
#endif
|
|
|
|
|
2019-01-14 16:30:43 +11:00
|
|
|
/* OpenGL 3.3 core requirement, can be extended but it's already very big */
|
|
|
|
#define IRRADIANCE_MAX_POOL_LAYER 256
|
2018-07-10 15:02:25 +02:00
|
|
|
#define IRRADIANCE_MAX_POOL_SIZE 1024
|
|
|
|
#define MAX_IRRADIANCE_SAMPLES \
|
|
|
|
(IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_X) * \
|
|
|
|
(IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_Y)
|
|
|
|
|
|
|
|
/* TODO should be replace by a more elegant alternative. */
|
|
|
|
extern void DRW_opengl_context_enable(void);
|
|
|
|
extern void DRW_opengl_context_disable(void);
|
|
|
|
|
|
|
|
extern void DRW_opengl_render_context_enable(void *re_gl_context);
|
|
|
|
extern void DRW_opengl_render_context_disable(void *re_gl_context);
|
2019-08-17 01:17:30 +10:00
|
|
|
extern void DRW_gpu_render_context_enable(void *re_gpu_context);
|
|
|
|
extern void DRW_gpu_render_context_disable(void *re_gpu_context);
|
2018-07-10 15:02:25 +02:00
|
|
|
|
|
|
|
typedef struct EEVEE_LightBake {
|
|
|
|
Depsgraph *depsgraph;
|
|
|
|
ViewLayer *view_layer;
|
|
|
|
ViewLayer *view_layer_input;
|
|
|
|
LightCache *lcache;
|
|
|
|
Scene *scene;
|
|
|
|
struct Main *bmain;
|
2018-07-27 17:33:53 +02:00
|
|
|
EEVEE_ViewLayerData *sldata;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-21 13:44:06 +10:00
|
|
|
/** Current probe being rendered. */
|
|
|
|
LightProbe **probe;
|
|
|
|
/** Target cube color texture. */
|
|
|
|
GPUTexture *rt_color;
|
|
|
|
/** Target cube depth texture. */
|
|
|
|
GPUTexture *rt_depth;
|
2021-02-05 16:23:34 +11:00
|
|
|
/** Target cube frame-buffers. */
|
2019-04-21 13:44:06 +10:00
|
|
|
GPUFrameBuffer *rt_fb[6];
|
2021-02-05 16:23:34 +11:00
|
|
|
/** Storage frame-buffer. */
|
2019-04-21 13:44:06 +10:00
|
|
|
GPUFrameBuffer *store_fb;
|
|
|
|
/** Cube render target resolution. */
|
|
|
|
int rt_res;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Shared */
|
2019-04-21 13:44:06 +10:00
|
|
|
/** Target layer to store the data to. */
|
|
|
|
int layer;
|
|
|
|
/** Sample count for the convolution. */
|
|
|
|
float samples_ct, invsamples_ct;
|
|
|
|
/** Sampling bias during convolution step. */
|
|
|
|
float lod_factor;
|
2020-07-15 13:11:22 +10:00
|
|
|
/** Max cube-map LOD to sample when convolving. */
|
2019-04-21 13:44:06 +10:00
|
|
|
float lod_max;
|
|
|
|
/** Number of probes to render + world probe. */
|
|
|
|
int cube_len, grid_len;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Irradiance grid */
|
2019-04-21 13:44:06 +10:00
|
|
|
/** Current probe being rendered (UBO data). */
|
|
|
|
EEVEE_LightGrid *grid;
|
2020-07-15 13:11:22 +10:00
|
|
|
/** Target cube-map at MIP 0. */
|
2019-04-21 13:44:06 +10:00
|
|
|
int irr_cube_res;
|
|
|
|
/** Size of the irradiance texture. */
|
|
|
|
int irr_size[3];
|
|
|
|
/** Total for all grids */
|
|
|
|
int total_irr_samples;
|
|
|
|
/** Nth sample of the current grid being rendered. */
|
|
|
|
int grid_sample;
|
|
|
|
/** Total number of samples for the current grid. */
|
|
|
|
int grid_sample_len;
|
|
|
|
/** Nth grid in the cache being rendered. */
|
|
|
|
int grid_curr;
|
|
|
|
/** The current light bounce being evaluated. */
|
|
|
|
int bounce_curr, bounce_len;
|
2021-02-05 16:23:34 +11:00
|
|
|
/** Resolution of the Visibility shadow-map. */
|
2019-04-21 13:44:06 +10:00
|
|
|
float vis_res;
|
|
|
|
/** Result of previous light bounce. */
|
|
|
|
GPUTexture *grid_prev;
|
2019-08-23 09:52:12 +02:00
|
|
|
/** Pointer to the owner_id of the probe object. */
|
2019-04-21 13:44:06 +10:00
|
|
|
LightProbe **grid_prb;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Reflection probe */
|
2019-04-21 13:44:06 +10:00
|
|
|
/** Current probe being rendered (UBO data). */
|
|
|
|
EEVEE_LightProbe *cube;
|
2020-07-15 13:11:22 +10:00
|
|
|
/** Target cube-map at MIP 0. */
|
2019-04-21 13:44:06 +10:00
|
|
|
int ref_cube_res;
|
|
|
|
/** Index of the current cube. */
|
|
|
|
int cube_offset;
|
2019-08-23 09:52:12 +02:00
|
|
|
/** Pointer to the owner_id of the probe object. */
|
2019-04-21 13:44:06 +10:00
|
|
|
LightProbe **cube_prb;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Dummy Textures */
|
|
|
|
struct GPUTexture *dummy_color, *dummy_depth;
|
|
|
|
struct GPUTexture *dummy_layer_color;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
int total, done; /* to compute progress */
|
|
|
|
short *stop, *do_update;
|
|
|
|
float *progress;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-21 13:44:06 +10:00
|
|
|
/** For only handling the resources. */
|
|
|
|
bool resource_only;
|
2018-07-10 15:02:25 +02:00
|
|
|
bool own_resources;
|
2021-02-05 16:23:34 +11:00
|
|
|
/** If the light-cache was created for baking, it's first owned by the baker. */
|
2019-04-21 13:44:06 +10:00
|
|
|
bool own_light_cache;
|
|
|
|
/** ms. delay the start of the baking to not slowdown interactions (TODO remove) */
|
|
|
|
int delay;
|
|
|
|
/** Scene frame to bake. */
|
|
|
|
int frame;
|
|
|
|
|
|
|
|
/** If running in parallel (in a separate thread), use this context. */
|
|
|
|
void *gl_context, *gpu_context;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 17:27:10 +02:00
|
|
|
ThreadMutex *mutex;
|
2018-07-10 15:02:25 +02:00
|
|
|
} EEVEE_LightBake;
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Light Cache
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
/* Return memory footprint in bytes. */
|
2019-01-04 11:05:53 +11:00
|
|
|
static uint eevee_lightcache_memsize_get(LightCache *lcache)
|
2018-07-10 15:02:25 +02:00
|
|
|
{
|
2019-01-04 11:05:53 +11:00
|
|
|
uint size = 0;
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lcache->grid_tx.data) {
|
|
|
|
size += MEM_allocN_len(lcache->grid_tx.data);
|
|
|
|
}
|
|
|
|
if (lcache->cube_tx.data) {
|
|
|
|
size += MEM_allocN_len(lcache->cube_tx.data);
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int mip = 0; mip < lcache->mips_len; mip++) {
|
2018-07-10 15:02:25 +02:00
|
|
|
size += MEM_allocN_len(lcache->cube_mips[mip].data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2020-03-11 17:12:01 +01:00
|
|
|
static bool eevee_lightcache_version_check(LightCache *lcache)
|
|
|
|
{
|
|
|
|
switch (lcache->type) {
|
|
|
|
case LIGHTCACHE_TYPE_STATIC:
|
|
|
|
return lcache->version == LIGHTCACHE_STATIC_VERSION;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-05 02:26:16 +02:00
|
|
|
static bool eevee_lightcache_can_be_saved(LightCache *lcache)
|
|
|
|
{
|
|
|
|
if (lcache->grid_tx.data) {
|
|
|
|
if (MEM_allocN_len(lcache->grid_tx.data) >= INT_MAX) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lcache->cube_tx.data) {
|
|
|
|
if (MEM_allocN_len(lcache->cube_tx.data) >= INT_MAX) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
static int eevee_lightcache_irradiance_sample_count(LightCache *lcache)
|
|
|
|
{
|
|
|
|
int total_irr_samples = 0;
|
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 1; i < lcache->grid_len; i++) {
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_LightGrid *egrid = lcache->grid_data + i;
|
|
|
|
total_irr_samples += egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2];
|
|
|
|
}
|
|
|
|
return total_irr_samples;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EEVEE_lightcache_info_update(SceneEEVEE *eevee)
|
|
|
|
{
|
2020-03-11 17:12:01 +01:00
|
|
|
LightCache *lcache = eevee->light_cache_data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lcache != NULL) {
|
2020-03-11 17:12:01 +01:00
|
|
|
if (!eevee_lightcache_version_check(lcache)) {
|
|
|
|
BLI_strncpy(eevee->light_cache_info,
|
|
|
|
TIP_("Incompatible Light cache version, please bake again"),
|
|
|
|
sizeof(eevee->light_cache_info));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lcache->cube_tx.tex_size[2] > GPU_max_texture_layers()) {
|
|
|
|
BLI_strncpy(eevee->light_cache_info,
|
2020-08-04 19:52:18 +02:00
|
|
|
TIP_("Error: Light cache is too big for the GPU to be loaded"),
|
|
|
|
sizeof(eevee->light_cache_info));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lcache->flag & LIGHTCACHE_INVALID) {
|
|
|
|
BLI_strncpy(eevee->light_cache_info,
|
|
|
|
TIP_("Error: Light cache dimensions not supported by the GPU"),
|
2020-03-11 17:12:01 +01:00
|
|
|
sizeof(eevee->light_cache_info));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-01 21:23:05 +01:00
|
|
|
if (lcache->flag & LIGHTCACHE_BAKING) {
|
2018-12-23 21:58:59 +01:00
|
|
|
BLI_strncpy(
|
2019-06-11 22:25:01 +02:00
|
|
|
eevee->light_cache_info, TIP_("Baking light cache"), sizeof(eevee->light_cache_info));
|
2018-11-01 21:23:05 +01:00
|
|
|
return;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-05 02:26:16 +02:00
|
|
|
if (!eevee_lightcache_can_be_saved(lcache)) {
|
|
|
|
BLI_strncpy(eevee->light_cache_info,
|
|
|
|
TIP_("Error: LightCache is too large and will not be saved to disk"),
|
|
|
|
sizeof(eevee->light_cache_info));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
char formatted_mem[15];
|
2019-09-09 08:38:01 -07:00
|
|
|
BLI_str_format_byte_unit(formatted_mem, eevee_lightcache_memsize_get(lcache), false);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
int irr_samples = eevee_lightcache_irradiance_sample_count(lcache);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
BLI_snprintf(eevee->light_cache_info,
|
|
|
|
sizeof(eevee->light_cache_info),
|
2019-06-11 22:25:01 +02:00
|
|
|
TIP_("%d Ref. Cubemaps, %d Irr. Samples (%s in memory)"),
|
2018-07-10 15:02:25 +02:00
|
|
|
lcache->cube_len - 1,
|
|
|
|
irr_samples,
|
|
|
|
formatted_mem);
|
|
|
|
}
|
|
|
|
else {
|
2018-12-23 21:58:59 +01:00
|
|
|
BLI_strncpy(eevee->light_cache_info,
|
2019-06-11 22:25:01 +02:00
|
|
|
TIP_("No light cache in this scene"),
|
2018-12-23 21:58:59 +01:00
|
|
|
sizeof(eevee->light_cache_info));
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void irradiance_pool_size_get(int visibility_size, int total_samples, int r_size[3])
|
|
|
|
{
|
|
|
|
/* Compute how many irradiance samples we can store per visibility sample. */
|
|
|
|
int irr_per_vis = (visibility_size / IRRADIANCE_SAMPLE_SIZE_X) *
|
|
|
|
(visibility_size / IRRADIANCE_SAMPLE_SIZE_Y);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* The irradiance itself take one layer, hence the +1 */
|
|
|
|
int layer_ct = MIN2(irr_per_vis + 1, IRRADIANCE_MAX_POOL_LAYER);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
int texel_ct = (int)ceilf((float)total_samples / (float)(layer_ct - 1));
|
|
|
|
r_size[0] = visibility_size *
|
|
|
|
max_ii(1, min_ii(texel_ct, (IRRADIANCE_MAX_POOL_SIZE / visibility_size)));
|
|
|
|
r_size[1] = visibility_size *
|
|
|
|
max_ii(1, (texel_ct / (IRRADIANCE_MAX_POOL_SIZE / visibility_size)));
|
|
|
|
r_size[2] = layer_ct;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool EEVEE_lightcache_validate(const LightCache *light_cache,
|
|
|
|
const int cube_len,
|
|
|
|
const int cube_res,
|
|
|
|
const int grid_len,
|
|
|
|
const int irr_size[3])
|
|
|
|
{
|
2021-03-02 13:55:25 +01:00
|
|
|
if (!eevee_lightcache_version_check(lbake->lcache)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-08-04 19:52:18 +02:00
|
|
|
if (light_cache && !(light_cache->flag & LIGHTCACHE_INVALID)) {
|
2018-07-10 15:02:25 +02:00
|
|
|
/* See if we need the same amount of texture space. */
|
|
|
|
if ((irr_size[0] == light_cache->grid_tx.tex_size[0]) &&
|
|
|
|
(irr_size[1] == light_cache->grid_tx.tex_size[1]) &&
|
|
|
|
(irr_size[2] == light_cache->grid_tx.tex_size[2]) && (grid_len == light_cache->grid_len)) {
|
2020-02-25 13:12:52 +01:00
|
|
|
int mip_len = log2_floor_u(cube_res) - MIN_CUBE_LOD_LEVEL;
|
2018-07-10 15:02:25 +02:00
|
|
|
if ((cube_res == light_cache->cube_tx.tex_size[0]) &&
|
2020-03-11 17:12:01 +01:00
|
|
|
(cube_len == light_cache->cube_tx.tex_size[2] / 6) &&
|
|
|
|
(cube_len == light_cache->cube_len) && (mip_len == light_cache->mips_len)) {
|
2018-07-10 15:02:25 +02:00
|
|
|
return true;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
LightCache *EEVEE_lightcache_create(const int grid_len,
|
|
|
|
const int cube_len,
|
|
|
|
const int cube_size,
|
|
|
|
const int vis_size,
|
|
|
|
const int irr_size[3])
|
|
|
|
{
|
|
|
|
LightCache *light_cache = MEM_callocN(sizeof(LightCache), "LightCache");
|
|
|
|
|
2020-03-11 17:12:01 +01:00
|
|
|
light_cache->version = LIGHTCACHE_STATIC_VERSION;
|
|
|
|
light_cache->type = LIGHTCACHE_TYPE_STATIC;
|
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
light_cache->cube_data = MEM_callocN(sizeof(EEVEE_LightProbe) * cube_len, "EEVEE_LightProbe");
|
|
|
|
light_cache->grid_data = MEM_callocN(sizeof(EEVEE_LightGrid) * grid_len, "EEVEE_LightGrid");
|
|
|
|
|
2019-03-20 18:17:16 +11:00
|
|
|
light_cache->grid_tx.tex = DRW_texture_create_2d_array(
|
|
|
|
irr_size[0], irr_size[1], irr_size[2], IRRADIANCE_FORMAT, DRW_TEX_FILTER, NULL);
|
2018-07-10 15:02:25 +02:00
|
|
|
light_cache->grid_tx.tex_size[0] = irr_size[0];
|
|
|
|
light_cache->grid_tx.tex_size[1] = irr_size[1];
|
|
|
|
light_cache->grid_tx.tex_size[2] = irr_size[2];
|
|
|
|
|
2020-03-11 17:12:01 +01:00
|
|
|
int mips_len = log2_floor_u(cube_size) - MIN_CUBE_LOD_LEVEL;
|
|
|
|
|
2020-09-07 19:17:04 +02:00
|
|
|
/* Try to create a cubemap array. */
|
|
|
|
DRWTextureFlag cube_texflag = DRW_TEX_FILTER | DRW_TEX_MIPMAP;
|
|
|
|
light_cache->cube_tx.tex = DRW_texture_create_cube_array(
|
|
|
|
cube_size, cube_len, GPU_R11F_G11F_B10F, cube_texflag, NULL);
|
|
|
|
if (light_cache->cube_tx.tex == NULL) {
|
|
|
|
/* Try fallback to 2D array. */
|
|
|
|
light_cache->cube_tx.tex = DRW_texture_create_2d_array(
|
|
|
|
cube_size, cube_size, cube_len * 6, GPU_R11F_G11F_B10F, cube_texflag, NULL);
|
2020-03-11 17:12:01 +01:00
|
|
|
}
|
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
light_cache->cube_tx.tex_size[0] = cube_size;
|
|
|
|
light_cache->cube_tx.tex_size[1] = cube_size;
|
2020-03-11 17:12:01 +01:00
|
|
|
light_cache->cube_tx.tex_size[2] = cube_len * 6;
|
2018-07-10 15:02:25 +02:00
|
|
|
|
2020-03-11 17:12:01 +01:00
|
|
|
light_cache->mips_len = mips_len;
|
2018-07-10 15:02:25 +02:00
|
|
|
light_cache->vis_res = vis_size;
|
|
|
|
light_cache->ref_res = cube_size;
|
|
|
|
|
|
|
|
light_cache->cube_mips = MEM_callocN(sizeof(LightCacheTexture) * light_cache->mips_len,
|
|
|
|
"LightCacheTexture");
|
|
|
|
|
2020-08-04 19:52:18 +02:00
|
|
|
if (light_cache->grid_tx.tex == NULL || light_cache->cube_tx.tex == NULL) {
|
|
|
|
/* We could not create the requested textures size. Stop baking and do not use the cache. */
|
|
|
|
light_cache->flag = LIGHTCACHE_INVALID;
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
2020-08-04 19:52:18 +02:00
|
|
|
else {
|
|
|
|
light_cache->flag = LIGHTCACHE_UPDATE_WORLD | LIGHTCACHE_UPDATE_CUBE | LIGHTCACHE_UPDATE_GRID;
|
2018-07-10 15:02:25 +02:00
|
|
|
|
2020-08-04 19:52:18 +02:00
|
|
|
for (int mip = 0; mip < light_cache->mips_len; mip++) {
|
|
|
|
GPU_texture_get_mipmap_size(
|
|
|
|
light_cache->cube_tx.tex, mip + 1, light_cache->cube_mips[mip].tex_size);
|
|
|
|
}
|
|
|
|
}
|
2018-07-10 15:02:25 +02:00
|
|
|
|
|
|
|
return light_cache;
|
|
|
|
}
|
|
|
|
|
2020-03-11 17:12:01 +01:00
|
|
|
static bool eevee_lightcache_static_load(LightCache *lcache)
|
2018-07-10 15:02:25 +02:00
|
|
|
{
|
2020-03-11 17:12:01 +01:00
|
|
|
/* We use fallback if a texture is not setup and there is no data to restore it. */
|
2020-09-10 14:31:17 +02:00
|
|
|
if ((!lcache->grid_tx.tex && !lcache->grid_tx.data) || !lcache->grid_data ||
|
|
|
|
(!lcache->cube_tx.tex && !lcache->cube_tx.data) || !lcache->cube_data) {
|
2020-03-11 17:12:01 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
/* If cache is too big for this GPU. */
|
|
|
|
if (lcache->cube_tx.tex_size[2] > GPU_max_texture_layers()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lcache->grid_tx.tex == NULL) {
|
2020-09-04 22:56:30 +02:00
|
|
|
lcache->grid_tx.tex = GPU_texture_create_2d_array(
|
2020-09-05 17:33:56 +02:00
|
|
|
"lightcache_irradiance", UNPACK3(lcache->grid_tx.tex_size), 1, IRRADIANCE_FORMAT, NULL);
|
2021-02-17 12:38:21 -03:00
|
|
|
GPU_texture_update(lcache->grid_tx.tex, GPU_DATA_UBYTE, lcache->grid_tx.data);
|
2020-08-04 19:52:18 +02:00
|
|
|
|
|
|
|
if (lcache->grid_tx.tex == NULL) {
|
|
|
|
lcache->flag |= LIGHTCACHE_NOT_USABLE;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
GPU_texture_filter_mode(lcache->grid_tx.tex, true);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-11 17:12:01 +01:00
|
|
|
if (lcache->cube_tx.tex == NULL) {
|
2020-09-07 19:17:04 +02:00
|
|
|
/* Try to create a cubemap array. */
|
|
|
|
lcache->cube_tx.tex = GPU_texture_create_cube_array("lightcache_cubemaps",
|
|
|
|
lcache->cube_tx.tex_size[0],
|
|
|
|
lcache->cube_tx.tex_size[2] / 6,
|
|
|
|
lcache->mips_len + 1,
|
|
|
|
GPU_R11F_G11F_B10F,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (lcache->cube_tx.tex == NULL) {
|
|
|
|
/* Try fallback to 2D array. */
|
2020-09-05 17:33:56 +02:00
|
|
|
lcache->cube_tx.tex = GPU_texture_create_2d_array("lightcache_cubemaps_fallback",
|
|
|
|
UNPACK3(lcache->cube_tx.tex_size),
|
|
|
|
lcache->mips_len + 1,
|
|
|
|
GPU_R11F_G11F_B10F,
|
|
|
|
NULL);
|
2020-03-11 17:12:01 +01:00
|
|
|
}
|
|
|
|
|
2020-08-04 19:52:18 +02:00
|
|
|
if (lcache->cube_tx.tex == NULL) {
|
|
|
|
lcache->flag |= LIGHTCACHE_NOT_USABLE;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-09-05 17:33:56 +02:00
|
|
|
for (int mip = 0; mip <= lcache->mips_len; mip++) {
|
|
|
|
const void *data = (mip == 0) ? lcache->cube_tx.data : lcache->cube_mips[mip - 1].data;
|
|
|
|
GPU_texture_update_mipmap(lcache->cube_tx.tex, mip, GPU_DATA_10_11_11_REV, data);
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
2020-06-02 10:47:45 +02:00
|
|
|
GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true);
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
2020-03-11 17:12:01 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool EEVEE_lightcache_load(LightCache *lcache)
|
|
|
|
{
|
|
|
|
if (lcache == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eevee_lightcache_version_check(lcache)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-08-04 19:52:18 +02:00
|
|
|
if (lcache->flag & (LIGHTCACHE_INVALID | LIGHTCACHE_NOT_USABLE)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-03-11 17:12:01 +01:00
|
|
|
switch (lcache->type) {
|
|
|
|
case LIGHTCACHE_TYPE_STATIC:
|
|
|
|
return eevee_lightcache_static_load(lcache);
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void eevee_lightbake_readback_irradiance(LightCache *lcache)
|
|
|
|
{
|
|
|
|
MEM_SAFE_FREE(lcache->grid_tx.data);
|
2021-02-17 12:38:21 -03:00
|
|
|
lcache->grid_tx.data = GPU_texture_read(lcache->grid_tx.tex, GPU_DATA_UBYTE, 0);
|
2018-07-10 15:02:25 +02:00
|
|
|
lcache->grid_tx.data_type = LIGHTCACHETEX_BYTE;
|
|
|
|
lcache->grid_tx.components = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eevee_lightbake_readback_reflections(LightCache *lcache)
|
|
|
|
{
|
|
|
|
MEM_SAFE_FREE(lcache->cube_tx.data);
|
|
|
|
lcache->cube_tx.data = GPU_texture_read(lcache->cube_tx.tex, GPU_DATA_10_11_11_REV, 0);
|
|
|
|
lcache->cube_tx.data_type = LIGHTCACHETEX_UINT;
|
|
|
|
lcache->cube_tx.components = 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int mip = 0; mip < lcache->mips_len; mip++) {
|
2018-07-10 15:02:25 +02:00
|
|
|
LightCacheTexture *cube_mip = lcache->cube_mips + mip;
|
|
|
|
MEM_SAFE_FREE(cube_mip->data);
|
|
|
|
GPU_texture_get_mipmap_size(lcache->cube_tx.tex, mip + 1, cube_mip->tex_size);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
cube_mip->data = GPU_texture_read(lcache->cube_tx.tex, GPU_DATA_10_11_11_REV, mip + 1);
|
|
|
|
cube_mip->data_type = LIGHTCACHETEX_UINT;
|
|
|
|
cube_mip->components = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EEVEE_lightcache_free(LightCache *lcache)
|
|
|
|
{
|
|
|
|
DRW_TEXTURE_FREE_SAFE(lcache->cube_tx.tex);
|
|
|
|
MEM_SAFE_FREE(lcache->cube_tx.data);
|
|
|
|
DRW_TEXTURE_FREE_SAFE(lcache->grid_tx.tex);
|
|
|
|
MEM_SAFE_FREE(lcache->grid_tx.data);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lcache->cube_mips) {
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < lcache->mips_len; i++) {
|
2018-07-10 15:02:25 +02:00
|
|
|
MEM_SAFE_FREE(lcache->cube_mips[i].data);
|
|
|
|
}
|
|
|
|
MEM_SAFE_FREE(lcache->cube_mips);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
MEM_SAFE_FREE(lcache->cube_data);
|
|
|
|
MEM_SAFE_FREE(lcache->grid_data);
|
|
|
|
MEM_freeN(lcache);
|
|
|
|
}
|
|
|
|
|
2020-11-06 13:35:19 +01:00
|
|
|
static void write_lightcache_texture(BlendWriter *writer, LightCacheTexture *tex)
|
|
|
|
{
|
|
|
|
if (tex->data) {
|
|
|
|
size_t data_size = tex->components * tex->tex_size[0] * tex->tex_size[1] * tex->tex_size[2];
|
|
|
|
if (tex->data_type == LIGHTCACHETEX_FLOAT) {
|
|
|
|
data_size *= sizeof(float);
|
|
|
|
}
|
|
|
|
else if (tex->data_type == LIGHTCACHETEX_UINT) {
|
|
|
|
data_size *= sizeof(uint);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: We can't save more than what 32bit systems can handle.
|
|
|
|
* The solution would be to split the texture but it is too late for 2.90. (see T78529) */
|
|
|
|
if (data_size < INT_MAX) {
|
|
|
|
BLO_write_raw(writer, data_size, tex->data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EEVEE_lightcache_blend_write(BlendWriter *writer, LightCache *cache)
|
|
|
|
{
|
|
|
|
write_lightcache_texture(writer, &cache->grid_tx);
|
|
|
|
write_lightcache_texture(writer, &cache->cube_tx);
|
|
|
|
|
|
|
|
if (cache->cube_mips) {
|
|
|
|
BLO_write_struct_array(writer, LightCacheTexture, cache->mips_len, cache->cube_mips);
|
|
|
|
for (int i = 0; i < cache->mips_len; i++) {
|
|
|
|
write_lightcache_texture(writer, &cache->cube_mips[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLO_write_struct_array(writer, LightGridCache, cache->grid_len, cache->grid_data);
|
|
|
|
BLO_write_struct_array(writer, LightProbeCache, cache->cube_len, cache->cube_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void direct_link_lightcache_texture(BlendDataReader *reader, LightCacheTexture *lctex)
|
|
|
|
{
|
|
|
|
lctex->tex = NULL;
|
|
|
|
|
|
|
|
if (lctex->data) {
|
|
|
|
BLO_read_data_address(reader, &lctex->data);
|
|
|
|
if (lctex->data && BLO_read_requires_endian_switch(reader)) {
|
|
|
|
int data_size = lctex->components * lctex->tex_size[0] * lctex->tex_size[1] *
|
|
|
|
lctex->tex_size[2];
|
|
|
|
|
|
|
|
if (lctex->data_type == LIGHTCACHETEX_FLOAT) {
|
|
|
|
BLI_endian_switch_float_array((float *)lctex->data, data_size * sizeof(float));
|
|
|
|
}
|
|
|
|
else if (lctex->data_type == LIGHTCACHETEX_UINT) {
|
|
|
|
BLI_endian_switch_uint32_array((uint *)lctex->data, data_size * sizeof(uint));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lctex->data == NULL) {
|
|
|
|
zero_v3_int(lctex->tex_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EEVEE_lightcache_blend_read_data(BlendDataReader *reader, LightCache *cache)
|
|
|
|
{
|
|
|
|
cache->flag &= ~LIGHTCACHE_NOT_USABLE;
|
|
|
|
direct_link_lightcache_texture(reader, &cache->cube_tx);
|
|
|
|
direct_link_lightcache_texture(reader, &cache->grid_tx);
|
|
|
|
|
|
|
|
if (cache->cube_mips) {
|
|
|
|
BLO_read_data_address(reader, &cache->cube_mips);
|
|
|
|
for (int i = 0; i < cache->mips_len; i++) {
|
|
|
|
direct_link_lightcache_texture(reader, &cache->cube_mips[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLO_read_data_address(reader, &cache->cube_data);
|
|
|
|
BLO_read_data_address(reader, &cache->grid_data);
|
|
|
|
}
|
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Light Bake Context
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake)
|
|
|
|
{
|
2020-08-05 15:26:49 +02:00
|
|
|
if (GPU_use_main_context_workaround() && !BLI_thread_is_main()) {
|
|
|
|
GPU_context_main_lock();
|
|
|
|
DRW_opengl_context_enable();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lbake->gl_context) {
|
|
|
|
DRW_opengl_render_context_enable(lbake->gl_context);
|
2018-07-18 00:12:21 +02:00
|
|
|
if (lbake->gpu_context == NULL) {
|
2020-09-08 03:19:15 +02:00
|
|
|
lbake->gpu_context = GPU_context_create(NULL);
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
2019-08-17 01:17:30 +10:00
|
|
|
DRW_gpu_render_context_enable(lbake->gpu_context);
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
DRW_opengl_context_enable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eevee_lightbake_context_disable(EEVEE_LightBake *lbake)
|
|
|
|
{
|
2020-08-05 15:26:49 +02:00
|
|
|
if (GPU_use_main_context_workaround() && !BLI_thread_is_main()) {
|
|
|
|
DRW_opengl_context_disable();
|
|
|
|
GPU_context_main_unlock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lbake->gl_context) {
|
2019-08-17 01:17:30 +10:00
|
|
|
DRW_gpu_render_context_disable(lbake->gpu_context);
|
2018-07-10 15:02:25 +02:00
|
|
|
DRW_opengl_render_context_disable(lbake->gl_context);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DRW_opengl_context_disable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Light Bake Job
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
static void eevee_lightbake_count_probes(EEVEE_LightBake *lbake)
|
|
|
|
{
|
|
|
|
Depsgraph *depsgraph = lbake->depsgraph;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* At least one of each for the world */
|
|
|
|
lbake->grid_len = lbake->cube_len = lbake->total_irr_samples = 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
|
2018-12-18 18:18:00 +01:00
|
|
|
const int ob_visibility = BKE_object_visibility(ob, DAG_EVAL_RENDER);
|
|
|
|
if ((ob_visibility & OB_VISIBLE_SELF) == 0) {
|
2018-07-10 15:02:25 +02:00
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (ob->type == OB_LIGHTPROBE) {
|
|
|
|
LightProbe *prb = (LightProbe *)ob->data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (prb->type == LIGHTPROBE_TYPE_GRID) {
|
|
|
|
lbake->total_irr_samples += prb->grid_resolution_x * prb->grid_resolution_y *
|
|
|
|
prb->grid_resolution_z;
|
|
|
|
lbake->grid_len++;
|
|
|
|
}
|
2020-03-11 17:12:01 +01:00
|
|
|
else if (prb->type == LIGHTPROBE_TYPE_CUBE && lbake->cube_len < EEVEE_PROBE_MAX) {
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->cube_len++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eevee_lightbake_create_render_target(EEVEE_LightBake *lbake, int rt_res)
|
|
|
|
{
|
|
|
|
lbake->rt_depth = DRW_texture_create_cube(rt_res, GPU_DEPTH_COMPONENT24, 0, NULL);
|
|
|
|
lbake->rt_color = DRW_texture_create_cube(
|
|
|
|
rt_res, GPU_RGBA16F, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < 6; i++) {
|
2018-07-10 15:02:25 +02:00
|
|
|
GPU_framebuffer_ensure_config(&lbake->rt_fb[i],
|
|
|
|
{GPU_ATTACHMENT_TEXTURE_CUBEFACE(lbake->rt_depth, i),
|
|
|
|
GPU_ATTACHMENT_TEXTURE_CUBEFACE(lbake->rt_color, i)});
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
GPU_framebuffer_ensure_config(&lbake->store_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_NONE});
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake)
|
|
|
|
{
|
|
|
|
Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph);
|
|
|
|
SceneEEVEE *eevee = &scene_eval->eevee;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->bounce_len = eevee->gi_diffuse_bounces;
|
|
|
|
lbake->vis_res = eevee->gi_visibility_resolution;
|
|
|
|
lbake->rt_res = eevee->gi_cubemap_resolution;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
irradiance_pool_size_get(lbake->vis_res, lbake->total_irr_samples, lbake->irr_size);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-11 17:12:01 +01:00
|
|
|
lbake->ref_cube_res = lbake->rt_res;
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->cube_prb = MEM_callocN(sizeof(LightProbe *) * lbake->cube_len, "EEVEE Cube visgroup ptr");
|
|
|
|
lbake->grid_prb = MEM_callocN(sizeof(LightProbe *) * lbake->grid_len, "EEVEE Grid visgroup ptr");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-20 18:17:16 +11:00
|
|
|
lbake->grid_prev = DRW_texture_create_2d_array(lbake->irr_size[0],
|
2019-01-04 19:08:09 +11:00
|
|
|
lbake->irr_size[1],
|
|
|
|
lbake->irr_size[2],
|
|
|
|
IRRADIANCE_FORMAT,
|
|
|
|
DRW_TEX_FILTER,
|
|
|
|
NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Ensure Light Cache is ready to accept new data. If not recreate one.
|
|
|
|
* WARNING: All the following must be threadsafe. It's currently protected
|
|
|
|
* by the DRW mutex. */
|
2020-03-11 17:12:01 +01:00
|
|
|
lbake->lcache = eevee->light_cache_data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-19 18:19:49 +02:00
|
|
|
/* TODO validate irradiance and reflection cache independently... */
|
2018-10-29 10:24:42 +11:00
|
|
|
if (!EEVEE_lightcache_validate(
|
|
|
|
lbake->lcache, lbake->cube_len, lbake->ref_cube_res, lbake->grid_len, lbake->irr_size)) {
|
2020-03-11 17:12:01 +01:00
|
|
|
eevee->light_cache_data = lbake->lcache = NULL;
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lbake->lcache == NULL) {
|
2018-10-29 10:24:42 +11:00
|
|
|
lbake->lcache = EEVEE_lightcache_create(
|
|
|
|
lbake->grid_len, lbake->cube_len, lbake->ref_cube_res, lbake->vis_res, lbake->irr_size);
|
2020-08-04 19:52:18 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->own_light_cache = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-11 17:12:01 +01:00
|
|
|
eevee->light_cache_data = lbake->lcache;
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-11 17:12:01 +01:00
|
|
|
EEVEE_lightcache_load(eevee->light_cache_data);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->lcache->flag |= LIGHTCACHE_BAKING;
|
|
|
|
lbake->lcache->cube_len = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
wmJob *EEVEE_lightbake_job_create(struct wmWindowManager *wm,
|
|
|
|
struct wmWindow *win,
|
|
|
|
struct Main *bmain,
|
2019-03-27 20:47:15 +01:00
|
|
|
struct ViewLayer *view_layer,
|
|
|
|
struct Scene *scene,
|
|
|
|
int delay,
|
|
|
|
int frame)
|
2018-07-10 15:02:25 +02:00
|
|
|
{
|
|
|
|
EEVEE_LightBake *lbake = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* only one render job at a time */
|
2019-01-25 07:10:13 +11:00
|
|
|
if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) {
|
2018-07-10 15:02:25 +02:00
|
|
|
return NULL;
|
2019-01-25 07:10:13 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
wmJob *wm_job = WM_jobs_get(wm,
|
|
|
|
win,
|
|
|
|
scene,
|
|
|
|
"Bake Lighting",
|
|
|
|
WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS,
|
|
|
|
WM_JOB_TYPE_LIGHT_BAKE);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* If job exists do not recreate context and depsgraph. */
|
|
|
|
EEVEE_LightBake *old_lbake = (EEVEE_LightBake *)WM_jobs_customdata_get(wm_job);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (old_lbake && (old_lbake->view_layer_input == view_layer) && (old_lbake->bmain == bmain)) {
|
|
|
|
lbake = MEM_callocN(sizeof(EEVEE_LightBake), "EEVEE_LightBake");
|
|
|
|
/* Cannot reuse depsgraph for now because we cannot get the update from the
|
|
|
|
* main database directly. TODO reuse depsgraph and only update positions. */
|
|
|
|
/* lbake->depsgraph = old_lbake->depsgraph; */
|
2019-09-09 14:49:05 +02:00
|
|
|
lbake->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 17:27:10 +02:00
|
|
|
lbake->mutex = BLI_mutex_alloc();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 17:27:10 +02:00
|
|
|
BLI_mutex_lock(old_lbake->mutex);
|
|
|
|
old_lbake->own_resources = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->scene = scene;
|
|
|
|
lbake->bmain = bmain;
|
|
|
|
lbake->view_layer_input = view_layer;
|
|
|
|
lbake->gl_context = old_lbake->gl_context;
|
|
|
|
lbake->own_resources = true;
|
|
|
|
lbake->delay = delay;
|
2019-03-27 20:47:15 +01:00
|
|
|
lbake->frame = frame;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-05 15:26:49 +02:00
|
|
|
if (lbake->gl_context == NULL && !GPU_use_main_context_workaround()) {
|
2018-10-23 17:27:10 +02:00
|
|
|
lbake->gl_context = WM_opengl_context_create();
|
|
|
|
wm_window_reset_drawable();
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (old_lbake->stop != NULL) {
|
|
|
|
*old_lbake->stop = 1;
|
|
|
|
}
|
2018-10-23 17:27:10 +02:00
|
|
|
BLI_mutex_unlock(old_lbake->mutex);
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
else {
|
2019-03-27 20:47:15 +01:00
|
|
|
lbake = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, true, frame);
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->delay = delay;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
WM_jobs_customdata_set(wm_job, lbake, EEVEE_lightbake_job_data_free);
|
|
|
|
WM_jobs_timer(wm_job, 0.4, NC_SCENE | NA_EDITED, 0);
|
|
|
|
WM_jobs_callbacks(
|
|
|
|
wm_job, EEVEE_lightbake_job, NULL, EEVEE_lightbake_update, EEVEE_lightbake_update);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
G.is_break = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
return wm_job;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* MUST run on the main thread. */
|
|
|
|
void *EEVEE_lightbake_job_data_alloc(struct Main *bmain,
|
2019-03-27 20:47:15 +01:00
|
|
|
struct ViewLayer *view_layer,
|
|
|
|
struct Scene *scene,
|
|
|
|
bool run_as_job,
|
|
|
|
int frame)
|
2018-07-10 15:02:25 +02:00
|
|
|
{
|
|
|
|
BLI_assert(BLI_thread_is_main());
|
|
|
|
|
|
|
|
EEVEE_LightBake *lbake = MEM_callocN(sizeof(EEVEE_LightBake), "EEVEE_LightBake");
|
|
|
|
|
2019-09-09 14:49:05 +02:00
|
|
|
lbake->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->scene = scene;
|
|
|
|
lbake->bmain = bmain;
|
|
|
|
lbake->view_layer_input = view_layer;
|
|
|
|
lbake->own_resources = true;
|
|
|
|
lbake->own_light_cache = false;
|
2018-10-23 17:27:10 +02:00
|
|
|
lbake->mutex = BLI_mutex_alloc();
|
2019-03-27 20:47:15 +01:00
|
|
|
lbake->frame = frame;
|
2018-07-10 15:02:25 +02:00
|
|
|
|
2020-08-05 15:26:49 +02:00
|
|
|
if (run_as_job && !GPU_use_main_context_workaround()) {
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->gl_context = WM_opengl_context_create();
|
|
|
|
wm_window_reset_drawable();
|
|
|
|
}
|
|
|
|
|
|
|
|
return lbake;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EEVEE_lightbake_job_data_free(void *custom_data)
|
|
|
|
{
|
|
|
|
EEVEE_LightBake *lbake = (EEVEE_LightBake *)custom_data;
|
|
|
|
|
|
|
|
/* TODO reuse depsgraph. */
|
|
|
|
/* if (lbake->own_resources) { */
|
|
|
|
DEG_graph_free(lbake->depsgraph);
|
2019-04-17 06:17:24 +02:00
|
|
|
/* } */
|
2018-10-23 17:27:10 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
MEM_SAFE_FREE(lbake->cube_prb);
|
|
|
|
MEM_SAFE_FREE(lbake->grid_prb);
|
2018-10-23 17:27:10 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
BLI_mutex_free(lbake->mutex);
|
|
|
|
|
|
|
|
MEM_freeN(lbake);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
|
|
|
|
{
|
2018-10-23 17:27:10 +02:00
|
|
|
if (!lbake->resource_only) {
|
|
|
|
BLI_mutex_lock(lbake->mutex);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lbake->gl_context) {
|
|
|
|
DRW_opengl_render_context_enable(lbake->gl_context);
|
2019-08-17 01:17:30 +10:00
|
|
|
DRW_gpu_render_context_enable(lbake->gpu_context);
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
else if (!lbake->resource_only) {
|
|
|
|
DRW_opengl_context_enable();
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-27 17:33:53 +02:00
|
|
|
/* XXX Free the resources contained in the viewlayer data
|
|
|
|
* to be able to free the context before deleting the depsgraph. */
|
|
|
|
if (lbake->sldata) {
|
|
|
|
EEVEE_view_layer_data_free(lbake->sldata);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
DRW_TEXTURE_FREE_SAFE(lbake->rt_depth);
|
|
|
|
DRW_TEXTURE_FREE_SAFE(lbake->rt_color);
|
|
|
|
DRW_TEXTURE_FREE_SAFE(lbake->grid_prev);
|
|
|
|
GPU_FRAMEBUFFER_FREE_SAFE(lbake->store_fb);
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < 6; i++) {
|
2018-07-10 15:02:25 +02:00
|
|
|
GPU_FRAMEBUFFER_FREE_SAFE(lbake->rt_fb[i]);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-18 00:12:21 +02:00
|
|
|
if (lbake->gpu_context) {
|
2019-08-17 01:17:30 +10:00
|
|
|
DRW_gpu_render_context_disable(lbake->gpu_context);
|
|
|
|
DRW_gpu_render_context_enable(lbake->gpu_context);
|
2018-07-18 00:12:21 +02:00
|
|
|
GPU_context_discard(lbake->gpu_context);
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lbake->gl_context && lbake->own_resources) {
|
|
|
|
/* Delete the baking context. */
|
|
|
|
DRW_opengl_render_context_disable(lbake->gl_context);
|
|
|
|
WM_opengl_context_dispose(lbake->gl_context);
|
2018-07-18 00:12:21 +02:00
|
|
|
lbake->gpu_context = NULL;
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->gl_context = NULL;
|
|
|
|
}
|
|
|
|
else if (lbake->gl_context) {
|
|
|
|
DRW_opengl_render_context_disable(lbake->gl_context);
|
|
|
|
}
|
|
|
|
else if (!lbake->resource_only) {
|
|
|
|
DRW_opengl_context_disable();
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 17:27:10 +02:00
|
|
|
if (!lbake->resource_only) {
|
|
|
|
BLI_mutex_unlock(lbake->mutex);
|
|
|
|
}
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Cache as in draw cache not light cache. */
|
|
|
|
static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lbake)
|
|
|
|
{
|
2018-09-17 11:53:43 +02:00
|
|
|
EEVEE_TextureList *txl = vedata->txl;
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_StorageList *stl = vedata->stl;
|
|
|
|
EEVEE_FramebufferList *fbl = vedata->fbl;
|
|
|
|
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
|
|
|
|
Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph);
|
2018-07-27 17:33:53 +02:00
|
|
|
lbake->sldata = sldata;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-05 16:23:34 +11:00
|
|
|
/* Disable all effects BUT high bit-depth shadows. */
|
2018-07-10 15:02:25 +02:00
|
|
|
scene_eval->eevee.flag &= SCE_EEVEE_SHADOW_HIGH_BITDEPTH;
|
|
|
|
scene_eval->eevee.taa_samples = 1;
|
2018-11-15 18:13:07 +01:00
|
|
|
scene_eval->eevee.gi_irradiance_smoothing = 0.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
|
|
|
|
stl->g_data->background_alpha = 1.0f;
|
2021-02-21 01:31:59 +01:00
|
|
|
stl->g_data->render_timesteps = 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* XXX TODO remove this. This is in order to make the init functions work. */
|
2019-05-21 20:24:54 +02:00
|
|
|
if (DRW_view_default_get() == NULL) {
|
|
|
|
float winmat[4][4], viewmat[4][4];
|
|
|
|
unit_m4(viewmat);
|
|
|
|
unit_m4(winmat);
|
|
|
|
negate_v3(winmat[2]);
|
|
|
|
DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
|
|
|
|
DRW_view_default_set(view);
|
|
|
|
DRW_view_set_active(view);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-17 11:53:43 +02:00
|
|
|
/* HACK: set txl->color but unset it before Draw Manager frees it. */
|
|
|
|
txl->color = lbake->rt_color;
|
2020-08-07 22:36:11 +10:00
|
|
|
const int viewport_size[2] = {
|
2018-09-17 11:53:43 +02:00
|
|
|
GPU_texture_width(txl->color),
|
2019-02-03 14:01:45 +11:00
|
|
|
GPU_texture_height(txl->color),
|
2018-09-17 11:53:43 +02:00
|
|
|
};
|
|
|
|
DRW_render_viewport_size_set(viewport_size);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 15:52:04 +02:00
|
|
|
EEVEE_effects_init(sldata, vedata, NULL, true);
|
2020-06-02 16:58:07 +02:00
|
|
|
EEVEE_materials_init(sldata, vedata, stl, fbl);
|
2019-08-22 16:04:25 +02:00
|
|
|
EEVEE_shadows_init(sldata);
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_lightprobes_init(sldata, vedata);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_effects_cache_init(sldata, vedata);
|
|
|
|
EEVEE_materials_cache_init(sldata, vedata);
|
2019-05-21 21:31:58 +02:00
|
|
|
EEVEE_subsurface_cache_init(sldata, vedata);
|
2019-05-31 11:35:01 +02:00
|
|
|
EEVEE_volumes_cache_init(sldata, vedata);
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_lights_cache_init(sldata, vedata);
|
|
|
|
EEVEE_lightprobes_cache_init(sldata, vedata);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_lightbake_cache_init(sldata, vedata, lbake->rt_color, lbake->rt_depth);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lbake->probe) {
|
|
|
|
EEVEE_LightProbesInfo *pinfo = sldata->probes;
|
|
|
|
LightProbe *prb = *lbake->probe;
|
|
|
|
pinfo->vis_data.collection = prb->visibility_grp;
|
|
|
|
pinfo->vis_data.invert = prb->flag & LIGHTPROBE_FLAG_INVERT_GROUP;
|
|
|
|
pinfo->vis_data.cached = false;
|
|
|
|
}
|
|
|
|
DRW_render_object_iter(vedata, NULL, lbake->depsgraph, EEVEE_render_cache);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-16 21:41:22 +02:00
|
|
|
EEVEE_volumes_cache_finish(sldata, vedata);
|
2019-05-16 16:43:41 +02:00
|
|
|
EEVEE_materials_cache_finish(sldata, vedata);
|
2018-10-28 21:41:40 +01:00
|
|
|
EEVEE_lights_cache_finish(sldata, vedata);
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_lightprobes_cache_finish(sldata, vedata);
|
2020-01-20 12:55:21 +01:00
|
|
|
EEVEE_shadows_update(sldata, vedata);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-28 19:38:41 +02:00
|
|
|
/* Disable volumetrics when baking. */
|
|
|
|
stl->effects->enabled_effects &= ~EFFECT_VOLUMETRIC;
|
|
|
|
|
2020-06-23 13:59:55 +02:00
|
|
|
EEVEE_subsurface_draw_init(sldata, vedata);
|
2019-05-16 21:41:22 +02:00
|
|
|
EEVEE_effects_draw_init(sldata, vedata);
|
|
|
|
EEVEE_volumes_draw_init(sldata, vedata);
|
|
|
|
|
2018-09-17 11:53:43 +02:00
|
|
|
txl->color = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
DRW_render_instance_buffer_finish();
|
|
|
|
DRW_hair_update();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eevee_lightbake_copy_irradiance(EEVEE_LightBake *lbake, LightCache *lcache)
|
|
|
|
{
|
|
|
|
DRW_TEXTURE_FREE_SAFE(lbake->grid_prev);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-05 16:23:34 +11:00
|
|
|
/* Copy texture by reading back and re-uploading it. */
|
2018-07-10 15:02:25 +02:00
|
|
|
float *tex = GPU_texture_read(lcache->grid_tx.tex, GPU_DATA_FLOAT, 0);
|
2019-03-20 18:17:16 +11:00
|
|
|
lbake->grid_prev = DRW_texture_create_2d_array(lbake->irr_size[0],
|
|
|
|
lbake->irr_size[1],
|
|
|
|
lbake->irr_size[2],
|
2018-07-10 15:02:25 +02:00
|
|
|
IRRADIANCE_FORMAT,
|
|
|
|
DRW_TEX_FILTER,
|
|
|
|
tex);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
MEM_freeN(tex);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eevee_lightbake_render_world_sample(void *ved, void *user_data)
|
|
|
|
{
|
|
|
|
EEVEE_Data *vedata = (EEVEE_Data *)ved;
|
|
|
|
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
|
|
|
|
EEVEE_LightBake *lbake = (EEVEE_LightBake *)user_data;
|
|
|
|
Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph);
|
2020-03-11 17:12:01 +01:00
|
|
|
LightCache *lcache = scene_eval->eevee.light_cache_data;
|
2018-11-15 19:41:15 +01:00
|
|
|
float clamp = scene_eval->eevee.gi_glossy_clamp;
|
2018-11-15 20:04:35 +01:00
|
|
|
float filter_quality = scene_eval->eevee.gi_filter_quality;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-19 18:19:49 +02:00
|
|
|
/* TODO do this once for the whole bake when we have independent DRWManagers. */
|
2018-07-10 15:02:25 +02:00
|
|
|
eevee_lightbake_cache_create(vedata, lbake);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-15 19:41:15 +01:00
|
|
|
sldata->common_data.ray_type = EEVEE_RAY_GLOSSY;
|
|
|
|
sldata->common_data.ray_depth = 1;
|
2020-08-20 23:09:37 +02:00
|
|
|
GPU_uniformbuf_update(sldata->common_ubo, &sldata->common_data);
|
2018-11-15 19:41:15 +01:00
|
|
|
EEVEE_lightbake_render_world(sldata, vedata, lbake->rt_fb);
|
2018-11-15 20:04:35 +01:00
|
|
|
EEVEE_lightbake_filter_glossy(sldata,
|
|
|
|
vedata,
|
|
|
|
lbake->rt_color,
|
|
|
|
lbake->store_fb,
|
|
|
|
0,
|
|
|
|
1.0f,
|
|
|
|
lcache->mips_len,
|
|
|
|
filter_quality,
|
|
|
|
clamp);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-15 19:41:15 +01:00
|
|
|
sldata->common_data.ray_type = EEVEE_RAY_DIFFUSE;
|
|
|
|
sldata->common_data.ray_depth = 1;
|
2020-08-20 23:09:37 +02:00
|
|
|
GPU_uniformbuf_update(sldata->common_ubo, &sldata->common_data);
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_lightbake_render_world(sldata, vedata, lbake->rt_fb);
|
|
|
|
EEVEE_lightbake_filter_diffuse(sldata, vedata, lbake->rt_color, lbake->store_fb, 0, 1.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-01-16 19:45:08 +01:00
|
|
|
if (lcache->flag & LIGHTCACHE_UPDATE_GRID) {
|
|
|
|
/* Clear the cache to avoid white values in the grid. */
|
|
|
|
GPU_framebuffer_texture_attach(lbake->store_fb, lbake->grid_prev, 0, 0);
|
|
|
|
GPU_framebuffer_bind(lbake->store_fb);
|
|
|
|
/* Clear to 1.0f for visibility. */
|
|
|
|
GPU_framebuffer_clear_color(lbake->store_fb, ((float[4]){1.0f, 1.0f, 1.0f, 1.0f}));
|
|
|
|
DRW_draw_pass(vedata->psl->probe_grid_fill);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-01-16 19:45:08 +01:00
|
|
|
SWAP(GPUTexture *, lbake->grid_prev, lcache->grid_tx.tex);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-01-16 19:45:08 +01:00
|
|
|
/* Make a copy for later. */
|
|
|
|
eevee_lightbake_copy_irradiance(lbake, lcache);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
lcache->cube_len = 1;
|
|
|
|
lcache->grid_len = lbake->grid_len;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
lcache->flag |= LIGHTCACHE_CUBE_READY | LIGHTCACHE_GRID_READY;
|
|
|
|
lcache->flag &= ~LIGHTCACHE_UPDATE_WORLD;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cell_id_to_grid_loc(EEVEE_LightGrid *egrid, int cell_idx, int r_local_cell[3])
|
|
|
|
{
|
|
|
|
/* Keep in sync with lightprobe_grid_display_vert */
|
|
|
|
r_local_cell[2] = cell_idx % egrid->resolution[2];
|
|
|
|
r_local_cell[1] = (cell_idx / egrid->resolution[2]) % egrid->resolution[1];
|
|
|
|
r_local_cell[0] = cell_idx / (egrid->resolution[2] * egrid->resolution[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void compute_cell_id(EEVEE_LightGrid *egrid,
|
|
|
|
LightProbe *probe,
|
|
|
|
int cell_idx,
|
|
|
|
int *r_final_idx,
|
|
|
|
int r_local_cell[3],
|
|
|
|
int *r_stride)
|
|
|
|
{
|
|
|
|
const int cell_count = probe->grid_resolution_x * probe->grid_resolution_y *
|
|
|
|
probe->grid_resolution_z;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Add one for level 0 */
|
|
|
|
int max_lvl = (int)floorf(log2f(
|
|
|
|
(float)MAX3(probe->grid_resolution_x, probe->grid_resolution_y, probe->grid_resolution_z)));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
int visited_cells = 0;
|
2018-08-02 18:32:50 +02:00
|
|
|
*r_stride = 0;
|
|
|
|
*r_final_idx = 0;
|
|
|
|
r_local_cell[0] = r_local_cell[1] = r_local_cell[2] = 0;
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int lvl = max_lvl; lvl >= 0; lvl--) {
|
2018-07-10 15:02:25 +02:00
|
|
|
*r_stride = 1 << lvl;
|
|
|
|
int prev_stride = *r_stride << 1;
|
2019-09-08 00:12:26 +10:00
|
|
|
for (int i = 0; i < cell_count; i++) {
|
2018-07-10 15:02:25 +02:00
|
|
|
*r_final_idx = i;
|
|
|
|
cell_id_to_grid_loc(egrid, *r_final_idx, r_local_cell);
|
|
|
|
if (((r_local_cell[0] % *r_stride) == 0) && ((r_local_cell[1] % *r_stride) == 0) &&
|
|
|
|
((r_local_cell[2] % *r_stride) == 0)) {
|
|
|
|
if (!(((r_local_cell[0] % prev_stride) == 0) && ((r_local_cell[1] % prev_stride) == 0) &&
|
|
|
|
((r_local_cell[2] % prev_stride) == 0)) ||
|
|
|
|
((i == 0) && (lvl == max_lvl))) {
|
|
|
|
if (visited_cells == cell_idx) {
|
|
|
|
return;
|
|
|
|
}
|
2020-08-07 11:49:59 +02:00
|
|
|
|
|
|
|
visited_cells++;
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
BLI_assert(0);
|
|
|
|
}
|
|
|
|
|
2020-08-07 22:56:13 +10:00
|
|
|
static void grid_loc_to_world_loc(EEVEE_LightGrid *egrid, const int local_cell[3], float r_pos[3])
|
2018-07-10 15:02:25 +02:00
|
|
|
{
|
|
|
|
copy_v3_v3(r_pos, egrid->corner);
|
|
|
|
madd_v3_v3fl(r_pos, egrid->increment_x, local_cell[0]);
|
|
|
|
madd_v3_v3fl(r_pos, egrid->increment_y, local_cell[1]);
|
|
|
|
madd_v3_v3fl(r_pos, egrid->increment_z, local_cell[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eevee_lightbake_render_grid_sample(void *ved, void *user_data)
|
|
|
|
{
|
|
|
|
EEVEE_Data *vedata = (EEVEE_Data *)ved;
|
|
|
|
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
|
|
|
|
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
|
|
|
|
EEVEE_LightBake *lbake = (EEVEE_LightBake *)user_data;
|
|
|
|
EEVEE_LightGrid *egrid = lbake->grid;
|
|
|
|
LightProbe *prb = *lbake->probe;
|
|
|
|
Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph);
|
2020-03-11 17:12:01 +01:00
|
|
|
LightCache *lcache = scene_eval->eevee.light_cache_data;
|
2018-07-10 15:02:25 +02:00
|
|
|
int grid_loc[3], sample_id, sample_offset, stride;
|
|
|
|
float pos[3];
|
|
|
|
const bool is_last_bounce_sample = ((egrid->offset + lbake->grid_sample) ==
|
|
|
|
(lbake->total_irr_samples - 1));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* No bias for rendering the probe. */
|
|
|
|
egrid->level_bias = 1.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Use the previous bounce for rendering this bounce. */
|
|
|
|
SWAP(GPUTexture *, lbake->grid_prev, lcache->grid_tx.tex);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-19 18:19:49 +02:00
|
|
|
/* TODO do this once for the whole bake when we have independent DRWManagers.
|
2018-07-10 15:02:25 +02:00
|
|
|
* Warning: Some of the things above require this. */
|
|
|
|
eevee_lightbake_cache_create(vedata, lbake);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Compute sample position */
|
|
|
|
compute_cell_id(egrid, prb, lbake->grid_sample, &sample_id, grid_loc, &stride);
|
|
|
|
sample_offset = egrid->offset + sample_id;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
grid_loc_to_world_loc(egrid, grid_loc, pos);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */
|
|
|
|
common_data->spec_toggle = false;
|
2020-11-04 19:34:19 +01:00
|
|
|
common_data->sss_toggle = false;
|
2018-07-10 15:02:25 +02:00
|
|
|
common_data->prb_num_planar = 0;
|
|
|
|
common_data->prb_num_render_cube = 0;
|
2018-11-08 19:17:41 +01:00
|
|
|
common_data->ray_type = EEVEE_RAY_DIFFUSE;
|
|
|
|
common_data->ray_depth = lbake->bounce_curr + 1;
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lbake->bounce_curr == 0) {
|
|
|
|
common_data->prb_num_render_grid = 0;
|
|
|
|
}
|
2020-08-20 23:09:37 +02:00
|
|
|
GPU_uniformbuf_update(sldata->common_ubo, &sldata->common_data);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_lightbake_render_scene(sldata, vedata, lbake->rt_fb, pos, prb->clipsta, prb->clipend);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Restore before filtering. */
|
|
|
|
SWAP(GPUTexture *, lbake->grid_prev, lcache->grid_tx.tex);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_lightbake_filter_diffuse(
|
|
|
|
sldata, vedata, lbake->rt_color, lbake->store_fb, sample_offset, prb->intensity);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lbake->bounce_curr == 0) {
|
|
|
|
/* We only need to filter the visibility for the first bounce. */
|
2019-01-04 19:08:09 +11:00
|
|
|
EEVEE_lightbake_filter_visibility(sldata,
|
|
|
|
vedata,
|
|
|
|
lbake->rt_depth,
|
|
|
|
lbake->store_fb,
|
|
|
|
sample_offset,
|
|
|
|
prb->clipsta,
|
|
|
|
prb->clipend,
|
|
|
|
egrid->visibility_range,
|
|
|
|
prb->vis_blur,
|
|
|
|
lbake->vis_res);
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Update level for progressive update. */
|
|
|
|
if (is_last_bounce_sample) {
|
|
|
|
egrid->level_bias = 1.0f;
|
|
|
|
}
|
|
|
|
else if (lbake->bounce_curr == 0) {
|
|
|
|
egrid->level_bias = (float)(stride << 1);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Only run this for the last sample of a bounce. */
|
|
|
|
if (is_last_bounce_sample) {
|
|
|
|
eevee_lightbake_copy_irradiance(lbake, lcache);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* If it is the last sample grid sample (and last bounce). */
|
|
|
|
if ((lbake->bounce_curr == lbake->bounce_len - 1) && (lbake->grid_curr == lbake->grid_len - 1) &&
|
|
|
|
(lbake->grid_sample == lbake->grid_sample_len - 1)) {
|
|
|
|
lcache->flag &= ~LIGHTCACHE_UPDATE_GRID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eevee_lightbake_render_probe_sample(void *ved, void *user_data)
|
|
|
|
{
|
|
|
|
EEVEE_Data *vedata = (EEVEE_Data *)ved;
|
|
|
|
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
|
|
|
|
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
|
|
|
|
EEVEE_LightBake *lbake = (EEVEE_LightBake *)user_data;
|
|
|
|
Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph);
|
2020-03-11 17:12:01 +01:00
|
|
|
LightCache *lcache = scene_eval->eevee.light_cache_data;
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_LightProbe *eprobe = lbake->cube;
|
|
|
|
LightProbe *prb = *lbake->probe;
|
2018-11-15 19:41:15 +01:00
|
|
|
float clamp = scene_eval->eevee.gi_glossy_clamp;
|
2018-11-15 20:04:35 +01:00
|
|
|
float filter_quality = scene_eval->eevee.gi_filter_quality;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-19 18:19:49 +02:00
|
|
|
/* TODO do this once for the whole bake when we have independent DRWManagers. */
|
2018-07-10 15:02:25 +02:00
|
|
|
eevee_lightbake_cache_create(vedata, lbake);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */
|
|
|
|
common_data->spec_toggle = false;
|
2020-11-04 19:34:19 +01:00
|
|
|
common_data->sss_toggle = false;
|
2018-07-10 15:02:25 +02:00
|
|
|
common_data->prb_num_planar = 0;
|
|
|
|
common_data->prb_num_render_cube = 0;
|
2018-11-08 19:17:41 +01:00
|
|
|
common_data->ray_type = EEVEE_RAY_GLOSSY;
|
|
|
|
common_data->ray_depth = 1;
|
2020-08-20 23:09:37 +02:00
|
|
|
GPU_uniformbuf_update(sldata->common_ubo, &sldata->common_data);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_lightbake_render_scene(
|
|
|
|
sldata, vedata, lbake->rt_fb, eprobe->position, prb->clipsta, prb->clipend);
|
2018-11-17 22:20:04 +11:00
|
|
|
EEVEE_lightbake_filter_glossy(sldata,
|
|
|
|
vedata,
|
|
|
|
lbake->rt_color,
|
|
|
|
lbake->store_fb,
|
|
|
|
lbake->cube_offset,
|
|
|
|
prb->intensity,
|
|
|
|
lcache->mips_len,
|
|
|
|
filter_quality,
|
|
|
|
clamp);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
lcache->cube_len += 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* If it's the last probe. */
|
|
|
|
if (lbake->cube_offset == lbake->cube_len - 1) {
|
|
|
|
lcache->flag &= ~LIGHTCACHE_UPDATE_CUBE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static float eevee_lightbake_grid_influence_volume(EEVEE_LightGrid *grid)
|
|
|
|
{
|
|
|
|
return mat4_to_scale(grid->mat);
|
|
|
|
}
|
|
|
|
|
|
|
|
static float eevee_lightbake_cube_influence_volume(EEVEE_LightProbe *eprb)
|
|
|
|
{
|
|
|
|
return mat4_to_scale(eprb->attenuationmat);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool eevee_lightbake_grid_comp(EEVEE_LightGrid *grid_a, EEVEE_LightGrid *grid_b)
|
|
|
|
{
|
|
|
|
float vol_a = eevee_lightbake_grid_influence_volume(grid_a);
|
|
|
|
float vol_b = eevee_lightbake_grid_influence_volume(grid_b);
|
|
|
|
return (vol_a < vol_b);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool eevee_lightbake_cube_comp(EEVEE_LightProbe *prb_a, EEVEE_LightProbe *prb_b)
|
|
|
|
{
|
|
|
|
float vol_a = eevee_lightbake_cube_influence_volume(prb_a);
|
|
|
|
float vol_b = eevee_lightbake_cube_influence_volume(prb_b);
|
|
|
|
return (vol_a < vol_b);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SORT_PROBE(elems_type, prbs, elems, elems_len, comp_fn) \
|
|
|
|
{ \
|
|
|
|
bool sorted = false; \
|
|
|
|
while (!sorted) { \
|
|
|
|
sorted = true; \
|
2019-04-02 17:54:04 +11:00
|
|
|
for (int i = 0; i < (elems_len)-1; i++) { \
|
|
|
|
if ((comp_fn)((elems) + i, (elems) + i + 1)) { \
|
|
|
|
SWAP(elems_type, (elems)[i], (elems)[i + 1]); \
|
|
|
|
SWAP(LightProbe *, (prbs)[i], (prbs)[i + 1]); \
|
2018-07-10 15:02:25 +02:00
|
|
|
sorted = false; \
|
2019-04-17 06:17:24 +02:00
|
|
|
} \
|
2018-07-10 15:02:25 +02:00
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
2019-04-02 17:54:04 +11:00
|
|
|
((void)0)
|
2018-07-10 15:02:25 +02:00
|
|
|
|
|
|
|
static void eevee_lightbake_gather_probes(EEVEE_LightBake *lbake)
|
|
|
|
{
|
|
|
|
Depsgraph *depsgraph = lbake->depsgraph;
|
|
|
|
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
|
2020-03-11 17:12:01 +01:00
|
|
|
LightCache *lcache = scene_eval->eevee.light_cache_data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* At least one for the world */
|
|
|
|
int grid_len = 1;
|
|
|
|
int cube_len = 1;
|
|
|
|
int total_irr_samples = 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Convert all lightprobes to tight UBO data from all lightprobes in the scene.
|
|
|
|
* This allows a large number of probe to be precomputed (even dupli ones). */
|
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
|
2018-12-18 18:18:00 +01:00
|
|
|
const int ob_visibility = BKE_object_visibility(ob, DAG_EVAL_RENDER);
|
|
|
|
if ((ob_visibility & OB_VISIBLE_SELF) == 0) {
|
2018-07-10 15:02:25 +02:00
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (ob->type == OB_LIGHTPROBE) {
|
|
|
|
LightProbe *prb = (LightProbe *)ob->data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
if (prb->type == LIGHTPROBE_TYPE_GRID) {
|
|
|
|
lbake->grid_prb[grid_len] = prb;
|
|
|
|
EEVEE_LightGrid *egrid = &lcache->grid_data[grid_len++];
|
|
|
|
EEVEE_lightprobes_grid_data_from_object(ob, egrid, &total_irr_samples);
|
|
|
|
}
|
2020-03-11 17:12:01 +01:00
|
|
|
else if (prb->type == LIGHTPROBE_TYPE_CUBE && cube_len < EEVEE_PROBE_MAX) {
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->cube_prb[cube_len] = prb;
|
|
|
|
EEVEE_LightProbe *eprobe = &lcache->cube_data[cube_len++];
|
|
|
|
EEVEE_lightprobes_cube_data_from_object(ob, eprobe);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
SORT_PROBE(EEVEE_LightGrid,
|
|
|
|
lbake->grid_prb + 1,
|
|
|
|
lcache->grid_data + 1,
|
|
|
|
lbake->grid_len - 1,
|
|
|
|
eevee_lightbake_grid_comp);
|
|
|
|
SORT_PROBE(EEVEE_LightProbe,
|
|
|
|
lbake->cube_prb + 1,
|
|
|
|
lcache->cube_data + 1,
|
|
|
|
lbake->cube_len - 1,
|
|
|
|
eevee_lightbake_cube_comp);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->total = lbake->total_irr_samples * lbake->bounce_len + lbake->cube_len;
|
|
|
|
lbake->done = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EEVEE_lightbake_update(void *custom_data)
|
|
|
|
{
|
|
|
|
EEVEE_LightBake *lbake = (EEVEE_LightBake *)custom_data;
|
|
|
|
Scene *scene_orig = lbake->scene;
|
|
|
|
|
2021-02-05 16:23:34 +11:00
|
|
|
/* If a new light-cache was created, free the old one and reference the new. */
|
2020-03-11 17:12:01 +01:00
|
|
|
if (lbake->lcache && scene_orig->eevee.light_cache_data != lbake->lcache) {
|
|
|
|
if (scene_orig->eevee.light_cache_data != NULL) {
|
|
|
|
EEVEE_lightcache_free(scene_orig->eevee.light_cache_data);
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
2020-03-11 17:12:01 +01:00
|
|
|
scene_orig->eevee.light_cache_data = lbake->lcache;
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->own_light_cache = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
EEVEE_lightcache_info_update(&lbake->scene->eevee);
|
|
|
|
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&scene_orig->id, ID_RECALC_COPY_ON_WRITE);
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool lightbake_do_sample(EEVEE_LightBake *lbake,
|
|
|
|
void (*render_callback)(void *ved, void *user_data))
|
|
|
|
{
|
|
|
|
if (G.is_break == true || *lbake->stop) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Depsgraph *depsgraph = lbake->depsgraph;
|
|
|
|
|
2021-02-05 16:23:34 +11:00
|
|
|
/* TODO: make DRW manager instantiable (and only lock on drawing) */
|
2018-07-10 15:02:25 +02:00
|
|
|
eevee_lightbake_context_enable(lbake);
|
|
|
|
DRW_custom_pipeline(&draw_engine_eevee_type, depsgraph, render_callback, lbake);
|
|
|
|
lbake->done += 1;
|
|
|
|
*lbake->progress = lbake->done / (float)lbake->total;
|
|
|
|
*lbake->do_update = 1;
|
|
|
|
eevee_lightbake_context_disable(lbake);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EEVEE_lightbake_job(void *custom_data, short *stop, short *do_update, float *progress)
|
|
|
|
{
|
|
|
|
EEVEE_LightBake *lbake = (EEVEE_LightBake *)custom_data;
|
|
|
|
Depsgraph *depsgraph = lbake->depsgraph;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-18 15:51:32 +02:00
|
|
|
DEG_graph_relations_update(depsgraph);
|
2020-08-18 17:40:45 +02:00
|
|
|
DEG_evaluate_on_framechange(depsgraph, lbake->frame);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
lbake->view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
|
|
|
lbake->stop = stop;
|
|
|
|
lbake->do_update = do_update;
|
|
|
|
lbake->progress = progress;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-11 18:51:56 +01:00
|
|
|
if (G.background) {
|
|
|
|
/* Make sure to init GL capabilities before counting probes. */
|
|
|
|
eevee_lightbake_context_enable(lbake);
|
|
|
|
eevee_lightbake_context_disable(lbake);
|
|
|
|
}
|
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Count lightprobes */
|
|
|
|
eevee_lightbake_count_probes(lbake);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* We need to create the FBOs in the right context.
|
|
|
|
* We cannot do it in the main thread. */
|
|
|
|
eevee_lightbake_context_enable(lbake);
|
|
|
|
eevee_lightbake_create_resources(lbake);
|
2020-08-04 19:52:18 +02:00
|
|
|
|
|
|
|
/* Resource allocation can fail. Early exit in this case. */
|
|
|
|
if (lbake->lcache->flag & LIGHTCACHE_INVALID) {
|
|
|
|
*lbake->stop = 1;
|
|
|
|
*lbake->do_update = 1;
|
|
|
|
lbake->lcache->flag &= ~LIGHTCACHE_BAKING;
|
|
|
|
eevee_lightbake_context_disable(lbake);
|
|
|
|
eevee_lightbake_delete_resources(lbake);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
eevee_lightbake_create_render_target(lbake, lbake->rt_res);
|
|
|
|
eevee_lightbake_context_disable(lbake);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Gather all probes data */
|
|
|
|
eevee_lightbake_gather_probes(lbake);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
LightCache *lcache = lbake->lcache;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* HACK: Sleep to delay the first rendering operation
|
|
|
|
* that causes a small freeze (caused by VBO generation)
|
|
|
|
* because this step is locking at this moment. */
|
|
|
|
/* TODO remove this. */
|
|
|
|
if (lbake->delay) {
|
|
|
|
PIL_sleep_ms(lbake->delay);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Render world irradiance and reflection first */
|
|
|
|
if (lcache->flag & LIGHTCACHE_UPDATE_WORLD) {
|
|
|
|
lbake->probe = NULL;
|
|
|
|
lightbake_do_sample(lbake, eevee_lightbake_render_world_sample);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Render irradiance grids */
|
|
|
|
if (lcache->flag & LIGHTCACHE_UPDATE_GRID) {
|
2019-09-08 00:12:26 +10:00
|
|
|
for (lbake->bounce_curr = 0; lbake->bounce_curr < lbake->bounce_len; lbake->bounce_curr++) {
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Bypass world, start at 1. */
|
|
|
|
lbake->probe = lbake->grid_prb + 1;
|
|
|
|
lbake->grid = lcache->grid_data + 1;
|
|
|
|
for (lbake->grid_curr = 1; lbake->grid_curr < lbake->grid_len;
|
2019-09-08 00:12:26 +10:00
|
|
|
lbake->grid_curr++, lbake->probe++, lbake->grid++) {
|
2018-07-10 15:02:25 +02:00
|
|
|
LightProbe *prb = *lbake->probe;
|
|
|
|
lbake->grid_sample_len = prb->grid_resolution_x * prb->grid_resolution_y *
|
|
|
|
prb->grid_resolution_z;
|
|
|
|
for (lbake->grid_sample = 0; lbake->grid_sample < lbake->grid_sample_len;
|
|
|
|
++lbake->grid_sample) {
|
|
|
|
lightbake_do_sample(lbake, eevee_lightbake_render_grid_sample);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Render reflections */
|
|
|
|
if (lcache->flag & LIGHTCACHE_UPDATE_CUBE) {
|
|
|
|
/* Bypass world, start at 1. */
|
|
|
|
lbake->probe = lbake->cube_prb + 1;
|
|
|
|
lbake->cube = lcache->cube_data + 1;
|
|
|
|
for (lbake->cube_offset = 1; lbake->cube_offset < lbake->cube_len;
|
2019-09-08 00:12:26 +10:00
|
|
|
lbake->cube_offset++, lbake->probe++, lbake->cube++) {
|
2018-07-10 15:02:25 +02:00
|
|
|
lightbake_do_sample(lbake, eevee_lightbake_render_probe_sample);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Read the resulting lighting data to save it to file/disk. */
|
|
|
|
eevee_lightbake_context_enable(lbake);
|
|
|
|
eevee_lightbake_readback_irradiance(lcache);
|
|
|
|
eevee_lightbake_readback_reflections(lcache);
|
|
|
|
eevee_lightbake_context_disable(lbake);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
lcache->flag |= LIGHTCACHE_BAKED;
|
|
|
|
lcache->flag &= ~LIGHTCACHE_BAKING;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Assume that if lbake->gl_context is NULL
|
|
|
|
* we are not running in this in a job, so update
|
2019-06-12 09:04:10 +10:00
|
|
|
* the scene light-cache pointer before deleting it. */
|
2018-07-10 15:02:25 +02:00
|
|
|
if (lbake->gl_context == NULL) {
|
|
|
|
BLI_assert(BLI_thread_is_main());
|
|
|
|
EEVEE_lightbake_update(lbake);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
eevee_lightbake_delete_resources(lbake);
|
2020-04-10 12:10:13 +02:00
|
|
|
|
|
|
|
/* Free GPU smoke textures and the smoke domain list correctly: See also T73921.*/
|
|
|
|
EEVEE_volumes_free_smoke_textures();
|
2018-07-10 15:02:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This is to update the world irradiance and reflection contribution from
|
|
|
|
* within the viewport drawing (does not have the overhead of a full light cache rebuild.) */
|
|
|
|
void EEVEE_lightbake_update_world_quick(EEVEE_ViewLayerData *sldata,
|
|
|
|
EEVEE_Data *vedata,
|
|
|
|
const Scene *scene)
|
|
|
|
{
|
|
|
|
LightCache *lcache = vedata->stl->g_data->light_cache;
|
2018-11-15 19:41:15 +01:00
|
|
|
float clamp = scene->eevee.gi_glossy_clamp;
|
2018-11-15 20:04:35 +01:00
|
|
|
float filter_quality = scene->eevee.gi_filter_quality;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_LightBake lbake = {
|
2019-01-07 00:06:58 +11:00
|
|
|
.resource_only = true,
|
2018-07-10 15:02:25 +02:00
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Create resources. */
|
|
|
|
eevee_lightbake_create_render_target(&lbake, scene->eevee.gi_cubemap_resolution);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_lightbake_cache_init(sldata, vedata, lbake.rt_color, lbake.rt_depth);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-08 19:17:41 +01:00
|
|
|
sldata->common_data.ray_type = EEVEE_RAY_GLOSSY;
|
|
|
|
sldata->common_data.ray_depth = 1;
|
2020-08-20 23:09:37 +02:00
|
|
|
GPU_uniformbuf_update(sldata->common_ubo, &sldata->common_data);
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_lightbake_render_world(sldata, vedata, lbake.rt_fb);
|
2018-11-15 20:04:35 +01:00
|
|
|
EEVEE_lightbake_filter_glossy(sldata,
|
|
|
|
vedata,
|
|
|
|
lbake.rt_color,
|
|
|
|
lbake.store_fb,
|
|
|
|
0,
|
|
|
|
1.0f,
|
|
|
|
lcache->mips_len,
|
|
|
|
filter_quality,
|
|
|
|
clamp);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-08 19:17:41 +01:00
|
|
|
sldata->common_data.ray_type = EEVEE_RAY_DIFFUSE;
|
|
|
|
sldata->common_data.ray_depth = 1;
|
2020-08-20 23:09:37 +02:00
|
|
|
GPU_uniformbuf_update(sldata->common_ubo, &sldata->common_data);
|
2018-11-08 19:17:41 +01:00
|
|
|
EEVEE_lightbake_render_world(sldata, vedata, lbake.rt_fb);
|
2018-07-10 15:02:25 +02:00
|
|
|
EEVEE_lightbake_filter_diffuse(sldata, vedata, lbake.rt_color, lbake.store_fb, 0, 1.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
/* Don't hide grids if they are already rendered. */
|
|
|
|
lcache->grid_len = max_ii(1, lcache->grid_len);
|
|
|
|
lcache->cube_len = 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
lcache->flag |= LIGHTCACHE_CUBE_READY | LIGHTCACHE_GRID_READY;
|
|
|
|
lcache->flag &= ~LIGHTCACHE_UPDATE_WORLD;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-10 15:02:25 +02:00
|
|
|
eevee_lightbake_delete_resources(&lbake);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|