Fix #131506: EEVEE: GP disappear when resolution scale > 1

Now EEVEE outputs the in-progress render depth buffer
for GPencil to intersect with.

The overlays will clear the depth buffer in such situation
and still do the depth prepass for correct intersection.

Moreover, this patch makes overlay engine not requiring
a depth prepass when run with EEVEE at 1:1 render resolution.
This avoids significant overhead of the depth prepass.

Pull Request: https://projects.blender.org/blender/blender/pulls/133971
This commit is contained in:
Clément Foucault
2025-02-03 14:45:46 +01:00
committed by Clément Foucault
parent aa8769599c
commit 3929a37786
4 changed files with 21 additions and 11 deletions

View File

@@ -623,11 +623,6 @@ void film_store_weight(ivec2 texel, float value)
float film_display_depth_amend(ivec2 texel, float depth)
{
if (scaling_factor > 1) {
/* The workaround below creates ugly artifacts for overlays relying on depth equal tests.
* In this case, it is better to rely on overlay engine to do a depth pass (see #124013). */
return 1.0;
}
/* This effectively offsets the depth of the whole 2x2 region to the lowest value of the region
* twice. One for X and one for Y direction. */
/* TODO(fclem): This could be improved as it gives flickering result at depth discontinuity.

View File

@@ -59,6 +59,12 @@ void Instance::init()
state.xray_opacity = state.xray_enabled ? XRAY_ALPHA(state.v3d) : 1.0f;
state.xray_flag_enabled = SHADING_XRAY_FLAG_ENABLED(state.v3d->shading) &&
!state.is_depth_only_drawing;
/* Only workbench ensures the depth buffer is matching overlays.
* Force depth prepass for other render engines.
* EEVEE is an exception (if not using mixed resolution) to avoid a significant overhead. */
state.is_render_depth_available = state.v3d->shading.type <= OB_SOLID ||
(BKE_scene_uses_blender_eevee(state.scene) &&
BKE_render_preview_pixel_size(&state.scene->r) == 1);
if (!state.hide_overlays) {
state.overlay = state.v3d->overlay;
@@ -88,6 +94,8 @@ void Instance::init()
state.is_wireframe_mode = false;
state.hide_overlays = (space_image->overlay.flag & SI_OVERLAY_SHOW_OVERLAYS) == 0;
state.xray_enabled = false;
/* Avoid triggering the depth prepass. */
state.is_render_depth_available = true;
/* During engine initialization phase the `space_image` isn't locked and we are able to
* retrieve the needed data. During cache_init the image engine locks the `space_image` and
@@ -520,7 +528,14 @@ void Instance::draw_v3d(Manager &manager, View &view)
GPU_framebuffer_clear_color_depth(resources.overlay_line_fb, clear_color, 1.0f);
}
else {
GPU_framebuffer_clear_color(resources.overlay_line_fb, clear_color);
if (!state.is_render_depth_available) {
/* If the render engine is not outputing correct depth,
* clear the depth and render a depth prepass. */
GPU_framebuffer_clear_color_depth(resources.overlay_line_fb, clear_color, 1.0f);
}
else {
GPU_framebuffer_clear_color(resources.overlay_line_fb, clear_color);
}
}
/* TODO(fclem): Split overlay and rename draw functions. */
@@ -719,10 +734,8 @@ bool Instance::object_needs_prepass(const ObjectRef &ob_ref, bool in_paint_mode)
}
if (!state.xray_enabled) {
/* Only workbench ensures the depth buffer is matching overlays.
* Force depth prepass for other render engines. */
/* TODO(fclem): Make an exception for EEVEE if not using mixed resolution. */
return state.v3d && (state.v3d->shading.type > OB_SOLID) && (ob_ref.object->dt >= OB_SOLID);
/* Force depth prepass if depth buffer form render engine is not available. */
return !state.is_render_depth_available && (ob_ref.object->dt >= OB_SOLID);
}
return false;

View File

@@ -256,7 +256,7 @@ class Prepass : Overlay {
pass = curves_ps_;
break;
case OB_GREASE_PENCIL:
if (!res.is_selection()) {
if (!res.is_selection() && state.is_render_depth_available) {
/* Disable during display, only enable for selection.
* The grease pencil engine already renders it properly. */
return;

View File

@@ -144,6 +144,8 @@ struct State {
bool is_material_select = false;
/** Whether we should render the background or leave it transparent. */
bool draw_background = false;
/** True if the render engine outputs satisfactory depth information to the depth buffer. */
bool is_render_depth_available = false;
/** Should text draw in this mode? */
bool show_text = false;
bool hide_overlays = false;