From f7d309a879000e3b7548cdc853748740ffea4d86 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 12 Jun 2023 14:45:29 +0200 Subject: [PATCH 1/3] Rectangle texture samples are now clamped to border --- crates/re_renderer/shader/rectangle_fs.wgsl | 66 ++++++++++++++------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/crates/re_renderer/shader/rectangle_fs.wgsl b/crates/re_renderer/shader/rectangle_fs.wgsl index 4b623f14a8d7..37489b03ebb6 100644 --- a/crates/re_renderer/shader/rectangle_fs.wgsl +++ b/crates/re_renderer/shader/rectangle_fs.wgsl @@ -40,10 +40,25 @@ fn decode_color(sampled_value: Vec4) -> Vec4 { return rgba; } +/// Takes a floating point texel coordinate and outputs a neighrest neighbor +fn to_clamp_to_border_sample(coord: Vec2, texture_dimension: Vec2) -> IVec2 { + return IVec2(clamp(floor(coord), Vec2(0.0), texture_dimension - Vec2(1.0))); +} + +/// Takes a floating point texel coordinate and outputs the four integer texel coordinates that are used for bilinear filtering. +/// All four samples are clamped to the texture border. +fn clamped_bilinear_sample_positions(coord: Vec2, texture_dimension: Vec2) -> array { + let v00 = to_clamp_to_border_sample(coord + vec2(-0.5, -0.5), texture_dimension); + let v01 = to_clamp_to_border_sample(coord + vec2(-0.5, 0.5), texture_dimension); + let v10 = to_clamp_to_border_sample(coord + vec2( 0.5, -0.5), texture_dimension); + let v11 = to_clamp_to_border_sample(coord + vec2( 0.5, 0.5), texture_dimension); + return array(IVec2(v00), IVec2(v01), IVec2(v10), IVec2(v11)); +} + fn filter_bilinear(coord: Vec2, v00: Vec4, v01: Vec4, v10: Vec4, v11: Vec4) -> Vec4 { - let top = mix(v00, v10, fract(coord.x - 0.5)); - let bottom = mix(v01, v11, fract(coord.x - 0.5)); - return mix(top, bottom, fract(coord.y - 0.5)); + let top = mix(v00, v10, fract(coord.x - 0.5 + 10.0)); + let bottom = mix(v01, v11, fract(coord.x - 0.5 + 10.0)); + return mix(top, bottom, fract(coord.y - 0.5 + 10.0)); } @fragment @@ -51,42 +66,51 @@ fn fs_main(in: VertexOut) -> @location(0) Vec4 { // Sample the main texture: var normalized_value: Vec4; if rect_info.sample_type == SAMPLE_TYPE_FLOAT { - let coord = in.texcoord * Vec2(textureDimensions(texture_float).xy); + let texture_dimensions = Vec2(textureDimensions(texture_float).xy); + let coord = in.texcoord * texture_dimensions; if tex_filter(coord) == FILTER_NEAREST { // nearest - normalized_value = decode_color(textureLoad(texture_float, IVec2(coord), 0)); + normalized_value = decode_color(textureLoad(texture_float, + to_clamp_to_border_sample(coord, texture_dimensions), 0)); } else { // bilinear - let v00 = decode_color(textureLoad(texture_float, IVec2(coord + vec2(-0.5, -0.5)), 0)); - let v01 = decode_color(textureLoad(texture_float, IVec2(coord + vec2(-0.5, 0.5)), 0)); - let v10 = decode_color(textureLoad(texture_float, IVec2(coord + vec2( 0.5, -0.5)), 0)); - let v11 = decode_color(textureLoad(texture_float, IVec2(coord + vec2( 0.5, 0.5)), 0)); + let sample_positions = clamped_bilinear_sample_positions(coord, Vec2(textureDimensions(texture_float).xy)); + let v00 = decode_color(textureLoad(texture_float, sample_positions[0], 0)); + let v01 = decode_color(textureLoad(texture_float, sample_positions[1], 0)); + let v10 = decode_color(textureLoad(texture_float, sample_positions[2], 0)); + let v11 = decode_color(textureLoad(texture_float, sample_positions[3], 0)); normalized_value = filter_bilinear(coord, v00, v01, v10, v11); } } else if rect_info.sample_type == SAMPLE_TYPE_SINT { - let coord = in.texcoord * Vec2(textureDimensions(texture_sint).xy); + let texture_dimensions = Vec2(textureDimensions(texture_sint).xy); + let coord = in.texcoord * texture_dimensions; if tex_filter(coord) == FILTER_NEAREST { // nearest - normalized_value = decode_color(Vec4(textureLoad(texture_sint, IVec2(coord), 0))); + normalized_value = decode_color(Vec4(textureLoad(texture_sint, + to_clamp_to_border_sample(coord, texture_dimensions), 0))); } else { // bilinear - let v00 = decode_color(Vec4(textureLoad(texture_sint, IVec2(coord + vec2(-0.5, -0.5)), 0))); - let v01 = decode_color(Vec4(textureLoad(texture_sint, IVec2(coord + vec2(-0.5, 0.5)), 0))); - let v10 = decode_color(Vec4(textureLoad(texture_sint, IVec2(coord + vec2( 0.5, -0.5)), 0))); - let v11 = decode_color(Vec4(textureLoad(texture_sint, IVec2(coord + vec2( 0.5, 0.5)), 0))); + let sample_positions = clamped_bilinear_sample_positions(coord, Vec2(textureDimensions(texture_float).xy)); + let v00 = decode_color(Vec4(textureLoad(texture_sint, sample_positions[0], 0))); + let v01 = decode_color(Vec4(textureLoad(texture_sint, sample_positions[1], 0))); + let v10 = decode_color(Vec4(textureLoad(texture_sint, sample_positions[2], 0))); + let v11 = decode_color(Vec4(textureLoad(texture_sint, sample_positions[3], 0))); normalized_value = filter_bilinear(coord, v00, v01, v10, v11); } } else if rect_info.sample_type == SAMPLE_TYPE_UINT { - let coord = in.texcoord * Vec2(textureDimensions(texture_uint).xy); + let texture_dimensions = Vec2(textureDimensions(texture_uint).xy); + let coord = in.texcoord * texture_dimensions; if tex_filter(coord) == FILTER_NEAREST { // nearest - normalized_value = decode_color(Vec4(textureLoad(texture_uint, IVec2(coord), 0))); + normalized_value = decode_color(Vec4(textureLoad(texture_uint, + to_clamp_to_border_sample(coord, texture_dimensions), 0))); } else { // bilinear - let v00 = decode_color(Vec4(textureLoad(texture_uint, IVec2(coord + vec2(-0.5, -0.5)), 0))); - let v01 = decode_color(Vec4(textureLoad(texture_uint, IVec2(coord + vec2(-0.5, 0.5)), 0))); - let v10 = decode_color(Vec4(textureLoad(texture_uint, IVec2(coord + vec2( 0.5, -0.5)), 0))); - let v11 = decode_color(Vec4(textureLoad(texture_uint, IVec2(coord + vec2( 0.5, 0.5)), 0))); + let sample_positions = clamped_bilinear_sample_positions(coord, Vec2(textureDimensions(texture_float).xy)); + let v00 = decode_color(Vec4(textureLoad(texture_uint, sample_positions[0], 0))); + let v01 = decode_color(Vec4(textureLoad(texture_uint, sample_positions[1], 0))); + let v10 = decode_color(Vec4(textureLoad(texture_uint, sample_positions[2], 0))); + let v11 = decode_color(Vec4(textureLoad(texture_uint, sample_positions[3], 0))); normalized_value = filter_bilinear(coord, v00, v01, v10, v11); } } else { From b5230c32bf1531960e98db65ecdc12b3ab240dd0 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 13 Jun 2023 11:07:01 +0200 Subject: [PATCH 2/3] fix naming, fix debugging left over --- crates/re_renderer/shader/rectangle_fs.wgsl | 35 +++++++++++---------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/crates/re_renderer/shader/rectangle_fs.wgsl b/crates/re_renderer/shader/rectangle_fs.wgsl index 37489b03ebb6..7d489a364c87 100644 --- a/crates/re_renderer/shader/rectangle_fs.wgsl +++ b/crates/re_renderer/shader/rectangle_fs.wgsl @@ -40,25 +40,26 @@ fn decode_color(sampled_value: Vec4) -> Vec4 { return rgba; } -/// Takes a floating point texel coordinate and outputs a neighrest neighbor -fn to_clamp_to_border_sample(coord: Vec2, texture_dimension: Vec2) -> IVec2 { +/// Takes a floating point texel coordinate and outputs a integer texel coordinate +/// on the neighrest neighbor, clamped to the texture edge. +fn clamp_to_edge_nearest_neighbor(coord: Vec2, texture_dimension: Vec2) -> IVec2 { return IVec2(clamp(floor(coord), Vec2(0.0), texture_dimension - Vec2(1.0))); } /// Takes a floating point texel coordinate and outputs the four integer texel coordinates that are used for bilinear filtering. -/// All four samples are clamped to the texture border. -fn clamped_bilinear_sample_positions(coord: Vec2, texture_dimension: Vec2) -> array { - let v00 = to_clamp_to_border_sample(coord + vec2(-0.5, -0.5), texture_dimension); - let v01 = to_clamp_to_border_sample(coord + vec2(-0.5, 0.5), texture_dimension); - let v10 = to_clamp_to_border_sample(coord + vec2( 0.5, -0.5), texture_dimension); - let v11 = to_clamp_to_border_sample(coord + vec2( 0.5, 0.5), texture_dimension); +/// All four samples are clamped to the texture edge. +fn clamp_to_edge_bilinear_samples(coord: Vec2, texture_dimension: Vec2) -> array { + let v00 = clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, -0.5), texture_dimension); + let v01 = clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, 0.5), texture_dimension); + let v10 = clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, -0.5), texture_dimension); + let v11 = clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, 0.5), texture_dimension); return array(IVec2(v00), IVec2(v01), IVec2(v10), IVec2(v11)); } fn filter_bilinear(coord: Vec2, v00: Vec4, v01: Vec4, v10: Vec4, v11: Vec4) -> Vec4 { - let top = mix(v00, v10, fract(coord.x - 0.5 + 10.0)); - let bottom = mix(v01, v11, fract(coord.x - 0.5 + 10.0)); - return mix(top, bottom, fract(coord.y - 0.5 + 10.0)); + let top = mix(v00, v10, fract(coord.x - 0.5)); + let bottom = mix(v01, v11, fract(coord.x - 0.5)); + return mix(top, bottom, fract(coord.y - 0.5)); } @fragment @@ -71,10 +72,10 @@ fn fs_main(in: VertexOut) -> @location(0) Vec4 { if tex_filter(coord) == FILTER_NEAREST { // nearest normalized_value = decode_color(textureLoad(texture_float, - to_clamp_to_border_sample(coord, texture_dimensions), 0)); + clamp_to_edge_nearest_neighbor(coord, texture_dimensions), 0)); } else { // bilinear - let sample_positions = clamped_bilinear_sample_positions(coord, Vec2(textureDimensions(texture_float).xy)); + let sample_positions = clamp_to_edge_bilinear_samples(coord, Vec2(textureDimensions(texture_float).xy)); let v00 = decode_color(textureLoad(texture_float, sample_positions[0], 0)); let v01 = decode_color(textureLoad(texture_float, sample_positions[1], 0)); let v10 = decode_color(textureLoad(texture_float, sample_positions[2], 0)); @@ -87,10 +88,10 @@ fn fs_main(in: VertexOut) -> @location(0) Vec4 { if tex_filter(coord) == FILTER_NEAREST { // nearest normalized_value = decode_color(Vec4(textureLoad(texture_sint, - to_clamp_to_border_sample(coord, texture_dimensions), 0))); + clamp_to_edge_nearest_neighbor(coord, texture_dimensions), 0))); } else { // bilinear - let sample_positions = clamped_bilinear_sample_positions(coord, Vec2(textureDimensions(texture_float).xy)); + let sample_positions = clamp_to_edge_bilinear_samples(coord, Vec2(textureDimensions(texture_float).xy)); let v00 = decode_color(Vec4(textureLoad(texture_sint, sample_positions[0], 0))); let v01 = decode_color(Vec4(textureLoad(texture_sint, sample_positions[1], 0))); let v10 = decode_color(Vec4(textureLoad(texture_sint, sample_positions[2], 0))); @@ -103,10 +104,10 @@ fn fs_main(in: VertexOut) -> @location(0) Vec4 { if tex_filter(coord) == FILTER_NEAREST { // nearest normalized_value = decode_color(Vec4(textureLoad(texture_uint, - to_clamp_to_border_sample(coord, texture_dimensions), 0))); + clamp_to_edge_nearest_neighbor(coord, texture_dimensions), 0))); } else { // bilinear - let sample_positions = clamped_bilinear_sample_positions(coord, Vec2(textureDimensions(texture_float).xy)); + let sample_positions = clamp_to_edge_bilinear_samples(coord, Vec2(textureDimensions(texture_float).xy)); let v00 = decode_color(Vec4(textureLoad(texture_uint, sample_positions[0], 0))); let v01 = decode_color(Vec4(textureLoad(texture_uint, sample_positions[1], 0))); let v10 = decode_color(Vec4(textureLoad(texture_uint, sample_positions[2], 0))); From 79e93cac39723d595b819468e473c6781aefbf0a Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 13 Jun 2023 11:38:41 +0200 Subject: [PATCH 3/3] fix int/uint textures on rectangle not querying correct size --- crates/re_renderer/shader/rectangle_fs.wgsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/re_renderer/shader/rectangle_fs.wgsl b/crates/re_renderer/shader/rectangle_fs.wgsl index 7d489a364c87..706b66977f23 100644 --- a/crates/re_renderer/shader/rectangle_fs.wgsl +++ b/crates/re_renderer/shader/rectangle_fs.wgsl @@ -75,7 +75,7 @@ fn fs_main(in: VertexOut) -> @location(0) Vec4 { clamp_to_edge_nearest_neighbor(coord, texture_dimensions), 0)); } else { // bilinear - let sample_positions = clamp_to_edge_bilinear_samples(coord, Vec2(textureDimensions(texture_float).xy)); + let sample_positions = clamp_to_edge_bilinear_samples(coord, texture_dimensions); let v00 = decode_color(textureLoad(texture_float, sample_positions[0], 0)); let v01 = decode_color(textureLoad(texture_float, sample_positions[1], 0)); let v10 = decode_color(textureLoad(texture_float, sample_positions[2], 0)); @@ -91,7 +91,7 @@ fn fs_main(in: VertexOut) -> @location(0) Vec4 { clamp_to_edge_nearest_neighbor(coord, texture_dimensions), 0))); } else { // bilinear - let sample_positions = clamp_to_edge_bilinear_samples(coord, Vec2(textureDimensions(texture_float).xy)); + let sample_positions = clamp_to_edge_bilinear_samples(coord, texture_dimensions); let v00 = decode_color(Vec4(textureLoad(texture_sint, sample_positions[0], 0))); let v01 = decode_color(Vec4(textureLoad(texture_sint, sample_positions[1], 0))); let v10 = decode_color(Vec4(textureLoad(texture_sint, sample_positions[2], 0))); @@ -107,7 +107,7 @@ fn fs_main(in: VertexOut) -> @location(0) Vec4 { clamp_to_edge_nearest_neighbor(coord, texture_dimensions), 0))); } else { // bilinear - let sample_positions = clamp_to_edge_bilinear_samples(coord, Vec2(textureDimensions(texture_float).xy)); + let sample_positions = clamp_to_edge_bilinear_samples(coord, texture_dimensions); let v00 = decode_color(Vec4(textureLoad(texture_uint, sample_positions[0], 0))); let v01 = decode_color(Vec4(textureLoad(texture_uint, sample_positions[1], 0))); let v10 = decode_color(Vec4(textureLoad(texture_uint, sample_positions[2], 0)));