1
2#![allow(non_upper_case_globals)]
3
4use crate::prelude::*;
5use std::{
6 any::{Any, type_name},
7 collections::BTreeMap,
8 ffi::{CString, c_void},
9 fmt::{self, Debug, Display, Formatter},
10 mem::{transmute, size_of},
11 path::Path,
12 ptr::null_mut,
13 rc::Rc,
14 string::FromUtf8Error,
15};
16use bincode::{Encode, Decode};
17
18#[derive(Clone)]
20pub enum ShaderError {
21 VSError(String),
23
24 GSError(String),
26
27 FSError(String),
29
30 CSError(String),
32
33 LinkageError(String),
35
36 AttribNotFound(String),
38
39 UniformNotFound(String),
41}
42
43#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq)]
45pub enum ShaderType {
46 Draw,
47 Compute,
48}
49
50pub struct Shader {
52 glcore: Rc<GLCore>,
53 program: u32,
54 shader_type: ShaderType,
55}
56
57#[derive(Debug)]
59pub struct ShaderUse<'a> {
60 pub shader: &'a Shader,
61}
62
63#[derive(Encode, Decode, Debug, Clone)]
65pub struct ShaderBinary {
66 format: u32,
67 shader_type: ShaderType,
68 binary: Vec<u8>,
69}
70
71#[derive(Debug)]
73pub enum ShaderBinaryLoadError {
74 IOError(std::io::Error),
75 DecodeError(bincode::error::DecodeError),
76}
77
78#[derive(Debug)]
80pub enum ShaderBinarySaveError {
81 IOError(std::io::Error),
82 EncodeError(bincode::error::EncodeError),
83}
84
85#[derive(Clone, Copy)]
87pub enum ShaderInputType {
88 Float = GL_FLOAT as isize,
89 Vec2 = GL_FLOAT_VEC2 as isize,
90 Vec3 = GL_FLOAT_VEC3 as isize,
91 Vec4 = GL_FLOAT_VEC4 as isize,
92 Mat2 = GL_FLOAT_MAT2 as isize,
93 Mat3 = GL_FLOAT_MAT3 as isize,
94 Mat4 = GL_FLOAT_MAT4 as isize,
95 Mat2x3 = GL_FLOAT_MAT2x3 as isize,
96 Mat2x4 = GL_FLOAT_MAT2x4 as isize,
97 Mat3x2 = GL_FLOAT_MAT3x2 as isize,
98 Mat3x4 = GL_FLOAT_MAT3x4 as isize,
99 Mat4x2 = GL_FLOAT_MAT4x2 as isize,
100 Mat4x3 = GL_FLOAT_MAT4x3 as isize,
101 Int = GL_INT as isize,
102 IVec2 = GL_INT_VEC2 as isize,
103 IVec3 = GL_INT_VEC3 as isize,
104 IVec4 = GL_INT_VEC4 as isize,
105 UInt = GL_UNSIGNED_INT as isize,
106 UVec2 = GL_UNSIGNED_INT_VEC2 as isize,
107 UVec3 = GL_UNSIGNED_INT_VEC3 as isize,
108 UVec4 = GL_UNSIGNED_INT_VEC4 as isize,
109 Double = GL_DOUBLE as isize,
110 DVec2 = GL_DOUBLE_VEC2 as isize,
111 DVec3 = GL_DOUBLE_VEC3 as isize,
112 DVec4 = GL_DOUBLE_VEC4 as isize,
113 DMat2 = GL_DOUBLE_MAT2 as isize,
114 DMat3 = GL_DOUBLE_MAT3 as isize,
115 DMat4 = GL_DOUBLE_MAT4 as isize,
116 DMat2x3 = GL_DOUBLE_MAT2x3 as isize,
117 DMat2x4 = GL_DOUBLE_MAT2x4 as isize,
118 DMat3x2 = GL_DOUBLE_MAT3x2 as isize,
119 DMat3x4 = GL_DOUBLE_MAT3x4 as isize,
120 DMat4x2 = GL_DOUBLE_MAT4x2 as isize,
121 DMat4x3 = GL_DOUBLE_MAT4x3 as isize,
122}
123
124#[derive(Debug, Clone, Copy)]
126pub struct ShaderInputVarType {
127 pub type_: ShaderInputType,
128 pub size: i32,
129}
130
131impl Shader {
132 pub fn get_name(&self) -> u32 {
134 self.program
135 }
136
137 fn compile_shader(glcore: &GLCore, shader_type: u32, shader_source: &str) -> Result<u32, String> {
139 let shader = glcore.glCreateShader(shader_type);
140 let bytes: Vec<i8> = shader_source.bytes().map(|byte| -> i8 {byte as i8}).collect();
141 let ptr_to_bytes = bytes.as_ptr();
142 let length = bytes.len() as i32;
143 glcore.glShaderSource(shader, 1, &ptr_to_bytes as *const *const i8, &length as *const i32);
144 glcore.glCompileShader(shader);
145
146 let mut compiled: i32 = 0;
147 glcore.glGetShaderiv(shader, GL_COMPILE_STATUS, &mut compiled as *mut i32);
148 if compiled != 0 {
149 Ok(shader)
150 } else {
151 let mut output_len: i32 = 0;
152 glcore.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &mut output_len as *mut i32);
153 let mut output = Vec::<u8>::new();
154 let mut output_len_ret: i32 = 0;
155 output.resize(output_len as usize, 0);
156 glcore.glGetShaderInfoLog(shader, output_len, &mut output_len_ret as *mut i32, output.as_mut_ptr() as *mut i8);
157 glcore.glDeleteShader(shader);
158 let output = String::from_utf8_lossy(&output).to_string();
159 Err(output)
160 }
161 }
162
163 fn link_program(glcore: &GLCore, program: u32) -> Result<(), ShaderError> {
165 glcore.glLinkProgram(program);
166 Self::get_linkage_status(glcore, program)
167 }
168
169 fn get_linkage_status(glcore: &GLCore, program: u32) -> Result<(), ShaderError> {
171 let mut linked: i32 = 0;
172 glcore.glGetProgramiv(program, GL_LINK_STATUS, &mut linked as *mut i32);
173 if linked != 0 {
174 Ok(())
175 } else {
176 let mut output_len: i32 = 0;
177 glcore.glGetProgramiv(program, GL_INFO_LOG_LENGTH, &mut output_len as *mut i32);
178 let mut output = Vec::<u8>::new();
179 let mut output_len_ret: i32 = 0;
180 output.resize(output_len as usize, 0);
181 glcore.glGetProgramInfoLog(program, output_len, &mut output_len_ret as *mut i32, output.as_mut_ptr() as *mut i8);
182 glcore.glDeleteProgram(program);
183 let output = String::from_utf8_lossy(&output).to_string();
184 Err(ShaderError::LinkageError(output))
185 }
186 }
187
188 pub fn new(glcore: Rc<GLCore>, vertex_shader: Option<&str>, geometry_shader: Option<&str>, fragment_shader: Option<&str>) -> Result<Self, ShaderError> {
190 let program = glcore.glCreateProgram();
191 if let Some(vertex_shader) = vertex_shader {
192 match Self::compile_shader(glcore.as_ref(), GL_VERTEX_SHADER, vertex_shader) {
193 Ok(shader) => {
194 glcore.glAttachShader(program, shader);
195 glcore.glDeleteShader(shader);
196 }
197 Err(output) => return Err(ShaderError::VSError(output)),
198 };
199 }
200 if let Some(geometry_shader) = geometry_shader {
201 match Self::compile_shader(glcore.as_ref(), GL_GEOMETRY_SHADER, geometry_shader) {
202 Ok(shader) => {
203 glcore.glAttachShader(program, shader);
204 glcore.glDeleteShader(shader);
205 }
206 Err(output) => return Err(ShaderError::GSError(output)),
207 };
208 }
209 if let Some(fragment_shader) = fragment_shader {
210 match Self::compile_shader(glcore.as_ref(), GL_FRAGMENT_SHADER, fragment_shader) {
211 Ok(shader) => {
212 glcore.glAttachShader(program, shader);
213 glcore.glDeleteShader(shader);
214 }
215 Err(output) => return Err(ShaderError::FSError(output)),
216 };
217 }
218 Self::link_program(glcore.as_ref(), program)?;
219 Ok(Self {
220 glcore,
221 program,
222 shader_type: ShaderType::Draw,
223 })
224 }
225
226 pub fn new_compute(glcore: Rc<GLCore>, shader_source: &str) -> Result<Self, ShaderError> {
228 let program = glcore.glCreateProgram();
229 match Self::compile_shader(glcore.as_ref(), GL_COMPUTE_SHADER, shader_source) {
230 Ok(shader) => {
231 glcore.glAttachShader(program, shader);
232 glcore.glDeleteShader(shader);
233 }
234 Err(output) => return Err(ShaderError::CSError(output)),
235 };
236 Self::link_program(glcore.as_ref(), program)?;
237 Ok(Self {
238 glcore,
239 program,
240 shader_type: ShaderType::Compute,
241 })
242 }
243
244 pub fn get_active_attribs(&self) -> Result<BTreeMap<String, ShaderInputVarType>, FromUtf8Error> {
246 let mut num_attribs: i32 = 0;
247 let mut max_length: i32 = 0;
248 self.glcore.glGetProgramiv(self.program, GL_ACTIVE_ATTRIBUTES, &mut num_attribs as *mut _);
249 self.glcore.glGetProgramiv(self.program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &mut max_length as *mut _);
250
251 let mut ret = BTreeMap::<String, ShaderInputVarType>::new();
252 for i in 0..num_attribs {
253 let mut name = vec![0i8; max_length as usize];
254 let mut size: i32 = 0;
255 let mut type_: u32 = 0;
256 self.glcore.glGetActiveAttrib(self.program, i as u32, max_length, null_mut::<i32>(), &mut size as *mut _, &mut type_ as *mut _, name.as_mut_ptr());
257 let name = String::from_utf8(unsafe{transmute::<Vec<i8>, Vec<u8>>(name)})?;
258 let name = name.trim_end_matches('\0').to_string();
259 let type_ = ShaderInputType::from(type_);
260 ret.insert(name, ShaderInputVarType{type_, size});
261 }
262 Ok(ret)
263 }
264
265 pub fn get_attrib_location(&self, attrib_name: &str) -> i32 {
267 let attrib_name = CString::new(attrib_name).unwrap();
268 self.glcore.glGetAttribLocation(self.program, attrib_name.as_ptr())
269 }
270
271 pub fn get_active_uniforms(&self) -> Result<BTreeMap<String, ShaderInputVarType>, FromUtf8Error> {
273 let mut num_uniforms: i32 = 0;
274 let mut max_length: i32 = 0;
275 self.glcore.glGetProgramiv(self.program, GL_ACTIVE_UNIFORMS, &mut num_uniforms as *mut _);
276 self.glcore.glGetProgramiv(self.program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &mut max_length as *mut _);
277
278 let mut ret = BTreeMap::<String, ShaderInputVarType>::new();
279 for i in 0..num_uniforms {
280 let mut name = vec![0i8; max_length as usize];
281 let mut size: i32 = 0;
282 let mut type_: u32 = 0;
283 self.glcore.glGetActiveUniform(self.program, i as u32, max_length, null_mut::<i32>(), &mut size as *mut _, &mut type_ as *mut _, name.as_mut_ptr());
284 let name = String::from_utf8(unsafe{transmute::<Vec<i8>, Vec<u8>>(name)})?;
285 let name = name.trim_end_matches('\0').to_string();
286 let type_ = ShaderInputType::from(type_);
287 ret.insert(name, ShaderInputVarType{type_, size});
288 }
289 Ok(ret)
290 }
291
292 pub fn get_uniform_location(&self, uniform_name: &str) -> i32 {
294 let uniform_name = CString::new(uniform_name).unwrap();
295 self.glcore.glGetUniformLocation(self.program, uniform_name.as_ptr())
296 }
297
298 pub fn get_program_binary(&self) -> ShaderBinary {
300 let mut binary_length = 0;
301 let mut binary_format = 0;
302 self.glcore.glGetProgramiv(self.program, GL_PROGRAM_BINARY_LENGTH, &mut binary_length as *mut _);
303 let mut binary = Vec::<u8>::new();
304 binary.resize(binary_length as usize, 0);
305 self.glcore.glGetProgramBinary(self.program, binary_length, null_mut(), &mut binary_format as *mut _, binary.as_mut_ptr() as *mut _);
306 ShaderBinary::new(binary_format, self.shader_type, binary)
307 }
308
309 pub fn from_program_binary(glcore: Rc<GLCore>, binary: &ShaderBinary) -> Result<Self, ShaderError> {
311 let program = glcore.glCreateProgram();
312 glcore.glProgramBinary(program, binary.format, binary.binary.as_ptr() as *const _, binary.binary.len() as i32);
313 match Self::get_linkage_status(&glcore, program) {
314 Ok(_) => Ok(Self {
315 glcore,
316 shader_type: binary.shader_type,
317 program,
318 }),
319 Err(e) => {
320 glcore.glDeleteProgram(program);
321 Err(e)
322 }
323 }
324 }
325
326 pub fn use_program<'a>(&'a self) -> ShaderUse<'a> {
328 ShaderUse::new(self)
329 }
330}
331
332impl<'a> ShaderUse<'a> {
333 fn new(shader: &'a Shader) -> Self {
335 shader.glcore.glUseProgram(shader.get_name());
336 Self {
337 shader,
338 }
339 }
340
341 pub fn dispatch_compute(&self, num_groups_x: u32, num_groups_y: u32, num_groups_z: u32) {
343 if self.shader.shader_type != ShaderType::Compute {
344 panic!("Only compute shaders could use the `dispatch_compute()` method.");
345 }
346 self.shader.glcore.glDispatchCompute(num_groups_x, num_groups_y, num_groups_z);
347 }
348
349 pub fn dispatch_compute_indirect(&self, buffer: &Buffer, index: usize) {
351 if self.shader.shader_type != ShaderType::Compute {
352 panic!("Only compute shaders could use the `dispatch_compute_indirect()` method.");
353 }
354 let bind = buffer.bind_to(BufferTarget::DispatchIndirectBuffer);
355 self.shader.glcore.glDispatchComputeIndirect(index * size_of::<DispatchIndirectCommand>());
356 bind.unbind();
357 }
358
359 pub unsafe fn vertex_attrib_matrix_pointer(&self, location: u32, cols: u32, rows: u32, base_type: ShaderInputType, normalize: bool, stride: isize, pointer: *const c_void) {
361 match base_type {
362 ShaderInputType::Float => {
363 for i in 0..rows {
364 self.shader.glcore.glVertexAttribPointer(location + i, cols as i32, base_type as u32, normalize as u8, stride as i32, pointer as *const _)
365 }
366 }
367 ShaderInputType::Double => {
368 for i in 0..rows {
369 self.shader.glcore.glVertexAttribLPointer(location + i, cols as i32, base_type as u32, stride as i32, pointer as *const _)
370 }
371 }
372 _ => panic!("Bad parameter for `vertex_attrib_matrix_pointer()`: base_type = {base_type:?}"),
373 }
374 }
375
376 pub unsafe fn set_attrib_ptr<T: Any>(&self, name: &str, attrib_type: &ShaderInputVarType, do_normalize: bool, stride: isize, ptr_param: *const c_void) -> Result<(), ShaderError> {
378 let location = self.shader.get_attrib_location(&name);
379 if location >= 0 {
380 let location = location as u32;
381 let (p_size, p_rows) = attrib_type.get_size_and_rows();
382 if type_name::<T>().ends_with("f32") {unsafe {self.vertex_attrib_matrix_pointer(location, p_size, p_rows, attrib_type.get_base_type(), do_normalize, stride, ptr_param)}} else
383 if type_name::<T>().ends_with("i32") {self.shader.glcore.glVertexAttribIPointer(location, p_size as i32, attrib_type.get_base_type() as u32, stride as i32, ptr_param)} else
384 if type_name::<T>().ends_with("u32") {self.shader.glcore.glVertexAttribIPointer(location, p_size as i32, attrib_type.get_base_type() as u32, stride as i32, ptr_param)} else
385 if type_name::<T>().ends_with("f64") {unsafe {self.vertex_attrib_matrix_pointer(location, p_size, p_rows, attrib_type.get_base_type(), do_normalize, stride, ptr_param)}} else
386 {panic!("The generic type parameter of `ShaderUse::set_attrib_ptr()` must be `f32`, `i32`, `u32`, `f64`")}
387 Ok(())
388 } else {
389 Err(ShaderError::AttribNotFound(name.to_owned()))
390 }
391 }
392
393 pub fn set_attrib(&self, name: &str, v: &dyn Any) -> Result<(), ShaderError> {
395 let location = self.shader.get_attrib_location(&name);
396 if location >= 0 {
397 let location = location as u32;
398 if let Some(v) = v.downcast_ref::<f32>() {self.shader.glcore.glVertexAttribPointer (location, 1, ShaderInputType::Float as u32, 0, 0, (v as *const f32) as *const _)} else
399 if let Some(v) = v.downcast_ref::<Vec2>() {self.shader.glcore.glVertexAttribPointer (location, 2, ShaderInputType::Float as u32, 0, 0, v.as_ptr() as *const _)} else
400 if let Some(v) = v.downcast_ref::<Vec3>() {self.shader.glcore.glVertexAttribPointer (location, 3, ShaderInputType::Float as u32, 0, 0, v.as_ptr() as *const _)} else
401 if let Some(v) = v.downcast_ref::<Vec4>() {self.shader.glcore.glVertexAttribPointer (location, 4, ShaderInputType::Float as u32, 0, 0, v.as_ptr() as *const _)} else
402 if let Some(v) = v.downcast_ref::<Mat2>() {unsafe {self.vertex_attrib_matrix_pointer(location, 2, 2, ShaderInputType::Float, false, 0, v.as_ptr() as *const _)}} else
403 if let Some(v) = v.downcast_ref::<Mat3>() {unsafe {self.vertex_attrib_matrix_pointer(location, 3, 3, ShaderInputType::Float, false, 0, v.as_ptr() as *const _)}} else
404 if let Some(v) = v.downcast_ref::<Mat4>() {unsafe {self.vertex_attrib_matrix_pointer(location, 4, 4, ShaderInputType::Float, false, 0, v.as_ptr() as *const _)}} else
405 if let Some(v) = v.downcast_ref::<Mat2x3>() {unsafe {self.vertex_attrib_matrix_pointer(location, 2, 3, ShaderInputType::Float, false, 0, v.as_ptr() as *const _)}} else
406 if let Some(v) = v.downcast_ref::<Mat2x4>() {unsafe {self.vertex_attrib_matrix_pointer(location, 2, 4, ShaderInputType::Float, false, 0, v.as_ptr() as *const _)}} else
407 if let Some(v) = v.downcast_ref::<Mat3x2>() {unsafe {self.vertex_attrib_matrix_pointer(location, 3, 2, ShaderInputType::Float, false, 0, v.as_ptr() as *const _)}} else
408 if let Some(v) = v.downcast_ref::<Mat3x4>() {unsafe {self.vertex_attrib_matrix_pointer(location, 3, 4, ShaderInputType::Float, false, 0, v.as_ptr() as *const _)}} else
409 if let Some(v) = v.downcast_ref::<Mat4x2>() {unsafe {self.vertex_attrib_matrix_pointer(location, 4, 2, ShaderInputType::Float, false, 0, v.as_ptr() as *const _)}} else
410 if let Some(v) = v.downcast_ref::<Mat4x3>() {unsafe {self.vertex_attrib_matrix_pointer(location, 4, 3, ShaderInputType::Float, false, 0, v.as_ptr() as *const _)}} else
411 if let Some(v) = v.downcast_ref::<i32>() {self.shader.glcore.glVertexAttribIPointer(location, 1, ShaderInputType::Int as u32, 0, (v as *const i32) as *const _)} else
412 if let Some(v) = v.downcast_ref::<IVec2>() {self.shader.glcore.glVertexAttribIPointer(location, 2, ShaderInputType::Int as u32, 0, v.as_ptr() as *const _)} else
413 if let Some(v) = v.downcast_ref::<IVec3>() {self.shader.glcore.glVertexAttribIPointer(location, 3, ShaderInputType::Int as u32, 0, v.as_ptr() as *const _)} else
414 if let Some(v) = v.downcast_ref::<IVec4>() {self.shader.glcore.glVertexAttribIPointer(location, 4, ShaderInputType::Int as u32, 0, v.as_ptr() as *const _)} else
415 if let Some(v) = v.downcast_ref::<u32>() {self.shader.glcore.glVertexAttribIPointer(location, 1, ShaderInputType::UInt as u32, 0, (v as *const u32) as *const _)} else
416 if let Some(v) = v.downcast_ref::<UVec2>() {self.shader.glcore.glVertexAttribIPointer(location, 2, ShaderInputType::UInt as u32, 0, v.as_ptr() as *const _)} else
417 if let Some(v) = v.downcast_ref::<UVec3>() {self.shader.glcore.glVertexAttribIPointer(location, 3, ShaderInputType::UInt as u32, 0, v.as_ptr() as *const _)} else
418 if let Some(v) = v.downcast_ref::<UVec4>() {self.shader.glcore.glVertexAttribIPointer(location, 4, ShaderInputType::UInt as u32, 0, v.as_ptr() as *const _)} else
419 if let Some(v) = v.downcast_ref::<f64>() {self.shader.glcore.glVertexAttribLPointer(location, 1, ShaderInputType::Double as u32, 0, (v as *const f64) as *const _)} else
420 if let Some(v) = v.downcast_ref::<DVec2>() {self.shader.glcore.glVertexAttribLPointer(location, 2, ShaderInputType::Double as u32, 0, v.as_ptr() as *const _)} else
421 if let Some(v) = v.downcast_ref::<DVec3>() {self.shader.glcore.glVertexAttribLPointer(location, 3, ShaderInputType::Double as u32, 0, v.as_ptr() as *const _)} else
422 if let Some(v) = v.downcast_ref::<DVec4>() {self.shader.glcore.glVertexAttribLPointer(location, 4, ShaderInputType::Double as u32, 0, v.as_ptr() as *const _)} else
423 if let Some(v) = v.downcast_ref::<DMat2>() {unsafe {self.vertex_attrib_matrix_pointer(location, 2, 2, ShaderInputType::Double, false, 0, v.as_ptr() as *const _)}} else
424 if let Some(v) = v.downcast_ref::<DMat3>() {unsafe {self.vertex_attrib_matrix_pointer(location, 3, 3, ShaderInputType::Double, false, 0, v.as_ptr() as *const _)}} else
425 if let Some(v) = v.downcast_ref::<DMat4>() {unsafe {self.vertex_attrib_matrix_pointer(location, 4, 4, ShaderInputType::Double, false, 0, v.as_ptr() as *const _)}} else
426 if let Some(v) = v.downcast_ref::<DMat2x3>() {unsafe {self.vertex_attrib_matrix_pointer(location, 2, 3, ShaderInputType::Double, false, 0, v.as_ptr() as *const _)}} else
427 if let Some(v) = v.downcast_ref::<DMat2x4>() {unsafe {self.vertex_attrib_matrix_pointer(location, 2, 4, ShaderInputType::Double, false, 0, v.as_ptr() as *const _)}} else
428 if let Some(v) = v.downcast_ref::<DMat3x2>() {unsafe {self.vertex_attrib_matrix_pointer(location, 3, 2, ShaderInputType::Double, false, 0, v.as_ptr() as *const _)}} else
429 if let Some(v) = v.downcast_ref::<DMat3x4>() {unsafe {self.vertex_attrib_matrix_pointer(location, 3, 4, ShaderInputType::Double, false, 0, v.as_ptr() as *const _)}} else
430 if let Some(v) = v.downcast_ref::<DMat4x2>() {unsafe {self.vertex_attrib_matrix_pointer(location, 4, 2, ShaderInputType::Double, false, 0, v.as_ptr() as *const _)}} else
431 if let Some(v) = v.downcast_ref::<DMat4x3>() {unsafe {self.vertex_attrib_matrix_pointer(location, 4, 3, ShaderInputType::Double, false, 0, v.as_ptr() as *const _)}} else
432 {panic!("Unknown type of attrib value: {v:?}")}
433 Ok(())
434 } else {
435 Err(ShaderError::AttribNotFound(name.to_owned()))
436 }
437 }
438
439 pub fn set_uniform(&self, name: &str, v: &dyn Any) -> Result<(), ShaderError> {
441 let location = self.shader.get_uniform_location(&name);
442 if location >= 0 {
443 if let Some(v) = v.downcast_ref::<f32>() {self.shader.glcore.glUniform1fv(location, 1, v as *const _)} else
444 if let Some(v) = v.downcast_ref::<Vec2>() {self.shader.glcore.glUniform2fv(location, 1, v.as_ptr())} else
445 if let Some(v) = v.downcast_ref::<Vec3>() {self.shader.glcore.glUniform3fv(location, 1, v.as_ptr())} else
446 if let Some(v) = v.downcast_ref::<Vec4>() {self.shader.glcore.glUniform4fv(location, 1, v.as_ptr())} else
447 if let Some(v) = v.downcast_ref::<Mat2>() {self.shader.glcore.glUniformMatrix2fv(location, 1, 0, v.as_ptr())} else
448 if let Some(v) = v.downcast_ref::<Mat3>() {self.shader.glcore.glUniformMatrix3fv(location, 1, 0, v.as_ptr())} else
449 if let Some(v) = v.downcast_ref::<Mat4>() {self.shader.glcore.glUniformMatrix4fv(location, 1, 0, v.as_ptr())} else
450 if let Some(v) = v.downcast_ref::<Mat2x3>() {self.shader.glcore.glUniformMatrix2x3fv(location, 1, 0, v.as_ptr())} else
451 if let Some(v) = v.downcast_ref::<Mat2x4>() {self.shader.glcore.glUniformMatrix2x4fv(location, 1, 0, v.as_ptr())} else
452 if let Some(v) = v.downcast_ref::<Mat3x2>() {self.shader.glcore.glUniformMatrix3x2fv(location, 1, 0, v.as_ptr())} else
453 if let Some(v) = v.downcast_ref::<Mat3x4>() {self.shader.glcore.glUniformMatrix3x4fv(location, 1, 0, v.as_ptr())} else
454 if let Some(v) = v.downcast_ref::<Mat4x2>() {self.shader.glcore.glUniformMatrix4x2fv(location, 1, 0, v.as_ptr())} else
455 if let Some(v) = v.downcast_ref::<Mat4x3>() {self.shader.glcore.glUniformMatrix4x3fv(location, 1, 0, v.as_ptr())} else
456 if let Some(v) = v.downcast_ref::<i32>() {self.shader.glcore.glUniform1iv(location, 1, v as *const _)} else
457 if let Some(v) = v.downcast_ref::<IVec2>() {self.shader.glcore.glUniform2iv(location, 1, v.as_ptr())} else
458 if let Some(v) = v.downcast_ref::<IVec3>() {self.shader.glcore.glUniform3iv(location, 1, v.as_ptr())} else
459 if let Some(v) = v.downcast_ref::<IVec4>() {self.shader.glcore.glUniform4iv(location, 1, v.as_ptr())} else
460 if let Some(v) = v.downcast_ref::<u32>() {self.shader.glcore.glUniform1uiv(location, 1, v as *const _)} else
461 if let Some(v) = v.downcast_ref::<UVec2>() {self.shader.glcore.glUniform2uiv(location, 1, v.as_ptr())} else
462 if let Some(v) = v.downcast_ref::<UVec3>() {self.shader.glcore.glUniform3uiv(location, 1, v.as_ptr())} else
463 if let Some(v) = v.downcast_ref::<UVec4>() {self.shader.glcore.glUniform4uiv(location, 1, v.as_ptr())} else
464 if let Some(v) = v.downcast_ref::<f64>() {self.shader.glcore.glUniform1dv(location, 1, v as *const _)} else
465 if let Some(v) = v.downcast_ref::<DVec2>() {self.shader.glcore.glUniform2dv(location, 1, v.as_ptr())} else
466 if let Some(v) = v.downcast_ref::<DVec3>() {self.shader.glcore.glUniform3dv(location, 1, v.as_ptr())} else
467 if let Some(v) = v.downcast_ref::<DVec4>() {self.shader.glcore.glUniform4dv(location, 1, v.as_ptr())} else
468 if let Some(v) = v.downcast_ref::<DMat2>() {self.shader.glcore.glUniformMatrix2dv(location, 1, 0, v.as_ptr())} else
469 if let Some(v) = v.downcast_ref::<DMat3>() {self.shader.glcore.glUniformMatrix3dv(location, 1, 0, v.as_ptr())} else
470 if let Some(v) = v.downcast_ref::<DMat4>() {self.shader.glcore.glUniformMatrix4dv(location, 1, 0, v.as_ptr())} else
471 if let Some(v) = v.downcast_ref::<DMat2x3>() {self.shader.glcore.glUniformMatrix2x3dv(location, 1, 0, v.as_ptr())} else
472 if let Some(v) = v.downcast_ref::<DMat2x4>() {self.shader.glcore.glUniformMatrix2x4dv(location, 1, 0, v.as_ptr())} else
473 if let Some(v) = v.downcast_ref::<DMat3x2>() {self.shader.glcore.glUniformMatrix3x2dv(location, 1, 0, v.as_ptr())} else
474 if let Some(v) = v.downcast_ref::<DMat3x4>() {self.shader.glcore.glUniformMatrix3x4dv(location, 1, 0, v.as_ptr())} else
475 if let Some(v) = v.downcast_ref::<DMat4x2>() {self.shader.glcore.glUniformMatrix4x2dv(location, 1, 0, v.as_ptr())} else
476 if let Some(v) = v.downcast_ref::<DMat4x3>() {self.shader.glcore.glUniformMatrix4x3dv(location, 1, 0, v.as_ptr())} else
477 {panic!("Unknown type of uniform value: {v:?}")}
478 Ok(())
479 } else {
480 Err(ShaderError::UniformNotFound(name.to_owned()))
481 }
482 }
483
484 pub fn setup_material_uniforms(&self, material: &dyn Material, prefix: Option<&str>, camel_case: bool) {
486 let glcore = &self.shader.glcore;
487 let shader_uniforms = self.shader.get_active_uniforms().unwrap();
488 let texture_names = material.get_names();
489 let mut active_texture = 0u32;
490 for name in texture_names.iter() {
491 let mut name_mod = String::new();
492 if let Some(prefix) = prefix {
493 name_mod.push_str(prefix);
494 }
495 if camel_case {
496 name_mod.push_str(&to_camel_case(name, prefix.is_some()));
497 } else {
498 name_mod.push_str(&name);
499 }
500 if let Some(_) = shader_uniforms.get(&name_mod) {
501 if let Some(texture) = material.get_by_name(&name) {
502 let location = self.shader.get_uniform_location(&name_mod);
503 if location == -1 {
504 continue;
505 }
506 match texture {
507 MaterialComponent::Texture(texture) => {
508 texture.set_active_unit(active_texture);
509 let bind = texture.bind();
510 glcore.glUniform1i(location, active_texture as i32);
511 bind.unbind();
512 active_texture += 1;
513 }
514 MaterialComponent::Color(color) => {
515 glcore.glUniform4f(location, color.x, color.y, color.z, color.w);
516 }
517 MaterialComponent::Luminance(lum) => {
518 glcore.glUniform1f(location, *lum);
519 }
520 }
521 }
522 }
523 }
524 }
525
526 pub fn unuse(self) {}
528}
529
530impl Drop for ShaderUse<'_> {
531 fn drop(&mut self) {
532 self.shader.glcore.glUseProgram(0)
533 }
534}
535
536impl Drop for Shader {
537 fn drop(&mut self) {
538 self.glcore.glDeleteProgram(self.program)
539 }
540}
541
542impl ShaderBinary {
543 pub fn new(format: u32, shader_type: ShaderType, binary: Vec<u8>) -> Self {
544 Self {
545 format,
546 shader_type,
547 binary,
548 }
549 }
550
551 pub fn load_from_file(path: &Path) -> Result<Self, ShaderBinaryLoadError> {
552 let config = bincode::config::standard()
553 .with_little_endian()
554 .with_fixed_int_encoding();
555 let mut file = std::fs::File::open(path)?;
556 Ok(bincode::decode_from_std_read(&mut file, config)?)
557 }
558
559 pub fn save_to_file(&self, path: &Path) -> Result<(), ShaderBinarySaveError> {
560 let config = bincode::config::standard()
561 .with_little_endian()
562 .with_fixed_int_encoding();
563 let mut file = std::fs::File::open(path)?;
564 bincode::encode_into_std_write(self, &mut file, config)?;
565 Ok(())
566 }
567}
568
569impl ShaderInputType {
570 pub fn is_float(&self) -> bool {
571 matches!(self, Self::Float | Self::Vec2 | Self::Vec3 | Self::Vec4 | Self::Mat2 | Self::Mat3 | Self::Mat4 | Self::Mat2x3 | Self::Mat2x4 | Self::Mat3x2 | Self::Mat3x4 | Self::Mat4x2 | Self::Mat4x3)
572 }
573
574 pub fn is_double(&self) -> bool {
575 matches!(self, Self::Double | Self::DVec2 | Self::DVec3 | Self::DVec4 | Self::DMat2 | Self::DMat3 | Self::DMat4 | Self::DMat2x3 | Self::DMat2x4 | Self::DMat3x2 | Self::DMat3x4 | Self::DMat4x2 | Self::DMat4x3)
576 }
577
578 pub fn is_integer(&self) -> bool {
579 matches!(self, Self::Int | Self::IVec2 | Self::IVec3 | Self::IVec4 | Self::UInt | Self::UVec2 | Self::UVec3 | Self::UVec4)
580 }
581
582 pub fn get_size_and_rows(&self) -> (u32, u32) {
583 match self {
584 Self::Float | Self::Double | Self::Int | Self::UInt => (1, 1),
585 Self::Vec2 | Self::DVec2 | Self::IVec2 | Self::UVec2 => (2, 1),
586 Self::Vec3 | Self::DVec3 | Self::IVec3 | Self::UVec3 => (3, 1),
587 Self::Vec4 | Self::DVec4 | Self::IVec4 | Self::UVec4 => (4, 1),
588 Self::Mat2 | Self::DMat2 => (2, 2),
589 Self::Mat3 | Self::DMat3 => (3, 3),
590 Self::Mat4 | Self::DMat4 => (4, 4),
591 Self::Mat2x3 | Self::DMat2x3 => (2, 3),
592 Self::Mat2x4 | Self::DMat2x4 => (2, 4),
593 Self::Mat3x2 | Self::DMat3x2 => (3, 2),
594 Self::Mat3x4 | Self::DMat3x4 => (3, 4),
595 Self::Mat4x2 | Self::DMat4x2 => (4, 2),
596 Self::Mat4x3 | Self::DMat4x3 => (4, 3),
597 }
598 }
599
600 pub fn get_base_type(&self) -> ShaderInputType {
601 match self {
602 Self::Float | Self::Vec2 | Self::Vec3 | Self::Vec4 | Self::Mat2 | Self::Mat3 | Self::Mat4 | Self::Mat2x3 | Self::Mat2x4 | Self::Mat3x2 | Self::Mat3x4 | Self::Mat4x2 | Self::Mat4x3 => Self::Float,
603 Self::Double | Self::DVec2 | Self::DVec3 | Self::DVec4 | Self::DMat2 | Self::DMat3 | Self::DMat4 | Self::DMat2x3 | Self::DMat2x4 | Self::DMat3x2 | Self::DMat3x4 | Self::DMat4x2 | Self::DMat4x3 => Self::Double,
604 Self::Int | Self::IVec2 | Self::IVec3 | Self::IVec4 => Self::Int,
605 Self::UInt | Self::UVec2 | Self::UVec3 | Self::UVec4 => Self::UInt,
606 }
607 }
608}
609
610impl ShaderInputVarType {
611 pub fn is_float(&self) -> bool {
612 self.type_.is_float()
613 }
614
615 pub fn is_double(&self) -> bool {
616 self.type_.is_double()
617 }
618
619 pub fn is_integer(&self) -> bool {
620 self.type_.is_integer()
621 }
622
623 pub fn get_size_and_rows(&self) -> (u32, u32) {
624 self.type_.get_size_and_rows()
625 }
626
627 pub fn get_type(&self) -> ShaderInputType {
628 self.type_
629 }
630
631 pub fn get_base_type(&self) -> ShaderInputType {
632 self.type_.get_base_type()
633 }
634}
635
636impl Debug for Shader {
637 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
638 f.debug_struct("Shader")
639 .field("program", &self.program)
640 .field("shader_type", &self.shader_type)
641 .finish()
642 }
643}
644
645impl Debug for ShaderError {
646 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
647 match self {
648 Self::VSError(infolog) => write!(f, "Vertex Shader Error:\n{infolog}"),
649 Self::GSError(infolog) => write!(f, "Geometry Shader Error:\n{infolog}"),
650 Self::FSError(infolog) => write!(f, "Fragment Shader Error:\n{infolog}"),
651 Self::CSError(infolog) => write!(f, "Compute Shader Error:\n{infolog}"),
652 Self::LinkageError(infolog) => write!(f, "Shader Linkage Error:\n{infolog}"),
653 Self::AttribNotFound(attrib) => write!(f, "Attrib not found: {attrib}"),
654 Self::UniformNotFound(uniform) => write!(f, "Uniform not found: {uniform}"),
655 }
656 }
657}
658
659impl From<u32> for ShaderInputType {
660 fn from(val: u32) -> Self {
661 match val {
662 GL_FLOAT => Self::Float,
663 GL_FLOAT_VEC2 => Self::Vec2,
664 GL_FLOAT_VEC3 => Self::Vec3,
665 GL_FLOAT_VEC4 => Self::Vec4,
666 GL_FLOAT_MAT2 => Self::Mat2,
667 GL_FLOAT_MAT3 => Self::Mat3,
668 GL_FLOAT_MAT4 => Self::Mat4,
669 GL_FLOAT_MAT2x3 => Self::Mat2x3,
670 GL_FLOAT_MAT2x4 => Self::Mat2x4,
671 GL_FLOAT_MAT3x2 => Self::Mat3x2,
672 GL_FLOAT_MAT3x4 => Self::Mat3x4,
673 GL_FLOAT_MAT4x2 => Self::Mat4x2,
674 GL_FLOAT_MAT4x3 => Self::Mat4x3,
675 GL_INT => Self::Int,
676 GL_INT_VEC2 => Self::IVec2,
677 GL_INT_VEC3 => Self::IVec3,
678 GL_INT_VEC4 => Self::IVec4,
679 GL_UNSIGNED_INT => Self::UInt,
680 GL_UNSIGNED_INT_VEC2 => Self::UVec2,
681 GL_UNSIGNED_INT_VEC3 => Self::UVec3,
682 GL_UNSIGNED_INT_VEC4 => Self::UVec4,
683 GL_DOUBLE => Self::Double,
684 GL_DOUBLE_VEC2 => Self::DVec2,
685 GL_DOUBLE_VEC3 => Self::DVec3,
686 GL_DOUBLE_VEC4 => Self::DVec4,
687 GL_DOUBLE_MAT2 => Self::DMat2,
688 GL_DOUBLE_MAT3 => Self::DMat3,
689 GL_DOUBLE_MAT4 => Self::DMat4,
690 GL_DOUBLE_MAT2x3 => Self::DMat2x3,
691 GL_DOUBLE_MAT2x4 => Self::DMat2x4,
692 GL_DOUBLE_MAT3x2 => Self::DMat3x2,
693 GL_DOUBLE_MAT3x4 => Self::DMat3x4,
694 GL_DOUBLE_MAT4x2 => Self::DMat4x2,
695 GL_DOUBLE_MAT4x3 => Self::DMat4x3,
696 _ => panic!("Invalid value {val} of `ShaderInputType`"),
697 }
698 }
699}
700
701impl Debug for ShaderInputType {
702 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
703 match self {
704 Self::Float => write!(f, "float"),
705 Self::Vec2 => write!(f, "vec2"),
706 Self::Vec3 => write!(f, "vec3"),
707 Self::Vec4 => write!(f, "vec4"),
708 Self::Mat2 => write!(f, "mat2"),
709 Self::Mat3 => write!(f, "mat3"),
710 Self::Mat4 => write!(f, "mat4"),
711 Self::Mat2x3 => write!(f, "mat2x3"),
712 Self::Mat2x4 => write!(f, "mat2x4"),
713 Self::Mat3x2 => write!(f, "mat3x2"),
714 Self::Mat3x4 => write!(f, "mat3x4"),
715 Self::Mat4x2 => write!(f, "mat4x2"),
716 Self::Mat4x3 => write!(f, "mat4x3"),
717 Self::Int => write!(f, "int"),
718 Self::IVec2 => write!(f, "ivec2"),
719 Self::IVec3 => write!(f, "ivec3"),
720 Self::IVec4 => write!(f, "ivec4"),
721 Self::UInt => write!(f, "uint"),
722 Self::UVec2 => write!(f, "uvec2"),
723 Self::UVec3 => write!(f, "uvec3"),
724 Self::UVec4 => write!(f, "uvec4"),
725 Self::Double => write!(f, "double"),
726 Self::DVec2 => write!(f, "dvec2"),
727 Self::DVec3 => write!(f, "dvec3"),
728 Self::DVec4 => write!(f, "dvec4"),
729 Self::DMat2 => write!(f, "dmat2"),
730 Self::DMat3 => write!(f, "dmat3"),
731 Self::DMat4 => write!(f, "dmat4"),
732 Self::DMat2x3 => write!(f, "dmat2x3"),
733 Self::DMat2x4 => write!(f, "dmat2x4"),
734 Self::DMat3x2 => write!(f, "dmat3x2"),
735 Self::DMat3x4 => write!(f, "dmat3x4"),
736 Self::DMat4x2 => write!(f, "dmat4x2"),
737 Self::DMat4x3 => write!(f, "dmat4x3"),
738 }
739 }
740}
741
742impl Display for ShaderInputType {
743 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
744 <Self as Debug>::fmt(self, f)
745 }
746}
747
748impl From<std::io::Error> for ShaderBinaryLoadError {
749 fn from(err: std::io::Error) -> Self {
750 Self::IOError(err)
751 }
752}
753
754impl From<bincode::error::DecodeError> for ShaderBinaryLoadError {
755 fn from(err: bincode::error::DecodeError) -> Self {
756 Self::DecodeError(err)
757 }
758}
759
760impl From<std::io::Error> for ShaderBinarySaveError {
761 fn from(err: std::io::Error) -> Self {
762 Self::IOError(err)
763 }
764}
765
766impl From<bincode::error::EncodeError> for ShaderBinarySaveError {
767 fn from(err: bincode::error::EncodeError) -> Self {
768 Self::EncodeError(err)
769 }
770}