From 8945b297628ca14aefc82e00fd3d6dce8a2f2638 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 18 Mar 2024 16:02:57 +0100 Subject: [PATCH] EEVEE: Overscan/Border mixed resolution rendering Mixed resolution rendering had some issues with overscan and border rendering. - `render_offset` was in display space and not in render space. Is now replaced by the `overscan_extent`. - `overscan_extent` introduced that stored the overscan of the render extent. - Fixed issues to determine the film sample weight when `scaling_factor` was used. It didn't match decompose the actual offset making the length of the same to large, what blurred the final samples. NOTE: there are some other issues related to border rendering which was already in main before mixed resolution rendering was added. I assume that viewport render image in camera view still adds an additional offset, which should be ignored. Fixes #119510 Fixes #119511 Pull Request: https://projects.blender.org/blender/blender/pulls/119524 --- source/blender/draw/engines/eevee_next/eevee_film.cc | 9 ++++----- .../draw/engines/eevee_next/eevee_shader_shared.hh | 10 +++++++--- source/blender/draw/engines/eevee_next/eevee_view.cc | 2 +- .../engines/eevee_next/shaders/eevee_film_lib.glsl | 8 +++++--- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_film.cc b/source/blender/draw/engines/eevee_next/eevee_film.cc index 7dd5d9b0e6f..13ca615c131 100644 --- a/source/blender/draw/engines/eevee_next/eevee_film.cc +++ b/source/blender/draw/engines/eevee_next/eevee_film.cc @@ -151,7 +151,7 @@ void Film::sync_mist() inline bool operator==(const FilmData &a, const FilmData &b) { return (a.extent == b.extent) && (a.offset == b.offset) && - (a.render_extent == b.render_extent) && (a.render_offset == b.render_offset) && + (a.render_extent == b.render_extent) && (a.overscan == b.overscan) && (a.filter_radius == b.filter_radius) && (a.scaling_factor == b.scaling_factor) && (a.background_opacity == b.background_opacity); } @@ -265,12 +265,11 @@ void Film::init(const int2 &extent, const rcti *output_rect) data_.offset = int2(output_rect->xmin, output_rect->ymin); data_.extent_inv = 1.0f / float2(data_.extent); data_.render_extent = math::divide_ceil(extent, int2(data_.scaling_factor)); - data_.render_offset = data_.offset; + data_.overscan = 0; if (inst_.camera.overscan() != 0.0f) { - int2 overscan = int2(inst_.camera.overscan() * math::max(UNPACK2(data_.render_extent))); - data_.render_extent += overscan * 2; - data_.render_offset += overscan; + data_.overscan = inst_.camera.overscan() * math::max(UNPACK2(data_.render_extent)); + data_.render_extent += data_.overscan * 2; } /* Disable filtering if sample count is 1. */ diff --git a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh index 9ba174578b0..845e1d6bb4c 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh @@ -262,10 +262,8 @@ struct FilmData { int2 extent; /** Offset to convert from Display space to Film space, in pixels. */ int2 offset; - /** Size of the render buffers when rendering the main views, in pixels. */ + /** Size of the render buffers including overscan when rendering the main views, in pixels. */ int2 render_extent; - /** Offset to convert from Film space to Render space, in pixels. */ - int2 render_offset; /** * Sub-pixel offset applied to the window matrix. * NOTE: In final film pixel unit. @@ -276,6 +274,11 @@ struct FilmData { float2 subpixel_offset; /** Scaling factor to convert texel to uvs. */ float2 extent_inv; + /** + * Number of border pixels on all sides inside the render_extent that do not contribute to the + * final image. + */ + int overscan; /** Is true if history is valid and can be sampled. Bypass history to resets accumulation. */ bool32_t use_history; /** Controlled by user in lookdev mode or by render settings. */ @@ -328,6 +331,7 @@ struct FilmData { /** Sum of the weights of all samples in the sample table. */ float samples_weight_total; int _pad1; + int _pad2; FilmSample samples[FILM_PRECOMP_SAMPLE_MAX]; }; BLI_STATIC_ASSERT_ALIGN(FilmData, 16) diff --git a/source/blender/draw/engines/eevee_next/eevee_view.cc b/source/blender/draw/engines/eevee_next/eevee_view.cc index 828875cc79a..4d0931e106d 100644 --- a/source/blender/draw/engines/eevee_next/eevee_view.cc +++ b/source/blender/draw/engines/eevee_next/eevee_view.cc @@ -216,7 +216,7 @@ void ShadingView::update_view() */ int2 scaling_factor = int2(inst_.film.scaling_factor_get()); int2 display_extent = inst_.film.display_extent_get(); - int2 overscan = inst_.film.get_data().render_offset - inst_.film.get_data().offset; + int overscan = inst_.film.get_data().overscan; int2 rescaled_render_extent = (extent_ - 2 * overscan) * scaling_factor; if (rescaled_render_extent != display_extent) { diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl index acb2d1e3862..d25f1f04f91 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl @@ -55,7 +55,8 @@ FilmSample film_sample_get(int sample_n, ivec2 texel_film) #else FilmSample film_sample = uniform_buf.film.samples[sample_n]; - film_sample.texel += (texel_film / scaling_factor) + uniform_buf.film.render_offset; + film_sample.texel += (texel_film + uniform_buf.film.offset) / scaling_factor + + uniform_buf.film.overscan; /* Use extend on borders. */ film_sample.texel = clamp(film_sample.texel, ivec2(0, 0), uniform_buf.film.render_extent - 1); @@ -64,9 +65,10 @@ FilmSample film_sample_get(int sample_n, ivec2 texel_film) if (scaling_factor > 1) { /* We need to compute the real distance and weight since a sample * can be used by many final pixel. */ - vec2 offset = (vec2(film_sample.texel) + 0.5 - uniform_buf.film.subpixel_offset) * + vec2 offset = (vec2(film_sample.texel - uniform_buf.film.overscan) + 0.5 - + uniform_buf.film.subpixel_offset) * scaling_factor - - (vec2(texel_film) + 0.5); + (vec2(texel_film + uniform_buf.film.offset) + 0.5); film_sample.weight = film_filter_weight(uniform_buf.film.filter_radius, length_squared(offset)); }