///|
fn pixel_to_ndc_vertices(
vertices : Array[Double],
screen_w : Double,
screen_h : Double,
) -> Array[Double] {
let out : Array[Double] = []
let mut i = 0
while i < vertices.length() {
let px = vertices[i]
let py = vertices[i + 1]
let u = vertices[i + 2]
let v = vertices[i + 3]
out.push(px / screen_w * 2.0 - 1.0)
out.push(1.0 - py / screen_h * 2.0)
out.push(u)
out.push(v)
i = i + 4
}
out
}
///|
fn new_primitive_command(
frame : RenderFrame2D,
vertex_data : Array[Double],
indices : Array[Int],
color : @gfx.Color,
) -> @gfx.DrawTrianglesCommand {
@gfx.new_draw_triangles_command(
frame.dst,
frame.shader,
[
@gfx.new_dst_region(
0,
0,
frame.screen_w,
frame.screen_h,
indices.length(),
),
],
0,
frame.pipeline_id,
frame.uniform_hash,
frame.blend,
vertex_data,
indices,
[],
color_to_uniform_dwords(color),
)
}
///|
pub fn append_primitive_batch(
commands : Array[@gfx.DrawTrianglesCommand],
frame : RenderFrame2D,
vertex_data : Array[Double],
indices : Array[Int],
color : @gfx.Color,
) -> Unit {
commands.push(new_primitive_command(frame, vertex_data, indices, color))
}
///|
pub(all) struct RectFill2D {
x : Double
y : Double
w : Double
h : Double
color : @gfx.Color
}
///|
pub fn RectFill2D::new(
x~ : Double,
y~ : Double,
w~ : Double,
h~ : Double,
color~ : @gfx.Color,
) -> RectFill2D {
{ x, y, w, h, color }
}
///|
pub fn append_rect_fill_geometry(
vertices : Array[Double],
indices : Array[Int],
frame : RenderFrame2D,
rect : RectFill2D,
) -> Unit {
let (rect_vertices, rect_indices) = ndc_rect_fill_vertices(
rect.x,
rect.y,
rect.w,
rect.h,
frame.screen_w.to_double(),
frame.screen_h.to_double(),
)
let base_vertex = vertices.length() / 4
for value in rect_vertices {
vertices.push(value)
}
for idx in rect_indices {
indices.push(base_vertex + idx)
}
}
///|
pub fn append_rect_fill(
commands : Array[@gfx.DrawTrianglesCommand],
frame : RenderFrame2D,
rect : RectFill2D,
) -> Unit {
let vertices : Array[Double] = []
let indices : Array[Int] = []
append_rect_fill_geometry(vertices, indices, frame, rect)
append_primitive_batch(commands, frame, vertices, indices, rect.color)
}
///|
pub(all) struct Line2D {
x0 : Double
y0 : Double
x1 : Double
y1 : Double
width : Double
color : @gfx.Color
}
///|
pub fn Line2D::new(
x0~ : Double,
y0~ : Double,
x1~ : Double,
y1~ : Double,
width? : Double = 1.0,
color~ : @gfx.Color,
) -> Line2D {
{ x0, y0, x1, y1, width, color }
}
///|
pub fn append_line(
commands : Array[@gfx.DrawTrianglesCommand],
frame : RenderFrame2D,
line : Line2D,
) -> Unit {
let (vertices, indices) = line_vertices(
line.x0,
line.y0,
line.x1,
line.y1,
line.width,
)
commands.push(
new_primitive_command(
frame,
pixel_to_ndc_vertices(
vertices,
frame.screen_w.to_double(),
frame.screen_h.to_double(),
),
indices,
line.color,
),
)
}
///|
pub(all) struct RectOutline2D {
x : Double
y : Double
w : Double
h : Double
line_width : Double
color : @gfx.Color
}
///|
pub fn RectOutline2D::new(
x~ : Double,
y~ : Double,
w~ : Double,
h~ : Double,
line_width? : Double = 1.0,
color~ : @gfx.Color,
) -> RectOutline2D {
{ x, y, w, h, line_width, color }
}
///|
pub fn append_rect_outline(
commands : Array[@gfx.DrawTrianglesCommand],
frame : RenderFrame2D,
rect : RectOutline2D,
) -> Unit {
let (vertices, indices) = rect_outline_vertices(
rect.x,
rect.y,
rect.w,
rect.h,
rect.line_width,
)
commands.push(
new_primitive_command(
frame,
pixel_to_ndc_vertices(
vertices,
frame.screen_w.to_double(),
frame.screen_h.to_double(),
),
indices,
rect.color,
),
)
}