use std::ffi::{c_void, CString}; use std::process::abort; use glfw::WindowSize; use crate::renderer::vertex_array::{PrimitiveKind, VertexArray}; use crate::renderer::vertex_buffers::{BufferUsage, VertexBuffers}; use crate::vector::Vec2; use crate::vertex::Vertex; mod vertex_array; mod vertex_buffers; pub fn initialize(window: &glfw::Window) -> Result<(), Error> { gl::load_with(|symbol| { let proc_name = unsafe { CString::from_vec_unchecked(symbol.into()) }; match window.get_proc_address(proc_name.as_c_str()) { Ok(addr) => addr as *const c_void, Err(err) => { println!( "FATAL ERROR: Failed to get adress of OpenGL function {}. {}", symbol, err ); abort(); } } }); let window_size = window.size().map_err(Error::GetWindowSizeFailed)?; set_viewport(&Vec2 { x: 0, y: 0 }, &window_size); Ok(()) } pub fn render<'renderable>(renderables: impl IntoIterator) { unsafe { gl::Clear(gl::COLOR_BUFFER_BIT); } for renderable in renderables { renderable.shader_program.activate(); renderable.vertex_arr.draw(PrimitiveKind::Triangles, 0, 3); } } #[derive(Debug)] pub struct Renderable { shader_program: crate::shader::Program, vertex_arr: VertexArray, /// Vertex buffer has to live as long as the vertex array _vertex_buffer: VertexBuffers<1>, } impl Renderable { pub fn new(shader_program: crate::shader::Program, vertices: &[Vertex]) -> Self { let vertex_arr = VertexArray::new(); vertex_arr.bind(); let vertex_buffer = VertexBuffers::<1>::new(); vertex_buffer .store(0, vertices, BufferUsage::Static) .unwrap(); VertexArray::configure_attrs(); Self { shader_program, vertex_arr, _vertex_buffer: vertex_buffer, } } } pub fn set_viewport(position: &Vec2, size: &WindowSize) { unsafe { #[allow(clippy::cast_possible_wrap)] gl::Viewport( position.x as i32, position.y as i32, size.width as i32, size.height as i32, ); } } /// Renderer error. #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Failed to get window size")] GetWindowSizeFailed(#[source] glfw::Error), }