1use std::cell::Cell;
2use web_sys::{WebGl2RenderingContext, WebGlProgram, WebGlUniformLocation};
3
4pub struct Uniform<T> {
11 name: String,
12 data: Cell<T>,
13}
14
15impl<T> Uniform<T> {
16 pub fn new(name: String, data: T) -> Uniform<T> {
21 Uniform {
22 name,
23 data: Cell::new(data),
24 }
25 }
26
27 pub fn name(&self) -> &str {
29 &self.name
30 }
31
32 pub fn set_data(&self, value: T) {
36 self.data.set(value)
37 }
38}
39
40impl<T: Copy> Uniform<T> {
41 pub fn get_data(&self) -> T {
45 self.data.get()
46 }
47}
48
49pub trait UniformValue {
55 fn set_uniform(&self, gl: &WebGl2RenderingContext, program: &WebGlProgram);
61}
62
63impl<T: UniformType + Copy> UniformValue for Uniform<T> {
64 fn set_uniform(&self, gl: &WebGl2RenderingContext, program: &WebGlProgram) {
65 if let Some(location) = gl.get_uniform_location(program, self.name()) {
66 self.get_data().uniform(gl, Some(&location))
67 }
68 }
69}
70
71pub trait UniformType {
73 fn uniform(&self, gl: &WebGl2RenderingContext, location: Option<&WebGlUniformLocation>);
79}
80
81macro_rules! impl_uniform {
82 ($t:ty, $fun:ident, $sel:ident, $($things:expr),+) => {
83 #[doc = concat!("Uniform type corresponding to `", stringify!($fun), "`.")]
84 impl UniformType for $t {
85 fn uniform(&$sel, gl: &WebGl2RenderingContext, location: Option<&WebGlUniformLocation>) {
86 gl.$fun(location, $($things,)+)
87 }
88 }
89 }
90}
91
92impl_uniform!(f32, uniform1f, self, *self);
93impl_uniform!(i32, uniform1i, self, *self);
94impl_uniform!(u32, uniform1ui, self, *self);
95impl_uniform!((f32, f32), uniform2f, self, self.0, self.1);
96impl_uniform!((i32, i32), uniform2i, self, self.0, self.1);
97impl_uniform!((u32, u32), uniform2ui, self, self.0, self.1);
98impl_uniform!((f32, f32, f32), uniform3f, self, self.0, self.1, self.2);
99impl_uniform!((i32, i32, i32), uniform3i, self, self.0, self.1, self.2);
100impl_uniform!((u32, u32, u32), uniform3ui, self, self.0, self.1, self.2);
101impl_uniform!(
102 (f32, f32, f32, f32),
103 uniform4f,
104 self,
105 self.0,
106 self.1,
107 self.2,
108 self.3
109);
110impl_uniform!(
111 (i32, i32, i32, i32),
112 uniform4i,
113 self,
114 self.0,
115 self.1,
116 self.2,
117 self.3
118);
119impl_uniform!(
120 (u32, u32, u32, u32),
121 uniform4ui,
122 self,
123 self.0,
124 self.1,
125 self.2,
126 self.3
127);