diff options
Diffstat (limited to 'engine/src/renderer/opengl.rs')
-rw-r--r-- | engine/src/renderer/opengl.rs | 99 |
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 { |