summaryrefslogtreecommitdiff
path: root/engine/src/renderer
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-02-19 23:06:17 +0100
committerHampusM <hampus@hampusmat.com>2024-02-19 23:06:17 +0100
commit88d6ae3e4854c5fb4b37f75a29aba4f13dcfb382 (patch)
tree033431187e1f6fc4aa4f36a7f46490af5ef338ce /engine/src/renderer
parente8c6c096b2068f4ea71b021bf02f56d266ed671c (diff)
refactor(engine): create shaders on start
Diffstat (limited to 'engine/src/renderer')
-rw-r--r--engine/src/renderer/mod.rs102
1 files changed, 83 insertions, 19 deletions
diff --git a/engine/src/renderer/mod.rs b/engine/src/renderer/mod.rs
index c72e1ce..64d5e3c 100644
--- a/engine/src/renderer/mod.rs
+++ b/engine/src/renderer/mod.rs
@@ -1,3 +1,4 @@
+use std::collections::HashMap;
use std::ffi::{c_void, CString};
use std::process::abort;
@@ -18,11 +19,16 @@ use crate::opengl::buffer::{
use crate::opengl::currently_bound::CurrentlyBound;
#[cfg(feature = "debug")]
use crate::opengl::debug::{MessageSeverity, MessageSource, MessageType};
-use crate::opengl::shader::Program as ShaderProgram;
+use crate::opengl::shader::{
+ Error as GlShaderError,
+ Program as GlShaderProgram,
+ Shader as GlShader,
+};
use crate::opengl::texture::{set_active_texture_unit, TextureUnit};
use crate::opengl::vertex_array::{PrimitiveKind, VertexArray};
use crate::opengl::{clear_buffers, enable, BufferClearMask, Capability};
use crate::projection::new_perspective;
+use crate::shader::Program as ShaderProgram;
use crate::vector::{Vec2, Vec3};
use crate::vertex::Vertex;
@@ -30,6 +36,7 @@ use crate::vertex::Vertex;
pub struct Renderer<CameraT>
{
camera: CameraT,
+ shader_programs: HashMap<u64, GlShaderProgram>,
}
impl<CameraT> Renderer<CameraT>
@@ -63,7 +70,44 @@ where
enable(Capability::DepthTest);
- Ok(Self { camera })
+ Ok(Self {
+ camera,
+ shader_programs: HashMap::new(),
+ })
+ }
+
+ pub fn create_shader_programs<'program>(
+ &mut self,
+ programs: impl IntoIterator<Item = &'program ShaderProgram>,
+ ) -> Result<(), Error>
+ {
+ for program in programs {
+ let gl_shaders = program
+ .shaders()
+ .iter()
+ .map(|shader| {
+ let gl_shader = GlShader::new(shader.kind());
+
+ gl_shader.set_source(shader.source())?;
+ gl_shader.compile()?;
+
+ Ok::<_, Error>(gl_shader)
+ })
+ .collect::<Result<Vec<_>, _>>()?;
+
+ let gl_shader_program = GlShaderProgram::new();
+
+ for gl_shader in &gl_shaders {
+ gl_shader_program.attach(gl_shader);
+ }
+
+ gl_shader_program.link()?;
+
+ self.shader_programs
+ .insert(program.u64_hash(), gl_shader_program);
+ }
+
+ Ok(())
}
pub fn render<'obj>(
@@ -76,15 +120,27 @@ where
clear_buffers(BufferClearMask::COLOR | BufferClearMask::DEPTH);
for obj in objects {
- obj.shader().activate(|shader_program_curr_bound| {
+ let shader_program = self
+ .shader_programs
+ .get(&obj.shader().u64_hash())
+ .ok_or(Error::MissingShaderProgram)?;
+
+ shader_program.activate(|shader_program_curr_bound| {
apply_transformation_matrices(
obj,
+ shader_program,
&self.camera,
window_size,
&shader_program_curr_bound,
);
- apply_light(obj, light_source, &self.camera, &shader_program_curr_bound);
+ apply_light(
+ obj,
+ shader_program,
+ light_source,
+ &self.camera,
+ &shader_program_curr_bound,
+ );
for (texture_id, texture) in obj.textures() {
let texture_unit = TextureUnit::from_texture_id(*texture_id)
@@ -97,7 +153,7 @@ where
Self::draw_object(obj);
- Ok(())
+ Ok::<_, Error>(())
})?;
}
@@ -220,16 +276,23 @@ pub enum Error
#[error("Texture ID is a invalid texture unit")]
TextureIdIsInvalidTextureUnit,
+
+ #[error(transparent)]
+ GlShader(#[from] GlShaderError),
+
+ #[error("No shader program object was found for object")]
+ MissingShaderProgram,
}
fn apply_transformation_matrices(
object: &Object,
+ gl_shader_program: &GlShaderProgram,
camera: &impl Camera,
window_size: &WindowSize,
- shader_program_curr_bound: &CurrentlyBound<ShaderProgram>,
+ shader_program_curr_bound: &CurrentlyBound<GlShaderProgram>,
)
{
- object.shader().set_uniform_matrix_4fv(
+ gl_shader_program.set_uniform_matrix_4fv(
shader_program_curr_bound,
cstr!("model"),
&object.transform().as_matrix(),
@@ -237,7 +300,7 @@ fn apply_transformation_matrices(
let view = create_view(camera);
- object.shader().set_uniform_matrix_4fv(
+ gl_shader_program.set_uniform_matrix_4fv(
shader_program_curr_bound,
cstr!("view"),
&view,
@@ -251,7 +314,7 @@ fn apply_transformation_matrices(
0.1,
);
- object.shader().set_uniform_matrix_4fv(
+ gl_shader_program.set_uniform_matrix_4fv(
shader_program_curr_bound,
cstr!("projection"),
&projection,
@@ -260,12 +323,13 @@ fn apply_transformation_matrices(
fn apply_light(
obj: &Object,
+ gl_shader_program: &GlShaderProgram,
light_source: Option<&LightSource>,
camera: &impl Camera,
- shader_program_curr_bound: &CurrentlyBound<ShaderProgram>,
+ shader_program_curr_bound: &CurrentlyBound<GlShaderProgram>,
)
{
- obj.shader().set_uniform_vec_3fv(
+ gl_shader_program.set_uniform_vec_3fv(
shader_program_curr_bound,
cstr!("light.position"),
&light_source.map_or_else(Vec3::default, |light_source| {
@@ -273,7 +337,7 @@ fn apply_light(
}),
);
- obj.shader().set_uniform_vec_3fv(
+ gl_shader_program.set_uniform_vec_3fv(
shader_program_curr_bound,
cstr!("light.ambient"),
&light_source
@@ -283,7 +347,7 @@ fn apply_light(
.into(),
);
- obj.shader().set_uniform_vec_3fv(
+ gl_shader_program.set_uniform_vec_3fv(
shader_program_curr_bound,
cstr!("light.diffuse"),
&light_source
@@ -293,7 +357,7 @@ fn apply_light(
.into(),
);
- obj.shader().set_uniform_vec_3fv(
+ gl_shader_program.set_uniform_vec_3fv(
shader_program_curr_bound,
cstr!("light.specular"),
&light_source
@@ -304,33 +368,33 @@ fn apply_light(
);
#[allow(clippy::cast_possible_wrap)]
- obj.shader().set_uniform_1i(
+ gl_shader_program.set_uniform_1i(
shader_program_curr_bound,
cstr!("material.ambient"),
obj.material().ambient_map().into_inner() as i32,
);
#[allow(clippy::cast_possible_wrap)]
- obj.shader().set_uniform_1i(
+ gl_shader_program.set_uniform_1i(
shader_program_curr_bound,
cstr!("material.diffuse"),
obj.material().diffuse_map().into_inner() as i32,
);
#[allow(clippy::cast_possible_wrap)]
- obj.shader().set_uniform_1i(
+ gl_shader_program.set_uniform_1i(
shader_program_curr_bound,
cstr!("material.specular"),
obj.material().specular_map().into_inner() as i32,
);
- obj.shader().set_uniform_1fv(
+ gl_shader_program.set_uniform_1fv(
shader_program_curr_bound,
cstr!("material.shininess"),
obj.material().shininess(),
);
- obj.shader().set_uniform_vec_3fv(
+ gl_shader_program.set_uniform_vec_3fv(
shader_program_curr_bound,
cstr!("view_pos"),
&camera.position(),