WIP: Eevee-next: Reflection Probes #108497

Closed
Jeroen Bakker wants to merge 24 commits from Jeroen-Bakker:eevee-next-reflection-probes into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
3 changed files with 39 additions and 7 deletions
Showing only changes of commit 01327c22ef - Show all commits

View File

@ -210,6 +210,7 @@ void Instance::end_sync()
lights.end_sync();
sampling.end_sync();
subsurface.end_sync();
reflection_probes.end_sync();
film.end_sync();
cryptomatte.end_sync();
pipelines.end_sync();

View File

@ -25,12 +25,17 @@ void ReflectionProbeModule::init()
MIPMAP_LEVELS);
GPU_texture_mipmap_mode(cubemaps_tx_, true, true);
}
for (ReflectionProbe &reflection_probe : cubemaps_) {
if (reflection_probe.type == ReflectionProbe::Type::Probe) {
reflection_probe.is_used = false;
}
}
}
void ReflectionProbeModule::sync()
{
for (int index : IndexRange(MAX_PROBES)) {
ReflectionProbe &cubemap = cubemaps_[index];
for (ReflectionProbe &cubemap : cubemaps_) {
if (!cubemap.needs_update()) {
continue;
}
@ -75,7 +80,10 @@ ReflectionProbe &ReflectionProbeModule::find_or_insert(ObjectHandle &ob_handle)
{
ReflectionProbe *first_unused = nullptr;
for (ReflectionProbe &reflection_probe : cubemaps_) {
if (reflection_probe.object_hash_value == ob_handle.object_key.hash_value) {
if (reflection_probe.type == ReflectionProbe::Type::Probe &&
reflection_probe.object_hash_value == ob_handle.object_key.hash_value)
{
reflection_probe.is_used = true;
return reflection_probe;
}
if (first_unused == nullptr && reflection_probe.type == ReflectionProbe::Type::Unused) {
@ -90,14 +98,23 @@ ReflectionProbe &ReflectionProbeModule::find_or_insert(ObjectHandle &ob_handle)
}
BLI_assert(first_unused != nullptr);
first_unused->is_dirty = true;
first_unused->is_used = true;
first_unused->object_hash_value = ob_handle.object_key.hash_value;
first_unused->type = ReflectionProbe::Type::Probe;
/* TODO: We should free slots that aren't used anymore. This could be implemented with a tag
* or priority list. */
return *first_unused;
}
void ReflectionProbeModule::end_sync()
{
for (ReflectionProbe &probe : cubemaps_) {
if (probe.type == ReflectionProbe::Type::Probe && !probe.is_used) {
probe.type = ReflectionProbe::Type::Unused;
probe.object_hash_value = 0;
}
}
}
/* -------------------------------------------------------------------- */
/** \name World
*
@ -105,7 +122,15 @@ ReflectionProbe &ReflectionProbeModule::find_or_insert(ObjectHandle &ob_handle)
bool ReflectionProbe::needs_update() const
{
return type != Type::Unused && is_dirty;
switch (type) {
case Type::Unused:
return false;
case Type::World:
return is_dirty;
case Type::Probe:
return is_dirty && is_used;
}
return false;
}
/** \} */

View File

@ -40,12 +40,17 @@ class ReflectionProbe {
public:
enum Type { Unused, World, Probe };
Type type;
Type type = Type::Unused;
bool is_dirty = false;
/* When reflection probe is a probe its ObjectKey.hash_value is copied here to keep track between
* draws.*/
uint32_t object_hash_value = 0;
/**
* Probes that aren't used during a draw can be cleared.
*/
bool is_used = false;
bool needs_update() const;
};
@ -82,6 +87,7 @@ class ReflectionProbeModule {
void sync();
void sync_object(Object *ob, ObjectHandle &ob_handle, ResourceHandle res_handle, bool is_dirty);
void end_sync();
template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
{