Skip to content

Commit

Permalink
Fix 2D/3D view artifacts on view's border when using fractional zoom (#…
Browse files Browse the repository at this point in the history
…8369)

### Related

* Fixes #8330

### What

Wasn't able to repro the issue in the first place though - tried
fractional zoom and a contrast heavy background to no avail
* [x] confirm this fixes it

---------

Co-authored-by: Antoine Beyeler <[email protected]>
  • Loading branch information
Wumpf and abey79 authored Dec 16, 2024
1 parent 6288d04 commit 02a8757
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 36 deletions.
4 changes: 2 additions & 2 deletions crates/viewer/re_renderer/shader/composite.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fn main(in: FragmentInput) -> @location(0) vec4f {
// Note that we can't use a simple textureLoad using @builtin(position) here despite the lack of filtering.
// The issue is that positions provided by @builtin(position) are not dependent on the set viewport,
// but are about the location of the texel in the target texture.
var color = textureSample(color_texture, nearest_sampler, in.texcoord);
var color = textureSample(color_texture, nearest_sampler_clamped, in.texcoord);


// TODO(andreas): We assume that the color from the texture does *not* have pre-multiplied alpha.
Expand All @@ -42,7 +42,7 @@ fn main(in: FragmentInput) -> @location(0) vec4f {

// Outlines
{
let closest_positions = textureSample(outline_voronoi_texture, nearest_sampler, in.texcoord);
let closest_positions = textureSample(outline_voronoi_texture, nearest_sampler_clamped, in.texcoord);

let distance_pixel_a = distance(pixel_coordinates, closest_positions.xy);
let distance_pixel_b = distance(pixel_coordinates, closest_positions.zw);
Expand Down
2 changes: 1 addition & 1 deletion crates/viewer/re_renderer/shader/copy_texture.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ var tex: texture_2d<f32>;

@fragment
fn main(in: FragmentInput) -> @location(0) vec4f {
return textureSample(tex, nearest_sampler, in.texcoord);
return textureSample(tex, nearest_sampler_clamped, in.texcoord);
}
2 changes: 1 addition & 1 deletion crates/viewer/re_renderer/shader/debug_overlay.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn main_vs(@builtin(vertex_index) vertex_index: u32) -> VertexOutput {
@fragment
fn main_fs(in: VertexOutput) -> @location(0) vec4f {
if uniforms.mode == ShowFloatTexture {
return vec4f(textureSample(debug_texture_float, nearest_sampler, in.texcoord).rgb, 1.0);
return vec4f(textureSample(debug_texture_float, nearest_sampler_clamped, in.texcoord).rgb, 1.0);
} else if uniforms.mode == ShowUintTexture {
let coords = vec2i(in.texcoord * vec2f(textureDimensions(debug_texture_uint).xy));
let raw_values = textureLoad(debug_texture_uint, coords, 0);
Expand Down
7 changes: 4 additions & 3 deletions crates/viewer/re_renderer/shader/global_bindings.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ struct FrameUniformBuffer {
var<uniform> frame: FrameUniformBuffer;

@group(0) @binding(1)
var nearest_sampler: sampler;

var nearest_sampler_repeat: sampler;
@group(0) @binding(2)
var trilinear_sampler: sampler;
var nearest_sampler_clamped: sampler;
@group(0) @binding(3)
var trilinear_sampler_repeat: sampler;

// See config.rs#DeviceTier
const DEVICE_TIER_GLES = 0u;
Expand Down
2 changes: 1 addition & 1 deletion crates/viewer/re_renderer/shader/instanced_mesh.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fn vs_main(in_vertex: VertexIn, in_instance: InstanceIn) -> VertexOut {

@fragment
fn fs_main_shaded(in: VertexOut) -> @location(0) vec4f {
let texture = linear_from_srgb(textureSample(albedo_texture, trilinear_sampler, in.texcoord).rgb);
let texture = linear_from_srgb(textureSample(albedo_texture, trilinear_sampler_repeat, in.texcoord).rgb);
let albedo = texture
* in.color.rgb
* material.albedo_factor.rgb
Expand Down
26 changes: 16 additions & 10 deletions crates/viewer/re_renderer/shader/outlines/jumpflooding_init.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
@group(0) @binding(0)
var mask_texture: texture_2d<u32>;

fn has_edge(closest_center_sample: vec2u, sample_coord: vec2i) -> vec2f {
let mask_neighbor = textureLoad(mask_texture, sample_coord, 0).xy;
fn has_edge(max_coord: vec2i, closest_center_sample: vec2u, sample_coord: vec2i) -> vec2f {
// Note that `textureLoad` calls with out-of-bounds coordinates are allowed to return *any*
// value on the texture or "transparent"/"opaque" zero.
// See https://www.w3.org/TR/WGSL/#textureload
// Therefore, if we want consistent behavior, we have to do the clamp ourselves.
let clamped_coord = clamp(sample_coord, vec2i(0), max_coord);
let mask_neighbor = textureLoad(mask_texture, clamped_coord, 0).xy;
return vec2f(closest_center_sample != mask_neighbor);
}

Expand All @@ -15,6 +20,7 @@ fn has_edge(closest_center_sample: vec2u, sample_coord: vec2i) -> vec2f {
fn main(in: FragmentInput) -> @location(0) vec4f {
let resolution = textureDimensions(mask_texture).xy;
let center_coord = vec2i(vec2f(resolution) * in.texcoord);
let max_coord = vec2i(resolution) - vec2i(1);

let mask_center = textureLoad(mask_texture, center_coord, 0).xy;

Expand All @@ -25,51 +31,51 @@ fn main(in: FragmentInput) -> @location(0) vec4f {

// Sample closest neighbors top/bottom/left/right
{ // right
let edge = has_edge(mask_center, center_coord + vec2i(1, 0));
let edge = has_edge(max_coord, mask_center, center_coord + vec2i(1, 0));
let edge_pos = vec2f(1.0, 0.5);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // bottom
let edge = has_edge(mask_center, center_coord + vec2i(0, 1));
let edge = has_edge(max_coord, mask_center, center_coord + vec2i(0, 1));
let edge_pos = vec2f(0.5, 1.0);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // left
let edge = has_edge(mask_center, center_coord + vec2i(-1, 0));
let edge = has_edge(max_coord, mask_center, center_coord + vec2i(-1, 0));
let edge_pos = vec2f(0.0, 0.5);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // top
let edge = has_edge(mask_center, center_coord + vec2i(0, -1));
let edge = has_edge(max_coord, mask_center, center_coord + vec2i(0, -1));
let edge_pos = vec2f(0.5, 0.0);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}

// Sample closest neighbors diagonally.
{ // top-right
let edge = has_edge(mask_center, center_coord + vec2i(1, -1));
let edge = has_edge(max_coord, mask_center, center_coord + vec2i(1, -1));
let edge_pos = vec2f(1.0, 0.0);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // bottom-right
let edge = has_edge(mask_center, center_coord + vec2i(1, 1));
let edge = has_edge(max_coord, mask_center, center_coord + vec2i(1, 1));
let edge_pos = vec2f(1.0, 1.0);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // bottom-left
let edge = has_edge(mask_center, center_coord + vec2i(-1, 1));
let edge = has_edge(max_coord, mask_center, center_coord + vec2i(-1, 1));
let edge_pos = vec2f(0.0, 1.0);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // top-left
let edge = has_edge(mask_center, center_coord + vec2i(-1, -1));
let edge = has_edge(max_coord, mask_center, center_coord + vec2i(-1, -1));
let edge_pos = vec2f(0.0, 0.0);
//edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy; // multiplied by zero, optimize out
num_edges_a_and_b += edge;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
@group(0) @binding(0)
var mask_texture: texture_multisampled_2d<u32>;

fn has_edge(closest_center_sample: vec2u, sample_coord: vec2i, sample_idx: i32) -> vec2f {
let mask_neighbor = textureLoad(mask_texture, sample_coord, sample_idx).xy;
fn has_edge(max_coord: vec2i, closest_center_sample: vec2u, sample_coord: vec2i, sample_idx: i32) -> vec2f {
// Note that `textureLoad` calls with out-of-bounds coordinates are allowed to return *any*
// value on the texture or "transparent"/"opaque" zero.
// See https://www.w3.org/TR/WGSL/#textureload
// Therefore, if we want consistent behavior, we have to do the clamp ourselves.
let clamped_coord = clamp(sample_coord, vec2i(0), max_coord);
let mask_neighbor = textureLoad(mask_texture, clamped_coord, sample_idx).xy;
return vec2f(closest_center_sample != mask_neighbor);
}

Expand Down Expand Up @@ -49,6 +54,7 @@ fn has_edge(closest_center_sample: vec2u, sample_coord: vec2i, sample_idx: i32)
fn main(in: FragmentInput) -> @location(0) vec4f {
let resolution = textureDimensions(mask_texture).xy;
let center_coord = vec2i(vec2f(resolution) * in.texcoord);
let max_coord = vec2i(resolution) - vec2i(1);

//let num_samples = textureNumSamples(mask_texture);
// TODO(andreas): Should we assert somehow on textureNumSamples here?
Expand All @@ -73,25 +79,25 @@ fn main(in: FragmentInput) -> @location(0) vec4f {

// Sample closest neighbors top/bottom/left/right
{ // right
let edge = has_edge(mask_right_top, center_coord + vec2i(1, 0), 2);
let edge = has_edge(max_coord, mask_right_top, center_coord + vec2i(1, 0), 2);
let edge_pos = vec2f(1.0, 0.5);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // bottom
let edge = has_edge(mask_bottom_right, center_coord + vec2i(0, 1), 0);
let edge = has_edge(max_coord, mask_bottom_right, center_coord + vec2i(0, 1), 0);
let edge_pos = vec2f(0.5, 1.0);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // left
let edge = has_edge(mask_left_bottom, center_coord + vec2i(-1, 0), 1);
let edge = has_edge(max_coord, mask_left_bottom, center_coord + vec2i(-1, 0), 1);
let edge_pos = vec2f(0.0, 0.5);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // top
let edge = has_edge(mask_top_left, center_coord + vec2i(0, -1), 3);
let edge = has_edge(max_coord, mask_top_left, center_coord + vec2i(0, -1), 3);
let edge_pos = vec2f(0.5, 0.0);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
Expand All @@ -100,25 +106,25 @@ fn main(in: FragmentInput) -> @location(0) vec4f {
// Sample closest neighbors diagonally.
// This is not strictly necessary, but empirically the result looks a lot better!
{ // top-right
let edge = has_edge(mask_right_top, center_coord + vec2i(1, -1), 2);
let edge = has_edge(max_coord, mask_right_top, center_coord + vec2i(1, -1), 2);
let edge_pos = vec2f(1.0, 0.0);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // bottom-right
let edge = has_edge(mask_bottom_right, center_coord + vec2i(1, 1), 0);
let edge = has_edge(max_coord, mask_bottom_right, center_coord + vec2i(1, 1), 0);
let edge_pos = vec2f(1.0, 1.0);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // bottom-left
let edge = has_edge(mask_left_bottom, center_coord + vec2i(-1, 1), 1);
let edge = has_edge(max_coord, mask_left_bottom, center_coord + vec2i(-1, 1), 1);
let edge_pos = vec2f(0.0, 1.0);
edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy;
num_edges_a_and_b += edge;
}
{ // top-left
let edge = has_edge(mask_top_left, center_coord + vec2i(-1, -1), 3);
let edge = has_edge(max_coord, mask_top_left, center_coord + vec2i(-1, -1), 3);
let edge_pos = vec2f(0.0, 0.0);
//edge_pos_a_and_b += vec4f(edge_pos, edge_pos) * edge.xxyy; // multiplied by zero, optimize out
num_edges_a_and_b += edge;
Expand Down
35 changes: 27 additions & 8 deletions crates/viewer/re_renderer/src/global_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ pub struct FrameUniformBuffer {

pub(crate) struct GlobalBindings {
pub(crate) layout: GpuBindGroupLayoutHandle,
nearest_neighbor_sampler: GpuSamplerHandle,
trilinear_sampler: GpuSamplerHandle,
nearest_neighbor_sampler_repeat: GpuSamplerHandle,
nearest_neighbor_sampler_clamped: GpuSamplerHandle,
trilinear_sampler_repeat: GpuSamplerHandle,
}

impl GlobalBindings {
Expand All @@ -73,24 +74,31 @@ impl GlobalBindings {
},
count: None,
},
// Sampler without any filtering.
// Sampler without any filtering, repeat.
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::NonFiltering),
count: None,
},
// Trilinear sampler.
// Sampler without any filtering, clamped.
wgpu::BindGroupLayoutEntry {
binding: 2,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::NonFiltering),
count: None,
},
// Trilinear sampler, repeat.
wgpu::BindGroupLayoutEntry {
binding: 3,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
count: None,
},
],
},
),
nearest_neighbor_sampler: pools.samplers.get_or_create(
nearest_neighbor_sampler_repeat: pools.samplers.get_or_create(
device,
&SamplerDesc {
label: "GlobalBindings::nearest_neighbor_sampler".into(),
Expand All @@ -100,7 +108,17 @@ impl GlobalBindings {
..Default::default()
},
),
trilinear_sampler: pools.samplers.get_or_create(
nearest_neighbor_sampler_clamped: pools.samplers.get_or_create(
device,
&SamplerDesc {
label: "GlobalBindings::nearest_neighbor_sampler_clamped".into(),
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
..Default::default()
},
),
trilinear_sampler_repeat: pools.samplers.get_or_create(
device,
&SamplerDesc {
label: "GlobalBindings::trilinear_sampler".into(),
Expand Down Expand Up @@ -131,8 +149,9 @@ impl GlobalBindings {
label: "GlobalBindings::create_bind_group".into(),
entries: smallvec![
frame_uniform_buffer_binding,
BindGroupEntry::Sampler(self.nearest_neighbor_sampler),
BindGroupEntry::Sampler(self.trilinear_sampler),
BindGroupEntry::Sampler(self.nearest_neighbor_sampler_repeat),
BindGroupEntry::Sampler(self.nearest_neighbor_sampler_clamped),
BindGroupEntry::Sampler(self.trilinear_sampler_repeat),
],
layout: self.layout,
},
Expand Down

0 comments on commit 02a8757

Please sign in to comment.