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