Fix #122456: EEVEE: Reset history on volume updates

Pull Request: https://projects.blender.org/blender/blender/pulls/123916
This commit is contained in:
Miguel Pozo
2024-07-02 17:07:43 +02:00
parent b0fbd550e0
commit 9691ff004a
5 changed files with 72 additions and 6 deletions

View File

@@ -124,6 +124,7 @@ void SyncModule::sync_mesh(Object *ob,
bool is_alpha_blend = false;
bool has_transparent_shadows = false;
bool has_volume = false;
float inflate_bounds = 0.0f;
for (auto i : material_array.gpu_materials.index_range()) {
gpu::Batch *geom = mat_geom[i];
@@ -137,6 +138,7 @@ void SyncModule::sync_mesh(Object *ob,
if (material.has_volume) {
volume_call(material.volume_occupancy, inst_.scene, ob, geom, res_handle);
volume_call(material.volume_material, inst_.scene, ob, geom, res_handle);
has_volume = true;
/* Do not render surface if we are rendering a volume object
* and do not have a surface closure. */
if (!material.has_surface) {
@@ -166,6 +168,10 @@ void SyncModule::sync_mesh(Object *ob,
}
}
if (has_volume) {
inst_.volume.object_sync(ob_handle);
}
if (inflate_bounds != 0.0f) {
inst_.manager->update_handle_bounds(res_handle, ob_ref, inflate_bounds);
}
@@ -203,6 +209,7 @@ bool SyncModule::sync_sculpt(Object *ob,
bool is_alpha_blend = false;
bool has_transparent_shadows = false;
bool has_volume = false;
float inflate_bounds = 0.0f;
for (SculptBatch &batch :
sculpt_batches_per_material_get(ob_ref.object, material_array.gpu_materials))
@@ -217,6 +224,7 @@ bool SyncModule::sync_sculpt(Object *ob,
if (material.has_volume) {
volume_call(material.volume_occupancy, inst_.scene, ob, geom, res_handle);
volume_call(material.volume_material, inst_.scene, ob, geom, res_handle);
has_volume = true;
/* Do not render surface if we are rendering a volume object
* and do not have a surface closure. */
if (material.has_surface == false) {
@@ -247,6 +255,10 @@ bool SyncModule::sync_sculpt(Object *ob,
}
}
if (has_volume) {
inst_.volume.object_sync(ob_handle);
}
/* Use a valid bounding box. The PBVH module already does its own culling, but a valid */
/* bounding box is still needed for directional shadow tile-map bounds computation. */
const Bounds<float3> bounds = bke::pbvh::bounds_get(*ob_ref.object->sculpt->pbvh);
@@ -294,6 +306,7 @@ void SyncModule::sync_point_cloud(Object *ob,
/* Only support single volume material for now. */
drawcall_add(material.volume_occupancy);
drawcall_add(material.volume_material);
inst_.volume.object_sync(ob_handle);
/* Do not render surface if we are rendering a volume object
* and do not have a surface closure. */
@@ -338,7 +351,7 @@ void SyncModule::sync_point_cloud(Object *ob,
* \{ */
void SyncModule::sync_volume(Object *ob,
ObjectHandle & /*ob_handle*/,
ObjectHandle &ob_handle,
ResourceHandle res_handle,
const ObjectRef &ob_ref)
{
@@ -372,6 +385,8 @@ void SyncModule::sync_volume(Object *ob,
drawcall_add(material.volume_occupancy, geom, res_handle);
drawcall_add(material.volume_material, geom, res_handle);
inst_.volume.object_sync(ob_handle);
}
/** \} */
@@ -566,6 +581,7 @@ void SyncModule::sync_curves(Object *ob,
/* Only support single volume material for now. */
drawcall_add(material.volume_occupancy);
drawcall_add(material.volume_material);
inst_.volume.object_sync(ob_handle);
/* Do not render surface if we are rendering a volume object
* and do not have a surface closure. */
if (material.has_surface == false) {

View File

@@ -58,7 +58,34 @@ void VolumeModule::init()
use_reprojection_ = (scene_eval->eevee.flag & SCE_EEVEE_TAA_REPROJECTION) != 0;
}
void VolumeModule::begin_sync() {}
void VolumeModule::begin_sync()
{
previous_objects_ = current_objects_;
current_objects_.clear();
}
void VolumeModule::world_sync(const WorldHandle &world_handle)
{
if (!use_reprojection_) {
return;
}
if (world_handle.recalc && !inst_.is_playback()) {
valid_history_ = false;
}
}
void VolumeModule::object_sync(const ObjectHandle &ob_handle)
{
if (!use_reprojection_) {
return;
}
if (ob_handle.recalc && !inst_.is_playback()) {
valid_history_ = false;
}
current_objects_.add(ob_handle.object_key);
}
void VolumeModule::end_sync()
{
@@ -94,6 +121,13 @@ void VolumeModule::end_sync()
valid_history_ = false;
}
if (valid_history_) {
/* Avoid the (potentially expensive) check if valid_history_ is already false. */
if (current_objects_ != previous_objects_) {
valid_history_ = false;
}
}
if (inst_.camera.is_perspective()) {
float sample_distribution = scene_eval->eevee.volumetric_sample_distribution;
sample_distribution = 4.0f * math::max(1.0f - sample_distribution, 1e-2f);

View File

@@ -35,6 +35,7 @@
#pragma once
#include "BLI_set.hh"
#include "eevee_shader_shared.hh"
namespace blender::eevee {
@@ -54,6 +55,10 @@ class VolumeModule {
bool use_reprojection_;
bool use_lights_;
/* Track added/removed volume objects to reset the accumulation history. */
Set<ObjectKey> previous_objects_;
Set<ObjectKey> current_objects_;
VolumesInfoData &data_;
/**
@@ -134,6 +139,10 @@ class VolumeModule {
void begin_sync();
void world_sync(const WorldHandle &world_handle);
void object_sync(const ObjectHandle &ob_handle);
void end_sync();
/* Render material properties. */

View File

@@ -101,14 +101,15 @@ void World::sync()
{
bool has_update = false;
WorldHandle wo_handle = {0};
if (inst_.scene->world != nullptr) {
/* Detect world update before overriding it. */
WorldHandle wo_handle = inst_.sync.sync_world();
wo_handle = inst_.sync.sync_world();
has_update = wo_handle.recalc != 0;
}
/* Sync volume first since its result can override the surface world. */
sync_volume();
sync_volume(wo_handle);
::World *bl_world;
if (inst_.use_studio_light()) {
@@ -156,7 +157,7 @@ void World::sync()
inst_.pipelines.world.sync(gpumat);
}
void World::sync_volume()
void World::sync_volume(const WorldHandle &world_handle)
{
/* Studio lights have no volume shader. */
::World *world = inst_.use_studio_light() ? nullptr : inst_.scene->world;
@@ -168,6 +169,8 @@ void World::sync_volume()
gpumat = inst_.shaders.world_shader_get(world, world->nodetree, MAT_PIPE_VOLUME_MATERIAL);
}
bool had_volume = has_volume_;
if (gpumat && (GPU_material_status(gpumat) == GPU_MAT_SUCCESS)) {
has_volume_ = GPU_material_has_volume_output(gpumat);
has_volume_scatter_ = GPU_material_flag_get(gpumat, GPU_MATFLAG_VOLUME_SCATTER);
@@ -179,6 +182,10 @@ void World::sync_volume()
/* World volume needs to be always synced for correct clearing of parameter buffers. */
inst_.pipelines.world_volume.sync(gpumat);
if (has_volume_ || had_volume) {
inst_.volume.world_sync(world_handle);
}
}
/** \} */

View File

@@ -127,7 +127,7 @@ class World {
}
private:
void sync_volume();
void sync_volume(const WorldHandle &world_handle);
/* Returns a dummy black world for when a valid world isn't present or when we want to suppress
* any light coming from the world. */