globject_rs/
glshader.rs

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/// Error produced from the shader
19#[derive(Clone)]
20pub enum ShaderError {
21	/// Vertex Shader error
22	VSError(String),
23
24	/// Geometry Shader error
25	GSError(String),
26
27	/// Fragment Shader error
28	FSError(String),
29	
30	/// Compute Shader error
31	CSError(String),
32
33	/// Shader program linkage error
34	LinkageError(String),
35
36	/// Attrib not found
37	AttribNotFound(String),
38
39	/// Uniform not found
40	UniformNotFound(String),
41}
42
43/// Error produced from the shader
44#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq)]
45pub enum ShaderType {
46	Draw,
47	Compute,
48}
49
50/// The OpenGL shader object
51pub struct Shader {
52	glcore: Rc<GLCore>,
53	program: u32,
54	shader_type: ShaderType,
55}
56
57/// The struct for monitoring using the shader
58#[derive(Debug)]
59pub struct ShaderUse<'a> {
60	pub shader: &'a Shader,
61}
62
63/// The pre-compiled OpenGL shader binary
64#[derive(Encode, Decode, Debug, Clone)]
65pub struct ShaderBinary {
66	format: u32,
67	shader_type: ShaderType,
68	binary: Vec<u8>,
69}
70
71/// The error info of loading the shader binary
72#[derive(Debug)]
73pub enum ShaderBinaryLoadError {
74	IOError(std::io::Error),
75	DecodeError(bincode::error::DecodeError),
76}
77
78/// The error info of storing the shader binary
79#[derive(Debug)]
80pub enum ShaderBinarySaveError {
81	IOError(std::io::Error),
82	EncodeError(bincode::error::EncodeError),
83}
84
85/// The OpenGL attrib types
86#[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/// The OpenGL attrib type with length
125#[derive(Debug, Clone, Copy)]
126pub struct ShaderInputVarType {
127	pub type_: ShaderInputType,
128	pub size: i32,
129}
130
131impl Shader {
132	/// Get the internal name
133	pub fn get_name(&self) -> u32 {
134		self.program
135	}
136
137	/// Compile a shader, returns the compiled shader object or the compiler info log
138	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	/// Link a shader program, returns compiler/linker info log if linkage isn't successful.
164	fn link_program(glcore: &GLCore, program: u32) -> Result<(), ShaderError> {
165		glcore.glLinkProgram(program);
166		Self::get_linkage_status(glcore, program)
167	}
168
169	/// Get the program linkage status, returns compiler/linker info log if linkage isn't successful.
170	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	/// Create a new traditional renderer shader program
189	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	/// Create a new compute shader program
227	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	/// Get all of the active attributes of the shader
245	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	/// Get the location of the shader attrib
266	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	/// Get all of the active uniforms of the shader
272	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	/// Get the location of the shader attrib
293	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	/// Get the compiled + linked program binary
299	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	/// Create a program from pre-compiled binary
310	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	/// Set to use the shader
327	pub fn use_program<'a>(&'a self) -> ShaderUse<'a> {
328		ShaderUse::new(self)
329	}
330}
331
332impl<'a> ShaderUse<'a> {
333	/// Create a new `using` state to the `Shader`
334	fn new(shader: &'a Shader) -> Self {
335		shader.glcore.glUseProgram(shader.get_name());
336		Self {
337			shader,
338		}
339	}
340
341	/// Dispatch the compute shader
342	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	/// Dispatch the compute shader
350	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	/// Wrapper for matrices of attrib
360	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	/// Set attrib value by pointer
377	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	/// Set attrib value
394	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	/// Set uniform value
440	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	/// Set shader uniform inputs by a material
485	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	/// Unuse the program.
527	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}