Refactor: EEVEE-Next: Light-probe management and structure #117941

Merged
Clément Foucault merged 7 commits from fclem/blender:cleanup-eevee-next-lightprobe-classes into main 2024-02-08 19:48:37 +01:00
30 changed files with 232 additions and 231 deletions
Showing only changes of commit 88e0285862 - Show all commits

View File

@ -110,7 +110,7 @@ void Camera::sync()
if (inst_.is_baking()) {
/* Any view so that shadows and light culling works during irradiance bake. */
draw::View &view = inst_.irradiance_cache.bake.view_z_;
draw::View &view = inst_.volume_probes.bake.view_z_;
data.viewmat = view.viewmat();
data.viewinv = view.viewinv();
data.winmat = view.winmat();

View File

@ -30,7 +30,6 @@
#define CULLING_TILE_GROUP_SIZE 256
/* Reflection Probes. */
#define REFLECTION_PROBES_MAX 128
#define REFLECTION_PROBE_GROUP_SIZE 16
#define REFLECTION_PROBE_SELECT_GROUP_SIZE 64
/* Number of additional pixels on the border of an octahedral map to reserve for fixing seams.
@ -38,8 +37,17 @@
#define REFLECTION_PROBE_MIPMAP_LEVELS 5
#define REFLECTION_PROBE_SH_GROUP_SIZE 512
#define REFLECTION_PROBE_SH_SAMPLES_PER_GROUP 64
/**
* Limited by the UBO size limit (16384 bytes / sizeof(SphereProbeData)).
*/
#define REFLECTION_PROBE_MAX 128
#define PLANAR_PROBES_MAX 16
/**
* Limited by the performance impact it can cause.
* Limited by the max layer count supported by a hardware (256).
* Limited by the UBO size limit (16384 bytes / sizeof(ProbePlanarData)).
*/
#define PLANAR_PROBE_MAX 16
/**
* IMPORTANT: Some data packing are tweaked for these values.

View File

@ -18,7 +18,7 @@ namespace blender::eevee {
void HiZBuffer::sync()
{
int2 render_extent = inst_.film.render_extent_get();
int2 probe_extent = int2(inst_.reflection_probes.probe_render_extent());
int2 probe_extent = int2(inst_.sphere_probes.probe_render_extent());
/* Padding to avoid complexity during down-sampling and screen tracing. */
int2 hiz_extent = math::ceil_to_multiple(math::max(render_extent, probe_extent),
int2(1u << (HIZ_MIP_COUNT - 1)));

View File

@ -93,8 +93,8 @@ void Instance::init(const int2 &output_res,
light_probes.init();
planar_probes.init();
/* Irradiance Cache needs reflection probes to be initialized. */
reflection_probes.init();
irradiance_cache.init();
sphere_probes.init();
volume_probes.init();
volume.init();
lookdev.init(visible_rect);
}
@ -128,8 +128,8 @@ void Instance::init_light_bake(Depsgraph *depsgraph, draw::Manager *manager)
light_probes.init();
planar_probes.init();
/* Irradiance Cache needs reflection probes to be initialized. */
reflection_probes.init();
irradiance_cache.init();
sphere_probes.init();
volume_probes.init();
volume.init();
lookdev.init(&empty_rect);
}
@ -175,7 +175,7 @@ void Instance::begin_sync()
volume.begin_sync();
pipelines.begin_sync();
cryptomatte.begin_sync();
reflection_probes.begin_sync();
sphere_probes.begin_sync();
light_probes.begin_sync();
gpencil_engine_enabled = false;
@ -189,7 +189,7 @@ void Instance::begin_sync()
film.sync();
render_buffers.sync();
ambient_occlusion.sync();
irradiance_cache.sync();
volume_probes.sync();
lookdev.sync();
use_surfaces = (view_layer->layflag & SCE_LAY_SOLID) != 0;
@ -304,7 +304,7 @@ void Instance::end_sync()
cryptomatte.end_sync();
pipelines.end_sync();
light_probes.end_sync();
reflection_probes.end_sync();
sphere_probes.end_sync();
planar_probes.end_sync();
uniform_data.push_update();
@ -345,7 +345,7 @@ void Instance::render_sync()
bool Instance::do_reflection_probe_sync() const
{
if (!reflection_probes.update_probes_this_sample_) {
if (!sphere_probes.update_probes_this_sample_) {
return false;
}
if (materials.queued_shaders_count > 0) {
@ -630,7 +630,7 @@ void Instance::light_bake_irradiance(
context_disable();
};
irradiance_cache.bake.init(probe);
volume_probes.bake.init(probe);
custom_pipeline_wrapper([&]() {
manager->begin_sync();
@ -641,19 +641,19 @@ void Instance::light_bake_irradiance(
capture_view.render_world();
irradiance_cache.bake.surfels_create(probe);
volume_probes.bake.surfels_create(probe);
if (irradiance_cache.bake.should_break()) {
if (volume_probes.bake.should_break()) {
return;
}
irradiance_cache.bake.surfels_lights_eval();
volume_probes.bake.surfels_lights_eval();
irradiance_cache.bake.clusters_build();
irradiance_cache.bake.irradiance_offset();
volume_probes.bake.clusters_build();
volume_probes.bake.irradiance_offset();
});
if (irradiance_cache.bake.should_break()) {
if (volume_probes.bake.should_break()) {
return;
}
@ -668,9 +668,9 @@ void Instance::light_bake_irradiance(
for (int i = 0; i < 16 && !sampling.finished(); i++) {
sampling.step();
irradiance_cache.bake.raylists_build();
irradiance_cache.bake.propagate_light();
irradiance_cache.bake.irradiance_capture();
volume_probes.bake.raylists_build();
volume_probes.bake.propagate_light();
volume_probes.bake.irradiance_capture();
}
if (sampling.finished()) {
@ -680,11 +680,11 @@ void Instance::light_bake_irradiance(
LightProbeGridCacheFrame *cache_frame;
if (sampling.finished()) {
cache_frame = irradiance_cache.bake.read_result_packed();
cache_frame = volume_probes.bake.read_result_packed();
}
else {
/* TODO(fclem): Only do this read-back if needed. But it might be tricky to know when. */
cache_frame = irradiance_cache.bake.read_result_unpacked();
cache_frame = volume_probes.bake.read_result_unpacked();
}
float progress = sampling.sample_index() / float(sampling.sample_count());

View File

@ -86,8 +86,6 @@ class Instance {
LightModule lights;
AmbientOcclusion ambient_occlusion;
RayTraceModule raytracing;
ReflectionProbeModule reflection_probes;
PlanarProbeModule planar_probes;
VelocityModule velocity;
MotionBlurModule motion_blur;
DepthOfField depth_of_field;
@ -103,8 +101,10 @@ class Instance {
World world;
LookdevView lookdev_view;
LookdevModule lookdev;
SphereProbeModule sphere_probes;
PlaneProbeModule planar_probes;
VolumeProbeModule volume_probes;
LightProbeModule light_probes;
IrradianceCache irradiance_cache;
VolumeModule volume;
/** Input data. */
@ -149,8 +149,6 @@ class Instance {
lights(*this),
ambient_occlusion(*this, uniform_data.data.ao),
raytracing(*this, uniform_data.data.raytrace),
reflection_probes(*this),
planar_probes(*this),
velocity(*this),
motion_blur(*this),
depth_of_field(*this),
@ -165,8 +163,10 @@ class Instance {
world(*this),
lookdev_view(*this),
lookdev(*this),
sphere_probes(*this),
planar_probes(*this),
volume_probes(*this),
light_probes(*this),
irradiance_cache(*this),
volume(*this, uniform_data.data.volumes){};
~Instance(){};

View File

@ -21,7 +21,7 @@ namespace blender::eevee {
/** \name Interface
* \{ */
void IrradianceCache::init()
void VolumeProbeModule::init()
{
display_grids_enabled_ = DRW_state_draw_support();
@ -71,7 +71,7 @@ void IrradianceCache::init()
irradiance_atlas_tx_.clear(float4(0.0f));
}
inst_.reflection_probes.tag_world_irradiance_for_update();
inst_.sphere_probes.tag_world_irradiance_for_update();
}
if (irradiance_atlas_tx_.is_valid() == false) {
@ -79,14 +79,14 @@ void IrradianceCache::init()
}
}
void IrradianceCache::sync()
void VolumeProbeModule::sync()
{
if (inst_.is_baking()) {
bake.sync();
}
}
Vector<IrradianceBrickPacked> IrradianceCache::bricks_alloc(int brick_len)
Vector<IrradianceBrickPacked> VolumeProbeModule::bricks_alloc(int brick_len)
{
if (brick_pool_.size() < brick_len) {
/* Fail allocation. Not enough brick in the atlas. */
@ -101,13 +101,13 @@ Vector<IrradianceBrickPacked> IrradianceCache::bricks_alloc(int brick_len)
return allocated;
}
void IrradianceCache::bricks_free(Vector<IrradianceBrickPacked> &bricks)
void VolumeProbeModule::bricks_free(Vector<IrradianceBrickPacked> &bricks)
{
brick_pool_.extend(bricks.as_span());
bricks.clear();
}
void IrradianceCache::set_view(View & /*view*/)
void VolumeProbeModule::set_view(View & /*view*/)
{
Vector<IrradianceGrid *> grid_loaded;
@ -391,7 +391,7 @@ void IrradianceCache::set_view(View & /*view*/)
do_update_world_ = false;
}
void IrradianceCache::viewport_draw(View &view, GPUFrameBuffer *view_fb)
void VolumeProbeModule::viewport_draw(View &view, GPUFrameBuffer *view_fb)
{
if (!inst_.is_baking()) {
debug_pass_draw(view, view_fb);
@ -399,7 +399,7 @@ void IrradianceCache::viewport_draw(View &view, GPUFrameBuffer *view_fb)
}
}
void IrradianceCache::debug_pass_draw(View &view, GPUFrameBuffer *view_fb)
void VolumeProbeModule::debug_pass_draw(View &view, GPUFrameBuffer *view_fb)
{
switch (inst_.debug_mode) {
case eDebugMode::DEBUG_IRRADIANCE_CACHE_SURFELS_NORMAL:
@ -527,7 +527,7 @@ void IrradianceCache::debug_pass_draw(View &view, GPUFrameBuffer *view_fb)
}
}
void IrradianceCache::display_pass_draw(View &view, GPUFrameBuffer *view_fb)
void VolumeProbeModule::display_pass_draw(View &view, GPUFrameBuffer *view_fb)
{
if (!display_grids_enabled_) {
return;
@ -701,7 +701,7 @@ void IrradianceBake::sync()
sub.shader_set(inst_.shaders.static_shader_get(SURFEL_RAY));
sub.bind_ssbo(SURFEL_BUF_SLOT, &surfels_buf_);
sub.bind_ssbo(CAPTURE_BUF_SLOT, &capture_info_buf_);
sub.bind_resources(inst_.reflection_probes);
sub.bind_resources(inst_.sphere_probes);
sub.push_constant("radiance_src", &radiance_src_);
sub.push_constant("radiance_dst", &radiance_dst_);
sub.barrier(GPU_BARRIER_SHADER_STORAGE);
@ -714,7 +714,7 @@ void IrradianceBake::sync()
pass.shader_set(inst_.shaders.static_shader_get(LIGHTPROBE_IRRADIANCE_RAY));
pass.bind_ssbo(SURFEL_BUF_SLOT, &surfels_buf_);
pass.bind_ssbo(CAPTURE_BUF_SLOT, &capture_info_buf_);
pass.bind_resources(inst_.reflection_probes);
pass.bind_resources(inst_.sphere_probes);
pass.bind_ssbo("list_start_buf", &list_start_buf_);
pass.bind_ssbo("list_info_buf", &list_info_buf_);
pass.push_constant("radiance_src", &radiance_src_);
@ -826,7 +826,7 @@ void IrradianceBake::surfels_create(const Object &probe_object)
capture_info_buf_.capture_emission = capture_emission_;
LightProbeModule &light_probes = inst_.light_probes;
ReflectionProbeData &world_data = *static_cast<ReflectionProbeData *>(&light_probes.world_cube_);
SphereProbeData &world_data = *static_cast<SphereProbeData *>(&light_probes.world_cube_);
capture_info_buf_.world_atlas_coord = world_data.atlas_coord;
dispatch_per_grid_sample_ = math::divide_ceil(grid_resolution, int3(IRRADIANCE_GRID_GROUP_SIZE));

View File

@ -24,7 +24,7 @@ class Instance;
class CapturePipeline;
class ShadowModule;
class Camera;
class ReflectionProbeModule;
class SphereProbeModule;
/**
* Baking related pass and data. Not used at runtime.
@ -186,7 +186,7 @@ class IrradianceBake {
* Runtime container of diffuse indirect lighting.
* Also have debug and baking components.
*/
class IrradianceCache {
class VolumeProbeModule {
public:
IrradianceBake bake;
@ -207,22 +207,22 @@ class IrradianceCache {
/** Pool of atlas regions to allocate to different grids. */
Vector<IrradianceBrickPacked> brick_pool_;
/** Stream data into the irradiance atlas texture. */
PassSimple grid_upload_ps_ = {"IrradianceCache.Upload"};
PassSimple grid_upload_ps_ = {"VolumeProbeModule.Upload"};
/** If true, will trigger the reupload of all grid data instead of just streaming new ones. */
bool do_full_update_ = true;
/** Display debug data. */
PassSimple debug_ps_ = {"IrradianceCache.Debug"};
PassSimple debug_ps_ = {"VolumeProbeModule.Debug"};
/** Debug surfel elements copied from the light cache. */
draw::StorageArrayBuffer<Surfel> debug_surfels_buf_;
/** Display grid cache data. */
bool display_grids_enabled_ = false;
PassSimple display_grids_ps_ = {"IrradianceCache.Display Grids"};
PassSimple display_grids_ps_ = {"VolumeProbeModule.Display Grids"};
public:
IrradianceCache(Instance &inst) : bake(inst), inst_(inst){};
~IrradianceCache(){};
VolumeProbeModule(Instance &inst) : bake(inst), inst_(inst){};
~VolumeProbeModule(){};
void init();
void sync();
@ -243,7 +243,7 @@ class IrradianceCache {
void debug_pass_draw(View &view, GPUFrameBuffer *view_fb);
void display_pass_draw(View &view, GPUFrameBuffer *view_fb);
friend class ReflectionProbeModule;
friend class SphereProbeModule;
};
} // namespace blender::eevee

View File

@ -6,7 +6,8 @@
* \ingroup eevee
*
* Module that handles light probe update tagging.
* Lighting data is contained in their respective module `IrradianceCache` and `ReflectionProbes`.
* Lighting data is contained in their respective module `VolumeProbeModule`, `SphereProbeModule`
* and `PlaneProbeModule`.
*/
#include "DNA_lightprobe_types.h"
@ -100,7 +101,7 @@ void LightProbeModule::sync_grid(const Object *ob, ObjectHandle &handle)
grid.viewport_display_size = lightprobe->data_display_size;
/* Force reupload. */
inst_.irradiance_cache.bricks_free(grid.bricks);
inst_.volume_probes.bricks_free(grid.bricks);
}
}
@ -115,14 +116,14 @@ void LightProbeModule::sync_cube(const Object *ob, ObjectHandle &handle)
cube.updated = true;
cube.do_render = true;
ReflectionProbeModule &probe_module = inst_.reflection_probes;
SphereProbeModule &probe_module = inst_.sphere_probes;
eLightProbeResolution probe_resolution = cube_object_resolution_;
int subdivision_lvl = probe_module.subdivision_level_get(probe_resolution);
if (cube.atlas_coord.subdivision_lvl != subdivision_lvl) {
cube.atlas_coord.free();
cube.atlas_coord = find_empty_atlas_region(subdivision_lvl);
ReflectionProbeData &cube_data = *static_cast<ReflectionProbeData *>(&cube);
SphereProbeData &cube_data = *static_cast<SphereProbeData *>(&cube);
/* Update gpu data sampling coordinates. */
cube_data.atlas_coord = cube.atlas_coord.as_sampling_coord(probe_module.max_resolution_);
/* Coordinates have changed. Area might contain random data. Do not use for rendering. */
@ -197,13 +198,13 @@ void LightProbeModule::sync_world(const ::World *world, bool has_update)
const eLightProbeResolution probe_resolution = static_cast<eLightProbeResolution>(
world->probe_resolution);
ReflectionProbeModule &sph_module = inst_.reflection_probes;
SphereProbeModule &sph_module = inst_.sphere_probes;
int subdivision_lvl = sph_module.subdivision_level_get(probe_resolution);
if (subdivision_lvl != world_cube_.atlas_coord.subdivision_lvl) {
world_cube_.atlas_coord.free();
world_cube_.atlas_coord = find_empty_atlas_region(subdivision_lvl);
ReflectionProbeData &world_data = *static_cast<ReflectionProbeData *>(&world_cube_);
SphereProbeData &world_data = *static_cast<SphereProbeData *>(&world_cube_);
world_data.atlas_coord = world_cube_.atlas_coord.as_sampling_coord(sph_module.max_resolution_);
has_update = true;
}
@ -256,11 +257,10 @@ void LightProbeModule::end_sync()
});
}
ReflectionProbeAtlasCoordinate LightProbeModule::find_empty_atlas_region(
int subdivision_level) const
SphereProbeAtlasCoord LightProbeModule::find_empty_atlas_region(int subdivision_level) const
{
int layer_count = cube_layer_count();
ReflectionProbeAtlasCoordinate::LocationFinder location_finder(layer_count, subdivision_level);
SphereProbeAtlasCoord::LocationFinder location_finder(layer_count, subdivision_level);
location_finder.mark_space_used(world_cube_.atlas_coord);
for (const ReflectionCube &probe : cube_map_.values()) {
@ -282,11 +282,11 @@ int LightProbeModule::cube_layer_count() const
/** \} */
/* -------------------------------------------------------------------- */
/** \name ReflectionProbeAtlasCoordinate
/** \name SphereProbeAtlasCoord
* \{ */
ReflectionProbeAtlasCoordinate::LocationFinder::LocationFinder(int allocated_layer_count,
int subdivision_level)
SphereProbeAtlasCoord::LocationFinder::LocationFinder(int allocated_layer_count,
int subdivision_level)
{
subdivision_level_ = subdivision_level;
areas_per_dimension_ = 1 << subdivision_level_;
@ -297,8 +297,7 @@ ReflectionProbeAtlasCoordinate::LocationFinder::LocationFinder(int allocated_lay
areas_occupancy_.resize(area_len, false);
}
void ReflectionProbeAtlasCoordinate::LocationFinder::mark_space_used(
const ReflectionProbeAtlasCoordinate &coord)
void SphereProbeAtlasCoord::LocationFinder::mark_space_used(const SphereProbeAtlasCoord &coord)
{
if (coord.atlas_layer == -1) {
/* Coordinate not allocated yet. */
@ -321,10 +320,9 @@ void ReflectionProbeAtlasCoordinate::LocationFinder::mark_space_used(
}
}
ReflectionProbeAtlasCoordinate ReflectionProbeAtlasCoordinate::LocationFinder::first_free_spot()
const
SphereProbeAtlasCoord SphereProbeAtlasCoord::LocationFinder::first_free_spot() const
{
ReflectionProbeAtlasCoordinate result;
SphereProbeAtlasCoord result;
result.subdivision_lvl = subdivision_level_;
for (int index : areas_occupancy_.index_range()) {
if (!areas_occupancy_[index]) {
@ -338,7 +336,7 @@ ReflectionProbeAtlasCoordinate ReflectionProbeAtlasCoordinate::LocationFinder::f
return result;
}
void ReflectionProbeAtlasCoordinate::LocationFinder::print_debug() const
void SphereProbeAtlasCoord::LocationFinder::print_debug() const
{
std::ostream &os = std::cout;
int layer = 0, row = 0, column = 0;

View File

@ -6,7 +6,8 @@
* \ingroup eevee
*
* Module that handles light probe update tagging.
* Lighting data is contained in their respective module `IrradianceCache` and `ReflectionProbes`.
* Lighting data is contained in their respective module `VolumeProbeModule`, `SphereProbeModule`
* and `PlaneProbeModule`.
*/
#pragma once
@ -19,13 +20,13 @@
namespace blender::eevee {
class Instance;
class IrradianceCache;
class VolumeProbeModule;
/* -------------------------------------------------------------------- */
/** \name ReflectionProbeAtlasCoordinate
/** \name SphereProbeAtlasCoord
* \{ */
struct ReflectionProbeAtlasCoordinate {
struct SphereProbeAtlasCoord {
/** On which layer of the texture array is this reflection probe stored. */
int atlas_layer = -1;
/** Gives the extent of this probe relative to the atlas size. */
@ -58,7 +59,7 @@ struct ReflectionProbeAtlasCoordinate {
return area_location() * area_extent(atlas_extent);
}
ReflectionProbeCoordinate as_sampling_coord(int atlas_extent) const
SphereProbeUvArea as_sampling_coord(int atlas_extent) const
{
/**
* We want to cover the last mip exactly at the pixel center to reduce padding texels and
@ -85,16 +86,16 @@ struct ReflectionProbeAtlasCoordinate {
const int sampling_area_extent = area_extent(atlas_extent) - mip_min_lvl_padding;
const int2 sampling_area_offset = area_offset(atlas_extent) + mip_min_lvl_padding / 2;
/* Convert to atlas UVs. */
ReflectionProbeCoordinate coord;
SphereProbeUvArea coord;
coord.scale = sampling_area_extent / float(atlas_extent);
coord.offset = float2(sampling_area_offset) / float(atlas_extent);
coord.layer = atlas_layer;
return coord;
}
ReflectionProbeWriteCoordinate as_write_coord(int atlas_extent, int mip_lvl) const
SphereProbePixelArea as_write_coord(int atlas_extent, int mip_lvl) const
{
ReflectionProbeWriteCoordinate coord;
SphereProbePixelArea coord;
coord.extent = atlas_extent >> (subdivision_lvl + mip_lvl);
coord.offset = (area_location() * coord.extent) >> mip_lvl;
coord.layer = atlas_layer;
@ -122,9 +123,9 @@ struct ReflectionProbeAtlasCoordinate {
LocationFinder(int allocated_layer_count, int subdivision_level);
/* Mark space to be occupied by the given probe_data. */
void mark_space_used(const ReflectionProbeAtlasCoordinate &coord);
void mark_space_used(const SphereProbeAtlasCoord &coord);
ReflectionProbeAtlasCoordinate first_free_spot() const;
SphereProbeAtlasCoord first_free_spot() const;
void print_debug() const;
};
@ -169,7 +170,7 @@ struct IrradianceGrid : public LightProbe, IrradianceGridData {
float intensity;
};
struct ReflectionCube : public LightProbe, ReflectionProbeData {
struct ReflectionCube : public LightProbe, SphereProbeData {
/** Used to sort the probes by priority. */
float volume;
/** True if the area in the atlas needs to be updated. */
@ -179,7 +180,7 @@ struct ReflectionCube : public LightProbe, ReflectionProbeData {
/** Far and near clipping distances for rendering. */
float2 clipping_distances;
/** Atlas region this probe is rendered at (or will be rendered at). */
ReflectionProbeAtlasCoordinate atlas_coord;
SphereProbeAtlasCoord atlas_coord;
};
struct ProbePlane : public LightProbe, ProbePlanarData {
@ -222,9 +223,9 @@ struct ProbePlane : public LightProbe, ProbePlanarData {
class LightProbeModule {
friend class IrradianceBake;
friend class IrradianceCache;
friend class PlanarProbeModule;
friend class ReflectionProbeModule;
friend class VolumeProbeModule;
friend class PlaneProbeModule;
friend class SphereProbeModule;
private:
Instance &inst_;
@ -264,7 +265,7 @@ class LightProbeModule {
int cube_layer_count() const;
/** Returns coordinates of an area in the atlas for a probe with the given subdivision level. */
ReflectionProbeAtlasCoordinate find_empty_atlas_region(int subdivision_level) const;
SphereProbeAtlasCoord find_empty_atlas_region(int subdivision_level) const;
};
} // namespace blender::eevee

View File

@ -235,8 +235,8 @@ void LookdevModule::sync_pass(PassSimple &pass,
pass.bind_image("aov_value_img", dummy_aov_value_tx_);
pass.bind_resources(inst_.uniform_data);
pass.bind_resources(inst_.hiz_buffer.front);
pass.bind_resources(inst_.reflection_probes);
pass.bind_resources(inst_.irradiance_cache);
pass.bind_resources(inst_.sphere_probes);
pass.bind_resources(inst_.volume_probes);
pass.bind_resources(inst_.shadows);
pass.bind_resources(inst_.volume.result);
pass.bind_resources(inst_.cryptomatte);

View File

@ -295,8 +295,8 @@ void ForwardPipeline::sync()
opaque_ps_.bind_resources(inst_.volume.result);
opaque_ps_.bind_resources(inst_.sampling);
opaque_ps_.bind_resources(inst_.hiz_buffer.front);
opaque_ps_.bind_resources(inst_.irradiance_cache);
opaque_ps_.bind_resources(inst_.reflection_probes);
opaque_ps_.bind_resources(inst_.volume_probes);
opaque_ps_.bind_resources(inst_.sphere_probes);
}
opaque_single_sided_ps_ = &opaque_ps_.sub("SingleSided");
@ -323,8 +323,8 @@ void ForwardPipeline::sync()
sub.bind_resources(inst_.volume.result);
sub.bind_resources(inst_.sampling);
sub.bind_resources(inst_.hiz_buffer.front);
sub.bind_resources(inst_.irradiance_cache);
sub.bind_resources(inst_.reflection_probes);
sub.bind_resources(inst_.volume_probes);
sub.bind_resources(inst_.sphere_probes);
}
}
@ -410,7 +410,7 @@ void ForwardPipeline::render(View &view, Framebuffer &prepass_fb, Framebuffer &c
inst_.hiz_buffer.set_dirty();
inst_.shadows.set_view(view, inst_.render_buffers.depth_tx);
inst_.irradiance_cache.set_view(view);
inst_.volume_probes.set_view(view);
if (has_opaque_) {
combined_fb.bind();
@ -463,8 +463,8 @@ void DeferredLayerBase::gbuffer_pass_sync(Instance &inst)
* Non-NPR shaders will override these resource bindings. */
gbuffer_ps_.bind_resources(inst.lights);
gbuffer_ps_.bind_resources(inst.shadows);
gbuffer_ps_.bind_resources(inst.reflection_probes);
gbuffer_ps_.bind_resources(inst.irradiance_cache);
gbuffer_ps_.bind_resources(inst.sphere_probes);
gbuffer_ps_.bind_resources(inst.volume_probes);
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL;
@ -591,8 +591,8 @@ void DeferredLayer::end_sync()
sub.bind_resources(inst_.shadows);
sub.bind_resources(inst_.sampling);
sub.bind_resources(inst_.hiz_buffer.front);
sub.bind_resources(inst_.reflection_probes);
sub.bind_resources(inst_.irradiance_cache);
sub.bind_resources(inst_.sphere_probes);
sub.bind_resources(inst_.volume_probes);
sub.state_stencil(0xFFu, i + 1, 0xFFu);
sub.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
@ -719,7 +719,7 @@ void DeferredLayer::render(View &main_view,
/* Update for lighting pass or AO node. */
inst_.hiz_buffer.update();
inst_.irradiance_cache.set_view(render_view);
inst_.volume_probes.set_view(render_view);
inst_.shadows.set_view(render_view, inst_.render_buffers.depth_tx);
if (/* FIXME(fclem): Vulkan doesn't implement load / store config yet. */
@ -1206,7 +1206,7 @@ void DeferredProbeLayer::end_sync()
pass.bind_resources(inst_.shadows);
pass.bind_resources(inst_.sampling);
pass.bind_resources(inst_.hiz_buffer.front);
pass.bind_resources(inst_.irradiance_cache);
pass.bind_resources(inst_.volume_probes);
pass.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
pass.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
@ -1254,7 +1254,7 @@ void DeferredProbeLayer::render(View &view,
inst_.hiz_buffer.set_source(&inst_.render_buffers.depth_tx);
inst_.lights.set_view(view, extent);
inst_.shadows.set_view(view, inst_.render_buffers.depth_tx);
inst_.irradiance_cache.set_view(view);
inst_.volume_probes.set_view(view);
/* Update for lighting pass. */
inst_.hiz_buffer.update();
@ -1347,8 +1347,8 @@ void PlanarProbePipeline::begin_sync()
pass.bind_resources(inst_.shadows);
pass.bind_resources(inst_.sampling);
pass.bind_resources(inst_.hiz_buffer.front);
pass.bind_resources(inst_.reflection_probes);
pass.bind_resources(inst_.irradiance_cache);
pass.bind_resources(inst_.sphere_probes);
pass.bind_resources(inst_.volume_probes);
pass.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
pass.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
@ -1408,7 +1408,7 @@ void PlanarProbePipeline::render(View &view,
inst_.hiz_buffer.set_source(&depth_layer_tx, 0);
inst_.lights.set_view(view, extent);
inst_.shadows.set_view(view, depth_layer_tx);
inst_.irradiance_cache.set_view(view);
inst_.volume_probes.set_view(view);
/* Update for lighting pass. */
inst_.hiz_buffer.update();
@ -1448,10 +1448,10 @@ void CapturePipeline::sync()
/* Surfel output is done using a SSBO, so no need for a fragment shader output color or depth. */
/* WORKAROUND: Avoid rasterizer discard, but the shaders actually use no fragment output. */
surface_ps_.state_set(DRW_STATE_WRITE_STENCIL);
surface_ps_.framebuffer_set(&inst_.irradiance_cache.bake.empty_raster_fb_);
surface_ps_.framebuffer_set(&inst_.volume_probes.bake.empty_raster_fb_);
surface_ps_.bind_ssbo(SURFEL_BUF_SLOT, &inst_.irradiance_cache.bake.surfels_buf_);
surface_ps_.bind_ssbo(CAPTURE_BUF_SLOT, &inst_.irradiance_cache.bake.capture_info_buf_);
surface_ps_.bind_ssbo(SURFEL_BUF_SLOT, &inst_.volume_probes.bake.surfels_buf_);
surface_ps_.bind_ssbo(CAPTURE_BUF_SLOT, &inst_.volume_probes.bake.capture_info_buf_);
surface_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
/* TODO(fclem): Remove. Bind to get the camera data,

View File

@ -34,7 +34,7 @@ void ProbePlane::set_view(const draw::View &view, int layer_id)
/** \name Planar Probe Module
* \{ */
void PlanarProbeModule::init()
void PlaneProbeModule::init()
{
/* This triggers the compilation of clipped shader only if we can detect lightprobe planes. */
if (inst_.is_viewport()) {
@ -50,7 +50,7 @@ void PlanarProbeModule::init()
do_display_draw_ = false;
}
void PlanarProbeModule::end_sync()
void PlaneProbeModule::end_sync()
{
/* When first planar probes are enabled it can happen that the first sample is off. */
if (!update_probes_ && !inst_.light_probes.plane_map_.is_empty()) {
@ -58,7 +58,7 @@ void PlanarProbeModule::end_sync()
}
}
void PlanarProbeModule::set_view(const draw::View &main_view, int2 main_view_extent)
void PlaneProbeModule::set_view(const draw::View &main_view, int2 main_view_extent)
{
GBuffer &gbuf = inst_.gbuffer;
@ -84,7 +84,7 @@ void PlanarProbeModule::set_view(const draw::View &main_view, int2 main_view_ext
int resource_index = 0;
int display_index = 0;
for (ProbePlane &probe : inst_.light_probes.plane_map_.values()) {
if (resource_index == PLANAR_PROBES_MAX) {
if (resource_index == PLANAR_PROBE_MAX) {
break;
}
@ -126,7 +126,7 @@ void PlanarProbeModule::set_view(const draw::View &main_view, int2 main_view_ext
gbuf.release();
if (resource_index < PLANAR_PROBES_MAX) {
if (resource_index < PLANAR_PROBE_MAX) {
/* Tag the end of the array. */
probe_planar_buf_[resource_index].layer_id = -1;
}
@ -139,7 +139,7 @@ void PlanarProbeModule::set_view(const draw::View &main_view, int2 main_view_ext
}
}
void PlanarProbeModule::viewport_draw(View &view, GPUFrameBuffer *view_fb)
void PlaneProbeModule::viewport_draw(View &view, GPUFrameBuffer *view_fb)
{
if (!do_display_draw_) {
return;

View File

@ -26,7 +26,7 @@ struct ObjectHandle;
/** \name Planar Probe Module
* \{ */
class PlanarProbeModule {
class PlaneProbeModule {
friend class Instance;
friend class HiZBuffer;
friend class PlanarProbePipeline;
@ -40,7 +40,7 @@ class PlanarProbeModule {
draw::View view = {"planar.view"};
};
std::array<PlanarResources, PLANAR_PROBES_MAX> resources_;
std::array<PlanarResources, PLANAR_PROBE_MAX> resources_;
Texture radiance_tx_ = {"planar.radiance_tx"};
Texture depth_tx_ = {"planar.depth_tx"};
@ -53,10 +53,10 @@ class PlanarProbeModule {
/** Viewport data display drawing. */
bool do_display_draw_ = false;
ProbePlanarDisplayDataBuf display_data_buf_;
PassSimple viewport_display_ps_ = {"PlanarProbeModule.Viewport Display"};
PassSimple viewport_display_ps_ = {"PlaneProbeModule.Viewport Display"};
public:
PlanarProbeModule(Instance &instance) : inst_(instance) {}
PlaneProbeModule(Instance &instance) : inst_(instance) {}
void init();
void end_sync();

View File

@ -106,8 +106,8 @@ void RayTraceModule::sync()
pass.bind_texture("depth_tx", &depth_tx);
pass.bind_resources(inst_.uniform_data);
pass.bind_resources(inst_.planar_probes);
pass.bind_resources(inst_.irradiance_cache);
pass.bind_resources(inst_.reflection_probes);
pass.bind_resources(inst_.volume_probes);
pass.bind_resources(inst_.sphere_probes);
pass.bind_resources(inst_.gbuffer);
/* TODO(@fclem): Use another dispatch with only tiles that touches planar captures. */
pass.dispatch(raytrace_tracing_dispatch_buf_);
@ -134,8 +134,8 @@ void RayTraceModule::sync()
pass.bind_image("ray_radiance_img", &ray_radiance_tx_);
pass.bind_resources(inst_.uniform_data);
pass.bind_resources(inst_.sampling);
pass.bind_resources(inst_.irradiance_cache);
pass.bind_resources(inst_.reflection_probes);
pass.bind_resources(inst_.volume_probes);
pass.bind_resources(inst_.sphere_probes);
pass.bind_resources(inst_.gbuffer);
pass.dispatch(raytrace_tracing_dispatch_buf_);
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
@ -150,8 +150,8 @@ void RayTraceModule::sync()
pass.bind_image("ray_radiance_img", &ray_radiance_tx_);
pass.bind_texture("depth_tx", &depth_tx);
pass.bind_resources(inst_.uniform_data);
pass.bind_resources(inst_.irradiance_cache);
pass.bind_resources(inst_.reflection_probes);
pass.bind_resources(inst_.volume_probes);
pass.bind_resources(inst_.sphere_probes);
pass.bind_resources(inst_.sampling);
pass.dispatch(raytrace_tracing_dispatch_buf_);
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
@ -269,8 +269,8 @@ void RayTraceModule::sync()
pass.bind_resources(inst_.uniform_data);
pass.bind_resources(inst_.sampling);
pass.bind_resources(inst_.gbuffer);
pass.bind_resources(inst_.irradiance_cache);
pass.bind_resources(inst_.reflection_probes);
pass.bind_resources(inst_.volume_probes);
pass.bind_resources(inst_.sphere_probes);
pass.dispatch(horizon_denoise_dispatch_buf_);
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}

View File

@ -11,12 +11,12 @@ namespace blender::eevee {
/** \name Reflection Probe Module
* \{ */
int ReflectionProbeModule::probe_render_extent() const
int SphereProbeModule::probe_render_extent() const
{
return instance_.scene->eevee.gi_cubemap_resolution / 2;
}
void ReflectionProbeModule::init()
void SphereProbeModule::init()
{
if (!instance_.is_viewport()) {
/* TODO(jbakker): should we check on the subtype as well? Now it also populates even when
@ -27,12 +27,12 @@ void ReflectionProbeModule::init()
do_display_draw_ = false;
}
void ReflectionProbeModule::begin_sync()
void SphereProbeModule::begin_sync()
{
update_probes_this_sample_ = update_probes_next_sample_;
LightProbeModule &light_probes = instance_.light_probes;
ReflectionProbeData &world_data = *static_cast<ReflectionProbeData *>(&light_probes.world_cube_);
SphereProbeData &world_data = *static_cast<SphereProbeData *>(&light_probes.world_cube_);
{
const RaytraceEEVEE &options = instance_.scene->eevee.ray_tracing_options;
float probe_brightness_clamp = (options.sample_clamp > 0.0) ? options.sample_clamp : 1e20;
@ -55,7 +55,7 @@ void ReflectionProbeModule::begin_sync()
pass.init();
pass.shader_set(instance_.shaders.static_shader_get(REFLECTION_PROBE_UPDATE_IRRADIANCE));
pass.push_constant("world_coord_packed", reinterpret_cast<int4 *>(&world_data.atlas_coord));
pass.bind_image("irradiance_atlas_img", &instance_.irradiance_cache.irradiance_atlas_tx_);
pass.bind_image("irradiance_atlas_img", &instance_.volume_probes.irradiance_atlas_tx_);
pass.bind_texture("reflection_probes_tx", &probes_tx_);
pass.dispatch(int2(1, 1));
}
@ -65,14 +65,14 @@ void ReflectionProbeModule::begin_sync()
pass.shader_set(instance_.shaders.static_shader_get(REFLECTION_PROBE_SELECT));
pass.push_constant("reflection_probe_count", &reflection_probe_count_);
pass.bind_ssbo("reflection_probe_buf", &data_buf_);
instance_.irradiance_cache.bind_resources(pass);
instance_.volume_probes.bind_resources(pass);
instance_.sampling.bind_resources(pass);
pass.dispatch(&dispatch_probe_select_);
pass.barrier(GPU_BARRIER_UNIFORM);
}
}
bool ReflectionProbeModule::ensure_atlas()
bool SphereProbeModule::ensure_atlas()
{
/* Make sure the atlas is always initialized even if there is nothing to render to it to fullfil
* the resource bindings. */
@ -96,7 +96,7 @@ bool ReflectionProbeModule::ensure_atlas()
return false;
}
void ReflectionProbeModule::end_sync()
void SphereProbeModule::end_sync()
{
const bool world_updated = instance_.light_probes.world_cube_.do_render;
const bool atlas_resized = ensure_atlas();
@ -120,7 +120,7 @@ void ReflectionProbeModule::end_sync()
}
}
void ReflectionProbeModule::ensure_cubemap_render_target(int resolution)
void SphereProbeModule::ensure_cubemap_render_target(int resolution)
{
if (cubemap_tx_.ensure_cube(
GPU_RGBA16F, resolution, GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ))
@ -130,12 +130,12 @@ void ReflectionProbeModule::ensure_cubemap_render_target(int resolution)
/* TODO(fclem): dealocate it. */
}
ReflectionProbeModule::ReflectionProbeUpdateInfo ReflectionProbeModule::update_info_from_probe(
SphereProbeModule::UpdateInfo SphereProbeModule::update_info_from_probe(
const ReflectionCube &probe)
{
const int max_shift = int(log2(max_resolution_));
ReflectionProbeModule::ReflectionProbeUpdateInfo info = {};
SphereProbeModule::UpdateInfo info = {};
info.atlas_coord = probe.atlas_coord;
info.resolution = 1 << (max_shift - probe.atlas_coord.subdivision_lvl - 1);
info.clipping_distances = probe.clipping_distances;
@ -145,14 +145,13 @@ ReflectionProbeModule::ReflectionProbeUpdateInfo ReflectionProbeModule::update_i
return info;
}
std::optional<ReflectionProbeModule::ReflectionProbeUpdateInfo> ReflectionProbeModule::
world_update_info_pop()
std::optional<SphereProbeModule::UpdateInfo> SphereProbeModule::world_update_info_pop()
{
ReflectionCube &world_probe = instance_.light_probes.world_cube_;
if (!world_probe.do_render && !do_world_irradiance_update) {
return std::nullopt;
}
ReflectionProbeModule::ReflectionProbeUpdateInfo info = update_info_from_probe(world_probe);
SphereProbeModule::UpdateInfo info = update_info_from_probe(world_probe);
info.do_world_irradiance_update = do_world_irradiance_update;
world_probe.do_render = false;
do_world_irradiance_update = false;
@ -160,8 +159,7 @@ std::optional<ReflectionProbeModule::ReflectionProbeUpdateInfo> ReflectionProbeM
return info;
}
std::optional<ReflectionProbeModule::ReflectionProbeUpdateInfo> ReflectionProbeModule::
probe_update_info_pop()
std::optional<SphereProbeModule::UpdateInfo> SphereProbeModule::probe_update_info_pop()
{
if (!instance_.do_reflection_probe_sync()) {
/* Do not update probes during this sample as we did not sync the draw::Passes. */
@ -172,7 +170,7 @@ std::optional<ReflectionProbeModule::ReflectionProbeUpdateInfo> ReflectionProbeM
if (!probe.do_render) {
continue;
}
ReflectionProbeModule::ReflectionProbeUpdateInfo info = update_info_from_probe(probe);
SphereProbeModule::UpdateInfo info = update_info_from_probe(probe);
probe.do_render = false;
probe.use_for_render = true;
ensure_cubemap_render_target(info.resolution);
@ -182,8 +180,7 @@ std::optional<ReflectionProbeModule::ReflectionProbeUpdateInfo> ReflectionProbeM
return std::nullopt;
}
void ReflectionProbeModule::remap_to_octahedral_projection(
const ReflectionProbeAtlasCoordinate &atlas_coord)
void SphereProbeModule::remap_to_octahedral_projection(const SphereProbeAtlasCoord &atlas_coord)
{
int resolution = max_resolution_ >> atlas_coord.subdivision_lvl;
/* Update shader parameters that change per dispatch. */
@ -195,22 +192,22 @@ void ReflectionProbeModule::remap_to_octahedral_projection(
instance_.manager->submit(remap_ps_);
}
void ReflectionProbeModule::update_world_irradiance()
void SphereProbeModule::update_world_irradiance()
{
instance_.manager->submit(update_irradiance_ps_);
}
void ReflectionProbeModule::update_probes_texture_mipmaps()
void SphereProbeModule::update_probes_texture_mipmaps()
{
GPU_texture_update_mipmap_chain(probes_tx_);
}
void ReflectionProbeModule::set_view(View & /*view*/)
void SphereProbeModule::set_view(View & /*view*/)
{
Vector<ReflectionCube *> probe_active;
for (auto &probe : instance_.light_probes.cube_map_.values()) {
/* Last slot is reserved for the world probe. */
if (reflection_probe_count_ >= REFLECTION_PROBES_MAX - 1) {
if (reflection_probe_count_ >= REFLECTION_PROBE_MAX - 1) {
break;
}
if (!probe.use_for_render) {
@ -254,7 +251,7 @@ void ReflectionProbeModule::set_view(View & /*view*/)
/* Add world probe at the end. */
data_buf_[probe_id++] = instance_.light_probes.world_cube_;
/* Tag the end of the array. */
if (probe_id < REFLECTION_PROBES_MAX) {
if (probe_id < REFLECTION_PROBE_MAX) {
data_buf_[probe_id].atlas_coord.layer = -1;
}
data_buf_.push_update();
@ -282,7 +279,7 @@ void ReflectionProbeModule::set_view(View & /*view*/)
instance_.manager->submit(select_ps_);
}
void ReflectionProbeModule::viewport_draw(View &view, GPUFrameBuffer *view_fb)
void SphereProbeModule::viewport_draw(View &view, GPUFrameBuffer *view_fb)
{
if (!do_display_draw_) {
return;

View File

@ -23,13 +23,12 @@ class Instance;
struct ObjectHandle;
struct WorldHandle;
class CaptureView;
struct ReflectionProbeUpdateInfo;
/* -------------------------------------------------------------------- */
/** \name Reflection Probe Module
* \{ */
class ReflectionProbeModule {
class SphereProbeModule {
friend LightProbeModule;
/* Capture View requires access to the cube-maps texture for frame-buffer configuration. */
friend class CaptureView;
@ -45,7 +44,7 @@ class ReflectionProbeModule {
static constexpr int max_resolution_ = 2048;
Instance &instance_;
ReflectionProbeDataBuf data_buf_;
SphereProbeDataBuf data_buf_;
/** Probes texture stored in octahedral mapping. */
Texture probes_tx_ = {"Probes"};
@ -70,10 +69,10 @@ class ReflectionProbeModule {
/** Mip level being sampled for remapping. */
int probe_mip_level_ = 0;
/** Updated Probe coordinates in the atlas. */
ReflectionProbeCoordinate probe_sampling_coord_;
ReflectionProbeWriteCoordinate probe_write_coord_;
SphereProbeUvArea probe_sampling_coord_;
SphereProbePixelArea probe_write_coord_;
/** World coordinates in the atlas. */
ReflectionProbeCoordinate world_sampling_coord_;
SphereProbeUvArea world_sampling_coord_;
/** Number of the probe to process in the select phase. */
int reflection_probe_count_ = 0;
@ -92,11 +91,11 @@ class ReflectionProbeModule {
/** Viewport data display drawing. */
bool do_display_draw_ = false;
ReflectionProbeDisplayDataBuf display_data_buf_;
PassSimple viewport_display_ps_ = {"ReflectionProbeModule.Viewport Display"};
SphereProbeDisplayDataBuf display_data_buf_;
PassSimple viewport_display_ps_ = {"ProbeSphereModule.Viewport Display"};
public:
ReflectionProbeModule(Instance &instance) : instance_(instance){};
SphereProbeModule(Instance &instance) : instance_(instance){};
void init();
void begin_sync();
@ -143,31 +142,31 @@ class ReflectionProbeModule {
*/
void ensure_cubemap_render_target(int resolution);
struct ReflectionProbeUpdateInfo {
struct UpdateInfo {
float3 probe_pos;
/** Resolution of the cube-map to be rendered. */
int resolution;
float2 clipping_distances;
ReflectionProbeAtlasCoordinate atlas_coord;
SphereProbeAtlasCoord atlas_coord;
bool do_render;
bool do_world_irradiance_update;
};
ReflectionProbeUpdateInfo update_info_from_probe(const ReflectionCube &probe);
UpdateInfo update_info_from_probe(const ReflectionCube &probe);
/**
* Pop the next reflection probe that requires to be updated.
*/
std::optional<ReflectionProbeUpdateInfo> world_update_info_pop();
std::optional<ReflectionProbeUpdateInfo> probe_update_info_pop();
std::optional<UpdateInfo> world_update_info_pop();
std::optional<UpdateInfo> probe_update_info_pop();
/**
* Internal processing passes.
*/
void remap_to_octahedral_projection(const ReflectionProbeAtlasCoordinate &atlas_coord);
void remap_to_octahedral_projection(const SphereProbeAtlasCoord &atlas_coord);
void update_probes_texture_mipmaps();
void update_world_irradiance();
};

View File

@ -1043,7 +1043,8 @@ enum LightProbeShape : uint32_t {
SHAPE_CUBOID = 1u,
};
struct ReflectionProbeCoordinate {
/* Sampling coordinates using UV space. */
struct SphereProbeUvArea {
/* 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. */
@ -1051,9 +1052,10 @@ struct ReflectionProbeCoordinate {
/* Layer of the atlas where the octahedron map is stored. */
float layer;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeCoordinate, 16)
BLI_STATIC_ASSERT_ALIGN(SphereProbeUvArea, 16)
struct ReflectionProbeWriteCoordinate {
/* Pixel read/write coordinates using pixel space. */
struct SphereProbePixelArea {
/* 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;
@ -1062,10 +1064,10 @@ struct ReflectionProbeWriteCoordinate {
/* Layer of the atlas where the octahedron map is stored. */
int layer;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeWriteCoordinate, 16)
BLI_STATIC_ASSERT_ALIGN(SphereProbePixelArea, 16)
/** Mapping data to locate a reflection probe in texture. */
struct ReflectionProbeData {
struct SphereProbeData {
/** Transform to probe local position with non-uniform scaling. */
float3x4 world_to_probe_transposed;
@ -1078,7 +1080,7 @@ struct ReflectionProbeData {
float influence_scale;
float influence_bias;
ReflectionProbeCoordinate atlas_coord;
SphereProbeUvArea atlas_coord;
/**
* Irradiance at the probe location encoded as spherical harmonics.
@ -1086,16 +1088,16 @@ struct ReflectionProbeData {
*/
ReflectionProbeLowFreqLight low_freq_light;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeData, 16)
BLI_STATIC_ASSERT_ALIGN(SphereProbeData, 16)
/** Viewport Display Pass. */
struct ReflectionProbeDisplayData {
struct SphereProbeDisplayData {
int probe_index;
float display_size;
float _pad0;
float _pad1;
};
BLI_STATIC_ASSERT_ALIGN(ReflectionProbeDisplayData, 16)
BLI_STATIC_ASSERT_ALIGN(SphereProbeDisplayData, 16)
/** \} */
@ -1191,7 +1193,7 @@ struct CaptureInfoData {
bool1 capture_emission;
int _pad0;
/* World light probe atlas coordinate. */
ReflectionProbeCoordinate world_atlas_coord;
SphereProbeUvArea world_atlas_coord;
};
BLI_STATIC_ASSERT_ALIGN(CaptureInfoData, 16)
@ -1583,10 +1585,9 @@ using MotionBlurDataBuf = draw::UniformBuffer<MotionBlurData>;
using MotionBlurTileIndirectionBuf = draw::StorageBuffer<MotionBlurTileIndirection, true>;
using RayTraceTileBuf = draw::StorageArrayBuffer<uint, 1024, true>;
using SubsurfaceTileBuf = RayTraceTileBuf;
using ReflectionProbeDataBuf =
draw::UniformArrayBuffer<ReflectionProbeData, REFLECTION_PROBES_MAX>;
using ReflectionProbeDisplayDataBuf = draw::StorageArrayBuffer<ReflectionProbeDisplayData>;
using ProbePlanarDataBuf = draw::UniformArrayBuffer<ProbePlanarData, PLANAR_PROBES_MAX>;
using SphereProbeDataBuf = draw::UniformArrayBuffer<SphereProbeData, REFLECTION_PROBE_MAX>;
using ProbePlanarDataBuf = draw::UniformArrayBuffer<ProbePlanarData, PLANAR_PROBE_MAX>;
using SphereProbeDisplayDataBuf = draw::StorageArrayBuffer<SphereProbeDisplayData>;
using ProbePlanarDisplayDataBuf = draw::StorageArrayBuffer<ProbePlanarDisplayData>;
using SamplingDataBuf = draw::StorageBuffer<SamplingData>;
using ShadowStatisticsBuf = draw::StorageBuffer<ShadowStatistics>;

View File

@ -831,9 +831,9 @@ void ShadowModule::begin_sync()
pass.init();
if (inst_.is_baking()) {
SurfelBuf &surfels_buf = inst_.irradiance_cache.bake.surfels_buf_;
CaptureInfoBuf &capture_info_buf = inst_.irradiance_cache.bake.capture_info_buf_;
float surfel_coverage_area = inst_.irradiance_cache.bake.surfel_density_;
SurfelBuf &surfels_buf = inst_.volume_probes.bake.surfels_buf_;
CaptureInfoBuf &capture_info_buf = inst_.volume_probes.bake.capture_info_buf_;
float surfel_coverage_area = inst_.volume_probes.bake.surfel_density_;
/* Directional shadows. */
float texel_size = ShadowDirectional::tile_size_get(0) / float(SHADOW_PAGE_RES);
@ -850,7 +850,7 @@ void ShadowModule::begin_sync()
sub.push_constant("directional_level", directional_level);
sub.push_constant("tilemap_projection_ratio", projection_ratio);
sub.bind_resources(inst_.lights);
sub.dispatch(&inst_.irradiance_cache.bake.dispatch_per_surfel_);
sub.dispatch(&inst_.volume_probes.bake.dispatch_per_surfel_);
/* Skip opaque and transparent tagging for light baking. */
return;

View File

@ -120,7 +120,7 @@ void ShadingView::render()
/* TODO(fclem): Move it after the first prepass (and hiz update) once pipeline is stabilized. */
inst_.lights.set_view(render_view_, extent_);
inst_.reflection_probes.set_view(render_view_);
inst_.sphere_probes.set_view(render_view_);
inst_.pipelines.background.render(render_view_);
@ -151,8 +151,8 @@ void ShadingView::render()
inst_.lights.debug_draw(render_view_, combined_fb_);
inst_.hiz_buffer.debug_draw(render_view_, combined_fb_);
inst_.shadows.debug_draw(render_view_, combined_fb_);
inst_.irradiance_cache.viewport_draw(render_view_, combined_fb_);
inst_.reflection_probes.viewport_draw(render_view_, combined_fb_);
inst_.volume_probes.viewport_draw(render_view_, combined_fb_);
inst_.sphere_probes.viewport_draw(render_view_, combined_fb_);
inst_.planar_probes.viewport_draw(render_view_, combined_fb_);
inst_.ambient_occlusion.render_pass(render_view_);
@ -237,7 +237,7 @@ void ShadingView::update_view()
void CaptureView::render_world()
{
const auto update_info = inst_.reflection_probes.world_update_info_pop();
const auto update_info = inst_.sphere_probes.world_update_info_pop();
if (!update_info.has_value()) {
return;
}
@ -256,19 +256,18 @@ void CaptureView::render_world()
update_info->clipping_distances.y);
view.sync(view_m4, win_m4);
combined_fb_.ensure(
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE_CUBEFACE(inst_.reflection_probes.cubemap_tx_, face));
combined_fb_.ensure(GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE_CUBEFACE(inst_.sphere_probes.cubemap_tx_, face));
GPU_framebuffer_bind(combined_fb_);
inst_.pipelines.world.render(view);
}
inst_.reflection_probes.remap_to_octahedral_projection(update_info->atlas_coord);
inst_.reflection_probes.update_probes_texture_mipmaps();
inst_.sphere_probes.remap_to_octahedral_projection(update_info->atlas_coord);
inst_.sphere_probes.update_probes_texture_mipmaps();
}
if (update_info->do_world_irradiance_update) {
inst_.reflection_probes.update_world_irradiance();
inst_.sphere_probes.update_world_irradiance();
}
GPU_debug_group_end();
@ -279,7 +278,7 @@ void CaptureView::render_probes()
Framebuffer prepass_fb;
View view = {"Capture.View"};
bool do_update_mipmap_chain = false;
while (const auto update_info = inst_.reflection_probes.probe_update_info_pop()) {
while (const auto update_info = inst_.sphere_probes.probe_update_info_pop()) {
GPU_debug_group_begin("Probe.Capture");
do_update_mipmap_chain = true;
@ -305,17 +304,15 @@ void CaptureView::render_probes()
update_info->clipping_distances.y);
view.sync(view_m4, win_m4);
combined_fb_.ensure(
GPU_ATTACHMENT_TEXTURE(inst_.render_buffers.depth_tx),
GPU_ATTACHMENT_TEXTURE_CUBEFACE(inst_.reflection_probes.cubemap_tx_, face));
combined_fb_.ensure(GPU_ATTACHMENT_TEXTURE(inst_.render_buffers.depth_tx),
GPU_ATTACHMENT_TEXTURE_CUBEFACE(inst_.sphere_probes.cubemap_tx_, face));
gbuffer_fb_.ensure(
GPU_ATTACHMENT_TEXTURE(inst_.render_buffers.depth_tx),
GPU_ATTACHMENT_TEXTURE_CUBEFACE(inst_.reflection_probes.cubemap_tx_, face),
GPU_ATTACHMENT_TEXTURE(inst_.gbuffer.header_tx),
GPU_ATTACHMENT_TEXTURE_LAYER(inst_.gbuffer.normal_tx.layer_view(0), 0),
GPU_ATTACHMENT_TEXTURE_LAYER(inst_.gbuffer.closure_tx.layer_view(0), 0),
GPU_ATTACHMENT_TEXTURE_LAYER(inst_.gbuffer.closure_tx.layer_view(1), 0));
gbuffer_fb_.ensure(GPU_ATTACHMENT_TEXTURE(inst_.render_buffers.depth_tx),
GPU_ATTACHMENT_TEXTURE_CUBEFACE(inst_.sphere_probes.cubemap_tx_, face),
GPU_ATTACHMENT_TEXTURE(inst_.gbuffer.header_tx),
GPU_ATTACHMENT_TEXTURE_LAYER(inst_.gbuffer.normal_tx.layer_view(0), 0),
GPU_ATTACHMENT_TEXTURE_LAYER(inst_.gbuffer.closure_tx.layer_view(0), 0),
GPU_ATTACHMENT_TEXTURE_LAYER(inst_.gbuffer.closure_tx.layer_view(1), 0));
GPU_framebuffer_bind(combined_fb_);
GPU_framebuffer_clear_color_depth(combined_fb_, float4(0.0f, 0.0f, 0.0f, 1.0f), 1.0f);
@ -325,12 +322,12 @@ void CaptureView::render_probes()
inst_.render_buffers.release();
inst_.gbuffer.release();
GPU_debug_group_end();
inst_.reflection_probes.remap_to_octahedral_projection(update_info->atlas_coord);
inst_.sphere_probes.remap_to_octahedral_projection(update_info->atlas_coord);
}
if (do_update_mipmap_chain) {
/* TODO: only update the regions that have been updated. */
inst_.reflection_probes.update_probes_texture_mipmaps();
inst_.sphere_probes.update_probes_texture_mipmaps();
}
}

View File

@ -192,8 +192,8 @@ void VolumeModule::end_sync()
scatter_ps_.shader_set(
inst_.shaders.static_shader_get(use_lights_ ? VOLUME_SCATTER_WITH_LIGHTS : VOLUME_SCATTER));
inst_.lights.bind_resources(scatter_ps_);
inst_.reflection_probes.bind_resources(scatter_ps_);
inst_.irradiance_cache.bind_resources(scatter_ps_);
inst_.sphere_probes.bind_resources(scatter_ps_);
inst_.volume_probes.bind_resources(scatter_ps_);
inst_.shadows.bind_resources(scatter_ps_);
inst_.sampling.bind_resources(scatter_ps_);
scatter_ps_.bind_image("in_scattering_img", &prop_scattering_tx_);

View File

@ -34,7 +34,7 @@ LightProbeSample lightprobe_load(vec3 P, vec3 Ng, vec3 V)
}
/* Return the best parallax corrected ray direction from the probe center. */
vec3 lightprobe_sphere_parallax(ReflectionProbeData probe, vec3 P, vec3 L)
vec3 lightprobe_sphere_parallax(SphereProbeData probe, vec3 P, vec3 L)
{
bool is_world = (probe.influence_scale == 0.0);
if (is_world) {
@ -63,7 +63,7 @@ vec3 lightprobe_sphere_parallax(ReflectionProbeData probe, vec3 P, vec3 L)
vec3 lightprobe_spherical_sample_normalized_with_parallax(
int probe_index, vec3 P, vec3 L, float lod, SphericalHarmonicL1 P_sh)
{
ReflectionProbeData probe = reflection_probe_buf[probe_index];
SphereProbeData probe = reflection_probe_buf[probe_index];
ReflectionProbeLowFreqLight shading_sh = reflection_probes_extract_low_freq(P_sh);
vec3 normalization_factor = reflection_probes_normalization_eval(
L, shading_sh, probe.low_freq_light);

View File

@ -67,7 +67,7 @@ void irradiance_capture_world(vec3 L, inout SphericalHarmonicL1 sh)
float visibility = 0.0;
if (capture_info_buf.capture_world_direct) {
ReflectionProbeCoordinate atlas_coord = capture_info_buf.world_atlas_coord;
SphereProbeUvArea atlas_coord = capture_info_buf.world_atlas_coord;
radiance = reflection_probes_sample(L, 0.0, atlas_coord).rgb;
/* Clamped brightness. */

View File

@ -68,7 +68,7 @@ int lightprobe_planar_select(vec3 P, vec3 V, vec3 L)
float best_score = saturate(dot(L, -V));
int best_index = -1;
for (int index = 0; index < PLANAR_PROBES_MAX; index++) {
for (int index = 0; index < PLANAR_PROBE_MAX; index++) {
if (probe_planar_buf[index].layer_id == -1) {
/* ProbePlanarData doesn't contain any gap, exit at first item that is invalid. */
break;

View File

@ -11,9 +11,9 @@
#ifdef REFLECTION_PROBE
int reflection_probes_select(vec3 P, float random_probe)
{
for (int index = 0; index < REFLECTION_PROBES_MAX; index++) {
ReflectionProbeData probe_data = reflection_probe_buf[index];
/* ReflectionProbeData doesn't contain any gap, exit at first item that is invalid. */
for (int index = 0; index < REFLECTION_PROBE_MAX; index++) {
SphereProbeData probe_data = reflection_probe_buf[index];
/* SphereProbeData doesn't contain any gap, exit at first item that is invalid. */
if (probe_data.atlas_coord.layer == -1) {
/* We hit the end of the array. Return last valid index. */
return index - 1;
@ -29,6 +29,6 @@ int reflection_probes_select(vec3 P, float random_probe)
}
}
/* This should never happen (world probe is always last). */
return REFLECTION_PROBES_MAX - 1;
return REFLECTION_PROBE_MAX - 1;
}
#endif /* REFLECTION_PROBE */

View File

@ -7,7 +7,7 @@
#pragma BLENDER_REQUIRE(eevee_spherical_harmonics_lib.glsl)
#ifdef REFLECTION_PROBE
vec4 reflection_probes_sample(vec3 L, float lod, ReflectionProbeCoordinate atlas_coord)
vec4 reflection_probes_sample(vec3 L, float lod, SphereProbeUvArea atlas_coord)
{
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);

View File

@ -7,18 +7,18 @@
#pragma BLENDER_REQUIRE(eevee_octahedron_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_colorspace_lib.glsl)
ReflectionProbeCoordinate reinterpret_as_atlas_coord(ivec4 packed_coord)
SphereProbeUvArea reinterpret_as_atlas_coord(ivec4 packed_coord)
{
ReflectionProbeCoordinate unpacked;
SphereProbeUvArea 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)
SphereProbePixelArea reinterpret_as_write_coord(ivec4 packed_coord)
{
ReflectionProbeWriteCoordinate unpacked;
SphereProbePixelArea unpacked;
unpacked.offset = packed_coord.xy;
unpacked.extent = packed_coord.z;
unpacked.layer = packed_coord.w;
@ -40,9 +40,9 @@ vec2 mirror_repeat_uv(vec2 uv)
void main()
{
ReflectionProbeCoordinate 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);
SphereProbeUvArea world_coord = reinterpret_as_atlas_coord(world_coord_packed);
SphereProbeUvArea sample_coord = reinterpret_as_atlas_coord(probe_coord_packed);
SphereProbePixelArea write_coord = reinterpret_as_write_coord(write_coord_packed);
/* Texel in probe. */
ivec2 local_texel = ivec2(gl_GlobalInvocationID.xy);

View File

@ -9,9 +9,9 @@
#pragma BLENDER_REQUIRE(eevee_octahedron_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
ReflectionProbeCoordinate reinterpret_as_atlas_coord(ivec4 packed_coord)
SphereProbeUvArea reinterpret_as_atlas_coord(ivec4 packed_coord)
{
ReflectionProbeCoordinate unpacked;
SphereProbeUvArea unpacked;
unpacked.offset = intBitsToFloat(packed_coord.xy);
unpacked.scale = intBitsToFloat(packed_coord.z);
unpacked.layer = intBitsToFloat(packed_coord.w);
@ -42,7 +42,7 @@ void main()
cooef.L1.M0 = vec4(0.0);
cooef.L1.Mp1 = vec4(0.0);
ReflectionProbeCoordinate atlas_coord = reinterpret_as_atlas_coord(world_coord_packed);
SphereProbeUvArea atlas_coord = reinterpret_as_atlas_coord(world_coord_packed);
float layer_mipmap = 5;
/* Perform multiple sample. */
uint store_index = gl_LocalInvocationID.x;

View File

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

View File

@ -213,7 +213,7 @@ GPU_SHADER_CREATE_INFO(eevee_lightprobe_data)
GPU_SHADER_CREATE_INFO(eevee_lightprobe_planar_data)
.define("REFLECTION_PROBE")
.uniform_buf(PLANAR_PROBE_BUF_SLOT, "ProbePlanarData", "probe_planar_buf[PLANAR_PROBES_MAX]")
.uniform_buf(PLANAR_PROBE_BUF_SLOT, "ProbePlanarData", "probe_planar_buf[PLANAR_PROBE_MAX]")
.sampler(PLANAR_PROBE_RADIANCE_TEX_SLOT, ImageType::FLOAT_2D_ARRAY, "planar_radiance_tx")
.sampler(PLANAR_PROBE_DEPTH_TEX_SLOT, ImageType::DEPTH_2D_ARRAY, "planar_depth_tx");

View File

@ -12,8 +12,8 @@
GPU_SHADER_CREATE_INFO(eevee_reflection_probe_data)
.define("REFLECTION_PROBE")
.uniform_buf(REFLECTION_PROBE_BUF_SLOT,
"ReflectionProbeData",
"reflection_probe_buf[REFLECTION_PROBES_MAX]")
"SphereProbeData",
"reflection_probe_buf[REFLECTION_PROBE_MAX]")
.sampler(REFLECTION_PROBE_TEX_SLOT, ImageType::FLOAT_2D_ARRAY, "reflection_probes_tx");
/* Sample cubemap and remap into an octahedral texture. */
@ -47,8 +47,8 @@ GPU_SHADER_CREATE_INFO(eevee_reflection_probe_select)
.local_group_size(REFLECTION_PROBE_SELECT_GROUP_SIZE)
.storage_buf(0,
Qualifier::READ_WRITE,
"ReflectionProbeData",
"reflection_probe_buf[REFLECTION_PROBES_MAX]")
"SphereProbeData",
"reflection_probe_buf[REFLECTION_PROBE_MAX]")
.push_constant(Type::INT, "reflection_probe_count")
.additional_info("eevee_shared", "eevee_sampling_data", "eevee_volume_probe_data")
.compute_source("eevee_reflection_probe_select_comp.glsl")
@ -60,7 +60,7 @@ GPU_SHADER_INTERFACE_INFO(eevee_display_probe_reflection_iface, "")
GPU_SHADER_CREATE_INFO(eevee_display_probe_reflection)
.additional_info("eevee_shared", "draw_view", "eevee_reflection_probe_data")
.storage_buf(0, Qualifier::READ, "ReflectionProbeDisplayData", "display_data_buf[]")
.storage_buf(0, Qualifier::READ, "SphereProbeDisplayData", "display_data_buf[]")
.vertex_source("eevee_display_probe_reflection_vert.glsl")
.vertex_out(eevee_display_probe_reflection_iface)
.fragment_source("eevee_display_probe_reflection_frag.glsl")