cgl_rs/graphics/
shader.rs

1//! The Shader module for CGL
2
3#![allow(non_camel_case_types)]
4use libc::{c_void, c_int, c_char, c_float, c_double};
5
6/// The internal window handle used by CGL
7#[repr(C)]
8pub(crate) struct CGL_shader {
9    _private: c_void
10}
11
12extern {
13   fn CGL_shader_create(vertex_shader_source: *const c_char, fragment_shader_source: *const c_char, error: *mut *mut c_char) -> *mut CGL_shader;
14   fn CGL_shader_compute_create(compute_shader_source: *const c_char, error: *mut *mut c_char) -> *mut CGL_shader;
15   fn CGL_shader_create_from_files(vertex_shader_file: *const c_char, fragment_shader_file: *const c_char, error: *mut *mut c_char) -> *mut CGL_shader;
16   fn CGL_shader_compute_create_from_files(compute_shader_file: *const c_char, error: *mut *mut c_char) -> *mut CGL_shader;
17   fn CGL_shader_destroy(shader: *mut CGL_shader) -> ();
18   fn CGL_shader_bind(shader: *mut CGL_shader) -> ();
19   fn CGL_shader_get_uniform_location(shader: *mut CGL_shader, name: *const c_char) -> c_int;
20   fn CGL_shader_set_uniform_mat4(shader: *mut CGL_shader, location: c_int, matrix: *const crate::math::Matrix4x4) -> ();
21   fn CGL_shader_set_uniform_vec4(shader: *mut CGL_shader, location: c_int, vector: *const crate::math::Vector4) -> ();
22   fn CGL_shader_set_uniform_vec3(shader: *mut CGL_shader, location: c_int, vector: *const crate::math::Vector3) -> ();
23   fn CGL_shader_set_uniform_vec2(shader: *mut CGL_shader, location: c_int, vector: *const crate::math::Vector2) -> ();
24   fn CGL_shader_set_uniform_int(shader: *mut CGL_shader, location: c_int, value: c_int) -> ();
25   fn CGL_shader_set_uniform_bool(shader: *mut CGL_shader, location: c_int, value: c_int) -> ();
26   fn CGL_shader_set_uniform_float(shader: *mut CGL_shader, location: c_int, value: c_float) -> ();
27   fn CGL_shader_set_uniform_double(shader: *mut CGL_shader, location: c_int, value: c_double) -> ();
28   fn CGL_shader_set_uniform_vec2v(shader: *mut CGL_shader, location: c_int, x: c_float, y: c_float) -> ();
29   fn CGL_shader_set_uniform_vec3v(shader: *mut CGL_shader, location: c_int, x: c_float, y: c_float, z: c_float) -> ();
30   fn CGL_shader_set_uniform_vec4v(shader: *mut CGL_shader, location: c_int, x: c_float, y: c_float, z: c_float, w: c_float) -> ();
31   fn CGL_shader_set_uniform_ivec2v(shader: *mut CGL_shader, location: c_int, x: c_int, y: c_int) -> ();
32   fn CGL_shader_set_uniform_ivec3v(shader: *mut CGL_shader, location: c_int, x: c_int, y: c_int, z: c_int) -> ();
33   fn CGL_shader_set_uniform_ivec4v(shader: *mut CGL_shader, location: c_int, x: c_int, y: c_int, z: c_int, w: c_int) -> ();
34   fn CGL_shader_set_user_data(shader: *mut CGL_shader, user_data: *mut c_void) -> ();
35   fn CGL_shader_get_user_data(shader: *mut CGL_shader) -> *mut c_void;
36   fn CGL_shader_compute_dispatch(shader: *mut CGL_shader, x: c_int, y: c_int, z: c_int) -> ();
37}
38
39/// A shader object
40#[derive(Debug)]
41pub struct Shader {
42    handle: *mut CGL_shader,
43    has_been_destroyed: bool,
44    uniform_locations: std::collections::HashMap<String, i32>
45}
46
47
48const BASIC_VERTEX_SHADER: &str = r#"#version 430 core
49
50layout (location = 0) in vec3 aPos;
51
52void main()
53{
54    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
55}
56"#;
57
58const BASIC_FRAGMENT_SHADER: &str = r#"#version 430 core
59
60out vec4 FragColor;
61
62void main()
63{
64    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
65}
66"#;
67
68const BASIC_COMPUTE_SHADER: &str = r#"#version 430 core
69
70layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
71
72void main()
73{
74    // Do nothing
75}
76"#;
77
78impl Shader {
79
80    /// Creates a new shader object from the provided vertex and fragment shader source code.
81    ///
82    /// # Arguments
83    ///
84    /// * `vertex_shader_source` - The source code for the vertex shader.
85    /// * `fragment_shader_source` - The source code for the fragment shader.
86    ///
87    /// # Returns
88    ///
89    /// Returns a `Result` containing the newly created `Shader` object if successful, or a `String` containing an error message if unsuccessful.
90    ///
91    /// # Example
92    ///
93    /// ```no_run
94    /// let vertex_shader_source = r#"#version 430 core
95    ///
96    ///     layout (location = 0) in vec3 aPos;
97    ///
98    ///     void main()
99    ///     {
100    ///         gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
101    ///     }
102    /// "#;
103    ///
104    /// let fragment_shader_source = r#"#version 430 core
105    ///
106    ///     out vec4 FragColor;
107    ///
108    ///     void main()
109    ///     {
110    ///         FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
111    ///     }
112    /// "#;
113    ///
114    /// cgl_rs::init();
115    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
116    /// cgl_rs::graphics::init();
117    /// {
118    ///    let shader = cgl_rs::graphics::Shader::from_source(vertex_shader_source, fragment_shader_source).unwrap();
119    ///    // Do stuff with the shader
120    /// }
121    /// cgl_rs::graphics::shutdown();
122    /// window.destroy();
123    /// cgl_rs::shutdown();
124    /// ```
125    pub fn from_source(vertex_shader_source: &str, fragment_shader_source: &str) -> Result<Shader, String> {
126        let mut error_string_ptr: *mut c_char = std::ptr::null_mut();
127        let error_string_ptr_ptr: *mut *mut c_char = &mut error_string_ptr;
128        let handle = unsafe {
129            let vertex_shader_source_c = std::ffi::CString::new(vertex_shader_source).unwrap();
130            let fragment_shader_source_c = std::ffi::CString::new(fragment_shader_source).unwrap();
131            CGL_shader_create(vertex_shader_source_c.as_ptr(), fragment_shader_source_c.as_ptr(), error_string_ptr_ptr)
132        };
133        if handle.is_null() {
134            let error_string = unsafe { std::ffi::CStr::from_ptr(*error_string_ptr_ptr) };
135            let error_string = error_string.to_str().unwrap();
136            unsafe { libc::free(error_string_ptr as *mut c_void) };
137            return Err(error_string.to_string());
138        }
139        Ok(Shader {
140            handle,
141            has_been_destroyed: false,
142            uniform_locations: std::collections::HashMap::new()
143        })
144    }
145
146    /// Creates a new shader object from the provided vertex and fragment shader source files.
147    ///
148    /// # Arguments
149    ///
150    /// * `vertex_shader_path` - The path to the file containing the source code for the vertex shader.
151    /// * `fragment_shader_path` - The path to the file containing the source code for the fragment shader.
152    ///
153    /// # Returns
154    ///
155    /// Returns a `Result` containing the newly created `Shader` object if successful, or a `String` containing an error message if unsuccessful.
156    ///
157    /// # Example
158    ///
159    /// ```no_run
160    /// cgl_rs::init();
161    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
162    /// cgl_rs::graphics::init();
163    /// {
164    ///    let shader = cgl_rs::graphics::Shader::from_files("path/to/vertex_shader.glsl", "path/to/fragment_shader.glsl").unwrap();
165    ///    // Do stuff with the shader
166    /// }
167    /// cgl_rs::graphics::shutdown();
168    /// window.destroy();
169    /// cgl_rs::shutdown();
170    /// ```
171    pub fn from_files(vertex_shader_path: &str, fragment_shader_path: &str) -> Result<Shader, String> {
172        let mut error_string_ptr: *mut c_char = std::ptr::null_mut();
173        let error_string_ptr_ptr: *mut *mut c_char = &mut error_string_ptr;
174        let handle = unsafe {
175            let vertex_shader_path_c = std::ffi::CString::new(vertex_shader_path).unwrap();
176            let fragment_shader_path_c = std::ffi::CString::new(fragment_shader_path).unwrap();
177            CGL_shader_create_from_files(vertex_shader_path_c.as_ptr(), fragment_shader_path_c.as_ptr(), error_string_ptr_ptr)
178        };
179        if handle.is_null() {
180            let error_string = unsafe { std::ffi::CStr::from_ptr(*error_string_ptr_ptr) };
181            let error_string = error_string.to_str().unwrap();
182            unsafe { libc::free(error_string_ptr as *mut c_void) };
183            return Err(error_string.to_string());
184        }
185        Ok(Shader {
186            handle,
187            has_been_destroyed: false,
188            uniform_locations: std::collections::HashMap::new()
189        })
190    }
191
192    /// Creates a new compute shader object from the provided compute shader source code.
193    ///
194    /// # Arguments
195    ///
196    /// * `compute_shader_source` - The source code for the compute shader.
197    ///
198    /// # Returns
199    ///
200    /// Returns a `Result` containing the newly created `Shader` object if successful, or a `String` containing an error message if unsuccessful.
201    ///
202    /// # Example
203    ///
204    /// ```no_run
205    /// let compute_shader_source = r#"#version 430 core
206    /// 
207    ///    layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
208    /// 
209    ///    void main()
210    ///    {
211    ///       // Do stuff
212    ///    }
213    /// "#;
214    /// 
215    /// 
216    /// cgl_rs::init();
217    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
218    /// cgl_rs::graphics::init();
219    /// {
220    ///    let shader = cgl_rs::graphics::Shader::compute_from_source("path/to/compute_shader.glsl").unwrap();
221    ///    // Do stuff with the shader
222    /// }
223    /// cgl_rs::graphics::shutdown();
224    /// window.destroy();
225    /// cgl_rs::shutdown();
226    /// ```
227    pub fn compute_from_source(compute_shader_source: &str) -> Result<Shader, String> {
228        let mut error_string_ptr: *mut c_char = std::ptr::null_mut();
229        let error_string_ptr_ptr: *mut *mut c_char = &mut error_string_ptr;
230        let handle = unsafe {
231            let compute_shader_source_c = std::ffi::CString::new(compute_shader_source).unwrap();
232            CGL_shader_compute_create(compute_shader_source_c.as_ptr(), error_string_ptr_ptr)
233        };
234        if handle.is_null() {
235            let error_string = unsafe { std::ffi::CStr::from_ptr(*error_string_ptr_ptr) };
236            let error_string = error_string.to_str().unwrap();
237            unsafe { libc::free(error_string_ptr as *mut c_void) };
238            return Err(error_string.to_string());
239        }
240        Ok(Shader {
241            handle,
242            has_been_destroyed: false,
243            uniform_locations: std::collections::HashMap::new()
244        })
245    }
246
247    /// Creates a new compute shader object from the provided compute shader file.
248    ///
249    /// # Arguments
250    ///
251    /// * `compute_shader_path` - The path to the compute shader file.
252    ///
253    /// # Returns
254    ///
255    /// Returns a `Result` containing the newly created `Shader` object if successful, or a `String` containing an error message if unsuccessful.
256    ///
257    /// # Example
258    ///
259    /// ```no_run
260    /// cgl_rs::init();
261    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
262    /// cgl_rs::graphics::init();
263    /// {
264    ///    let shader = cgl_rs::graphics::Shader::compute_from_files("path/to/compute_shader.glsl").unwrap();
265    ///    // Do stuff with the shader
266    /// }
267    /// cgl_rs::graphics::shutdown();
268    /// window.destroy();
269    /// cgl_rs::shutdown();
270    /// ```
271    pub fn compute_from_files(compute_shader_path: &str) -> Result<Shader, String> {
272        let mut error_string_ptr: *mut c_char = std::ptr::null_mut();
273        let error_string_ptr_ptr: *mut *mut c_char = &mut error_string_ptr;
274        let handle = unsafe {
275            let compute_shader_path_c = std::ffi::CString::new(compute_shader_path).unwrap();
276            CGL_shader_compute_create_from_files(compute_shader_path_c.as_ptr(), error_string_ptr_ptr)
277        };
278        if handle.is_null() {
279            let error_string = unsafe { std::ffi::CStr::from_ptr(*error_string_ptr_ptr) };
280            let error_string = error_string.to_str().unwrap();
281            unsafe { libc::free(error_string_ptr as *mut c_void) };
282            return Err(error_string.to_string());
283        }
284        Ok(Shader {
285            handle,
286            has_been_destroyed: false,
287            uniform_locations: std::collections::HashMap::new()
288        })
289    }
290
291    /// Creates a basic compute shader object with a simple compute shader.
292    ///
293    /// # Returns
294    ///
295    /// Returns a `Result` containing the newly created `Shader` object if successful, or a `String` containing an error message if unsuccessful.
296    ///
297    /// # Example
298    ///
299    /// ```
300    /// cgl_rs::init();
301    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
302    /// cgl_rs::graphics::init();
303    /// {
304    ///    let shader = cgl_rs::graphics::Shader::create_dummy_compute().unwrap();
305    ///    // Do stuff with the shader
306    /// }
307    /// cgl_rs::graphics::shutdown();
308    /// window.destroy();
309    /// cgl_rs::shutdown();
310    /// ```
311    pub fn create_dummy_compute() -> Result<Shader, String> {
312        Shader::compute_from_source(BASIC_COMPUTE_SHADER)
313    }
314
315    /// Creates a basic shader object with a simple vertex and fragment shader.
316    ///
317    /// # Returns
318    ///
319    /// Returns a `Result` containing the newly created `Shader` object if successful, or a `String` containing an error message if unsuccessful.
320    ///
321    /// # Example
322    ///
323    /// ```
324    /// cgl_rs::init();
325    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
326    /// cgl_rs::graphics::init();
327    /// {
328    ///    let shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
329    ///    // Do stuff with the shader
330    /// }
331    /// cgl_rs::graphics::shutdown();
332    /// window.destroy();
333    /// cgl_rs::shutdown();
334    /// ```
335    pub fn create_dummy() -> Result<Shader, String> {
336        Shader::from_source(BASIC_VERTEX_SHADER, BASIC_FRAGMENT_SHADER)
337    }
338
339    /// Destroys the shader object.
340    ///
341    /// # Remarks
342    ///
343    /// This function destroys the shader object and frees any resources associated with it. If the shader object has already been destroyed, this function does nothing.
344    ///
345    /// # Example
346    ///
347    /// ```
348    /// cgl_rs::init();
349    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
350    /// cgl_rs::graphics::init();
351    /// {
352    ///    let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
353    ///    // Do stuff with the shader
354    ///    shader.destroy();
355    /// }
356    /// cgl_rs::graphics::shutdown();
357    /// window.destroy();
358    /// cgl_rs::shutdown();
359    /// ```
360    pub fn destroy(&mut self) {
361        if !self.has_been_destroyed {
362            unsafe {
363                CGL_shader_destroy(self.handle);
364            }
365            self.has_been_destroyed = true;
366        }
367    }
368
369
370    /// Retrieves the location of0 a uniform variable in the shader program.
371    ///
372    /// # Arguments
373    ///
374    /// * `uniform_name` - A string slice containing the name of the uniform variable.
375    ///
376    /// # Returns
377    ///
378    /// Returns an `i32` representing the location of the uniform variable in the shader program.
379    ///
380    /// # Remarks
381    ///
382    /// This function caches the uniform location for future use, so it is more efficient to call this function once and store the result than to call it repeatedly.
383    ///
384    /// # Example
385    ///
386    /// ```
387    /// cgl_rs::init();
388    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
389    /// cgl_rs::graphics::init();
390    /// {
391    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
392    ///     let uniform_location = shader.get_uniform_location("uniform_name");
393    ///     // Do stuff with the uniform location
394    /// }
395    /// cgl_rs::graphics::shutdown();
396    /// window.destroy();
397    /// cgl_rs::shutdown();
398    /// ```
399    pub fn get_uniform_location(&mut self, uniform_name: &str) -> i32 {
400        if self.uniform_locations.contains_key(uniform_name) {
401            return self.uniform_locations[uniform_name];
402        }
403        let uniform_name_c = std::ffi::CString::new(uniform_name).unwrap();
404        let location = unsafe {
405            CGL_shader_get_uniform_location(self.handle, uniform_name_c.as_ptr()) as i32
406        };
407        self.uniform_locations.insert(uniform_name.to_string(), location);
408        location
409    }
410
411
412    
413    /// Sets the value of a uniform variable of type Vector2 in the shader program.
414    ///
415    /// # Arguments
416    ///
417    /// * `uniform_name` - A string slice containing the name of the uniform variable.
418    /// * `value` - A reference to a Vector2 containing the value to set.
419    ///
420    /// # Example
421    ///
422    /// ```
423    /// cgl_rs::init();
424    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
425    /// cgl_rs::graphics::init();
426    /// {
427    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
428    ///     let vec2 = cgl_rs::math::Vector2::new(1.0, 2.0);
429    ///     shader.set_vec2("uniform_name", &vec2);
430    ///     // Do stuff with the uniform variable
431    /// }
432    /// cgl_rs::graphics::shutdown();
433    /// window.destroy();
434    /// cgl_rs::shutdown();
435    /// ```
436    pub fn set_vec2(&mut self, uniform_name: &str, value: &crate::math::Vector2) {
437        let location = self.get_uniform_location(uniform_name);
438        unsafe {
439            CGL_shader_set_uniform_vec2(self.handle, location, value);
440        }
441    }
442    
443    /// Sets the value of a uniform variable of type Vector3 in the shader program.
444    ///
445    /// # Arguments
446    ///
447    /// * `uniform_name` - A string slice containing the name of the uniform variable.
448    /// * `value` - A reference to a Vector3 containing the value to set.
449    ///
450    /// # Example
451    ///
452    /// ```
453    /// cgl_rs::init();
454    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
455    /// cgl_rs::graphics::init();
456    /// {
457    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
458    ///     let vec3 = cgl_rs::math::Vector3::new(1.0, 2.0, 3.0);
459    ///     shader.set_vec3("uniform_name", &vec3);
460    ///     // Do stuff with the uniform variable
461    /// }
462    /// cgl_rs::graphics::shutdown();
463    /// window.destroy();
464    /// cgl_rs::shutdown();
465    /// ```
466    pub fn set_vec3(&mut self, uniform_name: &str, value: &crate::math::Vector3) {
467        let location = self.get_uniform_location(uniform_name);
468        unsafe {
469            CGL_shader_set_uniform_vec3(self.handle, location, value);
470        }
471    }
472    
473    /// Sets the value of a uniform variable of type Vector4 in the shader program.
474    ///
475    /// # Arguments
476    ///
477    /// * `uniform_name` - A string slice containing the name of the uniform variable.
478    /// * `value` - A reference to a Vector4 containing the value to set.
479    ///
480    /// # Example
481    ///
482    /// ```
483    /// cgl_rs::init();
484    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
485    /// cgl_rs::graphics::init();
486    /// {
487    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
488    ///     let vec4 = cgl_rs::math::Vector4::new(1.0, 2.0, 3.0, 4.0);
489    ///     shader.set_vec4("uniform_name", &vec4);
490    ///     // Do stuff with the uniform variable
491    /// }
492    /// cgl_rs::graphics::shutdown();
493    /// window.destroy();
494    /// cgl_rs::shutdown();
495    /// ```
496    pub fn set_vec4(&mut self, uniform_name: &str, value: &crate::math::Vector4) {
497        let location = self.get_uniform_location(uniform_name);
498        unsafe {
499            CGL_shader_set_uniform_vec4(self.handle, location, value);
500        }
501    }
502    
503    /// Sets the value of a uniform variable of type Matrix4x4 in the shader program.
504    ///
505    /// # Arguments
506    ///
507    /// * `uniform_name` - A string slice containing the name of the uniform variable.
508    /// * `value` - A reference to a Matrix4x4 containing the value to set.
509    ///
510    /// # Example
511    ///
512    /// ```
513    /// cgl_rs::init();
514    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
515    /// cgl_rs::graphics::init();
516    /// {
517    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
518    ///     let mat4 = cgl_rs::math::Matrix4x4::identity();
519    ///     shader.set_mat4("uniform_name", &mat4);
520    ///     // Do stuff with the uniform variable
521    /// }
522    /// cgl_rs::graphics::shutdown();
523    /// window.destroy();
524    /// cgl_rs::shutdown();
525    /// ```
526    pub fn set_mat4(&mut self, uniform_name: &str, value: &crate::math::Matrix4x4) {
527        let location = self.get_uniform_location(uniform_name);
528        unsafe {
529            CGL_shader_set_uniform_mat4(self.handle, location, value);
530        }
531    }
532    
533    /// Sets the value of a uniform variable of type i32 in the shader program.
534    ///
535    /// # Arguments
536    ///
537    /// * `uniform_name` - A string slice containing the name of the uniform variable.
538    /// * `value` - An i32 value containing the value to set.
539    ///
540    /// # Example
541    ///
542    /// ```
543    /// cgl_rs::init();
544    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
545    /// cgl_rs::graphics::init();
546    /// {
547    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
548    ///     shader.set_int("uniform_name", 42);
549    ///     // Do stuff with the uniform variable
550    /// }
551    /// cgl_rs::graphics::shutdown();
552    /// window.destroy();
553    /// cgl_rs::shutdown();
554    /// ```
555    pub fn set_int(&mut self, uniform_name: &str, value: i32) {
556        let location = self.get_uniform_location(uniform_name);
557        unsafe {
558            CGL_shader_set_uniform_int(self.handle, location, value);
559        }
560    }
561
562    /// Sets the value of a uniform variable of type bool in the shader program.
563    ///
564    /// # Arguments
565    ///
566    /// * `uniform_name` - A string slice containing the name of the uniform variable.
567    /// * `value` - A boolean value containing the value to set.
568    ///
569    /// # Example
570    ///
571    /// ```
572    /// cgl_rs::init();
573    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
574    /// cgl_rs::graphics::init();
575    /// {
576    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
577    ///     shader.set_bool("uniform_name", true);
578    ///     // Do stuff with the uniform variable
579    /// }
580    /// cgl_rs::graphics::shutdown();
581    /// window.destroy();
582    /// cgl_rs::shutdown();
583    /// ```
584    pub fn set_bool(&mut self, uniform_name: &str, value: bool) {
585        let location = self.get_uniform_location(uniform_name);
586        unsafe {
587            CGL_shader_set_uniform_bool(self.handle, location, value as i32);
588        }
589    }
590
591    /// Sets the value of a uniform variable of type float in the shader program.
592    ///
593    /// # Arguments
594    ///
595    /// * `uniform_name` - A string slice containing the name of the uniform variable.
596    /// * `value` - A f32 value containing the value to set.
597    ///
598    /// # Example
599    ///
600    /// ```
601    /// cgl_rs::init();
602    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
603    /// cgl_rs::graphics::init();
604    /// {
605    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
606    ///     shader.set_float("uniform_name", 3.14);
607    ///     // Do stuff with the uniform variable
608    /// }
609    /// cgl_rs::graphics::shutdown();
610    /// window.destroy();
611    /// cgl_rs::shutdown();
612    /// ```
613    pub fn set_float(&mut self, uniform_name: &str, value: f32) {
614        let location = self.get_uniform_location(uniform_name);
615        unsafe {
616            CGL_shader_set_uniform_float(self.handle, location, value);
617        }
618    }
619
620    /// Sets the value of a uniform variable of type double in the shader program.
621    /// 
622    /// # Arguments
623    /// 
624    /// * `uniform_name` - A string slice containing the name of the uniform variable.
625    /// * `value` - A f64 value containing the value to set.
626    /// 
627    /// # Example
628    /// 
629    /// ```
630    /// cgl_rs::init();
631    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
632    /// cgl_rs::graphics::init();
633    /// {
634    ///    let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
635    ///    shader.set_double("uniform_name", 3.14);
636    /// }
637    /// cgl_rs::graphics::shutdown();
638    /// window.destroy();
639    /// cgl_rs::shutdown();
640    /// ```
641    pub fn set_double(&mut self, uniform_name: &str, value: f64) {
642        let location = self.get_uniform_location(uniform_name);
643        unsafe {
644            CGL_shader_set_uniform_double(self.handle, location, value);
645        }
646    }
647
648
649    /// Sets the value of a uniform variable of type vec2 in the shader program.
650    ///
651    /// # Arguments
652    ///
653    /// * `uniform_name` - A string slice containing the name of the uniform variable.
654    /// * `x` - A f32 value containing the x component of the vector.
655    /// * `y` - A f32 value containing the y component of the vector.
656    ///
657    /// # Example
658    ///
659    /// ```
660    /// cgl_rs::init();
661    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
662    /// cgl_rs::graphics::init();
663    /// {
664    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
665    ///     shader.set_vec2v("uniform_name", 1.0, 2.0);
666    ///     // Do stuff with the uniform variable
667    /// }
668    /// cgl_rs::graphics::shutdown();
669    /// window.destroy();
670    /// cgl_rs::shutdown();
671    /// ```
672    pub fn set_vec2v(&mut self, uniform_name: &str, x: f32, y: f32) {
673        let location = self.get_uniform_location(uniform_name);
674        unsafe {
675            CGL_shader_set_uniform_vec2v(self.handle, location, x, y);
676        }
677    }
678
679    /// Sets the value of a uniform variable of type vec3 in the shader program.
680    ///
681    /// # Arguments
682    ///
683    /// * `uniform_name` - A string slice containing the name of the uniform variable.
684    /// * `x` - A f32 value containing the x component of the vector.
685    /// * `y` - A f32 value containing the y component of the vector.
686    /// * `z` - A f32 value containing the z component of the vector.
687    ///
688    /// # Example
689    ///
690    /// ```
691    /// cgl_rs::init();
692    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
693    /// cgl_rs::graphics::init();
694    /// {
695    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
696    ///     shader.set_vec3v("uniform_name", 1.0, 2.0, 3.0);
697    ///     // Do stuff with the uniform variable
698    /// }
699    /// cgl_rs::graphics::shutdown();
700    /// window.destroy();
701    /// cgl_rs::shutdown();
702    /// ```
703    pub fn set_vec3v(&mut self, uniform_name: &str, x: f32, y: f32, z: f32) {
704        let location = self.get_uniform_location(uniform_name);
705        unsafe {
706            CGL_shader_set_uniform_vec3v(self.handle, location, x, y, z);
707        }
708    }
709
710    /// Sets the value of a uniform variable of type vec4 in the shader program.
711    ///
712    /// # Arguments
713    ///
714    /// * `uniform_name` - A string slice containing the name of the uniform variable.
715    /// * `x` - A f32 value containing the x component of the vector.
716    /// * `y` - A f32 value containing the y component of the vector.
717    /// * `z` - A f32 value containing the z component of the vector.
718    /// * `w` - A f32 value containing the w component of the vector.
719    ///
720    /// # Example
721    ///
722    /// ```
723    /// cgl_rs::init();
724    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
725    /// cgl_rs::graphics::init();
726    /// {
727    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
728    ///     shader.set_vec4v("uniform_name", 1.0, 2.0, 3.0, 4.0);
729    ///     // Do stuff with the uniform variable
730    /// }
731    /// cgl_rs::graphics::shutdown();
732    /// window.destroy();
733    /// cgl_rs::shutdown();
734    /// ```
735    pub fn set_vec4v(&mut self, uniform_name: &str, x: f32, y: f32, z: f32, w: f32) {
736        let location = self.get_uniform_location(uniform_name);
737        unsafe {
738            CGL_shader_set_uniform_vec4v(self.handle, location, x, y, z, w);
739        }
740    }
741
742    /// Sets the value of a uniform variable of type ivec2 in the shader program.
743    ///
744    /// # Arguments
745    ///
746    /// * `uniform_name` - A string slice containing the name of the uniform variable.
747    /// * `x` - An i32 value containing the x component of the vector.
748    /// * `y` - An i32 value containing the y component of the vector.
749    ///
750    /// # Example
751    ///
752    /// ```
753    /// cgl_rs::init();
754    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
755    /// cgl_rs::graphics::init();
756    /// {
757    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
758    ///     shader.set_ivec2v("uniform_name", 1, 2);
759    ///     // Do stuff with the uniform variable
760    /// }
761    /// cgl_rs::graphics::shutdown();
762    /// window.destroy();
763    /// cgl_rs::shutdown();
764    /// ```
765    pub fn set_ivec2v(&mut self, uniform_name: &str, x: i32, y: i32) {
766        let location = self.get_uniform_location(uniform_name);
767        unsafe {
768            CGL_shader_set_uniform_ivec2v(self.handle, location, x, y);
769        }
770    }
771
772    /// Sets the value of a uniform variable of type ivec3 in the shader program.
773    ///
774    /// # Arguments
775    ///
776    /// * `uniform_name` - A string slice containing the name of the uniform variable.
777    /// * `x` - An i32 value containing the x component of the vector.
778    /// * `y` - An i32 value containing the y component of the vector.
779    /// * `z` - An i32 value containing the z component of the vector.
780    ///
781    /// # Example
782    ///
783    /// ```
784    /// cgl_rs::init();
785    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
786    /// cgl_rs::graphics::init();
787    /// {
788    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
789    ///     shader.set_ivec3v("uniform_name", 1, 2, 3);
790    ///     // Do stuff with the uniform variable
791    /// }
792    /// cgl_rs::graphics::shutdown();
793    /// window.destroy();
794    /// cgl_rs::shutdown();
795    /// ```
796    pub fn set_ivec3v(&mut self, uniform_name: &str, x: i32, y: i32, z: i32) {
797        let location = self.get_uniform_location(uniform_name);
798        unsafe {
799            CGL_shader_set_uniform_ivec3v(self.handle, location, x, y, z);
800        }
801    }
802
803    /// Sets the value of a uniform variable of type ivec4 in the shader program.
804    ///
805    /// # Arguments
806    ///
807    /// * `uniform_name` - A string slice containing the name of the uniform variable.
808    /// * `x` - An i32 value containing the x component of the vector.
809    /// * `y` - An i32 value containing the y component of the vector.
810    /// * `z` - An i32 value containing the z component of the vector.
811    /// * `w` - An i32 value containing the w component of the vector.
812    ///
813    /// # Example
814    ///
815    /// ```
816    /// cgl_rs::init();
817    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
818    /// cgl_rs::graphics::init();
819    /// {
820    ///     let mut shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
821    ///     shader.set_ivec4v("uniform_name", 1, 2, 3, 4);
822    ///     // Do stuff with the uniform variable
823    /// }
824    /// cgl_rs::graphics::shutdown();
825    /// window.destroy();
826    /// cgl_rs::shutdown();
827    /// ```
828    pub fn set_ivec4v(&mut self, uniform_name: &str, x: i32, y: i32, z: i32, w: i32) {
829        let location = self.get_uniform_location(uniform_name);
830        unsafe {
831            CGL_shader_set_uniform_ivec4v(self.handle, location, x, y, z, w);
832        }
833    }
834
835    /// Dispatches a compute shader with the specified number of work groups.
836    ///
837    /// # Arguments
838    ///
839    /// * `x` - An i32 value containing the number of work groups in the x dimension.
840    /// * `y` - An i32 value containing the number of work groups in the y dimension.
841    /// * `z` - An i32 value containing the number of work groups in the z dimension.
842    ///
843    /// # Example
844    ///
845    /// ```
846    /// cgl_rs::init();
847    /// let mut window = cgl_rs::Window::new("Hello World", 800, 600).unwrap();
848    /// cgl_rs::graphics::init();
849    /// {
850    ///     let shader = cgl_rs::graphics::Shader::create_dummy_compute().unwrap();
851    ///     shader.dispatch(1, 1, 1);
852    ///     // Do stuff with the compute shader
853    /// }
854    /// cgl_rs::graphics::shutdown();
855    /// window.destroy();
856    /// cgl_rs::shutdown();
857    /// ```
858    pub fn dispatch(&self, x: i32, y: i32, z: i32) {
859        unsafe {
860            CGL_shader_compute_dispatch(self.handle, x, y, z);
861        }
862    }
863}
864
865impl Drop for Shader {
866    fn drop(&mut self) {
867        self.destroy();
868    }
869}
870
871
872impl Clone for Shader {
873    /// Clones the shader object.
874    ///
875    /// NOTE: The new instance will have the same handle, `has_been_destroyed` flag.
876    ///       This means that the new instance will not be able to receive events nor will the internal window handle be
877    ///       destroyed when the new instance is dropped. The internal window handle will be destroyed when the original
878    ///       instance is dropped.
879    /// 
880    /// 
881    /// # Example
882    ///
883    /// ```
884    /// cgl_rs::init();
885    /// let mut window =  cgl_rs::Window::new("Hello World", 600, 800).unwrap();
886    /// cgl_rs::graphics::init();
887    /// {
888    ///     let shader = cgl_rs::graphics::Shader::create_dummy().unwrap();
889    ///     let shader2 = shader.clone();
890    /// }
891    /// cgl_rs::graphics::shutdown();
892    /// window.destroy();
893    /// cgl_rs::shutdown();
894    /// ```
895    fn clone(&self) -> Self {
896        Shader {
897            handle: self.handle.clone(),
898            has_been_destroyed: true,
899            uniform_locations: self.uniform_locations.clone()
900        }
901    }
902}