summaryrefslogtreecommitdiff
path: root/engine/src/renderer/opengl.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-11-23 21:32:03 +0100
committerHampusM <hampus@hampusmat.com>2024-11-23 21:32:03 +0100
commitdaf280048d82eed42d44423ce50ae9e809ba91a9 (patch)
treefdd1580b3c50f2f7cebc5175b38777a7117c904f /engine/src/renderer/opengl.rs
parent999264a46f9a545771c6710b0893ca32cf6e7ee3 (diff)
refactor(engine): make shaders a renderer detail
Diffstat (limited to 'engine/src/renderer/opengl.rs')
-rw-r--r--engine/src/renderer/opengl.rs99
1 files changed, 64 insertions, 35 deletions
diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs
index 6e6347b..deb26a8 100644
--- a/engine/src/renderer/opengl.rs
+++ b/engine/src/renderer/opengl.rs
@@ -2,7 +2,9 @@
use std::collections::HashMap;
use std::ffi::{c_void, CString};
+use std::io::{Error as IoError, ErrorKind as IoErrorKind};
use std::ops::Deref;
+use std::path::Path;
use std::process::abort;
use ecs::actions::Actions;
@@ -24,8 +26,13 @@ use crate::mesh::Mesh;
use crate::opengl::buffer::{Buffer, Usage as BufferUsage};
#[cfg(feature = "debug")]
use crate::opengl::debug::{MessageSeverity, MessageSource, MessageType};
+use crate::opengl::glsl::{
+ preprocess as glsl_preprocess,
+ PreprocessingError as GlslPreprocessingError,
+};
use crate::opengl::shader::{
Error as GlShaderError,
+ Kind as ShaderKind,
Program as GlShaderProgram,
Shader as GlShader,
};
@@ -41,7 +48,6 @@ use crate::opengl::vertex_array::{
};
use crate::opengl::{clear_buffers, enable, BufferClearMask, Capability};
use crate::projection::{new_perspective_matrix, Projection};
-use crate::shader::Program as ShaderProgram;
use crate::texture::{Id as TextureId, Texture};
use crate::transform::{Position, Scale};
use crate::util::NeverDrop;
@@ -51,7 +57,6 @@ use crate::window::Window;
type RenderableEntity = (
Mesh,
- ShaderProgram,
Material,
Option<MaterialFlags>,
Option<Position>,
@@ -137,34 +142,24 @@ fn render(
let directional_lights = directional_lights.iter().collect::<Vec<_>>();
let GlobalGlObjects {
- shader_programs: gl_shader_programs,
+ shader_program,
textures: gl_textures,
} = &mut *gl_objects;
+ let shader_program =
+ shader_program.get_or_insert_with(|| create_default_shader_program().unwrap());
+
clear_buffers(BufferClearMask::COLOR | BufferClearMask::DEPTH);
for (
entity_index,
- (
- mesh,
- shader_program,
- material,
- material_flags,
- position,
- scale,
- draw_flags,
- gl_objects,
- ),
+ (mesh, material, material_flags, position, scale, draw_flags, gl_objects),
) in query.iter().enumerate()
{
let material_flags = material_flags
.map(|material_flags| material_flags.clone())
.unwrap_or_default();
- let shader_program = gl_shader_programs
- .entry(shader_program.u64_hash())
- .or_insert_with(|| create_gl_shader_program(&shader_program).unwrap());
-
let new_gl_objects;
let gl_objects = if let Some(gl_objects) = gl_objects.as_deref() {
@@ -248,7 +243,7 @@ fn render(
#[derive(Debug, Default, Component)]
struct GlobalGlObjects
{
- shader_programs: HashMap<u64, GlShaderProgram>,
+ shader_program: Option<GlShaderProgram>,
textures: HashMap<TextureId, GlTexture>,
}
@@ -300,34 +295,68 @@ fn create_gl_texture(texture: &Texture) -> GlTexture
gl_texture
}
-fn create_gl_shader_program(
- shader_program: &ShaderProgram,
-) -> Result<GlShaderProgram, GlShaderError>
+const VERTEX_GLSL_SHADER_SRC: &str = include_str!("opengl/glsl/vertex.glsl");
+const FRAGMENT_GLSL_SHADER_SRC: &str = include_str!("opengl/glsl/fragment.glsl");
+
+const VERTEX_DATA_GLSL_SHADER_SRC: &str = include_str!("opengl/glsl/vertex_data.glsl");
+const LIGHT_GLSL_SHADER_SRC: &str = include_str!("opengl/glsl/light.glsl");
+
+fn create_default_shader_program() -> Result<GlShaderProgram, CreateShaderError>
{
- let gl_shaders = shader_program
- .shaders()
- .iter()
- .map(|shader| {
- let gl_shader = GlShader::new(shader.kind());
+ let mut vertex_shader = GlShader::new(ShaderKind::Vertex);
- gl_shader.set_source(shader.source())?;
- gl_shader.compile()?;
+ vertex_shader.set_source(&*glsl_preprocess(
+ VERTEX_GLSL_SHADER_SRC,
+ &get_glsl_shader_content,
+ )?)?;
- Ok(gl_shader)
- })
- .collect::<Result<Vec<_>, _>>()?;
+ vertex_shader.compile()?;
- let gl_shader_program = GlShaderProgram::new();
+ let mut fragment_shader = GlShader::new(ShaderKind::Fragment);
- for gl_shader in &gl_shaders {
- gl_shader_program.attach(gl_shader);
- }
+ fragment_shader.set_source(&*glsl_preprocess(
+ FRAGMENT_GLSL_SHADER_SRC,
+ &get_glsl_shader_content,
+ )?)?;
+
+ fragment_shader.compile()?;
+
+ let mut gl_shader_program = GlShaderProgram::new();
+
+ gl_shader_program.attach(&vertex_shader);
+ gl_shader_program.attach(&fragment_shader);
gl_shader_program.link()?;
Ok(gl_shader_program)
}
+#[derive(Debug, thiserror::Error)]
+enum CreateShaderError
+{
+ #[error(transparent)]
+ ShaderError(#[from] GlShaderError),
+
+ #[error(transparent)]
+ PreprocessingError(#[from] GlslPreprocessingError),
+}
+
+fn get_glsl_shader_content(path: &Path) -> Result<Vec<u8>, std::io::Error>
+{
+ if path == Path::new("vertex_data.glsl") {
+ return Ok(VERTEX_DATA_GLSL_SHADER_SRC.as_bytes().to_vec());
+ }
+
+ if path == Path::new("light.glsl") {
+ return Ok(LIGHT_GLSL_SHADER_SRC.as_bytes().to_vec());
+ }
+
+ Err(IoError::new(
+ IoErrorKind::NotFound,
+ format!("Content for shader file {} not found", path.display()),
+ ))
+}
+
#[derive(Debug, Component)]
struct GlObjects
{