Refactor: EEVEE-Next: Light-probe management and structure #117941
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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)));
|
||||
|
@ -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());
|
||||
|
@ -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(){};
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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>;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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_);
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user