summaryrefslogtreecommitdiff
path: root/engine/src/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/renderer')
-rw-r--r--engine/src/renderer/opengl.rs85
-rw-r--r--engine/src/renderer/opengl/graphics_mesh.rs141
-rw-r--r--engine/src/renderer/opengl/vertex.rs65
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,
-}