From 4f94c7863f758368bdd0ff6d235796344ca22b65 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 15 Apr 2023 09:43:37 +0200 Subject: [PATCH 1/2] Revert "Revert "Implement billinear filtering of textures (#1850)" (#1859)" This reverts commit 625d2bdd241c09ff9d0ae394ba91565fa48455ec. --- crates/re_renderer/shader/rectangle.wgsl | 66 +++++++++++++++++-- crates/re_renderer/src/renderer/rectangles.rs | 18 ++++- crates/re_viewer/src/ui/view_tensor/ui.rs | 45 ++++++------- 3 files changed, 97 insertions(+), 32 deletions(-) diff --git a/crates/re_renderer/shader/rectangle.wgsl b/crates/re_renderer/shader/rectangle.wgsl index 2bf5f5517624..0bfdd52fc8cd 100644 --- a/crates/re_renderer/shader/rectangle.wgsl +++ b/crates/re_renderer/shader/rectangle.wgsl @@ -16,6 +16,9 @@ const COLOR_MAPPER_OFF = 1u; const COLOR_MAPPER_FUNCTION = 2u; const COLOR_MAPPER_TEXTURE = 3u; +const FILTER_NEAREST = 1u; +const FILTER_BILINEAR = 2u; + struct UniformBuffer { /// Top left corner position in world space. top_left_corner_position: Vec3, @@ -48,6 +51,9 @@ struct UniformBuffer { /// Exponent to raise the normalized texture value. /// Inverse brightness. gamma: f32, + + minification_filter: u32, + magnification_filter: u32, }; @group(1) @binding(0) @@ -90,6 +96,18 @@ fn vs_main(@builtin(vertex_index) v_idx: u32) -> VertexOut { return out; } +fn is_magnifying(pixel_coord: Vec2) -> bool { + return fwidth(pixel_coord.x) < 1.0; +} + +fn tex_filter(pixel_coord: Vec2) -> u32 { + if is_magnifying(pixel_coord) { + return rect_info.magnification_filter; + } else { + return rect_info.minification_filter; + } +} + @fragment fn fs_main(in: VertexOut) -> @location(0) Vec4 { // Sample the main texture: @@ -98,14 +116,50 @@ fn fs_main(in: VertexOut) -> @location(0) Vec4 { // TODO(emilk): support mipmaps sampled_value = textureSampleLevel(texture_float_filterable, texture_sampler, in.texcoord, 0.0); } else if rect_info.sample_type == SAMPLE_TYPE_FLOAT_NOFILTER { - let icoords = IVec2(in.texcoord * Vec2(textureDimensions(texture_float).xy)); - sampled_value = Vec4(textureLoad(texture_float, icoords, 0)); + let coord = in.texcoord * Vec2(textureDimensions(texture_float).xy); + if tex_filter(coord) == FILTER_NEAREST { + // nearest + sampled_value = textureLoad(texture_float, IVec2(coord + vec2(0.5)), 0); + } else { + // bilinear + let v00 = textureLoad(texture_float, IVec2(coord) + IVec2(0, 0), 0); + let v01 = textureLoad(texture_float, IVec2(coord) + IVec2(0, 1), 0); + let v10 = textureLoad(texture_float, IVec2(coord) + IVec2(1, 0), 0); + let v11 = textureLoad(texture_float, IVec2(coord) + IVec2(1, 1), 0); + let top = mix(v00, v10, fract(coord.x)); + let bottom = mix(v01, v11, fract(coord.x)); + sampled_value = mix(top, bottom, fract(coord.y)); + } } else if rect_info.sample_type == SAMPLE_TYPE_SINT_NOFILTER { - let icoords = IVec2(in.texcoord * Vec2(textureDimensions(texture_sint).xy)); - sampled_value = Vec4(textureLoad(texture_sint, icoords, 0)); + let coord = in.texcoord * Vec2(textureDimensions(texture_sint).xy); + if tex_filter(coord) == FILTER_NEAREST { + // nearest + sampled_value = Vec4(textureLoad(texture_sint, IVec2(coord + vec2(0.5)), 0)); + } else { + // bilinear + let v00 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(0, 0), 0)); + let v01 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(0, 1), 0)); + let v10 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(1, 0), 0)); + let v11 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(1, 1), 0)); + let top = mix(v00, v10, fract(coord.x)); + let bottom = mix(v01, v11, fract(coord.x)); + sampled_value = mix(top, bottom, fract(coord.y)); + } } else if rect_info.sample_type == SAMPLE_TYPE_UINT_NOFILTER { - let icoords = IVec2(in.texcoord * Vec2(textureDimensions(texture_uint).xy)); - sampled_value = Vec4(textureLoad(texture_uint, icoords, 0)); + let coord = in.texcoord * Vec2(textureDimensions(texture_uint).xy); + if tex_filter(coord) == FILTER_NEAREST { + // nearest + sampled_value = Vec4(textureLoad(texture_uint, IVec2(coord + vec2(0.5)), 0)); + } else { + // bilinear + let v00 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(0, 0), 0)); + let v01 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(0, 1), 0)); + let v10 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(1, 0), 0)); + let v11 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(1, 1), 0)); + let top = mix(v00, v10, fract(coord.x)); + let bottom = mix(v01, v11, fract(coord.x)); + sampled_value = mix(top, bottom, fract(coord.y)); + } } else { return ERROR_RGBA; // unknown sample type } diff --git a/crates/re_renderer/src/renderer/rectangles.rs b/crates/re_renderer/src/renderer/rectangles.rs index d002c73fea6c..c511e4d76177 100644 --- a/crates/re_renderer/src/renderer/rectangles.rs +++ b/crates/re_renderer/src/renderer/rectangles.rs @@ -192,6 +192,9 @@ mod gpu_data { const COLOR_MAPPER_FUNCTION: u32 = 2; const COLOR_MAPPER_TEXTURE: u32 = 3; + const FILTER_NEAREST: u32 = 1; + const FILTER_BILINEAR: u32 = 2; + #[repr(C, align(256))] #[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] pub struct UniformBuffer { @@ -213,7 +216,8 @@ mod gpu_data { color_mapper: u32, gamma: f32, - _row_padding: [u32; 2], + minification_filter: u32, + magnification_filter: u32, _end_padding: [wgpu_buffer_types::PaddingRow; 16 - 6], } @@ -275,6 +279,15 @@ mod gpu_data { } } + let minification_filter = match rectangle.texture_filter_minification { + super::TextureFilterMin::Linear => FILTER_BILINEAR, + super::TextureFilterMin::Nearest => FILTER_NEAREST, + }; + let magnification_filter = match rectangle.texture_filter_magnification { + super::TextureFilterMag::Linear => FILTER_BILINEAR, + super::TextureFilterMag::Nearest => FILTER_NEAREST, + }; + Ok(Self { top_left_corner_position: rectangle.top_left_corner_position.into(), colormap_function, @@ -287,7 +300,8 @@ mod gpu_data { range_min_max: (*range).into(), color_mapper: color_mapper_int, gamma: *gamma, - _row_padding: Default::default(), + minification_filter, + magnification_filter, _end_padding: Default::default(), }) } diff --git a/crates/re_viewer/src/ui/view_tensor/ui.rs b/crates/re_viewer/src/ui/view_tensor/ui.rs index d32024fd6f01..2dc7a000d715 100644 --- a/crates/re_viewer/src/ui/view_tensor/ui.rs +++ b/crates/re_viewer/src/ui/view_tensor/ui.rs @@ -426,32 +426,29 @@ impl TextureSettings { }); ui.end_row(); - // TODO(#1612): support texture filtering again - if false { - re_ui - .grid_left_hand_label(ui, "Filtering") - .on_hover_text("Filtering to use when magnifying"); - - fn tf_to_string(tf: egui::TextureFilter) -> &'static str { - match tf { - egui::TextureFilter::Nearest => "Nearest", - egui::TextureFilter::Linear => "Linear", - } + re_ui + .grid_left_hand_label(ui, "Filtering") + .on_hover_text("Filtering to use when magnifying"); + + fn tf_to_string(tf: egui::TextureFilter) -> &'static str { + match tf { + egui::TextureFilter::Nearest => "Nearest", + egui::TextureFilter::Linear => "Linear", } - egui::ComboBox::from_id_source("texture_filter") - .selected_text(tf_to_string(options.magnification)) - .show_ui(ui, |ui| { - ui.style_mut().wrap = Some(false); - ui.set_min_width(64.0); - - let mut selectable_value = |ui: &mut egui::Ui, e| { - ui.selectable_value(&mut options.magnification, e, tf_to_string(e)) - }; - selectable_value(ui, egui::TextureFilter::Linear); - selectable_value(ui, egui::TextureFilter::Nearest); - }); - ui.end_row(); } + egui::ComboBox::from_id_source("texture_filter") + .selected_text(tf_to_string(options.magnification)) + .show_ui(ui, |ui| { + ui.style_mut().wrap = Some(false); + ui.set_min_width(64.0); + + let mut selectable_value = |ui: &mut egui::Ui, e| { + ui.selectable_value(&mut options.magnification, e, tf_to_string(e)) + }; + selectable_value(ui, egui::TextureFilter::Nearest); + selectable_value(ui, egui::TextureFilter::Linear); + }); + ui.end_row(); } } From 98965aedcb572b9284c8b7fe895cf7849c65e077 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 15 Apr 2023 09:54:07 +0200 Subject: [PATCH 2/2] Split rectangle.wgsl into fragme/vertex parts to work around naga bug --- crates/re_renderer/shader/rectangle.wgsl | 122 +----------------- crates/re_renderer/shader/rectangle_fs.wgsl | 108 ++++++++++++++++ crates/re_renderer/shader/rectangle_vs.wgsl | 14 ++ crates/re_renderer/src/renderer/rectangles.rs | 13 +- crates/re_renderer/src/workspace_shaders.rs | 12 ++ 5 files changed, 145 insertions(+), 124 deletions(-) create mode 100644 crates/re_renderer/shader/rectangle_fs.wgsl create mode 100644 crates/re_renderer/shader/rectangle_vs.wgsl diff --git a/crates/re_renderer/shader/rectangle.wgsl b/crates/re_renderer/shader/rectangle.wgsl index 0bfdd52fc8cd..afd0de119ca2 100644 --- a/crates/re_renderer/shader/rectangle.wgsl +++ b/crates/re_renderer/shader/rectangle.wgsl @@ -77,128 +77,10 @@ var colormap_texture: texture_2d; @group(1) @binding(6) var texture_float_filterable: texture_2d; - struct VertexOut { @builtin(position) position: Vec4, @location(0) texcoord: Vec2, }; -@vertex -fn vs_main(@builtin(vertex_index) v_idx: u32) -> VertexOut { - let texcoord = Vec2(f32(v_idx / 2u), f32(v_idx % 2u)); - let pos = texcoord.x * rect_info.extent_u + texcoord.y * rect_info.extent_v + - rect_info.top_left_corner_position; - - var out: VertexOut; - out.position = apply_depth_offset(frame.projection_from_world * Vec4(pos, 1.0), rect_info.depth_offset); - out.texcoord = texcoord; - - return out; -} - -fn is_magnifying(pixel_coord: Vec2) -> bool { - return fwidth(pixel_coord.x) < 1.0; -} - -fn tex_filter(pixel_coord: Vec2) -> u32 { - if is_magnifying(pixel_coord) { - return rect_info.magnification_filter; - } else { - return rect_info.minification_filter; - } -} - -@fragment -fn fs_main(in: VertexOut) -> @location(0) Vec4 { - // Sample the main texture: - var sampled_value: Vec4; - if rect_info.sample_type == SAMPLE_TYPE_FLOAT_FILTER { - // TODO(emilk): support mipmaps - sampled_value = textureSampleLevel(texture_float_filterable, texture_sampler, in.texcoord, 0.0); - } else if rect_info.sample_type == SAMPLE_TYPE_FLOAT_NOFILTER { - let coord = in.texcoord * Vec2(textureDimensions(texture_float).xy); - if tex_filter(coord) == FILTER_NEAREST { - // nearest - sampled_value = textureLoad(texture_float, IVec2(coord + vec2(0.5)), 0); - } else { - // bilinear - let v00 = textureLoad(texture_float, IVec2(coord) + IVec2(0, 0), 0); - let v01 = textureLoad(texture_float, IVec2(coord) + IVec2(0, 1), 0); - let v10 = textureLoad(texture_float, IVec2(coord) + IVec2(1, 0), 0); - let v11 = textureLoad(texture_float, IVec2(coord) + IVec2(1, 1), 0); - let top = mix(v00, v10, fract(coord.x)); - let bottom = mix(v01, v11, fract(coord.x)); - sampled_value = mix(top, bottom, fract(coord.y)); - } - } else if rect_info.sample_type == SAMPLE_TYPE_SINT_NOFILTER { - let coord = in.texcoord * Vec2(textureDimensions(texture_sint).xy); - if tex_filter(coord) == FILTER_NEAREST { - // nearest - sampled_value = Vec4(textureLoad(texture_sint, IVec2(coord + vec2(0.5)), 0)); - } else { - // bilinear - let v00 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(0, 0), 0)); - let v01 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(0, 1), 0)); - let v10 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(1, 0), 0)); - let v11 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(1, 1), 0)); - let top = mix(v00, v10, fract(coord.x)); - let bottom = mix(v01, v11, fract(coord.x)); - sampled_value = mix(top, bottom, fract(coord.y)); - } - } else if rect_info.sample_type == SAMPLE_TYPE_UINT_NOFILTER { - let coord = in.texcoord * Vec2(textureDimensions(texture_uint).xy); - if tex_filter(coord) == FILTER_NEAREST { - // nearest - sampled_value = Vec4(textureLoad(texture_uint, IVec2(coord + vec2(0.5)), 0)); - } else { - // bilinear - let v00 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(0, 0), 0)); - let v01 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(0, 1), 0)); - let v10 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(1, 0), 0)); - let v11 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(1, 1), 0)); - let top = mix(v00, v10, fract(coord.x)); - let bottom = mix(v01, v11, fract(coord.x)); - sampled_value = mix(top, bottom, fract(coord.y)); - } - } else { - return ERROR_RGBA; // unknown sample type - } - - // Normalize the sample: - let range = rect_info.range_min_max; - var normalized_value: Vec4 = (sampled_value - range.x) / (range.y - range.x); - - // Apply gamma: - normalized_value = vec4(pow(normalized_value.rgb, vec3(rect_info.gamma)), normalized_value.a); // TODO(emilk): handle premultiplied alpha - - // Apply colormap, if any: - var texture_color: Vec4; - if rect_info.color_mapper == COLOR_MAPPER_OFF { - texture_color = normalized_value; - } else if rect_info.color_mapper == COLOR_MAPPER_FUNCTION { - let rgb = colormap_linear(rect_info.colormap_function, normalized_value.r); - texture_color = Vec4(rgb, 1.0); - } else if rect_info.color_mapper == COLOR_MAPPER_TEXTURE { - let colormap_size = textureDimensions(colormap_texture).xy; - let color_index = normalized_value.r * f32(colormap_size.x * colormap_size.y); - // TODO(emilk): interpolate between neighboring colors for non-integral color indices - let color_index_i32 = i32(color_index); - let x = color_index_i32 % colormap_size.x; - let y = color_index_i32 / colormap_size.x; - texture_color = textureLoad(colormap_texture, IVec2(x, y), 0); - } else { - return ERROR_RGBA; // unknown color mapper - } - - return texture_color * rect_info.multiplicative_tint; -} - -@fragment -fn fs_main_picking_layer(in: VertexOut) -> @location(0) UVec4 { - return UVec4(0u, 0u, 0u, 0u); // TODO(andreas): Implement picking layer id pass-through. -} - -@fragment -fn fs_main_outline_mask(in: VertexOut) -> @location(0) UVec2 { - return rect_info.outline_mask; -} +// The fragment and vertex shaders are in two separate files in order +// to work around this bug: https://github.com/gfx-rs/naga/issues/1743 diff --git a/crates/re_renderer/shader/rectangle_fs.wgsl b/crates/re_renderer/shader/rectangle_fs.wgsl new file mode 100644 index 000000000000..0d1a35cad961 --- /dev/null +++ b/crates/re_renderer/shader/rectangle_fs.wgsl @@ -0,0 +1,108 @@ +#import <./rectangle.wgsl> + +fn is_magnifying(pixel_coord: Vec2) -> bool { + return fwidth(pixel_coord.x) < 1.0; +} + +fn tex_filter(pixel_coord: Vec2) -> u32 { + if is_magnifying(pixel_coord) { + return rect_info.magnification_filter; + } else { + return rect_info.minification_filter; + } +} + +@fragment +fn fs_main(in: VertexOut) -> @location(0) Vec4 { + // Sample the main texture: + var sampled_value: Vec4; + if rect_info.sample_type == SAMPLE_TYPE_FLOAT_FILTER { + // TODO(emilk): support mipmaps + sampled_value = textureSampleLevel(texture_float_filterable, texture_sampler, in.texcoord, 0.0); + } else if rect_info.sample_type == SAMPLE_TYPE_FLOAT_NOFILTER { + let coord = in.texcoord * Vec2(textureDimensions(texture_float).xy); + if tex_filter(coord) == FILTER_NEAREST { + // nearest + sampled_value = textureLoad(texture_float, IVec2(coord + vec2(0.5)), 0); + } else { + // bilinear + let v00 = textureLoad(texture_float, IVec2(coord) + IVec2(0, 0), 0); + let v01 = textureLoad(texture_float, IVec2(coord) + IVec2(0, 1), 0); + let v10 = textureLoad(texture_float, IVec2(coord) + IVec2(1, 0), 0); + let v11 = textureLoad(texture_float, IVec2(coord) + IVec2(1, 1), 0); + let top = mix(v00, v10, fract(coord.x)); + let bottom = mix(v01, v11, fract(coord.x)); + sampled_value = mix(top, bottom, fract(coord.y)); + } + } else if rect_info.sample_type == SAMPLE_TYPE_SINT_NOFILTER { + let coord = in.texcoord * Vec2(textureDimensions(texture_sint).xy); + if tex_filter(coord) == FILTER_NEAREST { + // nearest + sampled_value = Vec4(textureLoad(texture_sint, IVec2(coord + vec2(0.5)), 0)); + } else { + // bilinear + let v00 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(0, 0), 0)); + let v01 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(0, 1), 0)); + let v10 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(1, 0), 0)); + let v11 = Vec4(textureLoad(texture_sint, IVec2(coord) + IVec2(1, 1), 0)); + let top = mix(v00, v10, fract(coord.x)); + let bottom = mix(v01, v11, fract(coord.x)); + sampled_value = mix(top, bottom, fract(coord.y)); + } + } else if rect_info.sample_type == SAMPLE_TYPE_UINT_NOFILTER { + let coord = in.texcoord * Vec2(textureDimensions(texture_uint).xy); + if tex_filter(coord) == FILTER_NEAREST { + // nearest + sampled_value = Vec4(textureLoad(texture_uint, IVec2(coord + vec2(0.5)), 0)); + } else { + // bilinear + let v00 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(0, 0), 0)); + let v01 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(0, 1), 0)); + let v10 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(1, 0), 0)); + let v11 = Vec4(textureLoad(texture_uint, IVec2(coord) + IVec2(1, 1), 0)); + let top = mix(v00, v10, fract(coord.x)); + let bottom = mix(v01, v11, fract(coord.x)); + sampled_value = mix(top, bottom, fract(coord.y)); + } + } else { + return ERROR_RGBA; // unknown sample type + } + + // Normalize the sample: + let range = rect_info.range_min_max; + var normalized_value: Vec4 = (sampled_value - range.x) / (range.y - range.x); + + // Apply gamma: + normalized_value = vec4(pow(normalized_value.rgb, vec3(rect_info.gamma)), normalized_value.a); // TODO(emilk): handle premultiplied alpha + + // Apply colormap, if any: + var texture_color: Vec4; + if rect_info.color_mapper == COLOR_MAPPER_OFF { + texture_color = normalized_value; + } else if rect_info.color_mapper == COLOR_MAPPER_FUNCTION { + let rgb = colormap_linear(rect_info.colormap_function, normalized_value.r); + texture_color = Vec4(rgb, 1.0); + } else if rect_info.color_mapper == COLOR_MAPPER_TEXTURE { + let colormap_size = textureDimensions(colormap_texture).xy; + let color_index = normalized_value.r * f32(colormap_size.x * colormap_size.y); + // TODO(emilk): interpolate between neighboring colors for non-integral color indices + let color_index_i32 = i32(color_index); + let x = color_index_i32 % colormap_size.x; + let y = color_index_i32 / colormap_size.x; + texture_color = textureLoad(colormap_texture, IVec2(x, y), 0); + } else { + return ERROR_RGBA; // unknown color mapper + } + + return texture_color * rect_info.multiplicative_tint; +} + +@fragment +fn fs_main_picking_layer(in: VertexOut) -> @location(0) UVec4 { + return UVec4(0u, 0u, 0u, 0u); // TODO(andreas): Implement picking layer id pass-through. +} + +@fragment +fn fs_main_outline_mask(in: VertexOut) -> @location(0) UVec2 { + return rect_info.outline_mask; +} diff --git a/crates/re_renderer/shader/rectangle_vs.wgsl b/crates/re_renderer/shader/rectangle_vs.wgsl new file mode 100644 index 000000000000..e0758c17c23a --- /dev/null +++ b/crates/re_renderer/shader/rectangle_vs.wgsl @@ -0,0 +1,14 @@ +#import <./rectangle.wgsl> + +@vertex +fn vs_main(@builtin(vertex_index) v_idx: u32) -> VertexOut { + let texcoord = Vec2(f32(v_idx / 2u), f32(v_idx % 2u)); + let pos = texcoord.x * rect_info.extent_u + texcoord.y * rect_info.extent_v + + rect_info.top_left_corner_position; + + var out: VertexOut; + out.position = apply_depth_offset(frame.projection_from_world * Vec4(pos, 1.0), rect_info.depth_offset); + out.texcoord = texcoord; + + return out; +} diff --git a/crates/re_renderer/src/renderer/rectangles.rs b/crates/re_renderer/src/renderer/rectangles.rs index c511e4d76177..5ff468e3ff6e 100644 --- a/crates/re_renderer/src/renderer/rectangles.rs +++ b/crates/re_renderer/src/renderer/rectangles.rs @@ -578,19 +578,24 @@ impl Renderer for RectangleRenderer { &pools.bind_group_layouts, ); - let shader_module = pools.shader_modules.get_or_create( + let shader_module_vs = pools.shader_modules.get_or_create( device, resolver, - &include_shader_module!("../../shader/rectangle.wgsl"), + &include_shader_module!("../../shader/rectangle_vs.wgsl"), + ); + let shader_module_fs = pools.shader_modules.get_or_create( + device, + resolver, + &include_shader_module!("../../shader/rectangle_fs.wgsl"), ); let render_pipeline_desc_color = RenderPipelineDesc { label: "RectangleRenderer::render_pipeline_color".into(), pipeline_layout, vertex_entrypoint: "vs_main".into(), - vertex_handle: shader_module, + vertex_handle: shader_module_vs, fragment_entrypoint: "fs_main".into(), - fragment_handle: shader_module, + fragment_handle: shader_module_fs, vertex_buffers: smallvec![], render_targets: smallvec![Some(wgpu::ColorTargetState { format: ViewBuilder::MAIN_TARGET_COLOR_FORMAT, diff --git a/crates/re_renderer/src/workspace_shaders.rs b/crates/re_renderer/src/workspace_shaders.rs index 0dd9316c8c4c..7d999da73645 100644 --- a/crates/re_renderer/src/workspace_shaders.rs +++ b/crates/re_renderer/src/workspace_shaders.rs @@ -109,6 +109,18 @@ pub fn init() { fs.create_file(virtpath, content).unwrap(); } + { + let virtpath = Path::new("shader/rectangle_fs.wgsl"); + let content = include_str!("../shader/rectangle_fs.wgsl").into(); + fs.create_file(virtpath, content).unwrap(); + } + + { + let virtpath = Path::new("shader/rectangle_vs.wgsl"); + let content = include_str!("../shader/rectangle_vs.wgsl").into(); + fs.create_file(virtpath, content).unwrap(); + } + { let virtpath = Path::new("shader/screen_triangle.wgsl"); let content = include_str!("../shader/screen_triangle.wgsl").into();