78 VolumeProbe &grid = volume_map_.lookup_or_add_default(handle.object_key);
80 if (handle.recalc != 0 || grid.initialized ==
false) {
81 const ::LightProbe *lightprobe =
static_cast<const ::
LightProbe *
>(ob->
data);
85 grid.surfel_density =
static_cast<const ::
LightProbe *
>(ob->
data)->grid_surfel_density;
86 grid.object_to_world = ob->object_to_world();
92 grid.normal_bias = lightprobe->grid_normal_bias;
93 grid.view_bias = lightprobe->grid_view_bias;
94 grid.facing_bias = lightprobe->grid_facing_bias;
96 grid.validity_threshold = lightprobe->grid_validity_threshold;
97 grid.dilation_threshold = lightprobe->grid_dilation_threshold;
98 grid.dilation_radius = lightprobe->grid_dilation_radius;
99 grid.intensity = lightprobe->intensity;
101 const bool has_valid_cache = grid.cache && grid.cache->grid_static_cache;
103 if (grid.viewport_display) {
104 int3 cache_size = grid.cache->grid_static_cache->size;
106 1.0f /
float3(cache_size + 1));
107 grid.viewport_display_size =
math::reduce_min(scale) * lightprobe->data_display_size;
115void LightProbeModule::sync_sphere(
const Object *ob, ObjectHandle &handle)
117 SphereProbe &cube = sphere_map_.lookup_or_add_default(handle.object_key);
119 if (handle.recalc != 0 || cube.initialized ==
false) {
122 cube.initialized =
true;
124 cube.do_render =
true;
128 int subdivision_lvl = probe_module.subdivision_level_get(probe_resolution);
130 if (cube.atlas_coord.subdivision_lvl != subdivision_lvl) {
131 cube.atlas_coord.free();
132 cube.atlas_coord = find_empty_atlas_region(subdivision_lvl);
135 cube_data.atlas_coord = cube.atlas_coord.as_sampling_coord();
137 cube.use_for_render =
false;
141 float influence_distance = light_probe.distinf;
142 float influence_falloff = light_probe.falloff;
143 float parallax_distance = light_probe.distpar;
144 parallax_distance = use_custom_parallax ?
max_ff(parallax_distance, influence_distance) :
147 auto to_eevee_shape = [](
int bl_shape_type) {
150 cube.influence_shape = to_eevee_shape(light_probe.attenuation_type);
151 cube.parallax_shape = to_eevee_shape(use_custom_parallax ? light_probe.parallax_type :
152 light_probe.attenuation_type);
155 cube.location = object_to_world.location();
158 cube.influence_scale = 1.0 /
max_ff(1e-8f, influence_falloff);
159 cube.influence_bias = cube.influence_scale;
160 cube.parallax_distance = parallax_distance / influence_distance;
161 cube.clipping_distances =
float2(light_probe.clipsta, light_probe.clipend);
165 cube.viewport_display_size = light_probe.data_display_size *
math::reduce_add(scale / 3.0f);
169void LightProbeModule::sync_planar(
const Object *ob, ObjectHandle &handle)
171 PlanarProbe &plane = planar_map_.lookup_or_add_default(handle.object_key);
173 if (handle.recalc != 0 || plane.initialized ==
false) {
176 plane.initialized =
true;
177 plane.updated =
true;
178 plane.plane_to_world = ob->object_to_world();
179 plane.plane_to_world.z_axis() =
math::normalize(plane.plane_to_world.z_axis()) *
180 light_probe->distinf;
181 plane.world_to_plane =
math::invert(plane.plane_to_world);
182 plane.clipping_offset = light_probe->clipsta;
189 const ::LightProbe *lightprobe =
static_cast<const ::
LightProbe *
>(ob->
data);
190 switch (lightprobe->type) {
192 sync_sphere(ob, handle);
195 sync_planar(ob, handle);
198 sync_volume(ob, handle);
207 world->probe_resolution);
210 int subdivision_lvl = sph_module.subdivision_level_get(probe_resolution);
214 world_sphere_.
atlas_coord = find_empty_atlas_region(subdivision_lvl);
228 volume_update_ =
false;
231 bool remove_grid = !grid.used;
232 if (grid.updated || remove_grid) {
233 volume_update_ = true;
235 grid.updated =
false;
241 sphere_update_ =
false;
244 bool remove_cube = !cube.
used;
245 if (cube.
updated || remove_cube) {
246 sphere_update_ =
true;
254 planar_update_ =
false;
257 bool remove_plane = !plane.used;
258 if (plane.updated || remove_plane) {
259 planar_update_ =
true;
261 plane.updated =
false;
269 int layer_count = sphere_layer_count();
272 location_finder.mark_space_used(world_sphere_.
atlas_coord);
273 for (
const SphereProbe &probe : sphere_map_.values()) {
274 location_finder.mark_space_used(probe.atlas_coord);
276 return location_finder.first_free_spot();
279int LightProbeModule::sphere_layer_count()
const
282 for (
const SphereProbe &probe : sphere_map_.values()) {
283 max_layer =
max_ii(max_layer, probe.atlas_coord.atlas_layer);
285 int layer_count = max_layer + 1;
296 int subdivision_level)
298 subdivision_level_ = subdivision_level;
299 areas_per_dimension_ = 1 << subdivision_level_;
300 areas_per_layer_ =
square_i(areas_per_dimension_);
303 int area_len = (allocated_layer_count + 1) * areas_per_layer_;
304 areas_occupancy_.
resize(area_len,
false);
317 const int2 pos_in_location_finder = (coord.
area_location() >> shift_right) << shift_left;
319 const int layer_offset = coord.
atlas_layer * areas_per_layer_;
320 const int areas_overlapped_per_dim = 1 << shift_left;
321 for (
const int y :
IndexRange(areas_overlapped_per_dim)) {
322 for (
const int x :
IndexRange(areas_overlapped_per_dim)) {
323 const int2 pos = pos_in_location_finder +
int2(x, y);
325 areas_occupancy_[
area_index + layer_offset].set();
334 for (
int index : areas_occupancy_.index_range()) {
335 if (!areas_occupancy_[index]) {
336 result.atlas_layer = index / areas_per_layer_;
337 result.area_index = index % areas_per_layer_;
348 std::ostream &os = std::cout;
349 int layer = 0, row = 0, column = 0;
350 os <<
"subdivision " << subdivision_level_ <<
"\n";
351 for (
bool spot_taken : areas_occupancy_) {
352 if (row == 0 && column == 0) {
353 os <<
"layer " << layer <<
"\n";
355 os << (spot_taken ?
'X' :
'-');
357 if (column == areas_per_dimension_) {
362 if (row == areas_per_dimension_) {
#define BLI_assert_unreachable()
MINLINE float max_ff(float a, float b)
MINLINE int square_i(int a)
MINLINE int max_ii(int a, int b)
@ LIGHTPROBE_FLAG_SHOW_DATA
@ LIGHTPROBE_FLAG_CUSTOM_PARALLAX
@ LIGHT_PROBE_RESOLUTION_128
@ LIGHT_PROBE_RESOLUTION_512
@ LIGHT_PROBE_RESOLUTION_4096
@ LIGHT_PROBE_RESOLUTION_256
@ LIGHT_PROBE_RESOLUTION_2048
@ LIGHT_PROBE_RESOLUTION_1024
void resize(const int64_t new_size_in_bits, const bool value=false)
A running instance of the engine.
VolumeProbeModule volume_probes
SphereProbeModule sphere_probes
void sync_world(const ::World *world, bool has_update)
friend class SphereProbeModule
void sync_probe(const Object *ob, ObjectHandle &handle)
LightProbeModule(Instance &inst)
void mark_space_used(const SphereProbeAtlasCoord &coord)
LocationFinder(int allocated_layer_count, int subdivision_level)
SphereProbeAtlasCoord first_free_spot() const
void bricks_free(Vector< IrradianceBrickPacked > &bricks)
Simple API to draw debug shapes and log in the viewport.
static eLightProbeResolution resolution_to_probe_resolution_enum(int resolution)
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
T reduce_min(const VecBase< T, Size > &a)
CartesianBasis invert(const CartesianBasis &basis)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< T, 3 > to_scale(const MatBase< T, NumCol, NumRow > &mat)
VecBase< T, 3 > transform_direction(const MatBase< T, 3, 3 > &mat, const VecBase< T, 3 > &direction)
T reduce_add(const VecBase< T, Size > &a)
T determinant(const MatBase< T, Size, Size > &mat)
MatBase< float, 4, 4 > float4x4
MatBase< float, 3, 4 > float3x4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
MatBase< float, 3, 3 > float3x3
struct LightProbeObjectCache * lightprobe_cache
int gi_cubemap_resolution
static MatBase identity()
int2 area_location() const
SphereProbeUvArea as_sampling_coord() const
LightProbeShape parallax_shape
float3x4 world_to_probe_transposed
SphereProbeUvArea atlas_coord
LightProbeShape influence_shape
float2 clipping_distances
SphereProbeAtlasCoord atlas_coord