From f8b358e4cfc96d5ceb9f6777ba5755fa15e04073 Mon Sep 17 00:00:00 2001 From: Justin Shrake Date: Mon, 6 May 2019 20:26:02 -0700 Subject: [PATCH] Add optional geometry shader config Closes #48 --- src/config.rs | 1 + src/effect.rs | 56 +++++++++++++++++++++++++++++++++++--------- src/effect_player.rs | 41 +++++++++++++++++++++----------- src/gl.rs | 14 +++++++---- 4 files changed, 82 insertions(+), 30 deletions(-) diff --git a/src/config.rs b/src/config.rs index b5c2a2c..241b7c3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -166,6 +166,7 @@ pub struct PassConfig { pub draw: DrawConfig, pub vertex: String, pub fragment: String, + pub geometry: Option, #[serde(flatten)] pub uniform_to_channel: BTreeMap, // render pass settings diff --git a/src/effect.rs b/src/effect.rs index 496dab0..9584210 100644 --- a/src/effect.rs +++ b/src/effect.rs @@ -689,15 +689,10 @@ impl<'a> Effect<'a> { uniform_sampler_strings }; let vertex_path = &pass_config.vertex; - let fragment_path = &pass_config.fragment; let vertex_source = self .shader_cache .get(vertex_path) .expect("vertex path not found in shader_cache"); - let fragment_source = self - .shader_cache - .get(fragment_path) - .expect("fragment path not found in shader_cache"); let vertex_shader_list = { let mut list = Vec::new(); list.push(self.version.clone()); @@ -708,6 +703,17 @@ impl<'a> Effect<'a> { list.push(vertex_source.clone()); list.join("\n") }; + let vertex_shader = + gl::create_shader(gl, gl::VERTEX_SHADER, &[vertex_shader_list.as_bytes()]) + .map_err(|err| Error::glsl_vertex(err, vertex_path.clone())) + .with_context(|_| ErrorKind::GLPass(pass_index))?; + assert!(vertex_shader != 0); + + let fragment_path = &pass_config.fragment; + let fragment_source = self + .shader_cache + .get(fragment_path) + .expect("fragment path not found in shader_cache"); let fragment_shader_list = { let mut list = Vec::new(); list.push(self.version.clone()); @@ -718,11 +724,6 @@ impl<'a> Effect<'a> { list.push(fragment_source.clone()); list.join("\n") }; - let vertex_shader = - gl::create_shader(gl, gl::VERTEX_SHADER, &[vertex_shader_list.as_bytes()]) - .map_err(|err| Error::glsl_vertex(err, vertex_path.clone())) - .with_context(|_| ErrorKind::GLPass(pass_index))?; - assert!(vertex_shader != 0); let fragment_shader = gl::create_shader(gl, gl::FRAGMENT_SHADER, &[fragment_shader_list.as_bytes()]) .map_err(|err| { @@ -731,7 +732,40 @@ impl<'a> Effect<'a> { }) .with_context(|_| ErrorKind::GLPass(pass_index))?; assert!(fragment_shader != 0); - let program = gl::create_program(gl, vertex_shader, fragment_shader) + + let geometry_shader = { + if let Some(geometry_path) = &pass_config.geometry { + let geometry_source = self + .shader_cache + .get(geometry_path) + .expect("fragment path not found in shader_cache"); + let geometry_shader_list = { + let mut list = Vec::new(); + list.push(self.version.clone()); + list.push(include_str!("./shadertoy_uniforms.glsl").to_string()); + list.append(&mut uniform_strings.clone()); + list.append(&mut uniform_sampler_strings.clone()); + list.push("#line 1 0".to_string()); + list.push(geometry_source.clone()); + list.join("\n") + }; + let geometry_shader = gl::create_shader( + gl, + gl::GEOMETRY_SHADER, + &[geometry_shader_list.as_bytes()], + ) + .map_err(|err| { + gl.delete_shader(vertex_shader); + gl.delete_shader(fragment_shader); + Error::glsl_fragment(err, geometry_path.clone()) + }) + .with_context(|_| ErrorKind::GLPass(pass_index))?; + Some(geometry_shader) + } else { + None + } + }; + let program = gl::create_program(gl, vertex_shader, fragment_shader, geometry_shader) .map_err(|err| { gl.delete_shader(vertex_shader); gl.delete_shader(fragment_shader); diff --git a/src/effect_player.rs b/src/effect_player.rs index 841f9c5..0585708 100644 --- a/src/effect_player.rs +++ b/src/effect_player.rs @@ -132,20 +132,33 @@ impl<'a> EffectPlayer<'a> { // clear and repopulate shader streams self.shader_streams.clear(); for pass_config in &effect_config.passes { - let vertex_path_str = &pass_config.vertex; - let fragment_path_str = &pass_config.fragment; - let vertex_path = Path::new(vertex_path_str); - let fragment_path = Path::new(fragment_path_str); - let vertex_path = - std::fs::canonicalize(vertex_path).expect("canonicalize failed on vertex path"); - let fragment_path = std::fs::canonicalize(fragment_path) - .expect("canonicalize failed on fragment path"); - let vertex_stream = FileStream::new(vertex_path.as_path())?; - let fragment_stream = FileStream::new(fragment_path.as_path())?; - self.shader_streams - .insert(vertex_path_str.clone(), vertex_stream); - self.shader_streams - .insert(fragment_path_str.clone(), fragment_stream); + { + let vertex_path_str = &pass_config.vertex; + let vertex_path = Path::new(vertex_path_str); + let vertex_path = std::fs::canonicalize(vertex_path) + .expect("canonicalize failed on vertex path"); + let vertex_stream = FileStream::new(vertex_path.as_path())?; + self.shader_streams + .insert(vertex_path_str.clone(), vertex_stream); + } + { + let fragment_path_str = &pass_config.fragment; + let fragment_path = Path::new(fragment_path_str); + let fragment_path = std::fs::canonicalize(fragment_path) + .expect("canonicalize failed on fragment path"); + let fragment_stream = FileStream::new(fragment_path.as_path())?; + self.shader_streams + .insert(fragment_path_str.clone(), fragment_stream); + } + if let Some(ref geometry_path_str) = pass_config.geometry { + let geometry_path = Path::new(geometry_path_str); + let geometry_path = std::fs::canonicalize(geometry_path) + .expect("canonicalize failed on geometry path"); + let geometry_stream = FileStream::new(geometry_path.as_path())?; + self.shader_streams + .insert(geometry_path_str.clone(), geometry_stream); + + } } self.effect.stage_config(effect_config)?; } diff --git a/src/gl.rs b/src/gl.rs index 788ffd8..9169ccd 100644 --- a/src/gl.rs +++ b/src/gl.rs @@ -48,10 +48,13 @@ pub fn create_shader(gl: &GLRc, shader_type: GLenum, source: &[&[u8]]) -> Result } #[allow(dead_code)] -pub fn create_program(gl: &GLRc, vs: GLuint, fs: GLuint) -> Result { +pub fn create_program(gl: &GLRc, vs: GLuint, fs: GLuint, gs: Option) -> Result { let program = gl.create_program(); assert!(program != 0); gl.attach_shader(program, vs); + if let Some(gs) = gs { + gl.attach_shader(program, gs); + } gl.attach_shader(program, fs); gl.link_program(program); let linked = unsafe { @@ -59,15 +62,16 @@ pub fn create_program(gl: &GLRc, vs: GLuint, fs: GLuint) -> Result