#![allow(clippy::unwrap_used)] use std::time::SystemTime; use lueur::{math::Zero, prelude::*}; #[repr(C)] struct Vec2 { x: f32, y: f32, } #[repr(C)] struct Vertex { pos: Vec2, uv: Vec2, } struct Example { pipeline: PipelineId, bindings: Bindings<1, 1>, size: Size, backend: T, } impl ApplicationExt for Example { 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 t = SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs_f64(); let mut frame = self.backend.frame(); frame.begin_default_pass(Default::default(), self.size); frame.apply_pipeline(&self.pipeline)?; frame.apply_bindings(&self.bindings)?; for i in 0..10 { let t = t + i as f64 * 0.3; frame.apply_uniforms(&shader::Uniforms { offset: [t.sin() as f32 * 0.5, (t * 3.).cos() as f32 * 0.5], })?; frame.draw(0, 6, 1)?; } frame.end_pass(); frame.commit(); Ok(()) } } impl Example { pub fn init(mut backend: T) -> Result, T::Error> { #[rustfmt::skip] let vertices: [Vertex; 4] = [ Vertex { pos : Vec2 { x: -0.5, y: -0.5 }, uv: Vec2 { x: 0., y: 0. } }, Vertex { pos : Vec2 { x: 0.5, y: -0.5 }, uv: Vec2 { x: 1., y: 0. } }, Vertex { pos : Vec2 { x: 0.5, y: 0.5 }, uv: Vec2 { x: 1., y: 1. } }, Vertex { pos : Vec2 { x: -0.5, y: 0.5 }, uv: Vec2 { x: 0., y: 1. } }, ]; let vertex_buffer = backend.buffer( BufferKind::Vertex, BufferUsage::Immutable, BufferSource::slice(&vertices), )?; let indices: [u16; 6] = [0, 1, 2, 0, 2, 3]; let index_buffer = backend.buffer( BufferKind::Index, BufferUsage::Immutable, BufferSource::slice(&indices), )?; let pixels: [Rgba8; 4 * 4] = [ Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF), Rgba8::new(0xFF, 0x00, 0x00, 0xFF), Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF), Rgba8::new(0xFF, 0x00, 0x00, 0xFF), Rgba8::new(0xFF, 0x00, 0x00, 0xFF), Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF), Rgba8::new(0xFF, 0x00, 0x00, 0xFF), Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF), Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF), Rgba8::new(0xFF, 0x00, 0x00, 0x00), Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF), Rgba8::new(0xFF, 0x00, 0x00, 0xFF), Rgba8::new(0xFF, 0x00, 0x00, 0xFF), Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF), Rgba8::new(0xFF, 0x00, 0x00, 0xFF), Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF), ]; let texture = backend.texture(gfx::Texture { data: pixels.as_slice(), size: Size::new(4, 4), min_filter: FilterMode::Linear, mag_filter: FilterMode::Linear, ..gfx::Texture::default() })?; let bindings = Bindings { vertex: [vertex_buffer], index: Some(index_buffer), textures: [texture], }; let shader = backend .shader( ShaderSource { vertex: shader::VERTEX, fragment: shader::FRAGMENT, geometry: None, }, shader::meta(), ) .unwrap(); let pipeline = backend.pipeline( shader, gfx::PipelineDescriptor { layout: &[gfx::BufferLayout { attrs: &[ VertexAttribute::new("in_pos", VertexFormat::Float2), VertexAttribute::new("in_uv", VertexFormat::Float2), ], ..gfx::BufferLayout::default() }], ..gfx::PipelineDescriptor::default() }, )?; Ok(Self { pipeline, bindings, backend, size: Size::ZERO, }) } } fn main() -> Result<(), Box> { logger::init(log::Level::Debug)?; let (mut win, events) = platform::init("texture", 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 = Example::init(backend)?; lueur::runtime::default::run(win, events, renderer)?; Ok(()) } mod shader { use super::*; pub const VERTEX: &str = r#"#version 100 attribute vec2 in_pos; attribute vec2 in_uv; uniform vec2 offset; varying lowp vec2 texcoord; void main() { gl_Position = vec4(in_pos + offset, 0, 1); texcoord = in_uv; }"#; pub const FRAGMENT: &str = r#"#version 100 varying lowp vec2 texcoord; uniform sampler2D tex; void main() { gl_FragColor = texture2D(tex, texcoord); }"#; pub fn meta() -> ShaderDescriptor<'static> { ShaderDescriptor { textures: &["tex"], uniforms: UniformBlockLayout { uniforms: &[UniformDescriptor { name: "offset", kind: UniformKind::Float2, arity: 1, }], }, } } #[repr(C)] pub struct Uniforms { pub offset: [f32; 2], } unsafe impl bytes::Packed for Uniforms {} }