diff options
author | HampusM <hampus@hampusmat.com> | 2023-10-23 20:25:42 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2023-10-23 20:25:42 +0200 |
commit | c12966c5b69841f49713f97f3d9fa7ba99fc42e7 (patch) | |
tree | 8a445fca96bf893d45f7d816c5aca24a5d72354c | |
parent | bd427836bfa6f7228951c18e43058d3e35577702 (diff) |
feat(engine): add using element buffers
-rw-r--r-- | engine/src/object.rs | 8 | ||||
-rw-r--r-- | engine/src/opengl/buffer.rs | 37 | ||||
-rw-r--r-- | engine/src/opengl/vertex_array.rs | 29 | ||||
-rw-r--r-- | engine/src/renderer/mod.rs | 59 |
4 files changed, 115 insertions, 18 deletions
diff --git a/engine/src/object.rs b/engine/src/object.rs index c3d82d0..02ae97a 100644 --- a/engine/src/object.rs +++ b/engine/src/object.rs @@ -23,7 +23,11 @@ impl Object /// /// # Errors /// Will return `Err` if shader creation fails or if shader program linking fails. - pub fn new(id: Id, vertices: &[Vertex]) -> Result<Self, Error> + pub fn new( + id: Id, + vertices: &[Vertex], + indices: Option<&[u32]>, + ) -> Result<Self, Error> { let vertex_shader = Shader::new(ShaderKind::Vertex); @@ -54,7 +58,7 @@ impl Object .link() .map_err(Error::LinkShaderProgramFailed)?; - let renderable = Renderable::new(shader_program, vertices); + let renderable = Renderable::new(shader_program, vertices, indices); let transform = Transform::new(); diff --git a/engine/src/opengl/buffer.rs b/engine/src/opengl/buffer.rs index 34514fd..3a4ecf0 100644 --- a/engine/src/opengl/buffer.rs +++ b/engine/src/opengl/buffer.rs @@ -4,13 +4,14 @@ use std::mem::size_of_val; use crate::opengl::currently_bound::CurrentlyBound; #[derive(Debug)] -pub struct Buffer<Item> +pub struct Buffer<Item, ModeT: Mode> { buffer: gl::types::GLuint, _item_pd: PhantomData<Item>, + _mode_pd: PhantomData<ModeT>, } -impl<Item> Buffer<Item> +impl<Item, ModeT: Mode> Buffer<Item, ModeT> { pub fn new() -> Self { @@ -23,6 +24,7 @@ impl<Item> Buffer<Item> Self { buffer, _item_pd: PhantomData, + _mode_pd: PhantomData, } } @@ -31,7 +33,7 @@ impl<Item> Buffer<Item> pub fn bind(&self, cb: impl FnOnce(CurrentlyBound<'_, Self>)) { unsafe { - gl::BindBuffer(gl::ARRAY_BUFFER, self.buffer); + gl::BindBuffer(ModeT::GL_ENUM, self.buffer); } // SAFETY: The buffer object is bound above @@ -46,7 +48,7 @@ impl<Item> Buffer<Item> unsafe { #[allow(clippy::cast_possible_wrap)] gl::BufferData( - gl::ARRAY_BUFFER, + ModeT::GL_ENUM, size_of_val(items) as gl::types::GLsizeiptr, items.as_ptr().cast(), usage.into_gl(), @@ -55,7 +57,7 @@ impl<Item> Buffer<Item> } } -impl<Item> Drop for Buffer<Item> +impl<Item, ModeT: Mode> Drop for Buffer<Item, ModeT> { fn drop(&mut self) { @@ -92,3 +94,28 @@ impl Usage } } } + +/// Buffer mode. +pub trait Mode +{ + #[doc(hidden)] + const GL_ENUM: gl::types::GLenum; +} + +/// Array buffer kind. +#[derive(Debug)] +pub struct ArrayKind; + +impl Mode for ArrayKind +{ + const GL_ENUM: gl::types::GLenum = gl::ARRAY_BUFFER; +} + +/// Element array buffer kind. +#[derive(Debug)] +pub struct ElementArrayKind; + +impl Mode for ElementArrayKind +{ + const GL_ENUM: gl::types::GLenum = gl::ELEMENT_ARRAY_BUFFER; +} diff --git a/engine/src/opengl/vertex_array.rs b/engine/src/opengl/vertex_array.rs index ba2ded2..6b6065c 100644 --- a/engine/src/opengl/vertex_array.rs +++ b/engine/src/opengl/vertex_array.rs @@ -1,6 +1,6 @@ use std::mem::size_of; -use crate::opengl::buffer::Buffer; +use crate::opengl::buffer::{ArrayKind as ArrayBufferKind, Buffer}; use crate::opengl::currently_bound::CurrentlyBound; use crate::vertex::{Attribute, AttributeComponentType, Vertex}; @@ -26,11 +26,11 @@ impl VertexArray } /// Draws the currently bound vertex array. - pub fn draw( + pub fn draw_arrays( _currently_bound: &CurrentlyBound<Self>, primitive_kind: PrimitiveKind, start_index: u32, - index_cnt: u32, + cnt: u32, ) { unsafe { @@ -38,14 +38,33 @@ impl VertexArray gl::DrawArrays( primitive_kind.into_gl(), start_index as gl::types::GLint, - index_cnt as gl::types::GLsizei, + cnt as gl::types::GLsizei, + ); + } + } + + /// Draws the currently bound vertex array. + pub fn draw_elements( + _currently_bound: &CurrentlyBound<Self>, + primitive_kind: PrimitiveKind, + offset: u32, + cnt: u32, + ) + { + unsafe { + #[allow(clippy::cast_possible_wrap)] + gl::DrawElements( + primitive_kind.into_gl(), + cnt as gl::types::GLsizei, + gl::UNSIGNED_INT, + (offset as gl::types::GLint) as *const _, ); } } pub fn configure_attrs( _currently_bound: &CurrentlyBound<Self>, - _vert_buf_curr_bound: &CurrentlyBound<Buffer<Vertex>>, + _vert_buf_curr_bound: &CurrentlyBound<Buffer<Vertex, ArrayBufferKind>>, ) { let mut offset = 0; diff --git a/engine/src/renderer/mod.rs b/engine/src/renderer/mod.rs index f31196d..a02bbc2 100644 --- a/engine/src/renderer/mod.rs +++ b/engine/src/renderer/mod.rs @@ -5,7 +5,12 @@ use cstr::cstr; use glfw::WindowSize; use crate::object::Object; -use crate::opengl::buffer::{Buffer, Usage}; +use crate::opengl::buffer::{ + ArrayKind as ArrayBufferKind, + Buffer, + ElementArrayKind as ElementArrayBufferKind, + Usage as BufferUsage, +}; #[cfg(feature = "debug")] use crate::opengl::debug::{MessageSeverity, MessageSource, MessageType}; use crate::opengl::shader::Program as ShaderProgram; @@ -106,7 +111,21 @@ pub fn render<'obj>(objects: impl IntoIterator<Item = &'obj Object>) .set_uniform_matrix_4fv(cstr!("transform"), &obj.transform().as_matrix()); obj.renderable().vertex_arr.bind(|vert_arr_curr_bound| { - VertexArray::draw(&vert_arr_curr_bound, PrimitiveKind::Triangles, 0, 3); + if let Some(index_info) = &obj.renderable().index_info { + VertexArray::draw_elements( + &vert_arr_curr_bound, + PrimitiveKind::Triangles, + 0, + index_info.cnt, + ); + } else { + VertexArray::draw_arrays( + &vert_arr_curr_bound, + PrimitiveKind::Triangles, + 0, + 3, + ); + } }); } } @@ -122,29 +141,57 @@ pub struct Renderable shader_program: ShaderProgram, vertex_arr: VertexArray, - /// Vertex buffer has to live as long as the vertex array - _vertex_buffer: Buffer<Vertex>, + /// Vertex and index buffer has to live as long as the vertex array + _vertex_buffer: Buffer<Vertex, ArrayBufferKind>, + index_info: Option<IndexInfo>, +} + +#[derive(Debug)] +struct IndexInfo +{ + _buffer: Buffer<u32, ElementArrayBufferKind>, + cnt: u32, } impl Renderable { - pub fn new(shader_program: ShaderProgram, vertices: &[Vertex]) -> Self + pub fn new( + shader_program: ShaderProgram, + vertices: &[Vertex], + indices: Option<&[u32]>, + ) -> Self { let vertex_arr = VertexArray::new(); let vertex_buffer = Buffer::new(); + let mut index_info = None; + vertex_arr.bind(|vert_arr_curr_bound| { vertex_buffer.bind(|vert_buf_curr_bound| { - Buffer::store(&vert_buf_curr_bound, vertices, Usage::Static); + Buffer::store(&vert_buf_curr_bound, vertices, BufferUsage::Static); VertexArray::configure_attrs(&vert_arr_curr_bound, &vert_buf_curr_bound); }); + + if let Some(indices) = indices { + let new_index_buffer = Buffer::new(); + + new_index_buffer.bind(|index_buf_curr_bound| { + Buffer::store(&index_buf_curr_bound, indices, BufferUsage::Static); + }); + + index_info = Some(IndexInfo { + _buffer: new_index_buffer, + cnt: indices.len().try_into().unwrap(), + }); + } }); Self { shader_program, vertex_arr, _vertex_buffer: vertex_buffer, + index_info, } } } |