ori-wgpu 0.1.0-alpha.1

WGPU backend for Ori
Documentation
struct Uniforms {
	resolution: vec2<f32>,
}

@group(0) @binding(0)
var<uniform> uniforms: Uniforms;

struct VertexInput {
	@location(0) position: vec2<f32>,
	@location(1) top_left: vec2<f32>,
	@location(2) bottom_right: vec2<f32>,
	@location(3) color: vec4<f32>,
	@location(4) border_color: vec4<f32>,
	@location(5) border_radius: vec4<f32>,
	@location(6) border_width: f32,
}

struct VertexOutput {
	@builtin(position) clip: vec4<f32>,
	@location(0) top_left: vec2<f32>,
	@location(1) bottom_right: vec2<f32>,
	@location(2) color: vec4<f32>,
	@location(3) border_color: vec4<f32>,
	@location(4) border_radius: vec4<f32>,
	@location(5) border_width: f32,
}

@vertex
fn vertex(in: VertexInput) -> VertexOutput {
	var out: VertexOutput;

	let position = in.position / uniforms.resolution * vec2<f32>(2.0, -2.0) - vec2<f32>(1.0, -1.0);
	out.clip = vec4<f32>(position, 0.0, 1.0);
	out.top_left = in.top_left;
	out.bottom_right = in.bottom_right;
	out.color = in.color;
	out.border_color = in.border_color;
	out.border_radius = in.border_radius;
	out.border_width = in.border_width;

	return out;
}

fn quad_distance(
	position: vec2<f32>,
	top_left: vec2<f32>,
	bottom_right: vec2<f32>,
	radius: f32,
) -> f32 {
	let top_left_distance = top_left - position + radius;
	let bottom_right_distance = position - bottom_right + radius;

	let dist = vec2<f32>(
		max(max(top_left_distance.x, bottom_right_distance.x), 0.0),
		max(max(top_left_distance.y, bottom_right_distance.y), 0.0),
	);

	return length(dist);
}

fn select_border_radius(
	position: vec2<f32>, 
	top_left: vec2<f32>, 
	bottom_right: vec2<f32>,
	radi: vec4<f32>,
) -> f32 {
	let center = (top_left + bottom_right) / 2.0;

	let rx = select(radi.x, radi.y, position.x > center.x);
	let ry = select(radi.w, radi.z, position.x > center.x);
	return select(rx, ry, position.y > center.y);
}

@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
	var color = in.color;

	let border_radius = select_border_radius(
		in.clip.xy,
		in.top_left,
		in.bottom_right,
		in.border_radius,
	);

	if in.border_width > 0.0 {
		let internal_border = max(border_radius - in.border_width, 0.0);

		let internal_dist = quad_distance(
			in.clip.xy,
			in.top_left + vec2<f32>(in.border_width),
			in.bottom_right - vec2<f32>(in.border_width),
			internal_border,
		);

		let border_mix = smoothstep(
			max(internal_border - 0.5, 0.0),
			internal_border + 0.5,
			internal_dist,
		);

		color = mix(color, in.border_color, border_mix);
	}

	let dist = quad_distance(
		in.clip.xy,
		in.top_left,
		in.bottom_right,
		border_radius,
	);

	let radius_alpha = 1.0 - smoothstep(
		max(border_radius - 0.5, 0.0),
		border_radius + 0.5,
		dist,
	);

	return vec4<f32>(
		color.x,
		color.y,
		color.z,
		color.w * radius_alpha,
	);
}