canary-rs/apps/magpie/src/service/gl.rs

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,
&params,
)
.unwrap();
target.finish().unwrap();
}
}