opengl_graphics/
shader_uniforms.rs

1//! Types and methods for setting shader uniforms
2
3// External crates.
4use gl;
5use gl::types::{GLboolean, GLint};
6use std::ffi::CString;
7use std::marker::PhantomData;
8
9// Local crate.
10use crate::back_end::GlGraphics;
11
12/// Describes a shader uniform of a given type.
13#[derive(Clone, Copy)]
14pub struct ShaderUniform<T: ?Sized> {
15    location: GLint,
16    phantom: PhantomData<T>,
17}
18
19/// Shader uniform type
20///
21/// For now a small subset
22pub trait UniformType {}
23
24/// Shader uniform float
25#[derive(Clone, Copy)]
26pub struct SUFloat {}
27impl UniformType for SUFloat {}
28
29/// Shader uniform integer
30#[derive(Clone, Copy)]
31pub struct SUInt {}
32impl UniformType for SUInt {}
33
34/// Shader uniform vector of size 2
35/// Vector elements are floats
36#[derive(Clone, Copy)]
37pub struct SUVec2 {}
38impl UniformType for SUVec2 {}
39
40/// Shader uniform vector of size 3
41/// Vector elements are floats
42#[derive(Clone, Copy)]
43pub struct SUVec3 {}
44impl UniformType for SUVec3 {}
45
46/// Shader uniform vector of size 4
47/// Vector elements are floats
48#[derive(Clone, Copy)]
49pub struct SUVec4 {}
50impl UniformType for SUVec4 {}
51
52/// Shader uniform 2x2 matrix
53/// Matrix elements are floats
54#[derive(Clone, Copy)]
55pub struct SUMat2x2 {}
56impl UniformType for SUMat2x2 {}
57
58/// Shader uniform 3x3 matrix
59/// Matrix elements are floats
60#[derive(Clone, Copy)]
61pub struct SUMat3x3 {}
62impl UniformType for SUMat3x3 {}
63
64/// Shader uniform 4x4 matrix
65/// Matrix elements are floats
66#[derive(Clone, Copy)]
67pub struct SUMat4x4 {}
68impl UniformType for SUMat4x4 {}
69
70impl GlGraphics {
71    /// Try to get uniform from the current shader of a given name.
72    pub fn get_uniform<T: UniformType + ?Sized>(&self, name: &str) -> Option<ShaderUniform<T>> {
73        self.get_current_program().and_then(|p| unsafe {
74            let c_source = CString::new(name).ok();
75            c_source.and_then(|name| {
76                let uniform = match gl::GetUniformLocation(p, name.as_ptr()) {
77                    -1 => None,
78                    location => Some(ShaderUniform {
79                        location,
80                        phantom: PhantomData,
81                    }),
82                };
83                drop(name);
84                uniform
85            })
86        })
87    }
88}
89
90impl ShaderUniform<SUFloat> {
91    /// Set the value of the float uniform.
92    pub fn set(&self, gl: &GlGraphics, value: f32) {
93        if let Some(p) = gl.get_current_program() {
94            unsafe { gl::ProgramUniform1f(p, self.location, value) };
95        }
96    }
97}
98
99impl ShaderUniform<SUInt> {
100    /// Set the value of the integer uniform.
101    pub fn set(&self, gl: &GlGraphics, value: i32) {
102        if let Some(p) = gl.get_current_program() {
103            unsafe { gl::ProgramUniform1i(p, self.location, value) };
104        }
105    }
106}
107
108impl ShaderUniform<SUVec2> {
109    /// Set the value of the vector 2 uniform.
110    pub fn set(&self, gl: &GlGraphics, value: &[f32; 2]) {
111        if let Some(p) = gl.get_current_program() {
112            unsafe { gl::ProgramUniform2f(p, self.location, value[0], value[1]) };
113        }
114    }
115}
116
117impl ShaderUniform<SUVec3> {
118    /// Set the value of the vector 3 uniform.
119    pub fn set(&self, gl: &GlGraphics, value: &[f32; 3]) {
120        if let Some(p) = gl.get_current_program() {
121            unsafe { gl::ProgramUniform3f(p, self.location, value[0], value[1], value[2]) }
122        }
123    }
124}
125
126impl ShaderUniform<SUVec4> {
127    /// Set the value of the vector 4 uniform.
128    pub fn set(&self, gl: &GlGraphics, value: &[f32; 4]) {
129        if let Some(p) = gl.get_current_program() {
130            unsafe {
131                gl::ProgramUniform4f(p, self.location, value[0], value[1], value[2], value[3])
132            }
133        }
134    }
135}
136
137impl ShaderUniform<SUMat2x2> {
138    /// Set the value of the 2x2 matrix uniform.
139    pub fn set(&self, gl: &GlGraphics, values: &[f32; 4]) {
140        if let Some(p) = gl.get_current_program() {
141            unsafe {
142                gl::ProgramUniformMatrix2fv(
143                    p,
144                    self.location,
145                    1 as GLint,
146                    false as GLboolean,
147                    values.as_ptr(),
148                )
149            }
150        }
151    }
152}
153
154impl ShaderUniform<SUMat3x3> {
155    /// Set the value of the 3x3 matrix uniform.
156    pub fn set(&self, gl: &GlGraphics, values: &[f32; 9]) {
157        if let Some(p) = gl.get_current_program() {
158            unsafe {
159                gl::ProgramUniformMatrix3fv(
160                    p,
161                    self.location,
162                    1 as GLint,
163                    false as GLboolean,
164                    values.as_ptr(),
165                )
166            }
167        }
168    }
169}
170
171impl ShaderUniform<SUMat4x4> {
172    /// Set the value of the 4x4 matrix uniform.
173    pub fn set(&self, gl: &GlGraphics, values: &[f32; 16]) {
174        if let Some(p) = gl.get_current_program() {
175            unsafe {
176                gl::ProgramUniformMatrix4fv(
177                    p,
178                    self.location,
179                    1 as GLint,
180                    false as GLboolean,
181                    values.as_ptr(),
182                )
183            }
184        }
185    }
186}