Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Outlines via masking & postprocessing in re_renderer #1532

Merged
merged 31 commits into from
Mar 9, 2023
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c4c78b9
outline example setup
Wumpf Feb 27, 2023
675bc5a
new outline mask phase, outline renderer skeleton
Wumpf Feb 27, 2023
03c69bd
outline processor setup
Wumpf Feb 28, 2023
f06fd4f
basic mesh mask drawing
Wumpf Feb 28, 2023
29583e7
outline mask has now its own depth buffer
Wumpf Mar 1, 2023
a703a59
add outline mask to meshinstance, unused so far
Wumpf Mar 1, 2023
d9af78c
scaffolding for jumpflooding in outlines
Wumpf Mar 1, 2023
40f2ba5
potentially working jumpflooding init shader
Wumpf Mar 1, 2023
0f25979
basically working jumpflooding, hardcoded red outlines for the moment
Wumpf Mar 1, 2023
47428f1
wip
Wumpf Mar 2, 2023
1abb07f
rebase fixup
Wumpf Mar 2, 2023
3b0af4e
renames
Wumpf Mar 7, 2023
cd80950
A lot better anti-aliasing handlign and documentation thereof
Wumpf Mar 7, 2023
1ce2ab7
don't render meshes that don't participate in outlines during outline…
Wumpf Mar 7, 2023
8eec43b
configurable mesh outlines. demonstrate internal outlines in example
Wumpf Mar 8, 2023
70f2e95
outline configurability, blend both outline a and b
Wumpf Mar 8, 2023
b75e8a6
Fix crash in write belt
Wumpf Mar 8, 2023
0bb0bd5
use texture sampler for jumpflooding to fix buggy outline point at to…
Wumpf Mar 8, 2023
e1c2183
simplify shader a bit by using pixel coordinates all the way
Wumpf Mar 8, 2023
1dfd840
use inf() to mark-up invalid positions
Wumpf Mar 8, 2023
c0bf404
outline documentation
Wumpf Mar 8, 2023
dad5cd2
fix thickness/radius confusion
Wumpf Mar 8, 2023
f619281
cleanup code in outlines.rs
Wumpf Mar 8, 2023
de51728
fix typos
Wumpf Mar 8, 2023
654e362
Fix documentation in outlines.rs
Wumpf Mar 8, 2023
649ca07
fix release mode compilation issue
Wumpf Mar 9, 2023
aac2ab5
Workaround for WebGL shader issue
Wumpf Mar 9, 2023
7ec31a2
Provide non-msaa version of outline renderer for WebGL compatibility
Wumpf Mar 9, 2023
c643bcf
hackish pause/unpause to simplify visualizing everything that goes on…
teh-cmc Mar 9, 2023
8acd9cb
pr feedback, fix demo timing
Wumpf Mar 9, 2023
1e75572
bump ci?
Wumpf Mar 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@
"cSpell.words": [
"andreas",
"bbox",
"bindgroup",
"emath",
"framebuffer",
"hoverable",
"ilog",
"jumpflooding",
"Keypoint",
"memoffset",
"nyud",
Expand All @@ -37,6 +40,7 @@
"texcoords",
"Tonemapper",
"tonemapping",
"voronoi",
"vram",
"Wgsl"
],
Expand Down
17 changes: 17 additions & 0 deletions crates/re_renderer/examples/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ pub trait Example {
fn on_keyboard_input(&mut self, input: winit::event::KeyboardInput);
}

#[allow(dead_code)]
pub struct SplitView {
pub target_location: glam::Vec2,
pub resolution_in_pixel: [u32; 2],
}

#[allow(dead_code)]
pub fn split_resolution(
resolution: [u32; 2],
num_rows: usize,
Expand Down Expand Up @@ -329,6 +331,21 @@ impl<E: Example + 'static> Application<E> {
}
}

#[allow(dead_code)]
pub fn load_rerun_mesh(re_ctx: &mut RenderContext) -> Vec<re_renderer::renderer::MeshInstance> {
let reader = std::io::Cursor::new(include_bytes!("rerun.obj.zip"));
let mut zip = zip::ZipArchive::new(reader).unwrap();
let mut zipped_obj = zip.by_name("rerun.obj").unwrap();
let mut obj_data = Vec::new();
std::io::Read::read_to_end(&mut zipped_obj, &mut obj_data).unwrap();
re_renderer::importer::obj::load_obj_from_buffer(
&obj_data,
re_renderer::resource_managers::ResourceLifeTime::LongLived,
re_ctx,
)
.unwrap()
}

async fn run<E: Example + 'static>(event_loop: EventLoop<()>, window: Window) {
let app = Application::<E>::new(event_loop, window).await.unwrap();
app.run();
Expand Down
18 changes: 3 additions & 15 deletions crates/re_renderer/examples/multiview.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{f32::consts::TAU, io::Read};
use std::f32::consts::TAU;

use ecolor::Hsva;
use framework::Example;
Expand All @@ -12,7 +12,6 @@ use re_renderer::{
GenericSkyboxDrawData, LineDrawData, LineStripFlags, MeshDrawData, MeshInstance,
TestTriangleDrawData,
},
resource_managers::ResourceLifeTime,
view_builder::{OrthographicCameraMode, Projection, TargetConfiguration, ViewBuilder},
Color32, LineStripSeriesBuilder, PointCloudBuilder, RenderContext, Rgba, Size,
};
Expand Down Expand Up @@ -62,6 +61,7 @@ fn build_mesh_instances(
*p,
) * model_mesh_instances.world_from_mesh,
additive_tint: *c,
..Default::default()
},
)
})
Expand Down Expand Up @@ -206,19 +206,7 @@ impl Example for Multiview {
.map(|_| random_color(&mut rnd))
.collect_vec();

let model_mesh_instances = {
let reader = std::io::Cursor::new(include_bytes!("assets/rerun.obj.zip"));
let mut zip = zip::ZipArchive::new(reader).unwrap();
let mut zipped_obj = zip.by_name("rerun.obj").unwrap();
let mut obj_data = Vec::new();
zipped_obj.read_to_end(&mut obj_data).unwrap();
re_renderer::importer::obj::load_obj_from_buffer(
&obj_data,
ResourceLifeTime::LongLived,
re_ctx,
)
.unwrap()
};
let model_mesh_instances = crate::framework::load_rerun_mesh(re_ctx);

let mesh_instance_positions_and_colors = lorenz_points(10.0)
.iter()
Expand Down
143 changes: 143 additions & 0 deletions crates/re_renderer/examples/outlines.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use itertools::Itertools;
use re_renderer::{
renderer::{MeshInstance, OutlineConfig},
view_builder::{Projection, TargetConfiguration, ViewBuilder},
};

mod framework;

struct Outlines {
model_mesh_instances: Vec<MeshInstance>,
}

struct MeshProperties {
outline_mask: Option<glam::UVec2>,
position: glam::Vec3,
rotation: glam::Quat,
}

impl framework::Example for Outlines {
fn title() -> &'static str {
"Outlines"
}

fn new(re_ctx: &mut re_renderer::RenderContext) -> Self {
Outlines {
model_mesh_instances: crate::framework::load_rerun_mesh(re_ctx),
}
}

fn draw(
&mut self,
re_ctx: &mut re_renderer::RenderContext,
resolution: [u32; 2],
time: &framework::Time,
pixels_from_point: f32,
) -> Vec<framework::ViewDrawResult> {
let mut view_builder = ViewBuilder::default();

let seconds_since_startup = time.seconds_since_startup();
// TODO(#1426): unify camera logic between examples.
// let camera_position = glam::vec3(
// (seconds_since_startup * 0.5).sin() * 10.0,
// 2.5,
// (seconds_since_startup * 0.5).cos() * 10.0,
// );
let camera_position = glam::vec3(1.0, 3.5, 7.0);

view_builder
.setup_view(
re_ctx,
TargetConfiguration {
name: "2D".into(),
Wumpf marked this conversation as resolved.
Show resolved Hide resolved
resolution_in_pixel: resolution,
view_from_world: macaw::IsoTransform::look_at_rh(
camera_position,
glam::Vec3::ZERO,
glam::Vec3::Y,
)
.unwrap(),
projection_from_view: Projection::Perspective {
vertical_fov: 70.0 * std::f32::consts::TAU / 360.0,
near_plane_distance: 0.01,
},
pixels_from_point,
outline_config: Some(OutlineConfig {
outline_radius_pixel: (seconds_since_startup * 2.0).sin().abs() * 10.0
+ 2.0,
color_layer_a: re_renderer::Rgba::from_rgb(1.0, 0.6, 0.0),
color_layer_b: re_renderer::Rgba::from_rgba_unmultiplied(
0.25, 0.3, 1.0, 0.5,
),
}),
..Default::default()
},
)
.unwrap();

let outline_mask_large_mesh = match ((seconds_since_startup * 0.5) as u64) % 5 {
0 => None,
1 => Some(glam::uvec2(1, 0)), // Same as the the y spinning mesh.
2 => Some(glam::uvec2(2, 0)), // Different than both meshes, outline A.
3 => Some(glam::uvec2(0, 1)), // Same as the the x spinning mesh.
4 => Some(glam::uvec2(0, 2)), // Different than both meshes, outline B.
_ => unreachable!(),
};

let mesh_properties = [
MeshProperties {
outline_mask: outline_mask_large_mesh,
position: glam::Vec3::ZERO,
rotation: glam::Quat::IDENTITY,
},
MeshProperties {
outline_mask: Some(glam::uvec2(1, 0)),
position: glam::vec3(2.0, 0.0, -3.0),
rotation: glam::Quat::from_rotation_y(seconds_since_startup),
},
MeshProperties {
outline_mask: Some(glam::uvec2(0, 1)),
position: glam::vec3(-2.0, 1.0, 3.0),
rotation: glam::Quat::from_rotation_x(seconds_since_startup),
},
];

let instances = mesh_properties
.into_iter()
.flat_map(|props| {
self.model_mesh_instances
.iter()
.map(move |instance| MeshInstance {
gpu_mesh: instance.gpu_mesh.clone(),
mesh: None,
world_from_mesh: glam::Affine3A::from_rotation_translation(
props.rotation,
props.position,
) * instance.world_from_mesh,
outline_mask: props.outline_mask,
..Default::default()
})
})
.collect_vec();

view_builder.queue_draw(&re_renderer::renderer::GenericSkyboxDrawData::new(re_ctx));
view_builder
.queue_draw(&re_renderer::renderer::MeshDrawData::new(re_ctx, &instances).unwrap());

let command_buffer = view_builder
.draw(re_ctx, ecolor::Rgba::TRANSPARENT)
.unwrap();

vec![framework::ViewDrawResult {
view_builder,
command_buffer,
target_location: glam::Vec2::ZERO,
}]
}

fn on_keyboard_input(&mut self, _input: winit::event::KeyboardInput) {}
}

fn main() {
framework::start::<Outlines>();
}
6 changes: 1 addition & 5 deletions crates/re_renderer/shader/composite.wgsl
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
#import <./types.wgsl>
#import <./utils/srgb.wgsl>
#import <./global_bindings.wgsl>

struct VertexOutput {
@builtin(position) position: Vec4,
@location(0) texcoord: Vec2,
};
#import <./screen_triangle_vertex.wgsl>

@group(1) @binding(0)
var input_texture: texture_2d<f32>;
Expand Down
6 changes: 1 addition & 5 deletions crates/re_renderer/shader/generic_skybox.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@
#import <./global_bindings.wgsl>
#import <./utils/srgb.wgsl>
#import <./utils/camera.wgsl>

struct VertexOutput {
@builtin(position) position: Vec4,
@location(0) texcoord: Vec2,
};
#import <./screen_triangle_vertex.wgsl>

fn skybox_dark_srgb(dir: Vec3) -> Vec3 {
let rgb = dir * 0.5 + Vec3(0.5);
Expand Down
11 changes: 10 additions & 1 deletion crates/re_renderer/shader/instanced_mesh.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ struct VertexOut {
@location(0) texcoord: Vec2,
@location(1) normal_world_space: Vec3,
@location(2) additive_tint_rgb: Vec3,

@location(3) @interpolate(flat)
outline_mask: UVec2,
};

@vertex
Expand All @@ -38,12 +41,13 @@ fn vs_main(in_vertex: VertexIn, in_instance: InstanceIn) -> VertexOut {
out.texcoord = in_vertex.texcoord;
out.normal_world_space = world_normal;
out.additive_tint_rgb = linear_from_srgb(in_instance.additive_tint_srgb.rgb);
out.outline_mask = in_instance.outline_mask;

return out;
}

@fragment
fn fs_main(in: VertexOut) -> @location(0) Vec4 {
fn fs_main_shaded(in: VertexOut) -> @location(0) Vec4 {
let albedo = textureSample(albedo_texture, trilinear_sampler, in.texcoord).rgb
* material.albedo_factor.rgb + in.additive_tint_rgb;

Expand All @@ -56,3 +60,8 @@ fn fs_main(in: VertexOut) -> @location(0) Vec4 {

return Vec4(radiance, 1.0);
}

@fragment
fn fs_main_outline_mask(in: VertexOut) -> @location(0) UVec2 {
return in.outline_mask;
}
1 change: 1 addition & 0 deletions crates/re_renderer/shader/mesh_vertex.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ struct InstanceIn {
@location(7) world_from_mesh_normal_row_1: Vec3,
@location(8) world_from_mesh_normal_row_2: Vec3,
@location(9) additive_tint_srgb: Vec4,
@location(10) outline_mask: UVec2,
};
Loading