From b9abf4b9a636fe819572a1eced744d808e78a0a5 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Tue, 6 Oct 2015 23:49:52 +0100 Subject: [PATCH] Clean up shader creation --- gl/Cargo.lock | 8 ++-- src/gl/mod.rs | 22 +++++++++++ src/render/mod.rs | 55 ++++++++------------------- src/render/shaders.rs | 86 +++++++++++++++++++++++++++++++++++++++++++ src/render/ui.rs | 60 +++++++++++++++++------------- 5 files changed, 162 insertions(+), 69 deletions(-) diff --git a/gl/Cargo.lock b/gl/Cargo.lock index b2ef40f..0beaf67 100644 --- a/gl/Cargo.lock +++ b/gl/Cargo.lock @@ -2,8 +2,8 @@ name = "steven_gl" version = "0.0.1" dependencies = [ - "gl_common 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "gl_generator 0.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "gl_common 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gl_generator 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "khronos_api 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -15,7 +15,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "gl_common" -version = "0.0.4" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -23,7 +23,7 @@ dependencies = [ [[package]] name = "gl_generator" -version = "0.0.27" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "khronos_api 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/gl/mod.rs b/src/gl/mod.rs index 15d1adf..4c76865 100644 --- a/src/gl/mod.rs +++ b/src/gl/mod.rs @@ -141,6 +141,28 @@ pub fn blend_func(s_factor: Factor, d_factor: Factor) { unsafe { gl::BlendFunc(s_factor, d_factor); } } +// Face specifies a face to act on. +pub type Face = u32; +pub const BACK: Face = gl::BACK; +pub const FRONT: Face = gl::FRONT; + +/// Sets the face to be culled by the gpu. +pub fn cull_face(face: Face) { + unsafe { gl::CullFace(face); } +} + +// FaceDirection is used to specify an order of vertices, normally +// used to set which is considered to be the front face. +pub type FaceDirection = u32; +pub const CLOCK_WISE: FaceDirection = gl::CW; +pub const COUNTER_CLOCK_WISE: FaceDirection = gl::CCW; + +/// Sets the direction of vertices used to specify the +/// front face (e.g. for culling). +pub fn front_face(dir: FaceDirection) { + unsafe { gl::FrontFace(dir) } +} + /// Type is a type of data used by various operations. pub type Type = u32; pub const UNSIGNED_BYTE: Type = gl::UNSIGNED_BYTE; diff --git a/src/render/mod.rs b/src/render/mod.rs index 8be919e..f532bae 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -14,8 +14,9 @@ mod atlas; pub mod glsl; +#[macro_use] +pub mod shaders; pub mod ui; -mod shaders; use std::collections::HashMap; use std::sync::{Arc, RwLock}; @@ -58,6 +59,20 @@ impl Renderer { shaders::add_shaders(&mut greg); let ui = ui::UIState::new(&greg, textures.clone(), res.clone()); + gl::enable(gl::DEPTH_TEST); + gl::enable(gl::CULL_FACE_FLAG); + gl::cull_face(gl::BACK); + gl::front_face(gl::CLOCK_WISE); + + // Shaders + + // UI + // Line Drawer + // Models + // Clouds + + gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); + Renderer { resource_version: version, textures: textures, @@ -556,44 +571,6 @@ impl Texture { } } -pub fn create_program(vertex: &str, fragment: &str) -> gl::Program { - let program = gl::Program::new(); - - let v = gl::Shader::new(gl::VERTEX_SHADER); - v.set_source(vertex); - v.compile(); - - if v.get_parameter(gl::COMPILE_STATUS) == 0 { - println!("Src: {}", vertex); - panic!("Shader error: {}", v.get_info_log()); - } else { - let log = v.get_info_log(); - if !log.is_empty() { - println!("{}", log); - } - } - - let f = gl::Shader::new(gl::FRAGMENT_SHADER); - f.set_source(fragment); - f.compile(); - - if f.get_parameter(gl::COMPILE_STATUS) == 0 { - println!("Src: {}", fragment); - panic!("Shader error: {}", f.get_info_log()); - } else { - let log = f.get_info_log(); - if !log.is_empty() { - println!("{}", log); - } - } - - program.attach_shader(v); - program.attach_shader(f); - program.link(); - program.use_program(); - program -} - #[allow(unused_must_use)] pub fn generate_element_buffer(size: usize) -> (Vec, gl::Type) { let mut ty = gl::UNSIGNED_SHORT; diff --git a/src/render/shaders.rs b/src/render/shaders.rs index 3576aae..0221f9d 100644 --- a/src/render/shaders.rs +++ b/src/render/shaders.rs @@ -13,6 +13,7 @@ // limitations under the License. use render::glsl; +use gl; pub fn add_shaders(reg: &mut glsl::Registry) { reg.register("lookup_texture", include_str!("shaders/lookup_texture.glsl")); @@ -20,4 +21,89 @@ pub fn add_shaders(reg: &mut glsl::Registry) { reg.register("ui_vertex", include_str!("shaders/ui_vertex.glsl")); reg.register("ui_frag", include_str!("shaders/ui_frag.glsl")); +} + +#[macro_export] +macro_rules! init_shader { + ( + Program $name:ident { + vert = $vert:expr, + frag = $frag:expr, + attribute = { + $( + $field:ident => $glname:expr, + )* + }, + uniform = { + $( + $ufield:ident => $uglname:expr, + )* + }, + } + ) => ( + struct $name { + program: gl::Program, + $( + $field: gl::Attribute, + )+ + $( + $ufield: gl::Uniform, + )+ + } + + impl $name { + pub fn new(reg: &glsl::Registry) -> $name { + let v = reg.get($vert); + let f = reg.get($frag); + let shader = shaders::create_program(&v, &f); + $name { + $( + $field: shader.attribute_location($glname), + )+ + $( + $ufield: shader.uniform_location($uglname), + )+ + program: shader, + } + } + } + ) +} + +pub fn create_program(vertex: &str, fragment: &str) -> gl::Program { + let program = gl::Program::new(); + + let v = gl::Shader::new(gl::VERTEX_SHADER); + v.set_source(vertex); + v.compile(); + + if v.get_parameter(gl::COMPILE_STATUS) == 0 { + println!("Src: {}", vertex); + panic!("Shader error: {}", v.get_info_log()); + } else { + let log = v.get_info_log(); + if !log.is_empty() { + println!("{}", log); + } + } + + let f = gl::Shader::new(gl::FRAGMENT_SHADER); + f.set_source(fragment); + f.compile(); + + if f.get_parameter(gl::COMPILE_STATUS) == 0 { + println!("Src: {}", fragment); + panic!("Shader error: {}", f.get_info_log()); + } else { + let log = f.get_info_log(); + if !log.is_empty() { + println!("{}", log); + } + } + + program.attach_shader(v); + program.attach_shader(f); + program.link(); + program.use_program(); + program } \ No newline at end of file diff --git a/src/render/ui.rs b/src/render/ui.rs index 0b891e0..d07ce4c 100644 --- a/src/render/ui.rs +++ b/src/render/ui.rs @@ -17,7 +17,10 @@ use std::io::Write; use std::collections::HashMap; use resources; use gl; +#[macro_use] use render; +use render::glsl; +use render::shaders; use byteorder::{WriteBytesExt, NativeEndian}; use image; use image::{GenericImage}; @@ -40,9 +43,7 @@ pub struct UIState { index_type: gl::Type, max_index: usize, - shader: gl::Program, - s_texture: gl::Uniform, - s_screensize: gl::Uniform, + shader: UIShader, // Font font_pages: Vec>, @@ -52,30 +53,39 @@ pub struct UIState { page_height: f64, } +init_shader! { + Program UIShader { + vert = "ui_vertex", + frag = "ui_frag", + attribute = { + position => "aPosition", + texture_info => "aTextureInfo", + texture_offset => "aTextureOffset", + color => "aColor", + }, + uniform = { + texture => "textures", + screensize => "screenSize", + }, + } +} + impl UIState { - pub fn new(glsl: &super::glsl::Registry, textures: Arc>, res: Arc>) -> UIState { - let v = glsl.get("ui_vertex"); - let f = glsl.get("ui_frag"); - let shader = super::create_program(&v, &f); - let s_position = shader.attribute_location("aPosition"); - let s_texture_info = shader.attribute_location("aTextureInfo"); - let s_texture_offset = shader.attribute_location("aTextureOffset"); - let s_color = shader.attribute_location("aColor"); - let s_texture = shader.uniform_location("textures"); - let s_screensize = shader.uniform_location("screenSize"); + pub fn new(glsl: &glsl::Registry, textures: Arc>, res: Arc>) -> UIState { + let shader = UIShader::new(glsl); let array = gl::VertexArray::new(); array.bind(); let buffer = gl::Buffer::new(); buffer.bind(gl::ARRAY_BUFFER); - s_position.enable(); - s_texture_info.enable(); - s_texture_offset.enable(); - s_color.enable(); - s_position.vertex_pointer_int(3, gl::SHORT, 28, 0); - s_texture_info.vertex_pointer(4, gl::UNSIGNED_SHORT, false, 28, 8); - s_texture_offset.vertex_pointer_int(3, gl::SHORT, 28, 16); - s_color.vertex_pointer(4, gl::UNSIGNED_BYTE, true, 28, 24); + shader.position.enable(); + shader.texture_info.enable(); + shader.texture_offset.enable(); + shader.color.enable(); + shader.position.vertex_pointer_int(3, gl::SHORT, 28, 0); + shader.texture_info.vertex_pointer(4, gl::UNSIGNED_SHORT, false, 28, 8); + shader.texture_offset.vertex_pointer_int(3, gl::SHORT, 28, 16); + shader.color.vertex_pointer(4, gl::UNSIGNED_BYTE, true, 28, 24); let index_buffer = gl::Buffer::new(); index_buffer.bind(gl::ELEMENT_ARRAY_BUFFER); @@ -107,8 +117,6 @@ impl UIState { max_index: 0, shader: shader, - s_texture: s_texture, - s_screensize: s_screensize, // Font font_pages: pages, @@ -135,8 +143,8 @@ impl UIState { gl::enable(gl::BLEND); gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); - self.shader.use_program(); - self.s_texture.set_int(0); + self.shader.program.use_program(); + self.shader.texture.set_int(0); if self.count > 0 { self.array.bind(); if self.max_index < self.count { @@ -147,7 +155,7 @@ impl UIState { self.max_index = self.count; } - self.s_screensize.set_float2(width as f32, height as f32); + self.shader.screensize.set_float2(width as f32, height as f32); self.buffer.bind(gl::ARRAY_BUFFER); if self.data.len() > self.prev_size {