diff options
Diffstat (limited to 'engine/src/renderer')
| -rw-r--r-- | engine/src/renderer/opengl.rs | 85 | ||||
| -rw-r--r-- | engine/src/renderer/opengl/graphics_mesh.rs | 141 | ||||
| -rw-r--r-- | engine/src/renderer/opengl/vertex.rs | 65 |
3 files changed, 169 insertions, 122 deletions
diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs index d31835a..2dd5467 100644 --- a/engine/src/renderer/opengl.rs +++ b/engine/src/renderer/opengl.rs @@ -91,6 +91,7 @@ use crate::renderer::{ }; use crate::shader::cursor::BindingValue as ShaderBindingValue; use crate::shader::{ + Context as ShaderContext, Error as ShaderError, Program as ShaderProgram, Stage as ShaderStage, @@ -111,7 +112,6 @@ use crate::windowing::window::{ mod glutin_compat; mod graphics_mesh; -mod vertex; declare_entity!( pub POST_RENDER_PHASE, @@ -137,7 +137,11 @@ struct GraphicsContext #[derive(Debug)] enum GraphicsContextObject { - Mesh(GraphicsMesh), + Mesh + { + mesh: GraphicsMesh, + compatible_shader_program_obj_id: RendererObjectId, + }, } #[derive(Debug, Default)] @@ -265,7 +269,10 @@ fn handle_model_removed( }; #[allow(irrefutable_let_patterns)] - let GraphicsContextObject::Mesh(mut graphics_mesh) = removed_graphics_ctx_obj + let GraphicsContextObject::Mesh { + mesh: mut graphics_mesh, + compatible_shader_program_obj_id: _, + } = removed_graphics_ctx_obj else { tracing::error!( model_entity_id=%model_ent_id, @@ -665,6 +672,7 @@ fn handle_commands( &mut RendererCommandQueue, )>, assets: Single<Assets>, + shader_context: Single<ShaderContext>, ) { for (mut graphics_ctx, mut renderer_object_store, mut command_queue) in @@ -680,7 +688,8 @@ fn handle_commands( let mut opt_curr_gl_ctx: Option<CurrentContextWithFns> = None; - let mut activated_gl_shader_program: Option<GlShaderProgram> = None; + let mut activated_gl_shader_program: Option<(RendererObjectId, GlShaderProgram)> = + None; for command in command_queue.drain() { let tracing_span = tracing::info_span!("handle_cmd"); @@ -794,7 +803,8 @@ fn handle_commands( gl_shader_program.activate(&curr_gl_ctx); - activated_gl_shader_program = Some(gl_shader_program); + activated_gl_shader_program = + Some((shader_program_obj_id, gl_shader_program)); } RendererCommand::SetShaderBinding(binding_location, binding_value) => { let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { @@ -918,18 +928,45 @@ fn handle_commands( continue; } - let key = *next_graphics_ctx_object_key; + let Some((RendererObjectId::Asset(curr_shader_program_asset_id), _)) = + &activated_gl_shader_program + else { + tracing::error!("No shader program is activated"); + continue; + }; - let graphics_mesh = match GraphicsMesh::new(&curr_gl_ctx, &mesh) { - Ok(graphics_mesh) => graphics_mesh, - Err(err) => { - tracing::error!("Failed to create mesh: {err}"); - continue; - } + let curr_shader_program_metadata = shader_context + .get_program_metadata(curr_shader_program_asset_id) + .expect("Not possible"); + + let Some(vertex_subset) = &curr_shader_program_metadata.vertex_subset + else { + tracing::error!( + "Current shader program does not have a vertex subset" + ); + continue; }; - graphics_ctx_objects - .insert(key, GraphicsContextObject::Mesh(graphics_mesh)); + let key = *next_graphics_ctx_object_key; + + let graphics_mesh = + match GraphicsMesh::new(&curr_gl_ctx, &mesh, &vertex_subset) { + Ok(graphics_mesh) => graphics_mesh, + Err(err) => { + tracing::error!("Failed to create mesh: {err}"); + continue; + } + }; + + graphics_ctx_objects.insert( + key, + GraphicsContextObject::Mesh { + mesh: graphics_mesh, + compatible_shader_program_obj_id: RendererObjectId::Asset( + *curr_shader_program_asset_id, + ), + }, + ); renderer_object_store.insert( mesh_object_id, @@ -970,8 +1007,10 @@ fn handle_commands( }; #[allow(irrefutable_let_patterns)] - let GraphicsContextObject::Mesh(graphics_mesh) = - mesh_graphics_ctx_obj + let GraphicsContextObject::Mesh { + mesh: graphics_mesh, + compatible_shader_program_obj_id, + } = mesh_graphics_ctx_obj else { tracing::error!( object_id=?mesh_object_id, @@ -981,6 +1020,20 @@ fn handle_commands( continue; }; + if Some(compatible_shader_program_obj_id) + != activated_gl_shader_program.as_ref().map( + |(activated_gl_shader_program_obj_id, _)| { + activated_gl_shader_program_obj_id + }, + ) + { + tracing::error!(concat!( + "Activated shader program is not the ", + "compatible shader program of the mesh" + )); + continue; + } + if let Err(err) = draw_mesh(&curr_gl_ctx, graphics_mesh) { tracing::error!("Failed to draw mesh: {err}"); }; diff --git a/engine/src/renderer/opengl/graphics_mesh.rs b/engine/src/renderer/opengl/graphics_mesh.rs index cb1c7fc..5d081c7 100644 --- a/engine/src/renderer/opengl/graphics_mesh.rs +++ b/engine/src/renderer/opengl/graphics_mesh.rs @@ -1,23 +1,25 @@ +use std::any::TypeId; + use opengl_bindings::CurrentContextWithFns as GlCurrentContextWithFns; use opengl_bindings::buffer::{Buffer as GlBuffer, Usage as GlBufferUsage}; use opengl_bindings::vertex_array::{ AttributeFormat as GlVertexArrayAttributeFormat, + BindVertexBufferError as GlVertexArrayBindVertexBufferError, DataType as GlVertexArrayDataType, VertexArray as GlVertexArray, VertexBufferSpec as GlVertexArrayVertexBufferSpec, }; +use zerocopy::IntoBytes; use crate::mesh::Mesh; -use crate::renderer::opengl::vertex::{ - AttributeComponentType as VertexAttributeComponentType, - Vertex as RendererVertex, -}; +use crate::reflection::Reflection; +use crate::shader::VertexSubset as ShaderVertexSubset; #[derive(Debug)] pub struct GraphicsMesh { /// Vertex and index buffer has to live as long as the vertex array - vertex_buffer: GlBuffer<RendererVertex>, + vertex_buffer: GlBuffer<u8>, pub index_buffer: Option<GlBuffer<u32>>, pub element_cnt: u32, pub vertex_arr: GlVertexArray, @@ -29,66 +31,120 @@ impl GraphicsMesh pub fn new( current_context: &GlCurrentContextWithFns<'_>, mesh: &Mesh, + vertex_subset: &ShaderVertexSubset, ) -> Result<Self, Error> { - tracing::info!( - "Creating vertex array, vertex buffer{}", - if mesh.indices().is_some() { - " and index buffer" - } else { - "" - } - ); - let vertex_arr = GlVertexArray::new(current_context); let vertex_buffer = GlBuffer::new(current_context); vertex_buffer - .store_mapped( + .init( current_context, - mesh.vertices(), + vertex_subset.layout.size() * mesh.vertices().len(), GlBufferUsage::Static, - |vertex| RendererVertex { - pos: vertex.pos.into(), - texture_coords: vertex.texture_coords.into(), - normal: vertex.normal.into(), - }, ) - .map_err(Error::StoreVerticesFailed)?; + .map_err(Error::InitVertexBufferFailed)?; + + for (vertex_index, vertex) in mesh.vertices().iter().enumerate() { + let vertex_bytes = vertex.as_bytes(); + + for vertex_subset_field in vertex_subset.fields.iter().flatten() { + let vertex_buffer_offset = (vertex_subset.layout.size() * vertex_index) + + vertex_subset_field.offset; + + let vertex_field_start_offset = + vertex_subset_field.reflection.byte_offset; + + let vertex_field_size = vertex_subset_field.reflection.layout.size(); + + vertex_buffer + .store_at_byte_offset( + current_context, + vertex_buffer_offset, + &vertex_bytes[vertex_field_start_offset + ..vertex_field_start_offset + vertex_field_size], + ) + .map_err(Error::StoreVerticesFailed)?; + } + } - let _ = vertex_arr.bind_vertex_buffer( + let vertex_buf_binding_index = 0; + + if let Err(err) = vertex_arr.bind_vertex_buffer( current_context, - 0, + vertex_buf_binding_index, &vertex_buffer, GlVertexArrayVertexBufferSpec { offset: 0, - vertex_size: size_of::<RendererVertex>(), + vertex_size: vertex_subset.layout.size(), }, - ); + ) { + match err { + GlVertexArrayBindVertexBufferError::OffsetValueTooLarge { + value: _, + max_value: _, + } => unreachable!(), + GlVertexArrayBindVertexBufferError::VertexSizeValueTooLarge { + value, + max_value, + } => { + panic!( + "Size of vertex ({}) is too large. Must be less than {max_value}", + value + ); + } + } + } - let mut offset = 0u32; + for vertex_subset_field in vertex_subset.fields.iter().flatten() { + let attrib_index: u32 = + vertex_subset_field.varying_input_offset.try_into().unwrap(); - for attrib in RendererVertex::attrs() { - vertex_arr.enable_attrib(current_context, attrib.index); + vertex_arr.enable_attrib(current_context, attrib_index); vertex_arr.set_attrib_format( current_context, - attrib.index, - GlVertexArrayAttributeFormat { - data_type: match attrib.component_type { - VertexAttributeComponentType::Float => { - GlVertexArrayDataType::Float + attrib_index, + match vertex_subset_field.reflection.reflection { + Reflection::Literal(_) => { + if vertex_subset_field.reflection.type_id != TypeId::of::<f32>() { + panic!("Unsupported vertex field data type"); + } + + GlVertexArrayAttributeFormat { + data_type: GlVertexArrayDataType::Float, + count: 1, + normalized: false, + offset: vertex_subset_field.offset.try_into().unwrap(), + } + } + Reflection::Array(array_vertex_field) => { + let Reflection::Literal(array_vertex_field_item) = + array_vertex_field.item_reflection + else { + panic!("Unsupported array item type in vertex field"); + }; + + if array_vertex_field_item.type_id != TypeId::of::<f32>() { + panic!("Unsupported array item type in vertex field"); } - }, - count: attrib.component_cnt as u8, - normalized: false, - offset, + + GlVertexArrayAttributeFormat { + data_type: GlVertexArrayDataType::Float, + count: array_vertex_field.length.try_into().unwrap(), + normalized: false, + offset: vertex_subset_field.offset.try_into().unwrap(), + } + } + _ => panic!("Unsupported vertex field data type"), }, ); - vertex_arr.set_attrib_vertex_buf_binding(current_context, attrib.index, 0); - - offset += attrib.component_size * attrib.component_cnt as u32; + vertex_arr.set_attrib_vertex_buf_binding( + current_context, + attrib_index, + vertex_buf_binding_index, + ); } if let Some(indices) = mesh.indices() { @@ -137,6 +193,9 @@ impl GraphicsMesh #[derive(Debug, thiserror::Error)] pub enum Error { + #[error("Failed to initialize vertex buffer")] + InitVertexBufferFailed(#[source] opengl_bindings::buffer::Error), + #[error("Failed to store vertices in vertex buffer")] StoreVerticesFailed(#[source] opengl_bindings::buffer::Error), diff --git a/engine/src/renderer/opengl/vertex.rs b/engine/src/renderer/opengl/vertex.rs deleted file mode 100644 index 5a1593e..0000000 --- a/engine/src/renderer/opengl/vertex.rs +++ /dev/null @@ -1,65 +0,0 @@ -use safer_ffi::derive_ReprC; - -#[derive(Debug, Clone)] -#[derive_ReprC] -#[repr(C)] -pub struct Vertex -{ - pub pos: opengl_bindings::data_types::Vec3<f32>, - pub texture_coords: opengl_bindings::data_types::Vec2<f32>, - pub normal: opengl_bindings::data_types::Vec3<f32>, -} - -impl Vertex -{ - pub fn attrs() -> &'static [Attribute] - { - #[allow(clippy::cast_possible_truncation)] - &[ - Attribute { - index: 0, - component_type: AttributeComponentType::Float, - component_cnt: AttributeComponentCnt::Three, - component_size: size_of::<f32>() as u32, - }, - Attribute { - index: 1, - component_type: AttributeComponentType::Float, - component_cnt: AttributeComponentCnt::Two, - component_size: size_of::<f32>() as u32, - }, - Attribute { - index: 2, - component_type: AttributeComponentType::Float, - component_cnt: AttributeComponentCnt::Three, - component_size: size_of::<f32>() as u32, - }, - ] - } -} - -#[derive(Debug)] -pub struct Attribute -{ - pub index: u32, - pub component_type: AttributeComponentType, - pub component_cnt: AttributeComponentCnt, - pub component_size: u32, -} - -#[derive(Debug)] -pub enum AttributeComponentType -{ - Float, -} - -#[derive(Debug, Clone, Copy)] -#[repr(u32)] -#[allow(dead_code)] -pub enum AttributeComponentCnt -{ - One = 1, - Two = 2, - Three = 3, - Four = 4, -} |
