summaryrefslogtreecommitdiff
path: root/engine/src/renderer/opengl/graphics_mesh.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/renderer/opengl/graphics_mesh.rs')
-rw-r--r--engine/src/renderer/opengl/graphics_mesh.rs141
1 files changed, 100 insertions, 41 deletions
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),