EEVEE-Next: Simplify sphere lightprobe coordinates

The storage coordinate is left unchanged and is
kept as `ReflectionProbeAtlasCoordinate`.
A new structure `ReflectionProbeCoordinate`
contain scale and offset for efficient sampling
without integer math.
The `ReflectionProbeWriteCoordinate` is only used
during the octahedral map processing.

This also has the benefit to centralize the coordinate
changes to a single class.

Pull Request: https://projects.blender.org/blender/blender/pulls/117011
This commit is contained in:
Clément Foucault
2024-01-13 02:59:36 +01:00
committed by Clément Foucault
parent dd0482da76
commit 29ec924f9f
11 changed files with 244 additions and 179 deletions

View File

@@ -825,8 +825,10 @@ void IrradianceBake::surfels_create(const Object &probe_object)
capture_info_buf_.capture_indirect = capture_indirect_;
capture_info_buf_.capture_emission = capture_emission_;
ReflectionProbeAtlasCoordinate atlas_coord = inst_.reflection_probes.world_atlas_coord_get();
capture_info_buf_.world_atlas_coord = *reinterpret_cast<int4 *>(&atlas_coord);
ReflectionProbeModule &reflections = inst_.reflection_probes;
ReflectionProbeAtlasCoordinate atlas_coord = reflections.world_atlas_coord_get();
ReflectionProbeCoordinate coord = atlas_coord.as_sampling_coord(reflections.atlas_extent());
capture_info_buf_.world_atlas_coord = coord;
dispatch_per_grid_sample_ = math::divide_ceil(grid_resolution, int3(IRRADIANCE_GRID_GROUP_SIZE));
capture_info_buf_.irradiance_grid_size = grid_resolution;

View File

@@ -177,9 +177,12 @@ void ReflectionProbeModule::init()
pass.init();
pass.shader_set(instance_.shaders.static_shader_get(REFLECTION_PROBE_REMAP));
pass.bind_texture("cubemap_tx", &cubemap_tx_);
pass.bind_image("octahedral_img", &probes_tx_);
pass.push_constant("probe_coord_packed", reinterpret_cast<int4 *>(&reflection_probe_coord_));
pass.push_constant("world_coord_packed", reinterpret_cast<int4 *>(&world_probe_coord_));
pass.bind_image("atlas_dst_mip_img", &atlas_dst_mip_tx_);
pass.bind_image("atlas_src_mip_img", &atlas_src_mip_tx_);
pass.push_constant("probe_coord_packed", reinterpret_cast<int4 *>(&probe_sampling_coord_));
pass.push_constant("write_coord_packed", reinterpret_cast<int4 *>(&probe_write_coord_));
pass.push_constant("world_coord_packed", reinterpret_cast<int4 *>(&world_write_coord_));
pass.push_constant("mip_level", &probe_mip_level_);
pass.dispatch(&dispatch_probe_pack_);
}
@@ -187,7 +190,7 @@ void ReflectionProbeModule::init()
PassSimple &pass = update_irradiance_ps_;
pass.init();
pass.shader_set(instance_.shaders.static_shader_get(REFLECTION_PROBE_UPDATE_IRRADIANCE));
pass.push_constant("world_coord_packed", reinterpret_cast<int4 *>(&world_probe_coord_));
pass.push_constant("world_coord_packed", reinterpret_cast<int4 *>(&world_sampling_coord_));
pass.bind_image("irradiance_atlas_img", &instance_.irradiance_cache.irradiance_atlas_tx_);
pass.bind_texture("reflection_probes_tx", &probes_tx_);
pass.dispatch(int2(1, 1));
@@ -248,7 +251,7 @@ void ReflectionProbeModule::sync_world(::World *world)
probe.atlas_coord = find_empty_atlas_region(layer_subdivision);
do_world_update_set(true);
}
world_probe_coord_ = probe.atlas_coord;
world_sampling_coord_ = probe.atlas_coord.as_sampling_coord(atlas_extent());
}
void ReflectionProbeModule::sync_world_lookdev()
@@ -260,7 +263,7 @@ void ReflectionProbeModule::sync_world_lookdev()
if (layer_subdivision != probe.atlas_coord.layer_subdivision) {
probe.atlas_coord = find_empty_atlas_region(layer_subdivision);
}
world_probe_coord_ = probe.atlas_coord;
world_sampling_coord_ = probe.atlas_coord.as_sampling_coord(atlas_extent());
do_world_update_set(true);
}
@@ -465,11 +468,21 @@ std::optional<ReflectionProbeUpdateInfo> ReflectionProbeModule::update_info_pop(
void ReflectionProbeModule::remap_to_octahedral_projection(
const ReflectionProbeAtlasCoordinate &atlas_coord)
{
ReflectionProbe &world_probe = probes_.lookup(world_object_key_);
int world_layer_subdivision = world_probe.atlas_coord.layer_subdivision;
int resolution = max_resolution_ >> atlas_coord.layer_subdivision;
/* Update shader parameters that change per dispatch. */
reflection_probe_coord_ = atlas_coord;
probe_sampling_coord_ = atlas_coord.as_sampling_coord(atlas_extent());
probe_write_coord_ = atlas_coord.as_write_coord(atlas_extent(), 0);
probe_mip_level_ = atlas_coord.layer_subdivision;
world_write_coord_ = world_probe.atlas_coord.as_write_coord(atlas_extent(), probe_mip_level_);
dispatch_probe_pack_ = int3(int2(ceil_division(resolution, REFLECTION_PROBE_GROUP_SIZE)), 1);
probes_tx_.ensure_mip_views();
atlas_dst_mip_tx_ = probes_tx_.mip_view(0);
atlas_src_mip_tx_ = probes_tx_.mip_view(probe_mip_level_ - world_layer_subdivision);
instance_.manager->submit(remap_ps_);
}
@@ -491,7 +504,7 @@ void ReflectionProbeModule::set_view(View & /*view*/)
if (reflection_probe_count_ >= REFLECTION_PROBES_MAX - 1) {
break;
}
probe.recalc_lod_factors(probes_tx_.width());
probe.prepare_for_upload(atlas_extent());
/* World is always considered active and added last. */
if (probe.type == ReflectionProbe::Type::WORLD) {
continue;

View File

@@ -28,7 +28,68 @@ struct ReflectionProbeUpdateInfo;
/** \name Reflection Probe
* \{ */
struct ReflectionProbeAtlasCoordinate {
/** On which layer of the texture array is this reflection probe stored. */
int layer = -1;
/**
* Subdivision of the layer. 0 = no subdivision and resolution would be
* ReflectionProbeModule::MAX_RESOLUTION.
*/
int layer_subdivision = -1;
/**
* Which area of the subdivided layer is the reflection probe located.
*
* A layer has (2^layer_subdivision)^2 areas.
*/
int area_index = -1;
/* Return the area extent in pixel. */
int area_extent(int atlas_extent) const
{
return atlas_extent >> layer_subdivision;
}
/* Coordinate of the area in [0..area_count_per_dimension[ range. */
int2 area_location() const
{
const int area_count_per_dimension = 1 << layer_subdivision;
return int2(area_index % area_count_per_dimension, area_index / area_count_per_dimension);
}
/* Coordinate of the bottom left corner of the area in [0..atlas_extent[ range. */
int2 area_offset(int atlas_extent) const
{
return area_location() * area_extent(atlas_extent);
}
ReflectionProbeCoordinate as_sampling_coord(int atlas_extent) const
{
const int area_count_per_dimension = 1 << layer_subdivision;
const float area_scale = 1.0f / area_count_per_dimension;
const float2 area_location = float2(this->area_location());
float texel_size = 1.0f / atlas_extent;
float border_size = REFLECTION_PROBE_BORDER_SIZE * texel_size;
ReflectionProbeCoordinate coord;
coord.offset = (border_size + 0.5f * texel_size + area_location) * area_scale;
coord.scale = (1.0f - 2.0f * border_size) * area_scale;
coord.layer = layer;
return coord;
}
ReflectionProbeWriteCoordinate as_write_coord(int atlas_extent, int mip_lvl) const
{
ReflectionProbeWriteCoordinate coord;
coord.extent = atlas_extent >> (layer_subdivision + mip_lvl);
coord.offset = (area_location() * coord.extent) >> mip_lvl;
coord.layer = layer;
return coord;
}
};
struct ReflectionProbe : ReflectionProbeData {
public:
enum class Type {
WORLD,
PROBE,
@@ -57,19 +118,19 @@ struct ReflectionProbe : ReflectionProbeData {
bool viewport_display;
float viewport_display_size;
ReflectionProbe()
{
this->atlas_coord.layer_subdivision = -1;
this->atlas_coord.layer = -1;
this->atlas_coord.area_index = -1;
}
ReflectionProbeAtlasCoordinate atlas_coord;
void recalc_lod_factors(int atlas_resolution)
void prepare_for_upload(int atlas_extent)
{
const float probe_resolution = atlas_resolution >> atlas_coord.layer_subdivision;
/* Compute LOD factor. */
const int probe_resolution = atlas_coord.area_extent(atlas_extent);
const float bias = 0.0;
const float lod_factor = bias + 0.5 * log(float(square_i(probe_resolution))) / log(2.0);
const float lod_factor = bias + 0.5 * log2f(square_i(probe_resolution));
this->lod_factor = lod_factor;
/* Compute sampling offset and scale. */
static_cast<ReflectionProbeData *>(this)->atlas_coord = atlas_coord.as_sampling_coord(
atlas_extent);
}
};
@@ -97,10 +158,11 @@ class ReflectionProbeModule {
ReflectionProbeDataBuf data_buf_;
ReflectionProbes probes_;
ReflectionProbe world_probe_data;
/** Probes texture stored in octahedral mapping. */
Texture probes_tx_ = {"Probes"};
/* Reference to a specific mip map layer of a texture. */
GPUTexture *atlas_dst_mip_tx_ = nullptr;
GPUTexture *atlas_src_mip_tx_ = nullptr;
PassSimple remap_ps_ = {"Probe.CubemapToOctahedral"};
PassSimple update_irradiance_ps_ = {"Probe.UpdateIrradiance"};
@@ -116,11 +178,15 @@ class ReflectionProbeModule {
*/
Texture cubemap_tx_ = {"Probe.Cubemap"};
/** Index of the probe being updated. */
int reflection_probe_index_ = 0;
int probe_index_ = 0;
/** Mip level being sampled for remapping. */
int probe_mip_level_ = 0;
/** Updated Probe coordinates in the atlas. */
ReflectionProbeAtlasCoordinate reflection_probe_coord_;
ReflectionProbeCoordinate probe_sampling_coord_;
ReflectionProbeWriteCoordinate probe_write_coord_;
/** World coordinates in the atlas. */
ReflectionProbeAtlasCoordinate world_probe_coord_;
ReflectionProbeCoordinate world_sampling_coord_;
ReflectionProbeWriteCoordinate world_write_coord_;
/** Number of the probe to process in the select phase. */
int reflection_probe_count_ = 0;
@@ -158,6 +224,11 @@ class ReflectionProbeModule {
void debug_print() const;
int atlas_extent() const
{
return probes_tx_.width();
}
ReflectionProbeAtlasCoordinate world_atlas_coord_get() const;
private:

View File

@@ -1013,6 +1013,83 @@ BLI_STATIC_ASSERT_ALIGN(ShadowSceneData, 16)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Lightprobe Sphere
* \{ */
struct ReflectionProbeLowFreqLight {
packed_float3 direction;
float ambient;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeLowFreqLight, 16)
enum LightProbeShape : uint32_t {
SHAPE_ELIPSOID = 0u,
SHAPE_CUBOID = 1u,
};
struct ReflectionProbeCoordinate {
/* Offset in UV space to the start of the sampling space of the octahedron map. */
float2 offset;
/* Scaling of the squared UV space of the octahedron map. */
float scale;
/* Layer of the atlas where the octahedron map is stored. */
float layer;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeCoordinate, 16)
struct ReflectionProbeWriteCoordinate {
/* Offset in pixel space to the start of the writing space of the octahedron map.
* Note that the writing space is not the same as the sampling space as we have borders. */
int2 offset;
/* Size of the area in pixel that is covered by this probe mip-map. */
int extent;
/* Layer of the atlas where the octahedron map is stored. */
int layer;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeWriteCoordinate, 16)
/** Mapping data to locate a reflection probe in texture. */
struct ReflectionProbeData {
/** Transform to probe local position with non-uniform scaling. */
float3x4 world_to_probe_transposed;
packed_float3 location;
float _pad2;
/** Shape of the parallax projection. */
LightProbeShape parallax_shape;
LightProbeShape influence_shape;
float parallax_distance;
/** Influence factor based on the distance to the parallax shape. */
float influence_scale;
float influence_bias;
/** LOD factor for mipmap selection. */
float lod_factor;
float _pad0;
float _pad1;
ReflectionProbeCoordinate atlas_coord;
/**
* Irradiance at the probe location encoded as spherical harmonics.
* Only contain the average luminance. Used for cube-map normalization.
*/
ReflectionProbeLowFreqLight low_freq_light;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeData, 16)
/** Viewport Display Pass. */
struct ReflectionProbeDisplayData {
int probe_index;
float display_size;
float _pad0;
float _pad1;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeDisplayData, 16)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Irradiance Cache
* \{ */
@@ -1105,8 +1182,7 @@ struct CaptureInfoData {
bool1 capture_emission;
int _pad0;
/* World light probe atlas coordinate. */
/* TODO(fclem): Remove this silly aliasing. */
int4 world_atlas_coord;
ReflectionProbeCoordinate world_atlas_coord;
};
BLI_STATIC_ASSERT_ALIGN(CaptureInfoData, 16)
@@ -1323,77 +1399,9 @@ static inline float3 burley_eval(float3 d, float r)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Reflection Probes
/** \name Lightprobe Planar Data
* \{ */
struct ReflectionProbeLowFreqLight {
packed_float3 direction;
float ambient;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeLowFreqLight, 16)
enum LightProbeShape : uint32_t {
SHAPE_ELIPSOID = 0u,
SHAPE_CUBOID = 1u,
};
struct ReflectionProbeAtlasCoordinate {
/** On which layer of the texture array is this reflection probe stored. */
int layer;
/**
* Subdivision of the layer. 0 = no subdivision and resolution would be
* ReflectionProbeModule::MAX_RESOLUTION.
*/
int layer_subdivision;
/**
* Which area of the subdivided layer is the reflection probe located.
*
* A layer has (2^layer_subdivision)^2 areas.
*/
int area_index;
int _pad1;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeAtlasCoordinate, 16)
/** Mapping data to locate a reflection probe in texture. */
struct ReflectionProbeData {
/** Transform to probe local position with non-uniform scaling. */
float3x4 world_to_probe_transposed;
packed_float3 location;
float _pad2;
/** Shape of the parallax projection. */
LightProbeShape parallax_shape;
LightProbeShape influence_shape;
float parallax_distance;
/** Influence factor based on the distance to the parallax shape. */
float influence_scale;
float influence_bias;
/** LOD factor for mipmap selection. */
float lod_factor;
float _pad0;
float _pad1;
ReflectionProbeAtlasCoordinate atlas_coord;
/**
* Irradiance at the probe location encoded as spherical harmonics.
* Only contain the average luminance. Used for cube-map normalization.
*/
ReflectionProbeLowFreqLight low_freq_light;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeData, 16)
/** Viewport Display Pass. */
struct ReflectionProbeDisplayData {
int probe_index;
float display_size;
float _pad0;
float _pad1;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeDisplayData, 16)
struct ProbePlanarData {
/** Matrices used to render the planar capture. */
float4x4 viewmat;
@@ -1424,6 +1432,7 @@ struct ProbePlanarDisplayData {
BLI_STATIC_ASSERT_ALIGN(ProbePlanarDisplayData, 16)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Pipeline Data
* \{ */
@@ -1437,6 +1446,7 @@ struct PipelineInfoData {
BLI_STATIC_ASSERT_ALIGN(PipelineInfoData, 16)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Uniform Data
* \{ */

View File

@@ -67,10 +67,7 @@ void irradiance_capture_world(vec3 L, inout SphericalHarmonicL1 sh)
float visibility = 0.0;
if (capture_info_buf.capture_world_direct) {
ReflectionProbeAtlasCoordinate atlas_coord = reinterpret_as_atlas_coord(
capture_info_buf.world_atlas_coord);
radiance = reflection_probes_sample(L, 0.0, atlas_coord).rgb;
radiance = reflection_probes_sample(L, 0.0, capture_info_buf.world_atlas_coord).rgb;
/* Clamped brightness. */
float luma = max(1e-8, reduce_max(radiance));

View File

@@ -37,28 +37,6 @@ vec3 octahedral_uv_to_direction(vec2 co)
return v;
}
/**
* Return the UV coordinates on the packed octahedral texture layer when applying the given
* octahedral_uv to a specific probe.
*/
vec2 octahedral_uv_to_layer_texture_coords(vec2 octahedral_uv,
ReflectionProbeAtlasCoordinate atlas_coord,
vec2 texel_size)
{
/* Fix artifacts near edges. Proved one texel on each side. */
octahedral_uv = octahedral_uv * (1.0 - 2.0 * REFLECTION_PROBE_BORDER_SIZE * texel_size) +
REFLECTION_PROBE_BORDER_SIZE * texel_size + 0.5 * texel_size;
int areas_per_dimension = 1 << atlas_coord.layer_subdivision;
vec2 area_scalar = vec2(1.0 / float(areas_per_dimension));
octahedral_uv *= area_scalar;
vec2 area_offset = vec2(atlas_coord.area_index % areas_per_dimension,
atlas_coord.area_index / areas_per_dimension) *
area_scalar;
return octahedral_uv + area_offset;
}
/**
* Return the octahedral uv coordinates for the given texture uv coordinate on the packed
* octahedral texture layer for the given probe.
@@ -67,7 +45,6 @@ vec2 octahedral_uv_to_layer_texture_coords(vec2 octahedral_uv,
* NOTE: Doesn't apply the translation part of the packing.
*/
vec2 octahedral_uv_from_layer_texture_coords(vec2 uv, vec2 texel_size)
{
/* Apply border region. */
vec2 shrinked_uv = (uv - REFLECTION_PROBE_BORDER_SIZE * texel_size) /
@@ -78,14 +55,3 @@ vec2 octahedral_uv_from_layer_texture_coords(vec2 uv, vec2 texel_size)
bool is_even = ((checker_pos.x + checker_pos.y) & 1) == 0;
return is_even ? fract(shrinked_uv) : vec2(1.0) - fract(shrinked_uv);
}
/* TODO(fclem): Find something better than this. Has no place here but its shared with files that
* needs it. */
ReflectionProbeAtlasCoordinate reinterpret_as_atlas_coord(ivec4 packed_coord)
{
ReflectionProbeAtlasCoordinate unpacked;
unpacked.layer = packed_coord.x;
unpacked.layer_subdivision = packed_coord.y;
unpacked.area_index = packed_coord.z;
return unpacked;
}

View File

@@ -7,12 +7,9 @@
#pragma BLENDER_REQUIRE(eevee_spherical_harmonics_lib.glsl)
#ifdef REFLECTION_PROBE
vec4 reflection_probes_sample(vec3 L, float lod, ReflectionProbeAtlasCoordinate atlas_coord)
vec4 reflection_probes_sample(vec3 L, float lod, ReflectionProbeCoordinate atlas_coord)
{
vec2 octahedral_uv_packed = octahedral_uv_from_direction(L);
vec2 texel_size = vec2(1.0 / float(1 << (11 - atlas_coord.layer_subdivision)));
vec2 octahedral_uv = octahedral_uv_to_layer_texture_coords(
octahedral_uv_packed, atlas_coord, texel_size);
vec2 octahedral_uv = octahedral_uv_from_direction(L) * atlas_coord.scale + atlas_coord.offset;
return textureLod(reflection_probes_tx, vec3(octahedral_uv, atlas_coord.layer), lod);
}
#endif

View File

@@ -6,55 +6,58 @@
#pragma BLENDER_REQUIRE(eevee_octahedron_lib.glsl)
ivec2 probe_area_offset(ReflectionProbeAtlasCoordinate atlas_coord, ivec3 texture_size)
ReflectionProbeCoordinate reinterpret_as_atlas_coord(ivec4 packed_coord)
{
ivec2 octahedral_size = ivec2(texture_size.x >> atlas_coord.layer_subdivision,
texture_size.y >> atlas_coord.layer_subdivision);
int probes_per_dimension = 1 << atlas_coord.layer_subdivision;
ivec2 area_coord = ivec2(atlas_coord.area_index % probes_per_dimension,
atlas_coord.area_index / probes_per_dimension);
ivec2 area_offset = area_coord * octahedral_size;
return area_offset;
ReflectionProbeCoordinate unpacked;
unpacked.offset = intBitsToFloat(packed_coord.xy);
unpacked.scale = intBitsToFloat(packed_coord.z);
unpacked.layer = intBitsToFloat(packed_coord.w);
return unpacked;
}
ReflectionProbeWriteCoordinate reinterpret_as_write_coord(ivec4 packed_coord)
{
ReflectionProbeWriteCoordinate unpacked;
unpacked.offset = packed_coord.xy;
unpacked.extent = packed_coord.z;
unpacked.layer = packed_coord.w;
return unpacked;
}
void main()
{
ReflectionProbeAtlasCoordinate probe_coord = reinterpret_as_atlas_coord(probe_coord_packed);
ReflectionProbeAtlasCoordinate world_coord = reinterpret_as_atlas_coord(world_coord_packed);
ReflectionProbeCoordinate sample_coord = reinterpret_as_atlas_coord(probe_coord_packed);
ReflectionProbeWriteCoordinate write_coord = reinterpret_as_write_coord(write_coord_packed);
ReflectionProbeWriteCoordinate world_coord = reinterpret_as_write_coord(world_coord_packed);
ivec3 texture_coord = ivec3(gl_GlobalInvocationID.xyz);
ivec3 texture_size = imageSize(octahedral_img);
/* Texel in probe. */
ivec2 local_texel = ivec2(gl_GlobalInvocationID.xy);
ivec3 octahedral_coord = ivec3(gl_GlobalInvocationID.xyz);
ivec2 octahedral_size = texture_size.xy >> probe_coord.layer_subdivision;
/* Exit when pixel being written doesn't fit in the area reserved for the probe. */
if (any(greaterThanEqual(octahedral_coord.xy, octahedral_size.xy))) {
if (any(greaterThanEqual(local_texel, ivec2(write_coord.extent)))) {
return;
}
vec2 texel_size = vec2(1.0) / vec2(octahedral_size);
vec2 uv = vec2(octahedral_coord.xy) / vec2(octahedral_size.xy);
vec2 octahedral_uv = octahedral_uv_from_layer_texture_coords(uv, texel_size);
vec3 R = octahedral_uv_to_direction(octahedral_uv);
vec4 col = textureLod(cubemap_tx, R, float(probe_coord.layer_subdivision));
/* Texel in probe atlas. */
ivec2 texel = local_texel + write_coord.offset;
/* UV in probe atlas. */
vec2 atlas_uv = (vec2(texel) + 0.5) / vec2(imageSize(atlas_dst_mip_img).xy);
/* UV in sampling area. */
vec2 sampling_uv = (atlas_uv - sample_coord.offset) / sample_coord.scale;
/* Direction in world space. */
vec3 direction = octahedral_uv_to_direction(sampling_uv);
vec4 col = textureLod(cubemap_tx, direction, float(mip_level));
/* Convert transmittance to transparency. */
col.a = 1.0 - col.a;
/* Composite world into reflection probes. */
bool is_world = all(equal(probe_coord_packed, world_coord_packed));
bool is_world = all(equal(write_coord_packed, world_coord_packed));
if (!is_world && col.a != 1.0) {
vec2 world_octahedral_size = vec2(texture_size.x >> world_coord.layer_subdivision,
texture_size.y >> world_coord.layer_subdivision);
ivec3 world_octahedral_coord = ivec3(ivec2(uv * world_octahedral_size), 0.0);
ivec2 world_area_offset = probe_area_offset(world_coord, texture_size);
vec4 world_col = imageLoad(
octahedral_img, world_octahedral_coord + ivec3(world_area_offset, world_coord.layer));
ivec2 world_texel = local_texel + world_coord.offset;
vec4 world_col = imageLoad(atlas_src_mip_img, ivec3(world_texel, world_coord.layer));
col.rgb = mix(world_col.rgb, col.rgb, col.a);
}
ivec2 area_offset = probe_area_offset(probe_coord, texture_size);
imageStore(octahedral_img, octahedral_coord + ivec3(area_offset, probe_coord.layer), col);
imageStore(atlas_dst_mip_img, ivec3(texel, write_coord.layer), col);
}

View File

@@ -9,6 +9,15 @@
#pragma BLENDER_REQUIRE(eevee_octahedron_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
ReflectionProbeCoordinate reinterpret_as_atlas_coord(ivec4 packed_coord)
{
ReflectionProbeCoordinate unpacked;
unpacked.offset = intBitsToFloat(packed_coord.xy);
unpacked.scale = intBitsToFloat(packed_coord.z);
unpacked.layer = intBitsToFloat(packed_coord.w);
return unpacked;
}
void atlas_store(vec4 sh_coefficient, ivec2 atlas_coord, int layer)
{
for (int x = 0; x < IRRADIANCE_GRID_BRICK_SIZE; x++) {
@@ -33,11 +42,8 @@ void main()
cooef.L1.M0 = vec4(0.0);
cooef.L1.Mp1 = vec4(0.0);
ReflectionProbeAtlasCoordinate atlas_coord = reinterpret_as_atlas_coord(world_coord_packed);
const int subdivision_64 = 5;
float layer_mipmap = clamp(
subdivision_64 - atlas_coord.layer_subdivision, 0, REFLECTION_PROBE_MIPMAP_LEVELS);
ReflectionProbeCoordinate atlas_coord = reinterpret_as_atlas_coord(world_coord_packed);
float layer_mipmap = 5;
/* Perform multiple sample. */
uint store_index = gl_LocalInvocationID.x;
float total_samples = float(gl_WorkGroupSize.x * REFLECTION_PROBE_SH_SAMPLES_PER_GROUP);

View File

@@ -88,10 +88,7 @@ void radiance_transfer_world(inout Surfel receiver, vec3 L)
float visibility = 0.0;
if (capture_info_buf.capture_world_indirect) {
ReflectionProbeAtlasCoordinate atlas_coord = reinterpret_as_atlas_coord(
capture_info_buf.world_atlas_coord);
radiance = reflection_probes_sample(L, 0.0, atlas_coord).rgb;
radiance = reflection_probes_sample(L, 0.0, capture_info_buf.world_atlas_coord).rgb;
}
if (capture_info_buf.capture_visibility_indirect) {

View File

@@ -20,9 +20,12 @@ GPU_SHADER_CREATE_INFO(eevee_reflection_probe_data)
GPU_SHADER_CREATE_INFO(eevee_reflection_probe_remap)
.local_group_size(REFLECTION_PROBE_GROUP_SIZE, REFLECTION_PROBE_GROUP_SIZE)
.push_constant(Type::IVEC4, "probe_coord_packed")
.push_constant(Type::IVEC4, "write_coord_packed")
.push_constant(Type::IVEC4, "world_coord_packed")
.push_constant(Type::INT, "mip_level")
.sampler(0, ImageType::FLOAT_CUBE, "cubemap_tx")
.image(0, GPU_RGBA16F, Qualifier::READ_WRITE, ImageType::FLOAT_2D_ARRAY, "octahedral_img")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "atlas_dst_mip_img")
.image(1, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D_ARRAY, "atlas_src_mip_img")
.compute_source("eevee_reflection_probe_remap_comp.glsl")
.additional_info("eevee_shared")
.do_static_compilation(true);