globject_rs/
glshader.rs

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/// Error produced from the shader
22#[derive(Clone)]
23pub enum ShaderError {
24	/// Vertex Shader error
25	VSError(String),
26
27	/// Geometry Shader error
28	GSError(String),
29
30	/// Fragment Shader error
31	FSError(String),
32	
33	/// Compute Shader error
34	CSError(String),
35
36	/// Unknown type of shader error
37	UnknownShaderError(String),
38
39	/// Shader program linkage error
40	LinkageError(String),
41
42	/// Attrib not found
43	AttribNotFound(String),
44
45	/// Uniform not found
46	UniformNotFound(String),
47
48	/// FromUtf8Error
49	FromUtf8Error(String),
50
51	/// texture error
52	TextureError(String),
53
54	/// Shader is not supported for the current OpenGL version
55	ShaderNotSupported(String),
56}
57
58/// Error produced from the shader
59#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq)]
60pub enum ShaderType {
61	Draw,
62	Compute,
63}
64
65/// The OpenGL shader object
66pub struct Shader {
67	glcore: Rc<GLCore>,
68	program: u32,
69	shader_type: ShaderType,
70}
71
72/// The struct for monitoring using the shader
73#[derive(Debug)]
74pub struct ShaderUse<'a> {
75	pub shader: &'a Shader,
76}
77
78/// The pre-compiled OpenGL shader binary
79#[derive(Encode, Decode, Debug, Clone)]
80pub struct ShaderBinary {
81	format: u32,
82	shader_type: ShaderType,
83	binary: Vec<u8>,
84}
85
86/// The error info of loading the shader binary
87#[derive(Debug)]
88pub enum ShaderBinaryLoadError {
89	IOError(std::io::Error),
90	DecodeError(bincode::error::DecodeError),
91}
92
93/// The error info of storing the shader binary
94#[derive(Debug)]
95pub enum ShaderBinarySaveError {
96	IOError(std::io::Error),
97	EncodeError(bincode::error::EncodeError),
98}
99
100/// The OpenGL attrib types
101#[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/// The OpenGL attrib type with length
140#[derive(Debug, Clone, Copy)]
141pub struct ShaderInputVarType {
142	pub type_: ShaderInputType,
143	pub size: i32,
144}
145
146impl Shader {
147	/// Get the internal name
148	pub fn get_name(&self) -> u32 {
149		self.program
150	}
151
152	/// Compile a shader, returns the compiled shader object or the compiler info log
153	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	/// Link a shader program, returns compiler/linker info log if linkage isn't successful.
185	fn link_program(glcore: &GLCore, program: u32) -> Result<(), ShaderError> {
186		glcore.glLinkProgram(program)?;
187		Self::get_linkage_status(glcore, program)
188	}
189
190	/// Get the program linkage status, returns compiler/linker info log if linkage isn't successful.
191	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	/// Create a new traditional renderer shader program
210	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	/// Create a new compute shader program
236	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	/// Get all of the active attributes of the shader
250	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	/// Get the location of the shader attrib
271	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	/// Get all of the active uniforms of the shader
277	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	/// Get the location of the shader attrib
298	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	/// Get the compiled + linked program binary
304	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	/// Create a program from pre-compiled binary
314	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	/// Set to use the shader
331	pub fn use_program<'a>(&'a self) -> Result<ShaderUse<'a>, ShaderError> {
332		ShaderUse::new(self)
333	}
334}
335
336impl<'a> ShaderUse<'a> {
337	/// Create a new `using` state to the `Shader`
338	fn new(shader: &'a Shader) -> Result<Self, ShaderError> {
339		shader.glcore.glUseProgram(shader.get_name())?;
340		Ok(Self {
341			shader,
342		})
343	}
344
345	/// Dispatch the compute shader
346	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	/// Dispatch the compute shader
355	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	/// Wrapper for matrices of attributes
369	///
370	/// # Safety
371	///
372	/// When binding an array buffer, the parameter `pointer` refers to an offset of the data from the array buffer.
373	/// When not bound to any array buffers, the parameter `pointer` is the pointer to your vertex data from the system memory.
374	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	/// Wrapper for setting attribute values by pointer
392	///
393	/// # Safety
394	///
395	/// When binding an array buffer, the parameter `pointer` refers to an offset of the data from the array buffer.
396	/// When not bound to any array buffers, the parameter `pointer` is the pointer to your vertex data from the system memory.
397	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	/// Set attrib value
414	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	/// Set uniform value
460	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	/// Set shader uniform inputs by a material
505	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	/// Unuse the program.
547	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}