#![allow(clippy::unwrap_used)] use lueur::{math::Zero, prelude::*}; #[repr(C)] struct Vertex { position: [f32; 2], color: [f32; 4], } pub struct Renderer { pipeline: gfx::PipelineId, bindings: gfx::Bindings<1, 0>, size: Size, backend: T, } impl ApplicationExt for Renderer { type Error = T::Error; fn window_resized(&mut self, size: platform::LogicalSize) -> Result<(), Self::Error> { self.size = Size::new(size.width as u32, size.height as u32); Ok(()) } fn present(&mut self) -> Result<(), Self::Error> { let mut frame = self.backend.frame(); frame.begin_default_pass(Default::default(), self.size); frame.apply_pipeline(&self.pipeline)?; frame.apply_bindings(&self.bindings)?; frame.draw(0, 3, 1)?; frame.end_pass(); frame.commit(); Ok(()) } } impl Renderer { pub fn init(mut backend: T) -> Result { #[rustfmt::skip] let vertices: [Vertex; 3] = [ Vertex { position: [-0.5, -0.5], color: [1., 1., 0., 1.] }, Vertex { position: [ 0.5, -0.5], color: [0., 1., 1., 1.] }, Vertex { position: [ 0.0, 0.5], color: [1., 0., 1., 1.] }, ]; let vertex_buffer = backend.buffer( gfx::BufferKind::Vertex, gfx::BufferUsage::Immutable, gfx::BufferSource::slice(&vertices), )?; let index_buffer = backend.buffer( gfx::BufferKind::Index, gfx::BufferUsage::Immutable, gfx::BufferSource::slice(&[0, 1, 2]), )?; let bindings = gfx::Bindings { vertex: [vertex_buffer], index: Some(index_buffer), textures: [], }; let shader = backend .shader( gfx::ShaderSource { vertex: shader::VERTEX, fragment: shader::FRAGMENT, geometry: None, }, shader::descriptor(), ) .unwrap(); let pipeline = backend.pipeline( shader, gfx::PipelineDescriptor { layout: &[gfx::BufferLayout { attrs: &[ gfx::VertexAttribute::new("position", gfx::VertexFormat::Float2), gfx::VertexAttribute::new("color", gfx::VertexFormat::Float4), ], ..gfx::BufferLayout::default() }], ..gfx::PipelineDescriptor::default() }, )?; Ok(Self { backend, pipeline, bindings, size: Size::ZERO, }) } } fn main() -> Result<(), Box> { logger::init(log::Level::Debug)?; let (mut win, events) = platform::init("triangle", 640, 480, &[], platform::GraphicsContext::Gl)?; let ctx = unsafe { glow::Context::from_loader_function(|p| win.get_proc_address(p)) }; let backend = gfx::gl::Context::new(ctx, win.size())?; let renderer = Renderer::init(backend)?; lueur::runtime::default::run(win, events, renderer)?; Ok(()) } mod shader { use super::*; pub const VERTEX: &str = r#" #version 100 attribute vec2 position; attribute vec4 color; varying lowp vec4 f_color; void main() { gl_Position = vec4(position, 0, 1); f_color = color; } "#; pub const FRAGMENT: &str = r#" #version 100 varying lowp vec4 f_color; void main() { gl_FragColor = f_color; } "#; pub fn descriptor() -> gfx::ShaderDescriptor<'static> { gfx::ShaderDescriptor { textures: &[], uniforms: gfx::UniformBlockLayout { uniforms: &[] }, } } }