Fix: #126455: Missing refraction with only emissive material

When the opaque layer was populated with only emissive
material, no raytracing was used for it and no feedback
buffer was needed. Thus, the refraction layer had nothing
to raytrace against.

This fixes it by forcing the use of feedback buffer in this
corner case.

Pull Request: https://projects.blender.org/blender/blender/pulls/127771
This commit is contained in:
Clément Foucault
2024-09-18 12:29:02 +02:00
committed by Clément Foucault
parent b5d418a83f
commit 318eab5584
2 changed files with 16 additions and 5 deletions

View File

@@ -555,9 +555,14 @@ void DeferredLayer::begin_sync()
this->gbuffer_pass_sync(inst_);
}
void DeferredLayer::end_sync(bool is_first_pass, bool is_last_pass)
void DeferredLayer::end_sync(bool is_first_pass,
bool is_last_pass,
bool next_layer_has_transmission)
{
const SceneEEVEE &sce_eevee = inst_.scene->eevee;
const bool has_any_closure = closure_bits_ != 0;
/* We need the feedback output in case of refraction in the next pass (see #126455). */
const bool is_layer_refracted = (next_layer_has_transmission && has_any_closure);
const bool has_transmit_closure = (closure_bits_ & (CLOSURE_REFRACTION | CLOSURE_TRANSLUCENT));
const bool has_reflect_closure = (closure_bits_ & (CLOSURE_REFLECTION | CLOSURE_DIFFUSE));
use_raytracing_ = (has_transmit_closure || has_reflect_closure) &&
@@ -572,7 +577,8 @@ void DeferredLayer::end_sync(bool is_first_pass, bool is_last_pass)
use_screen_reflection_ = use_raytracing_ && has_reflect_closure;
use_split_radiance_ = use_raytracing_ || (use_clamp_direct_ || use_clamp_indirect_);
use_feedback_output_ = use_raytracing_ && (!is_last_pass || use_screen_reflection_);
use_feedback_output_ = (use_raytracing_ || is_layer_refracted) &&
(!is_last_pass || use_screen_reflection_);
{
RenderBuffersInfoData &rbuf_data = inst_.render_buffers.data;
@@ -890,8 +896,8 @@ void DeferredPipeline::begin_sync()
void DeferredPipeline::end_sync()
{
opaque_layer_.end_sync(true, refraction_layer_.is_empty());
refraction_layer_.end_sync(opaque_layer_.is_empty(), true);
opaque_layer_.end_sync(true, refraction_layer_.is_empty(), refraction_layer_.has_transmission());
refraction_layer_.end_sync(opaque_layer_.is_empty(), true, false);
debug_pass_sync();
}

View File

@@ -303,7 +303,7 @@ class DeferredLayer : DeferredLayerBase {
}
void begin_sync();
void end_sync(bool is_first_pass, bool is_last_pass);
void end_sync(bool is_first_pass, bool is_last_pass, bool next_layer_has_transmission);
PassMain::Sub *prepass_add(::Material *blender_mat, GPUMaterial *gpumat, bool has_motion);
PassMain::Sub *material_add(::Material *blender_mat, GPUMaterial *gpumat);
@@ -313,6 +313,11 @@ class DeferredLayer : DeferredLayerBase {
return closure_count_ == 0;
}
bool has_transmission() const
{
return closure_bits_ & CLOSURE_TRANSMISSION;
}
/* Returns the radiance buffer to feed the next layer. */
GPUTexture *render(View &main_view,
View &render_view,