DNA: Move irradiance grid light cache data to Object level #106808
|
@ -14,10 +14,48 @@ extern "C" {
|
|||
|
||||
struct LightProbe;
|
||||
struct Main;
|
||||
struct BlendWriter;
|
||||
struct BlendDataReader;
|
||||
struct LightProbeObjectCache;
|
||||
struct LightProbeGridCacheFrame;
|
||||
struct Object;
|
||||
|
||||
void BKE_lightprobe_type_set(struct LightProbe *probe, short lightprobe_type);
|
||||
void *BKE_lightprobe_add(struct Main *bmain, const char *name);
|
||||
|
||||
void BKE_lightprobe_cache_blend_write(struct BlendWriter *writer,
|
||||
struct LightProbeObjectCache *cache);
|
||||
|
||||
void BKE_lightprobe_cache_blend_read(struct BlendDataReader *reader,
|
||||
struct LightProbeObjectCache *cache);
|
||||
|
||||
/**
|
||||
* Create a single empty irradiance grid cache.
|
||||
*/
|
||||
struct LightProbeGridCacheFrame *BKE_lightprobe_grid_cache_frame_create(void);
|
||||
|
||||
/**
|
||||
* Free a single grid cache.
|
||||
*/
|
||||
void BKE_lightprobe_grid_cache_frame_free(struct LightProbeGridCacheFrame *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_cache_create(struct Object *object);
|
||||
|
||||
/**
|
||||
* Free all irradiance grids allocated for the given object.
|
||||
*/
|
||||
void BKE_lightprobe_cache_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_frame_sample_count(const struct LightProbeGridCacheFrame *cache);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "DNA_lightprobe_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
|
@ -129,3 +131,137 @@ void *BKE_lightprobe_add(Main *bmain, const char *name)
|
|||
|
||||
return probe;
|
||||
}
|
||||
|
||||
static void lightprobe_grid_cache_frame_blend_write(BlendWriter *writer,
|
||||
const LightProbeGridCacheFrame *cache)
|
||||
{
|
||||
BLO_write_struct_array(writer, LightProbeGridCacheFrame, cache->block_len, cache->block_infos);
|
||||
|
||||
int64_t sample_count = BKE_lightprobe_grid_cache_frame_sample_count(cache);
|
||||
|
||||
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L0);
|
||||
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L1_a);
|
||||
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L1_b);
|
||||
BLO_write_float3_array(writer, sample_count, (float *)cache->irradiance.L1_c);
|
||||
|
||||
BLO_write_float_array(writer, sample_count, cache->visibility.L0);
|
||||
BLO_write_float_array(writer, sample_count, cache->visibility.L1_a);
|
||||
BLO_write_float_array(writer, sample_count, cache->visibility.L1_b);
|
||||
BLO_write_float_array(writer, sample_count, cache->visibility.L1_c);
|
||||
|
||||
BLO_write_struct_array(
|
||||
writer, LightProbeGridCacheFrame, sample_count, cache->connectivity.bitmask);
|
||||
}
|
||||
|
||||
static void lightprobe_grid_cache_frame_blend_read(BlendDataReader *reader,
|
||||
LightProbeGridCacheFrame *cache)
|
||||
{
|
||||
if (!ELEM(cache->data_layout,
|
||||
LIGHTPROBE_CACHE_ADAPTIVE_RESOLUTION,
|
||||
LIGHTPROBE_CACHE_UNIFORM_GRID)) {
|
||||
/* Do not try to read data from incompatible layout. Clear all pointers. */
|
||||
memset(cache, 0, sizeof(*cache));
|
||||
return;
|
||||
}
|
||||
|
||||
BLO_read_data_address(reader, &cache->block_infos);
|
||||
|
||||
int64_t sample_count = BKE_lightprobe_grid_cache_frame_sample_count(cache);
|
||||
|
||||
/* Baking data is not stored. */
|
||||
cache->baking.L0 = nullptr;
|
||||
cache->baking.L1_a = nullptr;
|
||||
cache->baking.L1_b = nullptr;
|
||||
cache->baking.L1_c = nullptr;
|
||||
cache->surfels = nullptr;
|
||||
cache->surfels_len = 0;
|
||||
|
||||
BLO_read_float3_array(reader, sample_count, (float **)&cache->irradiance.L0);
|
||||
BLO_read_float3_array(reader, sample_count, (float **)&cache->irradiance.L1_a);
|
||||
BLO_read_float3_array(reader, sample_count, (float **)&cache->irradiance.L1_b);
|
||||
BLO_read_float3_array(reader, sample_count, (float **)&cache->irradiance.L1_c);
|
||||
|
||||
BLO_read_float_array(reader, sample_count, &cache->visibility.L0);
|
||||
BLO_read_float_array(reader, sample_count, &cache->visibility.L1_a);
|
||||
BLO_read_float_array(reader, sample_count, &cache->visibility.L1_b);
|
||||
BLO_read_float_array(reader, sample_count, &cache->visibility.L1_c);
|
||||
|
||||
BLO_read_data_address(reader, &cache->connectivity.bitmask);
|
||||
}
|
||||
|
||||
void BKE_lightprobe_cache_blend_write(BlendWriter *writer, LightProbeObjectCache *cache)
|
||||
{
|
||||
if (cache->grid_static_cache != nullptr) {
|
||||
BLO_write_struct(writer, LightProbeGridCacheFrame, cache->grid_static_cache);
|
||||
lightprobe_grid_cache_frame_blend_write(writer, cache->grid_static_cache);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_lightprobe_cache_blend_read(BlendDataReader *reader, LightProbeObjectCache *cache)
|
||||
{
|
||||
if (cache->grid_static_cache != nullptr) {
|
||||
BLO_read_data_address(reader, &cache->grid_static_cache);
|
||||
lightprobe_grid_cache_frame_blend_read(reader, cache->grid_static_cache);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
LightProbeGridCacheFrame *BKE_lightprobe_grid_cache_frame_create()
|
||||
{
|
||||
LightProbeGridCacheFrame *cache = static_cast<LightProbeGridCacheFrame *>(
|
||||
MEM_callocN(sizeof(LightProbeGridCacheFrame), "LightProbeGridCacheFrame"));
|
||||
return cache;
|
||||
}
|
||||
|
||||
void BKE_lightprobe_grid_cache_frame_free(LightProbeGridCacheFrame *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->surfels);
|
||||
|
||||
MEM_SAFE_FREE(cache);
|
||||
}
|
||||
|
||||
void BKE_lightprobe_cache_create(Object *object)
|
||||
{
|
||||
BLI_assert(object->lightprobe_cache == nullptr);
|
||||
|
||||
object->lightprobe_cache = static_cast<LightProbeObjectCache *>(
|
||||
MEM_callocN(sizeof(LightProbeObjectCache), "LightProbeObjectCache"));
|
||||
}
|
||||
|
||||
void BKE_lightprobe_cache_free(Object *object)
|
||||
{
|
||||
if (object->lightprobe_cache == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
LightProbeObjectCache *cache = object->lightprobe_cache;
|
||||
|
||||
if (cache->shared == false) {
|
||||
if (cache->grid_static_cache != nullptr) {
|
||||
BKE_lightprobe_grid_cache_frame_free(cache->grid_static_cache);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(object->lightprobe_cache);
|
||||
}
|
||||
|
||||
int64_t BKE_lightprobe_grid_cache_frame_sample_count(const LightProbeGridCacheFrame *cache)
|
||||
{
|
||||
if (cache->data_layout == 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,18 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in
|
|||
if (ob_src->lightgroup) {
|
||||
ob_dst->lightgroup = (LightgroupMembership *)MEM_dupallocN(ob_src->lightgroup);
|
||||
}
|
||||
|
||||
if ((flag & LIB_ID_COPY_SET_COPIED_ON_WRITE) != 0) {
|
||||
if (ob_src->lightprobe_cache) {
|
||||
/* Reference the original object data. */
|
||||
ob_dst->lightprobe_cache = (LightProbeObjectCache *)MEM_dupallocN(ob_src->lightprobe_cache);
|
||||
ob_dst->lightprobe_cache->shared = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Do not copy lightprobe's cache. */
|
||||
ob_dst->lightprobe_cache = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void object_free_data(ID *id)
|
||||
|
@ -319,6 +331,8 @@ static void object_free_data(ID *id)
|
|||
BKE_previewimg_free(&ob->preview);
|
||||
|
||||
MEM_SAFE_FREE(ob->lightgroup);
|
||||
|
||||
BKE_lightprobe_cache_free(ob);
|
||||
}
|
||||
|
||||
static void library_foreach_modifiersForeachIDLink(void *user_data,
|
||||
|
@ -597,6 +611,11 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
|
|||
if (ob->lightgroup) {
|
||||
BLO_write_struct(writer, LightgroupMembership, ob->lightgroup);
|
||||
}
|
||||
|
||||
if (ob->lightprobe_cache) {
|
||||
BLO_write_struct(writer, LightProbeObjectCache, ob->lightprobe_cache);
|
||||
BKE_lightprobe_cache_blend_write(writer, ob->lightprobe_cache);
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX deprecated - old animation system */
|
||||
|
@ -815,6 +834,11 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
BKE_previewimg_blend_read(reader, ob->preview);
|
||||
|
||||
BLO_read_data_address(reader, &ob->lightgroup);
|
||||
|
||||
BLO_read_data_address(reader, &ob->lightprobe_cache);
|
||||
if (ob->lightprobe_cache) {
|
||||
BKE_lightprobe_cache_blend_read(reader, ob->lightprobe_cache);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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_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_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_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(TEXTURE_OT_new);
|
||||
WM_operatortype_append(WORLD_OT_new);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "BKE_image.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lightprobe.h"
|
||||
#include "BKE_linestyle.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_material.h"
|
||||
|
@ -53,6 +54,7 @@
|
|||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_build.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#ifdef WITH_FREESTYLE
|
||||
# include "BKE_freestyle.h"
|
||||
|
@ -1332,6 +1334,8 @@ enum {
|
|||
LIGHTCACHE_SUBSET_ALL = 0,
|
||||
LIGHTCACHE_SUBSET_DIRTY,
|
||||
LIGHTCACHE_SUBSET_CUBE,
|
||||
LIGHTCACHE_SUBSET_SELECTED,
|
||||
LIGHTCACHE_SUBSET_ACTIVE,
|
||||
};
|
||||
|
||||
static void light_cache_bake_tag_cache(Scene *scene, wmOperator *op)
|
||||
|
@ -1348,6 +1352,9 @@ static void light_cache_bake_tag_cache(Scene *scene, wmOperator *op)
|
|||
case LIGHTCACHE_SUBSET_DIRTY:
|
||||
/* Leave tag untouched. */
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1492,6 +1499,169 @@ void SCENE_OT_light_cache_bake(wmOperatorType *ot)
|
|||
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
/* NOTE: New version destined to replace the old lightcache bake operator. */
|
||||
|
||||
static void lightprobe_cache_bake_start(bContext *C, wmOperator *op)
|
||||
{
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
auto is_irradiance_volume = [](Object *ob) -> bool {
|
||||
return ob->type == OB_LIGHTPROBE &&
|
||||
static_cast<LightProbe *>(ob->data)->type == LIGHTPROBE_TYPE_GRID;
|
||||
};
|
||||
|
||||
auto irradiance_volume_setup = [](Object *ob) {
|
||||
BKE_lightprobe_cache_free(ob);
|
||||
BKE_lightprobe_cache_create(ob);
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
|
||||
};
|
||||
|
||||
int subset = RNA_enum_get(op->ptr, "subset");
|
||||
switch (subset) {
|
||||
case LIGHTCACHE_SUBSET_ALL: {
|
||||
FOREACH_OBJECT_BEGIN (scene, view_layer, ob) {
|
||||
if (is_irradiance_volume(ob)) {
|
||||
irradiance_volume_setup(ob);
|
||||
}
|
||||
}
|
||||
FOREACH_OBJECT_END;
|
||||
break;
|
||||
}
|
||||
case LIGHTCACHE_SUBSET_DIRTY: {
|
||||
FOREACH_OBJECT_BEGIN (scene, view_layer, ob) {
|
||||
if (is_irradiance_volume(ob) && ob->lightprobe_cache && ob->lightprobe_cache->dirty) {
|
||||
irradiance_volume_setup(ob);
|
||||
}
|
||||
}
|
||||
FOREACH_OBJECT_END;
|
||||
break;
|
||||
}
|
||||
case LIGHTCACHE_SUBSET_SELECTED: {
|
||||
uint objects_len = 0;
|
||||
ObjectsInViewLayerParams parameters;
|
||||
parameters.filter_fn = nullptr;
|
||||
parameters.no_dup_data = true;
|
||||
Object **objects = BKE_view_layer_array_selected_objects_params(
|
||||
view_layer, nullptr, &objects_len, ¶meters);
|
||||
for (Object *ob : blender::MutableSpan<Object *>(objects, objects_len)) {
|
||||
if (is_irradiance_volume(ob)) {
|
||||
irradiance_volume_setup(ob);
|
||||
}
|
||||
}
|
||||
MEM_freeN(objects);
|
||||
break;
|
||||
}
|
||||
case LIGHTCACHE_SUBSET_ACTIVE: {
|
||||
Object *active_ob = CTX_data_active_object(C);
|
||||
if (is_irradiance_volume(active_ob)) {
|
||||
irradiance_volume_setup(active_ob);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int lightprobe_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
lightprobe_cache_bake_start(C, op);
|
||||
|
||||
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 bake. */
|
||||
static int lightprobe_cache_bake_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
lightprobe_cache_bake_start(C, op);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void OBJECT_OT_lightprobe_cache_bake(wmOperatorType *ot)
|
||||
{
|
||||
static const EnumPropertyItem light_cache_subset_items[] = {
|
||||
{LIGHTCACHE_SUBSET_ALL, "ALL", 0, "All Light Probes", "Bake all light probes"},
|
||||
{LIGHTCACHE_SUBSET_DIRTY,
|
||||
"DIRTY",
|
||||
0,
|
||||
"Dirty Only",
|
||||
"Only bake light probes that are marked as dirty"},
|
||||
{LIGHTCACHE_SUBSET_SELECTED,
|
||||
"SELECTED",
|
||||
0,
|
||||
"Selected Only",
|
||||
"Only bake selected light probes"},
|
||||
{LIGHTCACHE_SUBSET_ACTIVE, "ACTIVE", 0, "Active Only", "Only bake the active light probe"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
/* 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);
|
||||
|
||||
ot->prop = RNA_def_enum(
|
||||
ot->srna, "subset", light_cache_subset_items, 0, "Subset", "Subset of probes to update");
|
||||
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -1541,6 +1711,49 @@ void SCENE_OT_light_cache_free(wmOperatorType *ot)
|
|||
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->lightprobe_cache != 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->lightprobe_cache == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BKE_lightprobe_cache_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;
|
||||
/** Object visibility group, inclusive or exclusive. */
|
||||
struct Collection *visibility_grp;
|
||||
|
||||
/* Runtime display data */
|
||||
float distfalloff, distgridinf;
|
||||
} LightProbe;
|
||||
|
||||
/* Probe->type */
|
||||
|
@ -201,6 +198,137 @@ enum {
|
|||
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 linear 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 {
|
||||
float *L0;
|
||||
float *L1_a;
|
||||
float *L1_b;
|
||||
float *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 LightProbeGridCacheFrame
|
||||
*
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* A frame worth of baked lighting data.
|
||||
*/
|
||||
typedef struct LightProbeGridCacheFrame {
|
||||
/** Number of samples in the highest level of detail. */
|
||||
int size[3];
|
||||
/** Spatial layout type of the data stored inside the data arrays. */
|
||||
int data_layout;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** In-progress baked data. Not stored in file. */
|
||||
LightProbeBakingData baking;
|
||||
/** Baked data. */
|
||||
LightProbeIrradianceData irradiance;
|
||||
LightProbeVisibilityData visibility;
|
||||
LightProbeConnectivityData connectivity;
|
||||
|
||||
char _pad[4];
|
||||
|
||||
/** Number of debug surfels. */
|
||||
int surfels_len;
|
||||
/** Debug surfels used to visualize the baking process. Not stored in file. */
|
||||
void *surfels;
|
||||
} LightProbeGridCacheFrame;
|
||||
|
||||
/** #LightProbeGridCacheFrame.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,
|
||||
};
|
||||
|
||||
/**
|
||||
* Per object container of baked data.
|
||||
* Should be called #LightProbeCache but name is already taken.
|
||||
*/
|
||||
typedef struct LightProbeObjectCache {
|
||||
/** Allow correct versioning / different types of data for the same layout. */
|
||||
int cache_type;
|
||||
/** True if this cache references the original object's cache. */
|
||||
char shared;
|
||||
/** True if the cache has been tagged for automatic baking. */
|
||||
char dirty;
|
||||
|
||||
char _pad0[2];
|
||||
|
||||
struct LightProbeGridCacheFrame *grid_static_cache;
|
||||
} LightProbeObjectCache;
|
||||
|
||||
/** #LightProbeObjectCache.type (int) */
|
||||
enum {
|
||||
/** Light cache was just created and is not yet baked. Keep as 0 for default value. */
|
||||
LIGHTPROBE_CACHE_TYPE_NONE = 0,
|
||||
/** Light cache is baked for one specific frame and capture all indirect lighting. */
|
||||
LIGHTPROBE_CACHE_TYPE_STATIC = 1,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,7 @@ struct FluidsimSettings;
|
|||
struct GeometrySet;
|
||||
struct Ipo;
|
||||
struct LightgroupMembership;
|
||||
struct LightProbeGridCacheFrame;
|
||||
struct Material;
|
||||
struct Mesh;
|
||||
struct Object;
|
||||
|
@ -449,6 +450,11 @@ typedef struct Object {
|
|||
/** Lightgroup membership information. */
|
||||
struct LightgroupMembership *lightgroup;
|
||||
|
||||
/** Irradiance caches baked for this object (light-probes only). */
|
||||
struct LightProbeObjectCache *lightprobe_cache;
|
||||
|
||||
void *_pad9;
|
||||
|
||||
/** Runtime evaluation data (keep last). */
|
||||
Object_Runtime runtime;
|
||||
} Object;
|
||||
|
|
Loading…
Reference in New Issue
scene referred -> scene linear (scene referred is a category of color spaces, scene linear is the specific one)