use std::ffi::{c_void, CString}; use std::process::abort; use glfw::WindowSize; use crate::opengl::shader::Program as ShaderProgram; use crate::opengl::vertex_array::{PrimitiveKind, VertexArray}; use crate::opengl::vertex_buffer::{BufferUsage, VertexBuffer}; use crate::opengl::{clear_buffers, BufferClearMask}; use crate::vector::Vec2; use crate::vertex::Vertex; 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) { clear_buffers(BufferClearMask::COLOR); for renderable in renderables { renderable.shader_program.activate(); renderable.vertex_arr.bind(|vert_arr_curr_bound| { VertexArray::draw(&vert_arr_curr_bound, PrimitiveKind::Triangles, 0, 3); }); } } pub fn set_viewport(position: &Vec2, size: &WindowSize) { crate::opengl::set_viewport(position, size); } #[derive(Debug)] pub struct Renderable { shader_program: ShaderProgram, vertex_arr: VertexArray, /// Vertex buffer has to live as long as the vertex array _vertex_buffer: VertexBuffer, } impl Renderable { pub fn new(shader_program: ShaderProgram, vertices: &[Vertex]) -> Self { let vertex_arr = VertexArray::new(); let vertex_buffer = VertexBuffer::new(); vertex_arr.bind(|vert_arr_curr_bound| { vertex_buffer.bind(|vert_buf_curr_bound| { VertexBuffer::store(&vert_buf_curr_bound, vertices, BufferUsage::Static); VertexArray::configure_attrs(&vert_arr_curr_bound, &vert_buf_curr_bound); }); }); Self { shader_program, vertex_arr, _vertex_buffer: vertex_buffer, } } } /// Renderer error. #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Failed to get window size")] GetWindowSizeFailed(#[source] glfw::Error), }