Skip to content

Commit

Permalink
Implement SDF rendering for rectangles
Browse files Browse the repository at this point in the history
Also updates the interface images for new SDF based icons created by eleriaqueen.
  • Loading branch information
hasenbanck committed Dec 17, 2024
1 parent 9d4fc5b commit 92d3c57
Show file tree
Hide file tree
Showing 16 changed files with 267 additions and 54 deletions.
Binary file removed korangar/archive/data/texture/checked_box.png
Binary file not shown.
Binary file modified korangar/archive/data/texture/collapsed_arrow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified korangar/archive/data/texture/expanded_arrow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added korangar/archive/data/texture/filled_box.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed korangar/archive/data/texture/unchecked_box.png
Binary file not shown.
Binary file added korangar/archive/data/texture/unfilled_box.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions korangar/src/graphics/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ pub enum RectangleInstruction {
screen_size: ScreenSize,
color: Color,
},
Sdf {
screen_position: ScreenPosition,
screen_size: ScreenSize,
color: Color,
texture_position: Vector2<f32>,
texture_size: Vector2<f32>,
texture: Arc<Texture>,
},
Sprite {
screen_position: ScreenPosition,
screen_size: ScreenSize,
Expand All @@ -141,6 +149,14 @@ pub enum InterfaceRectangleInstruction {
color: Color,
corner_radius: CornerRadius,
},
Sdf {
screen_position: ScreenPosition,
screen_size: ScreenSize,
screen_clip: ScreenClip,
color: Color,
corner_radius: CornerRadius,
texture: Arc<Texture>,
},
Sprite {
screen_position: ScreenPosition,
screen_size: ScreenSize,
Expand Down
75 changes: 66 additions & 9 deletions korangar/src/graphics/passes/interface/rectangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,16 @@ impl Drawer<{ BindGroupCount::One }, { ColorAttachmentCount::One }, { DepthAttac
pass.set_bind_group(2, self.solid_pixel_texture.get_bind_group(), &[]);

for (index, instruction) in draw_data.iter().enumerate() {
if let InterfaceRectangleInstruction::Sprite { texture, .. } = instruction
&& texture.get_id() != current_texture_id
{
current_texture_id = texture.get_id();
pass.set_bind_group(2, texture.get_bind_group(), &[]);
match instruction {
InterfaceRectangleInstruction::Sdf { texture, .. } | InterfaceRectangleInstruction::Sprite { texture, .. }
if texture.get_id() != current_texture_id =>
{
current_texture_id = texture.get_id();
pass.set_bind_group(2, texture.get_bind_group(), &[]);
}
_ => {}
}

let index = index as u32;

pass.draw(0..6, index..index + 1);
Expand Down Expand Up @@ -276,6 +280,38 @@ impl Prepare for InterfaceRectangleDrawer {
padding: Default::default(),
});
}
InterfaceRectangleInstruction::Sdf {
screen_position,
screen_size,
screen_clip,
color,
corner_radius,
texture,
} => {
let mut texture_index = texture_views.len() as i32;
let id = texture.get_id();
let potential_index = self.lookup.get(&id);

if let Some(potential_index) = potential_index {
texture_index = *potential_index;
} else {
self.lookup.insert(id, texture_index);
texture_views.push(texture.get_texture_view());
}

self.instance_data.push(InstanceData {
color: color.components_linear(),
corner_radius: (*corner_radius).into(),
screen_clip: (*screen_clip).into(),
screen_position: (*screen_position).into(),
screen_size: (*screen_size).into(),
texture_position: [0.0, 0.0],
texture_size: [1.0, 1.0],
rectangle_type: 1,
texture_index,
padding: Default::default(),
});
}
InterfaceRectangleInstruction::Sprite {
screen_position,
screen_size,
Expand All @@ -285,7 +321,7 @@ impl Prepare for InterfaceRectangleDrawer {
texture,
smooth,
} => {
let rectangle_type = if *smooth { 1 } else { 2 };
let rectangle_type = if *smooth { 2 } else { 3 };

let mut texture_index = texture_views.len() as i32;
let id = texture.get_id();
Expand Down Expand Up @@ -327,7 +363,7 @@ impl Prepare for InterfaceRectangleDrawer {
screen_size: (*screen_size).into(),
texture_position: (*texture_position).into(),
texture_size: (*texture_size).into(),
rectangle_type: 3,
rectangle_type: 4,
texture_index: 0,
padding: Default::default(),
});
Expand Down Expand Up @@ -370,6 +406,27 @@ impl Prepare for InterfaceRectangleDrawer {
padding: Default::default(),
});
}
InterfaceRectangleInstruction::Sdf {
screen_position,
screen_size,
screen_clip,
color,
corner_radius,
texture: _,
} => {
self.instance_data.push(InstanceData {
color: color.components_linear(),
corner_radius: (*corner_radius).into(),
screen_clip: (*screen_clip).into(),
screen_position: (*screen_position).into(),
screen_size: (*screen_size).into(),
texture_position: [0.0, 0.0],
texture_size: [1.0, 1.0],
rectangle_type: 1,
texture_index: 0,
padding: Default::default(),
});
}
InterfaceRectangleInstruction::Sprite {
screen_position,
screen_size,
Expand All @@ -379,7 +436,7 @@ impl Prepare for InterfaceRectangleDrawer {
texture: _,
smooth,
} => {
let rectangle_type = if *smooth { 1 } else { 2 };
let rectangle_type = if *smooth { 2 } else { 3 };

self.instance_data.push(InstanceData {
color: color.components_linear(),
Expand Down Expand Up @@ -410,7 +467,7 @@ impl Prepare for InterfaceRectangleDrawer {
screen_size: (*screen_size).into(),
texture_position: (*texture_position).into(),
texture_size: (*texture_size).into(),
rectangle_type: 3,
rectangle_type: 4,
texture_index: 0,
padding: Default::default(),
});
Expand Down
13 changes: 9 additions & 4 deletions korangar/src/graphics/passes/interface/shader/rectangle.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,19 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {

switch (instance.rectangle_type) {
case 1u: {
// SDF
let pixel = textureSample(texture, linear_sampler, input.texture_coordinates);
color *= vec4(pixel.rgb, saturate((pixel.a - 0.5) * 2.0 / fwidth(pixel.a)));
}
case 2u: {
// Sprite (linear filtering)
color *= textureSample(texture, linear_sampler, input.texture_coordinates);
}
case 2u: {
case 3u: {
// Sprite (nearest filtering)
color *= textureSample(texture, nearest_sampler, input.texture_coordinates);
}
case 3u: {
case 4u: {
// Text (coverage)
color *= textureSample(font_atlas, nearest_sampler, input.texture_coordinates).r;
}
Expand Down Expand Up @@ -155,13 +160,13 @@ fn rectangle_with_rounded_edges(
let sample_distance = rectangle_sdf(relative_position + offset, half_size, corner_radius);
total += step(0.0, -sample_distance);
}
alpha = total * (1.0/9.0);
alpha = total * (1.0 / 9.0);
}

return color * alpha;
}

// 8-point Poisson Disk pattern
// 8-point Poisson Disk pattern that showed the best performance / quality characteristic.
const SAMPLE_OFFSETS: array<vec2<f32>, 8> = array<vec2<f32>, 8>(
vec2<f32>( 0.924, 0.382) * 0.5,
vec2<f32>( 0.382, 0.924) * 0.5,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,19 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {

switch (instance.rectangle_type) {
case 1u: {
// SDF
let pixel = textureSample(textures[instance.texture_index], linear_sampler, input.texture_coordinates);
color *= vec4(pixel.rgb, saturate((pixel.a - 0.5) * 2.0 / fwidth(pixel.a)));
}
case 2u: {
// Sprite (linear filtering)
color *= textureSample(textures[instance.texture_index], linear_sampler, input.texture_coordinates);
}
case 2u: {
case 3u: {
// Sprite (nearest filtering)
color *= textureSample(textures[instance.texture_index], nearest_sampler, input.texture_coordinates);
}
case 3u: {
case 4u: {
// Text (coverage)
color *= textureSample(font_atlas, nearest_sampler, input.texture_coordinates).r;
}
Expand Down
77 changes: 67 additions & 10 deletions korangar/src/graphics/passes/postprocessing/rectangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ pub(crate) struct InstanceData {
screen_size: [f32; 2],
texture_position: [f32; 2],
texture_size: [f32; 2],
rectangle_type: u32,
texture_index: i32,
linear_filtering: u32,
padding: [u32; 2],
}

Expand Down Expand Up @@ -215,12 +215,16 @@ impl Drawer<{ BindGroupCount::One }, { ColorAttachmentCount::One }, { DepthAttac
pass.set_bind_group(2, self.solid_pixel_texture.get_bind_group(), &[]);

for (index, instruction) in draw_data.instructions.iter().enumerate() {
if let RectangleInstruction::Sprite { texture, .. } = instruction
&& texture.get_id() != current_texture_id
{
current_texture_id = texture.get_id();
pass.set_bind_group(2, texture.get_bind_group(), &[]);
match instruction {
RectangleInstruction::Sdf { texture, .. } | RectangleInstruction::Sprite { texture, .. }
if texture.get_id() != current_texture_id =>
{
current_texture_id = texture.get_id();
pass.set_bind_group(2, texture.get_bind_group(), &[]);
}
_ => {}
}

let index = offset + index as u32;

pass.draw(0..6, index..index + 1);
Expand Down Expand Up @@ -274,8 +278,38 @@ impl Prepare for PostProcessingRectangleDrawer {
screen_size: (*screen_size).into(),
texture_position: [0.0; 2],
texture_size: [0.0; 2],
rectangle_type: 0,
texture_index: -1,
linear_filtering: 0,
padding: Default::default(),
});
}
RectangleInstruction::Sdf {
screen_position,
screen_size,
color,
texture_position,
texture_size,
texture,
} => {
let mut texture_index = texture_views.len() as i32;
let id = texture.get_id();
let potential_index = self.lookup.get(&id);

if let Some(potential_index) = potential_index {
texture_index = *potential_index;
} else {
self.lookup.insert(id, texture_index);
texture_views.push(texture.get_texture_view());
}

self.instance_data.push(InstanceData {
color: color.components_linear(),
screen_position: (*screen_position).into(),
screen_size: (*screen_size).into(),
texture_position: (*texture_position).into(),
texture_size: (*texture_size).into(),
rectangle_type: 1,
texture_index,
padding: Default::default(),
});
}
Expand All @@ -288,6 +322,8 @@ impl Prepare for PostProcessingRectangleDrawer {
linear_filtering,
texture,
} => {
let rectangle_type = if *linear_filtering { 2 } else { 3 };

let mut texture_index = texture_views.len() as i32;
let id = texture.get_id();
let potential_index = self.lookup.get(&id);
Expand All @@ -305,8 +341,8 @@ impl Prepare for PostProcessingRectangleDrawer {
screen_size: (*screen_size).into(),
texture_position: (*texture_position).into(),
texture_size: (*texture_size).into(),
rectangle_type,
texture_index,
linear_filtering: *linear_filtering as u32,
padding: Default::default(),
});
}
Expand Down Expand Up @@ -348,8 +384,27 @@ impl Prepare for PostProcessingRectangleDrawer {
screen_size: (*screen_size).into(),
texture_position: [0.0; 2],
texture_size: [0.0; 2],
rectangle_type: 0,
texture_index: -1,
linear_filtering: 0,
padding: Default::default(),
});
}
RectangleInstruction::Sdf {
screen_position,
screen_size,
color,
texture_position,
texture_size,
texture: _,
} => {
self.instance_data.push(InstanceData {
color: color.components_linear(),
screen_position: (*screen_position).into(),
screen_size: (*screen_size).into(),
texture_position: (*texture_position).into(),
texture_size: (*texture_size).into(),
rectangle_type: 1,
texture_index: 0,
padding: Default::default(),
});
}
Expand All @@ -362,14 +417,16 @@ impl Prepare for PostProcessingRectangleDrawer {
linear_filtering,
texture: _,
} => {
let rectangle_type = if *linear_filtering { 2 } else { 3 };

self.instance_data.push(InstanceData {
color: color.components_linear(),
screen_position: (*screen_position).into(),
screen_size: (*screen_size).into(),
texture_position: (*texture_position).into(),
texture_size: (*texture_size).into(),
rectangle_type,
texture_index: 0,
linear_filtering: *linear_filtering as u32,
padding: Default::default(),
});
}
Expand Down
28 changes: 19 additions & 9 deletions korangar/src/graphics/passes/postprocessing/shader/rectangle.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ struct InstanceData {
screen_size: vec2<f32>,
texture_position: vec2<f32>,
texture_size: vec2<f32>,
rectangle_type: u32,
texture_index: i32,
linear_filtering: u32,
}

struct VertexOutput {
Expand Down Expand Up @@ -42,14 +42,24 @@ fn vs_main(
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
let instance = instance_data[input.instance_index];

if instance.texture_index == -1 {
return instance.color;
}

if instance.linear_filtering == 0 {
return textureSample(texture, nearest_sampler, input.texture_coordinates) * instance.color;
} else {
return textureSample(texture, linear_sampler, input.texture_coordinates) * instance.color;
switch (instance.rectangle_type) {
case 1u: {
// SDF
let pixel = textureSample(texture, linear_sampler, input.texture_coordinates);
return vec4(pixel.rgb, saturate((pixel.a - 0.5) * 2.0 / fwidth(pixel.a))) * instance.color;
}
case 2u: {
// Sprite (linear filtering)
return textureSample(texture, linear_sampler, input.texture_coordinates) * instance.color;
}
case 3u: {
// Sprite (nearest filtering)
return textureSample(texture, nearest_sampler, input.texture_coordinates) * instance.color;
}
default: {
// Solid
return instance.color;
}
}
}

Expand Down
Loading

0 comments on commit 92d3c57

Please sign in to comment.