133 lines
3.6 KiB
Rust
133 lines
3.6 KiB
Rust
// Copyright (c) 2022 Marceline Cramer
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
use canary::{DrawCommand, Vec2, PX_PER_MM};
|
|
use glium::{program::ProgramCreationInput, Surface};
|
|
|
|
#[derive(Copy, Clone)]
|
|
pub struct Vertex {
|
|
pub position: [f32; 2],
|
|
pub color: [u8; 4],
|
|
}
|
|
|
|
glium::implement_vertex!(Vertex, position normalize(false), color normalize(true));
|
|
|
|
impl Vertex {
|
|
pub fn from_canary(size: Vec2, v: &canary::MeshVertex) -> Self {
|
|
// TODO do this in the vertex shader with a size uniform
|
|
let (r, g, b, a) = v.color.to_rgba_unmultiplied();
|
|
Self {
|
|
position: [
|
|
(v.position.x / size.x) * 2.0 - 1.0,
|
|
(v.position.y / size.y) * -2.0 + 1.0,
|
|
],
|
|
color: [r, g, b, a],
|
|
}
|
|
}
|
|
}
|
|
|
|
const VERTEX_SHADER_SRC: &str = r#"
|
|
#version 330
|
|
|
|
in vec2 position;
|
|
in vec4 color;
|
|
|
|
out vec4 frag_color;
|
|
|
|
void main() {
|
|
gl_Position = vec4(position, 0.0, 1.0);
|
|
frag_color = color;
|
|
}
|
|
"#;
|
|
|
|
const FRAGMENT_SHADER_SRC: &str = r#"
|
|
#version 330
|
|
|
|
in vec4 frag_color;
|
|
|
|
out vec4 fb_color;
|
|
|
|
void main() {
|
|
fb_color = frag_color;
|
|
}
|
|
"#;
|
|
|
|
pub struct Graphics {
|
|
pub display: glium::Display,
|
|
pub program: glium::Program,
|
|
}
|
|
|
|
impl Graphics {
|
|
pub fn new(display: glium::Display) -> Self {
|
|
let program = glium::Program::new(
|
|
&display,
|
|
ProgramCreationInput::SourceCode {
|
|
vertex_shader: VERTEX_SHADER_SRC,
|
|
tessellation_control_shader: None,
|
|
tessellation_evaluation_shader: None,
|
|
geometry_shader: None,
|
|
fragment_shader: FRAGMENT_SHADER_SRC,
|
|
transform_feedback_varyings: None,
|
|
outputs_srgb: true, // don't automatically apply gamma correction
|
|
uses_point_size: false,
|
|
},
|
|
)
|
|
.unwrap();
|
|
|
|
Self { display, program }
|
|
}
|
|
|
|
pub fn draw(&mut self, commands: &[DrawCommand]) {
|
|
let mut joined_vs: Vec<Vertex> = Vec::new();
|
|
let mut joined_is = Vec::new();
|
|
|
|
let (width, height) = {
|
|
let size = self.display.gl_window().window().inner_size();
|
|
let (width, height) = (size.width as f32, size.height as f32);
|
|
(width * PX_PER_MM, height * PX_PER_MM)
|
|
};
|
|
|
|
let size = Vec2 {
|
|
x: width,
|
|
y: height,
|
|
};
|
|
|
|
for command in commands.iter() {
|
|
match command {
|
|
canary::DrawCommand::Mesh { vertices, indices } => {
|
|
let voff = joined_vs.len() as canary::MeshIndex;
|
|
joined_vs.extend(vertices.iter().map(|v| Vertex::from_canary(size, v)));
|
|
joined_is.extend(indices.iter().map(|i| i + voff));
|
|
}
|
|
_ => unimplemented!(),
|
|
}
|
|
}
|
|
|
|
let vertex_buffer = glium::VertexBuffer::new(&self.display, &joined_vs).unwrap();
|
|
let index_buffer = glium::IndexBuffer::new(
|
|
&self.display,
|
|
glium::index::PrimitiveType::TrianglesList,
|
|
&joined_is,
|
|
)
|
|
.unwrap();
|
|
|
|
let params = glium::DrawParameters {
|
|
blend: glium::Blend::alpha_blending(),
|
|
..Default::default()
|
|
};
|
|
|
|
let mut target = self.display.draw();
|
|
target.clear_color(0.0, 0.0, 0.0, 0.0);
|
|
target
|
|
.draw(
|
|
&vertex_buffer,
|
|
&index_buffer,
|
|
&self.program,
|
|
&glium::uniforms::EmptyUniforms,
|
|
¶ms,
|
|
)
|
|
.unwrap();
|
|
target.finish().unwrap();
|
|
}
|
|
}
|