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}