WIP: eevee-next-world-irradiance #108304

Closed
Jeroen Bakker wants to merge 79 commits from Jeroen-Bakker:eevee-next-world-irradiance into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
6 changed files with 211 additions and 2 deletions
Showing only changes of commit 7b3d4c9e49 - Show all commits

View File

@ -107,6 +107,7 @@
#include "BLO_read_write.h"
#include "engines/eevee/eevee_lightcache.h"
#include "engines/eevee_next/eevee_lightcache.h"
#include "PIL_time.h"
@ -1439,7 +1440,11 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
EEVEE_lightcache_blend_read_data(reader, sce->eevee.light_cache_data);
}
}
EEVEE_lightcache_info_update(&sce->eevee);
RenderEngineType *engine_type = RE_engines_find(sce->r.engine);
bool use_eevee_next = STREQ(engine_type->idname, "BLENDER_EEVEE_NEXT");
(use_eevee_next ? EEVEE_NEXT_lightcache_info_update : EEVEE_lightcache_info_update)(&sce->eevee);
BKE_screen_view3d_shading_blend_read_data(reader, &sce->display.shading);

View File

@ -24,6 +24,7 @@
#include "PIL_time.h"
#include "../eevee_next/eevee_lightcache.h"
#include "eevee_lightcache.h"
#include "eevee_private.h"
@ -501,6 +502,11 @@ static void eevee_lightbake_readback_reflections(LightCache *lcache)
void EEVEE_lightcache_free(LightCache *lcache)
{
if (lcache->version == LIGHTCACHE_NEXT_STATIC_VERSION) {
EEVEE_NEXT_lightcache_free(lcache);
return;
}
DRW_TEXTURE_FREE_SAFE(lcache->cube_tx.tex);
MEM_SAFE_FREE(lcache->cube_tx.data);
DRW_TEXTURE_FREE_SAFE(lcache->grid_tx.tex);
@ -539,6 +545,10 @@ static void write_lightcache_texture(BlendWriter *writer, LightCacheTexture *tex
void EEVEE_lightcache_blend_write(BlendWriter *writer, LightCache *cache)
{
if (cache->version == LIGHTCACHE_NEXT_STATIC_VERSION) {
EEVEE_NEXT_lightcache_blend_write(writer, cache);
}
write_lightcache_texture(writer, &cache->grid_tx);
write_lightcache_texture(writer, &cache->cube_tx);
@ -579,6 +589,10 @@ static void direct_link_lightcache_texture(BlendDataReader *reader, LightCacheTe
void EEVEE_lightcache_blend_read_data(BlendDataReader *reader, LightCache *cache)
{
if (cache->version == LIGHTCACHE_NEXT_STATIC_VERSION) {
EEVEE_NEXT_lightcache_blend_read_data(reader, cache);
}
cache->flag &= ~LIGHTCACHE_NOT_USABLE;
direct_link_lightcache_texture(reader, &cache->cube_tx);
direct_link_lightcache_texture(reader, &cache->grid_tx);

View File

@ -92,6 +92,22 @@ class LightBake {
void update()
{
BLI_assert(BLI_thread_is_main());
Scene *original_scene = DEG_get_input_scene(depsgraph_);
if (original_scene->eevee.light_cache_data == nullptr) {
LightCache *light_cache = EEVEE_NEXT_lightcache_create();
LightCacheIrradianceGrid *grids = (LightCacheIrradianceGrid *)MEM_callocN(
1 * sizeof(LightCacheIrradianceGrid), "LightCacheIrradianceGrid");
grids[0].resolution[0] = 1;
grids[0].resolution[1] = 2;
grids[0].resolution[2] = 3;
light_cache->grid_len = 1;
light_cache->grids = grids;
original_scene->eevee.light_cache_data = light_cache;
}
EEVEE_NEXT_lightcache_info_update(&original_scene->eevee);
}
/**
@ -204,6 +220,10 @@ extern "C" {
using namespace blender::eevee;
/* -------------------------------------------------------------------- */
/** \name Light Bake Job
* \{ */
wmJob *EEVEE_NEXT_lightbake_job_create(struct wmWindowManager *wm,
struct wmWindow *win,
struct Main *bmain,
@ -269,6 +289,113 @@ void EEVEE_NEXT_lightbake_job(void *job_data, bool *stop, bool *do_update, float
{
reinterpret_cast<LightBake *>(job_data)->run(stop, do_update, progress);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Light Cache Create / Delete
* \{ */
LightCache *EEVEE_NEXT_lightcache_create()
{
LightCache *light_cache = (LightCache *)MEM_callocN(sizeof(LightCache), "LightCache");
light_cache->version = LIGHTCACHE_NEXT_STATIC_VERSION;
light_cache->type = LIGHTCACHE_TYPE_STATIC;
return light_cache;
}
void EEVEE_NEXT_lightcache_free(LightCache *light_cache)
{
if (light_cache->version < LIGHTCACHE_NEXT_STATIC_VERSION) {
/* Allow deleting old EEVEE cache. */
DRW_TEXTURE_FREE_SAFE(light_cache->cube_tx.tex);
MEM_SAFE_FREE(light_cache->cube_tx.data);
DRW_TEXTURE_FREE_SAFE(light_cache->grid_tx.tex);
MEM_SAFE_FREE(light_cache->grid_tx.data);
if (light_cache->cube_mips) {
for (int i = 0; i < light_cache->mips_len; i++) {
MEM_SAFE_FREE(light_cache->cube_mips[i].data);
}
MEM_SAFE_FREE(light_cache->cube_mips);
}
MEM_SAFE_FREE(light_cache->cube_data);
MEM_SAFE_FREE(light_cache->grid_data);
}
MEM_SAFE_FREE(light_cache->grids);
MEM_freeN(light_cache);
}
void EEVEE_NEXT_lightcache_info_update(SceneEEVEE *eevee)
{
LightCache *light_cache = eevee->light_cache_data;
if (light_cache == nullptr) {
BLI_strncpy(eevee->light_cache_info,
TIP_("No light cache in this scene"),
sizeof(eevee->light_cache_info));
return;
}
if (light_cache->version != LIGHTCACHE_NEXT_STATIC_VERSION) {
BLI_strncpy(eevee->light_cache_info,
TIP_("Incompatible Light cache version, please bake again"),
sizeof(eevee->light_cache_info));
return;
}
if (light_cache->flag & LIGHTCACHE_INVALID) {
BLI_strncpy(eevee->light_cache_info,
TIP_("Error: Light cache dimensions not supported by the GPU"),
sizeof(eevee->light_cache_info));
return;
}
if (light_cache->flag & LIGHTCACHE_BAKING) {
BLI_strncpy(
eevee->light_cache_info, TIP_("Baking light cache"), sizeof(eevee->light_cache_info));
return;
}
int irradiance_sample_len = 0;
for (const LightCacheIrradianceGrid &grid :
blender::Span<LightCacheIrradianceGrid>(light_cache->grids, light_cache->grid_len)) {
irradiance_sample_len += grid.resolution[0] * grid.resolution[1] * grid.resolution[2];
}
size_t size_in_bytes = irradiance_sample_len * sizeof(uint16_t) * 4 * 3;
char formatted_mem[BLI_STR_FORMAT_INT64_BYTE_UNIT_SIZE];
BLI_str_format_byte_unit(formatted_mem, size_in_bytes, false);
BLI_snprintf(eevee->light_cache_info,
sizeof(eevee->light_cache_info),
TIP_("%d Ref. Cubemaps, %d Irr. Samples (%s in memory)"),
light_cache->cube_len,
irradiance_sample_len,
formatted_mem);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Light Cache Read/Write to file
* \{ */
void EEVEE_NEXT_lightcache_blend_write(BlendWriter *writer, LightCache *light_cache)
{
BLO_write_struct_array(
writer, LightCacheIrradianceGrid, light_cache->grid_len, light_cache->grids);
}
void EEVEE_NEXT_lightcache_blend_read_data(BlendDataReader *reader, LightCache *light_cache)
{
BLO_read_data_address(reader, &light_cache->grids);
}
/** \} */
}
/** \} */

View File

@ -13,6 +13,10 @@ extern "C" {
/** Opaque type hiding eevee::LightBake. */
typedef struct EEVEE_NEXT_LightBake EEVEE_NEXT_LightBake;
/* -------------------------------------------------------------------- */
/** \name Light Bake Job
* \{ */
/**
* Create the job description.
* This is called for async (modal) bake operator.
@ -65,6 +69,39 @@ void EEVEE_NEXT_lightbake_job(void *job_data /* EEVEE_NEXT_LightBake */,
bool *do_update,
float *progress);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Light Cache Create / Delete
* \{ */
/**
* Create an empty light-cache.
*/
struct LightCache *EEVEE_NEXT_lightcache_create(void);
/**
* Free a light-cache and its associated data.
*/
void EEVEE_NEXT_lightcache_free(struct LightCache *lcache);
/**
* Update the UI message in the render panel about the state of the cache.
*/
void EEVEE_NEXT_lightcache_info_update(struct SceneEEVEE *eevee);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Light Cache Read/Write to file
* \{ */
void EEVEE_NEXT_lightcache_blend_write(struct BlendWriter *writer, struct LightCache *light_cache);
void EEVEE_NEXT_lightcache_blend_read_data(struct BlendDataReader *reader,
struct LightCache *light_cache);
/** \} */
#ifdef __cplusplus
}
#endif

View File

@ -1533,7 +1533,11 @@ static int light_cache_free_exec(bContext *C, wmOperator * /*op*/)
EEVEE_lightcache_free(scene->eevee.light_cache_data);
scene->eevee.light_cache_data = nullptr;
EEVEE_lightcache_info_update(&scene->eevee);
RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
bool use_eevee_next = STREQ(engine_type->idname, "BLENDER_EEVEE_NEXT");
((use_eevee_next) ? EEVEE_NEXT_lightcache_info_update :
EEVEE_lightcache_info_update)(&scene->eevee);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);

View File

@ -142,6 +142,21 @@ typedef struct LightCacheTexture {
char _pad[2];
} LightCacheTexture;
typedef struct LightCacheIrradianceGrid {
/** Transform to local space [0..resolution-1] range. */
float world_to_grid[4][4];
/** Number of samples in each dimension. */
int resolution[3];
/** Number of surfels in the cache. */
int surfels_len;
/** Currently only used at runtime for debugging the baking process. Not written to file. */
// struct GPUStorageBuf *surfels;
/** Irradiance Data. Stored as spherical harmonic. */
// LightCacheTexture *irradiance_L0_L1_a;
// LightCacheTexture *irradiance_L0_L1_b;
// LightCacheTexture *irradiance_L0_L1_c;
} LightCacheIrradianceGrid;
typedef struct LightCache {
int flag;
/** Version number to know if the cache data is compatible with this version of blender. */
@ -167,10 +182,17 @@ typedef struct LightCache {
/* All lightprobes data contained in the cache. */
LightProbeCache *cube_data;
LightGridCache *grid_data;
/* ---- EEVEE-Next ---- */
LightCacheIrradianceGrid *grids;
// LightCacheReflectionCube *cubes;
} LightCache;
/* Bump the version number for lightcache data structure changes. */
#define LIGHTCACHE_STATIC_VERSION 2
/* Cache generated by EEVEE-Next. Should be removed and be replaced by bumped
* LIGHTCACHE_STATIC_VERSION once EEVEE-Next is made default. */
#define LIGHTCACHE_NEXT_STATIC_VERSION 3
/* LightCache->type */
enum {