DNA: Move irradiance grid light cache data to Object level #106808
|
@ -14,10 +14,49 @@ extern "C" {
|
||||||
|
|
||||||
struct LightProbe;
|
struct LightProbe;
|
||||||
struct Main;
|
struct Main;
|
||||||
|
struct BlendWriter;
|
||||||
|
struct BlendDataReader;
|
||||||
|
struct LightProbeGridCache;
|
||||||
|
struct Object;
|
||||||
|
|
||||||
void BKE_lightprobe_type_set(struct LightProbe *probe, short lightprobe_type);
|
void BKE_lightprobe_type_set(struct LightProbe *probe, short lightprobe_type);
|
||||||
void *BKE_lightprobe_add(struct Main *bmain, const char *name);
|
void *BKE_lightprobe_add(struct Main *bmain, const char *name);
|
||||||
|
|
||||||
|
void BKE_lightprobe_grid_cache_blend_write(struct BlendWriter *writer,
|
||||||
|
struct LightProbeGridCache **grid_caches,
|
||||||
|
int grid_caches_len);
|
||||||
|
|
||||||
|
void BKE_lightprobe_grid_cache_blend_read(struct BlendDataReader *reader,
|
||||||
|
struct LightProbeGridCache **grid_caches,
|
||||||
|
int grid_caches_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a single empty irradiance grid cache.
|
||||||
|
*/
|
||||||
|
struct LightProbeGridCache *BKE_lightprobe_grid_cache_create(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a single grid cache.
|
||||||
|
*/
|
||||||
|
void BKE_lightprobe_grid_cache_free(struct LightProbeGridCache *cache);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the grid cache list depending on the lightprobe baking settings.
|
||||||
|
* The list is left empty to be filled by the baking process.
|
||||||
|
*/
|
||||||
|
void BKE_lightprobe_grid_caches_create(struct Object *object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free all irradiance grids allocated for the given object.
|
||||||
|
*/
|
||||||
|
void BKE_lightprobe_grid_caches_free(struct Object *object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of sample stored inside an irradiance cache.
|
||||||
|
* This depends on the light cache type.
|
||||||
|
*/
|
||||||
|
int64_t BKE_lightprobe_grid_cache_sample_count(const struct LightProbeGridCache *cache);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include "DNA_lightprobe_types.h"
|
#include "DNA_lightprobe_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
|
|
||||||
|
#include "BLI_math_base.h"
|
||||||
|
#include "BLI_span.hh"
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
#include "BKE_anim_data.h"
|
#include "BKE_anim_data.h"
|
||||||
|
@ -129,3 +131,174 @@ void *BKE_lightprobe_add(Main *bmain, const char *name)
|
||||||
|
|
||||||
return probe;
|
return probe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BKE_lightprobe_grid_cache_blend_write(BlendWriter *writer,
|
||||||
|
LightProbeGridCache **grid_caches,
|
||||||
|
int grid_caches_len)
|
||||||
|
{
|
||||||
|
blender::Span<const LightProbeGridCache *> caches(grid_caches, grid_caches_len);
|
||||||
|
for (const LightProbeGridCache *cache : caches) {
|
||||||
|
if (cache == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLO_write_struct(writer, LightProbeGridCache, cache);
|
||||||
|
|
||||||
|
if (cache->block_infos != nullptr) {
|
||||||
|
BLO_write_struct_array(writer, LightProbeGridCache, cache->block_len, cache->block_infos);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t sample_count = BKE_lightprobe_grid_cache_sample_count(cache);
|
||||||
|
|
||||||
|
if (cache->irradiance.L0 != nullptr) {
|
||||||
|
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L0);
|
||||||
|
}
|
||||||
|
if (cache->irradiance.L1_a != nullptr) {
|
||||||
|
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L1_a);
|
||||||
|
}
|
||||||
|
if (cache->irradiance.L1_b != nullptr) {
|
||||||
|
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L1_b);
|
||||||
|
}
|
||||||
|
if (cache->irradiance.L1_c != nullptr) {
|
||||||
|
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L1_c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache->visibility.L0 != nullptr) {
|
||||||
|
BLO_write_int8_array(writer, sample_count, (int8_t *)cache->visibility.L0);
|
||||||
|
}
|
||||||
|
if (cache->visibility.L1_a != nullptr) {
|
||||||
|
BLO_write_int8_array(writer, sample_count, (int8_t *)cache->visibility.L1_a);
|
||||||
|
}
|
||||||
|
if (cache->visibility.L1_b != nullptr) {
|
||||||
|
BLO_write_int8_array(writer, sample_count, (int8_t *)cache->visibility.L1_b);
|
||||||
|
}
|
||||||
|
if (cache->visibility.L1_c != nullptr) {
|
||||||
|
BLO_write_int8_array(writer, sample_count, (int8_t *)cache->visibility.L1_c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache->connectivity.bitmask != nullptr) {
|
||||||
|
BLO_write_struct_array(
|
||||||
|
writer, LightProbeGridCache, sample_count, cache->connectivity.bitmask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_lightprobe_grid_cache_blend_read(BlendDataReader *reader,
|
||||||
|
LightProbeGridCache **grid_caches,
|
||||||
|
int grid_caches_len)
|
||||||
|
{
|
||||||
|
blender::MutableSpan<LightProbeGridCache *> caches(grid_caches, grid_caches_len);
|
||||||
|
for (LightProbeGridCache *&cache : caches) {
|
||||||
|
if (cache == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLO_read_data_address(reader, &cache);
|
||||||
|
|
||||||
|
if (cache->block_infos != nullptr) {
|
||||||
|
BLO_read_data_address(reader, &cache->block_infos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Baking data is not stored. */
|
||||||
|
cache->baking.L0 = nullptr;
|
||||||
|
cache->baking.L1_a = nullptr;
|
||||||
|
cache->baking.L1_b = nullptr;
|
||||||
|
cache->baking.L1_c = nullptr;
|
||||||
|
|
||||||
|
if (cache->irradiance.L0 != nullptr) {
|
||||||
|
BLO_read_data_address(reader, &cache->irradiance.L0);
|
||||||
|
}
|
||||||
|
if (cache->irradiance.L1_a != nullptr) {
|
||||||
|
BLO_read_data_address(reader, &cache->irradiance.L1_a);
|
||||||
|
}
|
||||||
|
if (cache->irradiance.L1_b != nullptr) {
|
||||||
|
BLO_read_data_address(reader, &cache->irradiance.L1_b);
|
||||||
|
}
|
||||||
|
if (cache->irradiance.L1_c != nullptr) {
|
||||||
|
BLO_read_data_address(reader, &cache->irradiance.L1_c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache->visibility.L0 != nullptr) {
|
||||||
|
BLO_read_data_address(reader, &cache->visibility.L0);
|
||||||
|
}
|
||||||
|
if (cache->visibility.L1_a != nullptr) {
|
||||||
|
BLO_read_data_address(reader, &cache->visibility.L1_a);
|
||||||
|
}
|
||||||
|
if (cache->visibility.L1_b != nullptr) {
|
||||||
|
BLO_read_data_address(reader, &cache->visibility.L1_b);
|
||||||
|
}
|
||||||
|
if (cache->visibility.L1_c != nullptr) {
|
||||||
|
BLO_read_data_address(reader, &cache->visibility.L1_c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache->connectivity.bitmask != nullptr) {
|
||||||
|
BLO_read_data_address(reader, &cache->connectivity.bitmask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> static void spherical_harmonic_free(T &data)
|
||||||
|
{
|
||||||
|
MEM_SAFE_FREE(data.L0);
|
||||||
|
MEM_SAFE_FREE(data.L1_a);
|
||||||
|
MEM_SAFE_FREE(data.L1_b);
|
||||||
|
MEM_SAFE_FREE(data.L1_c);
|
||||||
|
}
|
||||||
|
|
||||||
|
LightProbeGridCache *BKE_lightprobe_grid_cache_create()
|
||||||
|
{
|
||||||
|
LightProbeGridCache *cache = static_cast<LightProbeGridCache *>(
|
||||||
|
MEM_callocN(sizeof(LightProbeGridCache), "LightProbeGridCache"));
|
||||||
|
cache->cache_type = LIGHTPROBE_CACHE_TYPE_NONE;
|
||||||
|
cache->data_layout = LIGHTPROBE_CACHE_UNIFORM_GRID;
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_lightprobe_grid_cache_free(LightProbeGridCache *cache)
|
||||||
|
{
|
||||||
|
MEM_SAFE_FREE(cache->block_infos);
|
||||||
|
spherical_harmonic_free(cache->baking);
|
||||||
|
spherical_harmonic_free(cache->irradiance);
|
||||||
|
spherical_harmonic_free(cache->visibility);
|
||||||
|
MEM_SAFE_FREE(cache->connectivity.bitmask);
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_lightprobe_grid_caches_create(Object *object)
|
||||||
|
{
|
||||||
|
BLI_assert(object->irradiance_caches == nullptr);
|
||||||
|
|
||||||
|
/* Single cache for now. */
|
||||||
|
const int grid_caches_len = 1;
|
||||||
|
LightProbeGridCache **grid_caches = static_cast<LightProbeGridCache **>(
|
||||||
|
MEM_callocN(sizeof(LightProbeGridCache *) * grid_caches_len, "irradiance_caches"));
|
||||||
|
object->irradiance_caches = grid_caches;
|
||||||
|
object->irradiance_caches_len = grid_caches_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_lightprobe_grid_caches_free(Object *object)
|
||||||
|
{
|
||||||
|
if (object->irradiance_caches == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
blender::MutableSpan<LightProbeGridCache *> caches(object->irradiance_caches,
|
||||||
|
object->irradiance_caches_len);
|
||||||
|
for (LightProbeGridCache *cache : caches) {
|
||||||
|
if (cache != nullptr) {
|
||||||
|
BKE_lightprobe_grid_cache_free(cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MEM_SAFE_FREE(object->irradiance_caches);
|
||||||
|
object->irradiance_caches_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t BKE_lightprobe_grid_cache_sample_count(const LightProbeGridCache *cache)
|
||||||
|
{
|
||||||
|
if (cache->cache_type == LIGHTPROBE_CACHE_ADAPTIVE_RESOLUTION) {
|
||||||
|
return cache->block_len * cube_i(cache->block_size);
|
||||||
|
}
|
||||||
|
/* LIGHTPROBE_CACHE_UNIFORM_GRID */
|
||||||
|
return cache->size[0] * cache->size[1] * cache->size[2];
|
||||||
|
}
|
||||||
|
|
|
@ -267,6 +267,19 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in
|
||||||
if (ob_src->lightgroup) {
|
if (ob_src->lightgroup) {
|
||||||
ob_dst->lightgroup = (LightgroupMembership *)MEM_dupallocN(ob_src->lightgroup);
|
ob_dst->lightgroup = (LightgroupMembership *)MEM_dupallocN(ob_src->lightgroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((flag & LIB_ID_COPY_SET_COPIED_ON_WRITE) != 0) {
|
||||||
|
/* Reference the original object data. */
|
||||||
|
ob_dst->irradiance_caches = ob_src->irradiance_caches;
|
||||||
|
ob_dst->irradiance_caches_len = ob_src->irradiance_caches_len;
|
||||||
|
ob_dst->irradiance_caches_shared = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Do not copy lightprobe's cache. */
|
||||||
|
ob_dst->irradiance_caches = nullptr;
|
||||||
|
ob_dst->irradiance_caches_len = 0;
|
||||||
|
ob_dst->irradiance_caches_shared = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void object_free_data(ID *id)
|
static void object_free_data(ID *id)
|
||||||
|
@ -319,6 +332,10 @@ static void object_free_data(ID *id)
|
||||||
BKE_previewimg_free(&ob->preview);
|
BKE_previewimg_free(&ob->preview);
|
||||||
|
|
||||||
MEM_SAFE_FREE(ob->lightgroup);
|
MEM_SAFE_FREE(ob->lightgroup);
|
||||||
|
|
||||||
|
if (ob->irradiance_caches_shared == false) {
|
||||||
|
BKE_lightprobe_grid_caches_free(ob);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void library_foreach_modifiersForeachIDLink(void *user_data,
|
static void library_foreach_modifiersForeachIDLink(void *user_data,
|
||||||
|
@ -597,6 +614,12 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
|
||||||
if (ob->lightgroup) {
|
if (ob->lightgroup) {
|
||||||
BLO_write_struct(writer, LightgroupMembership, ob->lightgroup);
|
BLO_write_struct(writer, LightgroupMembership, ob->lightgroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ob->irradiance_caches) {
|
||||||
|
BLO_write_pointer_array(writer, ob->irradiance_caches_len, ob->irradiance_caches);
|
||||||
|
BKE_lightprobe_grid_cache_blend_write(
|
||||||
|
writer, ob->irradiance_caches, ob->irradiance_caches_len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX deprecated - old animation system */
|
/* XXX deprecated - old animation system */
|
||||||
|
@ -815,6 +838,9 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
|
||||||
BKE_previewimg_blend_read(reader, ob->preview);
|
BKE_previewimg_blend_read(reader, ob->preview);
|
||||||
|
|
||||||
BLO_read_data_address(reader, &ob->lightgroup);
|
BLO_read_data_address(reader, &ob->lightgroup);
|
||||||
|
|
||||||
|
BLO_read_pointer_array(reader, (void **)&ob->irradiance_caches);
|
||||||
|
BKE_lightprobe_grid_cache_blend_read(reader, ob->irradiance_caches, ob->irradiance_caches_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX deprecated - old animation system */
|
/* XXX deprecated - old animation system */
|
||||||
|
|
|
@ -41,6 +41,9 @@ void SCENE_OT_view_layer_remove_unused_lightgroups(struct wmOperatorType *ot);
|
||||||
void SCENE_OT_light_cache_bake(struct wmOperatorType *ot);
|
void SCENE_OT_light_cache_bake(struct wmOperatorType *ot);
|
||||||
void SCENE_OT_light_cache_free(struct wmOperatorType *ot);
|
void SCENE_OT_light_cache_free(struct wmOperatorType *ot);
|
||||||
|
|
||||||
|
void OBJECT_OT_lightprobe_cache_bake(struct wmOperatorType *ot);
|
||||||
|
void OBJECT_OT_lightprobe_cache_free(struct wmOperatorType *ot);
|
||||||
|
|
||||||
void SCENE_OT_render_view_add(struct wmOperatorType *ot);
|
void SCENE_OT_render_view_add(struct wmOperatorType *ot);
|
||||||
void SCENE_OT_render_view_remove(struct wmOperatorType *ot);
|
void SCENE_OT_render_view_remove(struct wmOperatorType *ot);
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@ void ED_operatortypes_render()
|
||||||
WM_operatortype_append(OBJECT_OT_material_slot_move);
|
WM_operatortype_append(OBJECT_OT_material_slot_move);
|
||||||
WM_operatortype_append(OBJECT_OT_material_slot_remove_unused);
|
WM_operatortype_append(OBJECT_OT_material_slot_remove_unused);
|
||||||
|
|
||||||
|
WM_operatortype_append(OBJECT_OT_lightprobe_cache_bake);
|
||||||
|
WM_operatortype_append(OBJECT_OT_lightprobe_cache_free);
|
||||||
|
|
||||||
WM_operatortype_append(MATERIAL_OT_new);
|
WM_operatortype_append(MATERIAL_OT_new);
|
||||||
WM_operatortype_append(TEXTURE_OT_new);
|
WM_operatortype_append(TEXTURE_OT_new);
|
||||||
WM_operatortype_append(WORLD_OT_new);
|
WM_operatortype_append(WORLD_OT_new);
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "BKE_image.h"
|
#include "BKE_image.h"
|
||||||
#include "BKE_layer.h"
|
#include "BKE_layer.h"
|
||||||
#include "BKE_lib_id.h"
|
#include "BKE_lib_id.h"
|
||||||
|
#include "BKE_lightprobe.h"
|
||||||
#include "BKE_linestyle.h"
|
#include "BKE_linestyle.h"
|
||||||
#include "BKE_main.h"
|
#include "BKE_main.h"
|
||||||
#include "BKE_material.h"
|
#include "BKE_material.h"
|
||||||
|
@ -53,6 +54,7 @@
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
#include "DEG_depsgraph_build.h"
|
#include "DEG_depsgraph_build.h"
|
||||||
|
#include "DEG_depsgraph_query.h"
|
||||||
|
|
||||||
#ifdef WITH_FREESTYLE
|
#ifdef WITH_FREESTYLE
|
||||||
# include "BKE_freestyle.h"
|
# include "BKE_freestyle.h"
|
||||||
|
@ -1492,6 +1494,87 @@ void SCENE_OT_light_cache_bake(wmOperatorType *ot)
|
||||||
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
|
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NOTE: New version destined to replace the old lightcache bake operator. */
|
||||||
|
|
||||||
|
static int lightprobe_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
||||||
|
{
|
||||||
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
Object *active_ob = CTX_data_active_object(C);
|
||||||
|
|
||||||
|
BKE_lightprobe_grid_caches_free(active_ob);
|
||||||
|
BKE_lightprobe_grid_caches_create(active_ob);
|
||||||
|
|
||||||
|
DEG_id_tag_update(&active_ob->id, ID_RECALC_COPY_ON_WRITE);
|
||||||
|
|
||||||
|
WM_event_add_modal_handler(C, op);
|
||||||
|
|
||||||
|
/* store actual owner of job, so modal operator could check for it,
|
||||||
|
* the reason of this is that active scene could change when rendering
|
||||||
|
* several layers from compositor #31800. */
|
||||||
|
op->customdata = scene;
|
||||||
|
|
||||||
|
WM_cursor_wait(false);
|
||||||
|
|
||||||
|
return OPERATOR_RUNNING_MODAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lightprobe_cache_bake_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
|
{
|
||||||
|
Scene *scene = (Scene *)op->customdata;
|
||||||
|
|
||||||
|
/* No running bake, remove handler and pass through. */
|
||||||
|
if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_LIGHT_BAKE)) {
|
||||||
|
return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Running bake. */
|
||||||
|
switch (event->type) {
|
||||||
|
case EVT_ESCKEY:
|
||||||
|
return OPERATOR_RUNNING_MODAL;
|
||||||
|
}
|
||||||
|
return OPERATOR_PASS_THROUGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lightprobe_cache_bake_cancel(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
wmWindowManager *wm = CTX_wm_manager(C);
|
||||||
|
Scene *scene = (Scene *)op->customdata;
|
||||||
|
|
||||||
|
/* Kill on cancel, because job is using op->reports. */
|
||||||
|
WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Executes blocking render. */
|
||||||
|
static int lightprobe_cache_bake_exec(bContext * /*C*/, wmOperator * /*op*/)
|
||||||
|
{
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBJECT_OT_lightprobe_cache_bake(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
/* identifiers */
|
||||||
|
ot->name = "Bake Light Cache";
|
||||||
|
ot->idname = "OBJECT_OT_lightprobe_cache_bake";
|
||||||
|
ot->description = "Bake the active view layer lighting";
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->invoke = lightprobe_cache_bake_invoke;
|
||||||
|
ot->modal = lightprobe_cache_bake_modal;
|
||||||
|
ot->cancel = lightprobe_cache_bake_cancel;
|
||||||
|
ot->exec = lightprobe_cache_bake_exec;
|
||||||
|
|
||||||
|
ot->prop = RNA_def_int(ot->srna,
|
||||||
|
"delay",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2000,
|
||||||
|
"Delay",
|
||||||
|
"Delay in millisecond before baking starts",
|
||||||
|
0,
|
||||||
|
2000);
|
||||||
|
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
|
||||||
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
@ -1541,6 +1624,49 @@ void SCENE_OT_light_cache_free(wmOperatorType *ot)
|
||||||
ot->poll = light_cache_free_poll;
|
ot->poll = light_cache_free_poll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NOTE: New version destined to replace the old lightcache bake operator. */
|
||||||
|
|
||||||
|
static bool lightprobe_cache_free_poll(bContext *C)
|
||||||
|
{
|
||||||
|
Object *object = CTX_data_active_object(C);
|
||||||
|
|
||||||
|
return object && object->irradiance_caches != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lightprobe_cache_free_exec(bContext *C, wmOperator * /*op*/)
|
||||||
|
{
|
||||||
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
Object *object = CTX_data_active_object(C);
|
||||||
|
|
||||||
|
/* Kill potential bake job first (see #57011). */
|
||||||
|
wmWindowManager *wm = CTX_wm_manager(C);
|
||||||
|
WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE);
|
||||||
|
|
||||||
|
if (object->irradiance_caches == nullptr) {
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
BKE_lightprobe_grid_caches_free(object);
|
||||||
|
|
||||||
|
DEG_id_tag_update(&object->id, ID_RECALC_COPY_ON_WRITE);
|
||||||
|
|
||||||
|
WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, scene);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBJECT_OT_lightprobe_cache_free(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
/* identifiers */
|
||||||
|
ot->name = "Delete Light Cache";
|
||||||
|
ot->idname = "OBJECT_OT_lightprobe_cache_free";
|
||||||
|
ot->description = "Delete cached indirect lighting";
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->exec = lightprobe_cache_free_exec;
|
||||||
|
ot->poll = lightprobe_cache_free_poll;
|
||||||
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
|
@ -61,9 +61,6 @@ typedef struct LightProbe {
|
||||||
struct Image *image;
|
struct Image *image;
|
||||||
/** Object visibility group, inclusive or exclusive. */
|
/** Object visibility group, inclusive or exclusive. */
|
||||||
struct Collection *visibility_grp;
|
struct Collection *visibility_grp;
|
||||||
|
|
||||||
/* Runtime display data */
|
|
||||||
float distfalloff, distgridinf;
|
|
||||||
} LightProbe;
|
} LightProbe;
|
||||||
|
|
||||||
/* Probe->type */
|
/* Probe->type */
|
||||||
|
@ -201,6 +198,114 @@ enum {
|
||||||
LIGHTCACHETEX_UINT = (1 << 2),
|
LIGHTCACHETEX_UINT = (1 << 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Irradiance grid data storage
|
||||||
|
*
|
||||||
|
* Each spherical harmonic band is stored separately. This allow loading only a specific band.
|
||||||
|
* The layout of each array is set by the #LightProbeGridType.
|
||||||
|
* Any unavailable data is be set to nullptr.
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Irradiance data (RGB) stored along visibility (A).
|
||||||
|
* This is the format used during baking and is used for visualizing the baking process.
|
||||||
|
*/
|
||||||
|
typedef struct LightProbeBakingData {
|
||||||
|
float (*L0)[4];
|
||||||
|
float (*L1_a)[4];
|
||||||
|
float (*L1_b)[4];
|
||||||
|
float (*L1_c)[4];
|
||||||
|
} LightProbeBakingData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Irradiance stored as RGB triple using scene referred color space.
|
||||||
fclem marked this conversation as resolved
Outdated
|
|||||||
|
*/
|
||||||
|
typedef struct LightProbeIrradianceData {
|
||||||
|
float (*L0)[3];
|
||||||
|
float (*L1_a)[3];
|
||||||
|
float (*L1_b)[3];
|
||||||
|
float (*L1_c)[3];
|
||||||
|
} LightProbeIrradianceData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalized visibility of distant light. Used for compositing grids together.
|
||||||
|
*/
|
||||||
|
typedef struct LightProbeVisibilityData {
|
||||||
|
uint8_t *L0;
|
||||||
|
uint8_t *L1_a;
|
||||||
|
uint8_t *L1_b;
|
||||||
|
uint8_t *L1_c;
|
||||||
|
} LightProbeVisibilityData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to avoid light leaks. Validate visibility between each grid sample.
|
||||||
|
*/
|
||||||
|
typedef struct LightProbeConnectivityData {
|
||||||
|
/** Stores a bitmask of valid connections within a cell. */
|
||||||
|
uint8_t *bitmask;
|
||||||
|
} LightProbeConnectivityData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines one block of data inside the grid cache data arrays.
|
||||||
|
* The block size if the same for all the blocks.
|
||||||
|
*/
|
||||||
|
typedef struct LightProbeBlockData {
|
||||||
|
/* Offset inside the level-of-detail this block starts. */
|
||||||
|
int offset[3];
|
||||||
|
/* Level-of-detail this block is from. */
|
||||||
|
int level;
|
||||||
|
} LightProbeBlockData;
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name LightProbeGridCache
|
||||||
|
*
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
typedef struct LightProbeGridCache {
|
||||||
|
/** Allow correct versioning / different types of data for the same layout. */
|
||||||
|
int cache_type;
|
||||||
|
/** Spatial layout type of the data stored inside the data arrays. */
|
||||||
|
int data_layout;
|
||||||
|
|
||||||
|
char _pad0[4];
|
||||||
|
|
||||||
|
/** Number of samples in the highest level of detail. */
|
||||||
|
int size[3];
|
||||||
|
|
||||||
|
/** Sparse or adaptive layout only: number of blocks inside data arrays. */
|
||||||
|
int block_len;
|
||||||
|
/** Sparse or adaptive layout only: size of a block in samples. All 3 dimensions are equal. */
|
||||||
|
int block_size;
|
||||||
|
/** Sparse or adaptive layout only: specify the blocks positions. */
|
||||||
|
LightProbeBlockData *block_infos;
|
||||||
|
|
||||||
|
/** Baked data. */
|
||||||
|
LightProbeBakingData baking;
|
||||||
|
LightProbeIrradianceData irradiance;
|
||||||
|
LightProbeVisibilityData visibility;
|
||||||
|
LightProbeConnectivityData connectivity;
|
||||||
|
} LightProbeGridCache;
|
||||||
|
|
||||||
|
/** #LightProbeGridCache.type (int) */
|
||||||
|
enum {
|
||||||
|
/** Light cache was just created and is not yet baked. */
|
||||||
|
LIGHTPROBE_CACHE_TYPE_NONE = 0,
|
||||||
|
/** Light cache is baked for one specific frame and capture all indirect lighting. */
|
||||||
|
LIGHTPROBE_CACHE_TYPE_STATIC = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** #LightProbeGridCache.data_layout (int) */
|
||||||
|
enum {
|
||||||
|
/** Simple uniform grid. Raw output from GPU. Used during the baking process. */
|
||||||
|
LIGHTPROBE_CACHE_UNIFORM_GRID = 0,
|
||||||
|
/** Fills the space with different level of resolution. More efficient storage. */
|
||||||
|
LIGHTPROBE_CACHE_ADAPTIVE_RESOLUTION = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,6 +34,7 @@ struct FluidsimSettings;
|
||||||
struct GeometrySet;
|
struct GeometrySet;
|
||||||
struct Ipo;
|
struct Ipo;
|
||||||
struct LightgroupMembership;
|
struct LightgroupMembership;
|
||||||
|
struct LightProbeGridCache;
|
||||||
struct Material;
|
struct Material;
|
||||||
struct Mesh;
|
struct Mesh;
|
||||||
struct Object;
|
struct Object;
|
||||||
|
@ -448,6 +449,15 @@ typedef struct Object {
|
||||||
/** Lightgroup membership information. */
|
/** Lightgroup membership information. */
|
||||||
struct LightgroupMembership *lightgroup;
|
struct LightgroupMembership *lightgroup;
|
||||||
|
|
||||||
|
/** Irradiance caches baked for this object (light-probes only). */
|
||||||
|
struct LightProbeGridCache **irradiance_caches;
|
||||||
|
/** Number of caches inside `irradiance_caches`. */
|
||||||
|
int irradiance_caches_len;
|
||||||
|
/** True if `irradiance_caches` is a reference to the evaluated object's cache. */
|
||||||
|
char irradiance_caches_shared;
|
||||||
|
char _pad9[3];
|
||||||
|
void *_pad10;
|
||||||
|
|
||||||
/** Runtime evaluation data (keep last). */
|
/** Runtime evaluation data (keep last). */
|
||||||
Object_Runtime runtime;
|
Object_Runtime runtime;
|
||||||
} Object;
|
} Object;
|
||||||
|
|
Loading…
Reference in New Issue
scene referred -> scene linear (scene referred is a category of color spaces, scene linear is the specific one)