This commit is contained in:
Antonio Scandurra
2023-09-22 16:31:26 -06:00
parent a237aa8164
commit 6a95f9e349
5 changed files with 142 additions and 25 deletions
+24
View File
@@ -138,6 +138,9 @@ pub struct Bounds<T: Clone + Debug> {
pub size: Size<T>,
}
unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Bounds<T> {}
unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Bounds<T> {}
impl<T: Clone + Debug + Copy + Add<T, Output = T>> Bounds<T> {
pub fn upper_right(&self) -> Point<T> {
Point {
@@ -174,6 +177,12 @@ pub struct Edges<T: Clone + Debug> {
pub left: T,
}
impl<T: Clone + Debug + Copy> Copy for Edges<T> {}
unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Edges<T> {}
unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Edges<T> {}
impl Edges<Length> {
pub fn auto() -> Self {
Self {
@@ -231,6 +240,21 @@ impl Edges<Pixels> {
}
}
#[derive(Refineable, Clone, Default, Debug)]
#[refineable(debug)]
pub struct Corners<T: Clone + Debug> {
pub top_left: T,
pub top_right: T,
pub bottom_right: T,
pub bottom_left: T,
}
impl<T: Clone + Debug + Copy> Copy for Corners<T> {}
unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Corners<T> {}
unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Corners<T> {}
#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Pixels(pub(crate) f32);
+19 -12
View File
@@ -8,9 +8,10 @@ pub struct Renderer {
queue: wgpu::Queue,
surface: wgpu::Surface,
surface_config: wgpu::SurfaceConfiguration,
pipeline: wgpu::RenderPipeline,
quad_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
vertex_count: u32,
uniforms_buffer: wgpu::Buffer,
}
pub(crate) trait RenderTarget: HasRawWindowHandle + HasRawDisplayHandle {
@@ -52,12 +53,9 @@ impl Renderer {
// quality takes priority over input latency.
present_mode: wgpu::PresentMode::Fifo,
// Use the Premultiplied alpha mode. With premultiplication, the color components
// are multiplied by the alpha value before storage or blending, meaning calculations
// with colors already factor in the influence of alpha. This typically results
// in better performance and avoids a separate multiplication operation during blending.
alpha_mode: wgpu::CompositeAlphaMode::PreMultiplied,
// When blending, assume the RGB have not yet been multiplied by the alpha channel.
alpha_mode: wgpu::CompositeAlphaMode::PostMultiplied,
PostMultiplied
// Specify the color formats for the views the surface can have.
// In this case, the format is BGRA (blue, green, red, alpha) with unsigned
// normalised integers in the 8-bit range and the color space is sRGB (standard RGB).
@@ -78,6 +76,13 @@ impl Renderer {
source: wgpu::ShaderSource::Wgsl(include_str!("shader.frag.wgsl").into()),
});
let uniforms_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("Uniforms Buffer"),
size: std::mem::size_of::<QuadUniforms>() as wgpu::BufferAddress,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Render Pipeline Layout"),
bind_group_layouts: &[],
@@ -91,17 +96,17 @@ impl Renderer {
mapped_at_creation: false,
});
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
let quad_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("Render Pipeline"),
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &vs_module,
entry_point: "main",
entry_point: "quad",
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &fs_module,
entry_point: "main",
entry_point: "quad",
targets: &[Some(wgpu::ColorTargetState {
format: surface_config.format,
blend: Some(wgpu::BlendState::REPLACE),
@@ -122,9 +127,10 @@ impl Renderer {
queue,
surface,
surface_config,
pipeline,
quad_pipeline,
vertex_buffer,
vertex_count: 0,
uniforms_buffer,
}
}
.boxed()
@@ -163,8 +169,9 @@ impl Renderer {
depth_stencil_attachment: None,
});
render_pass.set_pipeline(&self.pipeline);
render_pass.set_pipeline(&self.quad_pipeline);
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
render_pass.set_bind_group(0, &self.uniforms_buffer, &[]);
render_pass.draw(0..self.vertex_count, 0..1);
}
+5 -7
View File
@@ -1,6 +1,5 @@
use crate::{FontId, GlyphId};
use super::{Bounds, Hsla, Pixels, Point};
use crate::{Corners, Edges, FontId, GlyphId};
use bytemuck::{Pod, Zeroable};
use plane_split::BspSplitter;
@@ -69,13 +68,12 @@ pub struct PrimitiveBatch {
pub struct Quad {
pub order: f32,
pub bounds: Bounds<Pixels>,
pub clip_bounds: Bounds<Pixels>,
pub clip_corner_radii: Corners<Pixels>,
pub background: Hsla,
pub border_color: Hsla,
pub corner_radius: Pixels,
pub border_left: Pixels,
pub border_right: Pixels,
pub border_top: Pixels,
pub border_bottom: Pixels,
pub corner_radii: Corners<Pixels>,
pub border_widths: Edges<Pixels>,
}
impl Quad {
+88
View File
@@ -0,0 +1,88 @@
[[stage(vertex)]]
fn quad_vertex(input: QuadVertexInput) -> QuadVertexOutput {
var output: QuadVertexOutput;
// Apply clip bounds
input.bounds_origin = max(input.bounds_origin, input.clip_bounds.xy);
input.bounds_size = min(input.bounds_size, input.clip_bounds.zw);
var ndc: vec2<f32> = (input.bounds_origin / uniforms.window_size) * 2.0 - 1.0;
output.position = vec4<f32>(ndc, 0.0, 1.0);
output.position.y = -output.position.y; // Inverting since NDC's origin is at the center and y is up
output.color = input.color;
output.bounds = input.bounds_size / uniforms.window_size; // Convert size to NDC
output.corner_radii = input.corner_radii / uniforms.window_size; // Convert corner radii to NDC
output.clip_bounds = input.clip_bounds / uniforms.window_size; // Convert clip bounds to NDC
output.clip_corner_radii = input.corner_radii / uniforms.window_size; // Convert clip corner radii to NDC
return output;
}
// #[derive(Debug, Clone, Copy)]
// #[repr(C)]
// pub struct gpui3::scene::Quad {
// pub order: f32,
// pub bounds: Bounds<Pixels>,
// pub clip_bounds: Bounds<Pixels>,
// pub clip_corner_radii: Corners<Pixels>,
// pub background: Hsla,
// pub border_color: Hsla,
// pub corner_radii: Corners<Pixels>,
// pub border_widths: Edges<Pixels>,
// }
struct QuadVertexInput {
[[location(0)]] order: f32;
[[location(1)]] bounds: vec4<f32>; // Bounds<Pixels>
[[location(2)]] clip_bounds: vec4<f32>; // Bounds<Pixels>
[[location(3)]] clip_corner_radii: vec4<f32>; // Corners<Pixels>
[[location(4)]] color: vec4<f32>; // Hsla
[[location(5)]] border_color: vec4<f32>; // Hsla
[[location(6)]] corner_radii: vec4<f32>; // Corners<Pixels>
[[location(7)]] border_widths: vec4<f32>; // Edges<Pixels>
};
[[block]]
struct Uniforms {
viewport: vec2<f32>;
};
[[binding(0), group(0)]] var<uniform> uniforms: Uniforms;
struct QuadVertexOutput {
[[builtin(position)]] position: vec4<f32>;
[[location(0)]] color: vec4<f32>;
[[location(1)]] border_color: vec4<f32>;
[[location(2)]] bounds: vec4<f32>;
[[location(3)]] corner_radii: vec4<f32>; // assuming topLeft, topRight, bottomRight, bottomLeft
[[location(4)]] clip_bounds: vec4<f32>;
[[location(5)]] clip_corner_radii: vec4<f32>;
[[location(6)]] border_widths: vec4<f32>;
};
[[stage(fragment)]]
fn quad_fragment(input: QuadVertexOutput) -> [[location(0)]] vec4<f32> {
var output_color: vec4<f32>;
var sdf = rounded_quad_sdf(input.position, input.bounds, input.corner_radii);
var alpha = clamp(1.0 - sdf, 0.0, 1.0);
var border_color: vec4<f32> = input.border_color;
var mix_factor: f32 = 1.0 - clamp(sdf, 0.0, 1.0); // Mixing factor dependent on sdf distance
var border_width_factor: vec4<f32> = normalize(input.border_widths); // Normalizing the border width to account for directional widths
output_color = mix(input.color, border_color, mix_factor * border_width_factor); // Modulate the mix_factor with the border_width_factor to handle different border widths
output_color.a = alpha;
return output_color;
}
[[stage(fragment)]]
fn rounded_quad_sdf(p: vec2<f32>, b: vec2<f32>, r: vec4<f32>) -> f32 {
var rx: vec2<f32>;
rx = select(r.xy, r.zw, greaterThan(p.x, 0.0));
rx.x = select(rx.x, rx.y, greaterThan(p.y, 0.0));
var q: vec2<f32> = abs(p)-b+rx.x;
return min(max(q.x,q.y),0.0) + length(max(q, vec2<f32>(0.0, 0.0))) - rx.x;
}
+6 -6
View File
@@ -1,7 +1,7 @@
use super::{
rems, AbsoluteLength, Bounds, DefiniteLength, Edges, EdgesRefinement, FontStyle, FontWeight,
Hsla, Length, Pixels, Point, PointRefinement, Rems, Result, RunStyle, SharedString, Size,
SizeRefinement, ViewContext, WindowContext,
use crate::{
rems, AbsoluteLength, Bounds, Corners, CornersRefinement, DefiniteLength, Edges,
EdgesRefinement, FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rems,
Result, RunStyle, SharedString, Size, SizeRefinement, ViewContext, WindowContext,
};
use refineable::Refineable;
pub use taffy::style::{
@@ -86,7 +86,7 @@ pub struct Style {
/// The radius of the corners of this element
#[refineable]
pub corner_radii: CornerRadii,
pub corner_radii: Corners<AbsoluteLength>,
/// The color of text within this element. Cascades to children unless overridden.
pub text_color: Option<Hsla>,
@@ -243,7 +243,7 @@ impl Default for Style {
flex_basis: Length::Auto,
fill: None,
border_color: None,
corner_radii: CornerRadii::default(),
corner_radii: Corners::default(),
text_color: None,
font_size: Some(rems(1.)),
font_family: None,