initial commit
This commit is contained in:
110
src/render/shader.wgsl
Normal file
110
src/render/shader.wgsl
Normal file
@@ -0,0 +1,110 @@
|
||||
@group(0) @binding(0)
|
||||
var<uniform> window: WindowUniform;
|
||||
@group(0) @binding(1)
|
||||
var<storage> data: array<u32>;
|
||||
|
||||
struct WindowUniform {
|
||||
dim: vec2<f32>,
|
||||
};
|
||||
|
||||
struct InstanceInput {
|
||||
@location(0) top_left_anchor: vec2<f32>,
|
||||
@location(1) top_left_offset: vec2<f32>,
|
||||
@location(2) bottom_right_anchor: vec2<f32>,
|
||||
@location(3) bottom_right_offset: vec2<f32>,
|
||||
@location(4) pointer: u32,
|
||||
}
|
||||
|
||||
struct RoundedRect {
|
||||
color: u32,
|
||||
radius: f32,
|
||||
thickness: f32,
|
||||
inner_radius: f32,
|
||||
}
|
||||
|
||||
struct VertexOutput {
|
||||
@location(0) pointer: u32,
|
||||
@location(1) top_left: vec2<f32>,
|
||||
@location(2) bot_right: vec2<f32>,
|
||||
@builtin(position) clip_position: vec4<f32>,
|
||||
};
|
||||
|
||||
struct Region {
|
||||
pos: vec2<f32>,
|
||||
top_left: vec2<f32>,
|
||||
bot_right: vec2<f32>,
|
||||
}
|
||||
|
||||
@vertex
|
||||
fn vs_main(
|
||||
@builtin(vertex_index) vi: u32,
|
||||
in: InstanceInput,
|
||||
) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
|
||||
let top_left = in.top_left_anchor * window.dim + in.top_left_offset;
|
||||
let bot_right = in.bottom_right_anchor * window.dim + in.bottom_right_offset;
|
||||
let size = bot_right - top_left;
|
||||
|
||||
var pos = top_left + vec2<f32>(
|
||||
f32(vi % 2u),
|
||||
f32(vi / 2u)
|
||||
) * size;
|
||||
pos = pos / window.dim * 2.0 - 1.0;
|
||||
out.clip_position = vec4<f32>(pos.x, -pos.y, 0.0, 1.0);
|
||||
out.pointer = in.pointer;
|
||||
out.top_left = top_left;
|
||||
out.bot_right = bot_right;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main(
|
||||
in: VertexOutput
|
||||
) -> @location(0) vec4<f32> {
|
||||
let pos = in.clip_position.xy;
|
||||
let ty = data[in.pointer];
|
||||
let dp = in.pointer + 1u;
|
||||
let region = Region(pos, in.top_left, in.bot_right);
|
||||
switch ty {
|
||||
case 0u: {
|
||||
return draw_rounded_rect(region, RoundedRect(
|
||||
data[dp + 0u],
|
||||
bitcast<f32>(data[dp + 1u]),
|
||||
bitcast<f32>(data[dp + 2u]),
|
||||
bitcast<f32>(data[dp + 3u]),
|
||||
));
|
||||
}
|
||||
default: {}
|
||||
}
|
||||
return vec4(1.0, 0.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
fn draw_rounded_rect(region: Region, rect: RoundedRect) -> vec4<f32> {
|
||||
var color = unpack4x8unorm(rect.color);
|
||||
|
||||
let edge = 0.5;
|
||||
|
||||
let size = region.bot_right - region.top_left;
|
||||
let corner = size / 2.0;
|
||||
let center = region.top_left + corner;
|
||||
|
||||
let dist = distance_from_rect(region.pos, center, corner, rect.radius);
|
||||
color.a *= 1.0 - smoothstep(-min(edge, rect.radius), edge, dist);
|
||||
|
||||
if rect.thickness > 0.0 {
|
||||
let dist2 = distance_from_rect(region.pos, center, corner - rect.thickness, rect.inner_radius);
|
||||
color.a *= smoothstep(-min(edge, rect.inner_radius), edge, dist2);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
fn distance_from_rect(pixel_pos: vec2<f32>, rect_center: vec2<f32>, rect_corner: vec2<f32>, radius: f32) -> f32 {
|
||||
// vec from center to pixel
|
||||
let p = pixel_pos - rect_center;
|
||||
// vec from inner rect corner to pixel
|
||||
let q = abs(p) - (rect_corner - radius);
|
||||
return length(max(q, vec2<f32>(0.0, 0.0))) - radius;
|
||||
}
|
||||
Reference in New Issue
Block a user