extern crate gl;
use gl::types::*;
use std::ffi::CString;
use std::fs::File;
use std::io::Read;
use std::error::Error;
pub enum ShaderType
{
Vertex ,
Fragment,
Compute ,
Geometry
}
impl ShaderType{
fn value(&self) -> GLenum{
match *self {
ShaderType::Vertex => gl::VERTEX_SHADER,
ShaderType::Fragment => gl::FRAGMENT_SHADER,
ShaderType::Compute => gl::COMPUTE_SHADER,
ShaderType::Geometry => gl::GEOMETRY_SHADER
}
}
}
pub struct Shader {
id: u32,
_shader_type: ShaderType
}
impl Drop for Shader {
fn drop(&mut self) {
unsafe {
println!("Dropping shader {}", self.id);
gl::DeleteShader(self.id);
}
}
}
impl Shader {
pub fn get_id(&self) -> GLuint {
self.id
}
pub fn new(shader_type: ShaderType) -> Shader {
unsafe {
Shader {
id: gl::CreateShader(shader_type.value()),
_shader_type: shader_type
}
}
}
pub fn load_from_memory(&mut self, data: &str) -> Result<(), Box<dyn Error>> {
unsafe {
let shader_id = self.id;
let c_string = CString::new(data)?;
gl::ShaderSource(shader_id, 1, &c_string.as_ptr(), ::std::ptr::null());
gl::CompileShader(shader_id);
let mut success: GLint = 0;
gl::GetShaderiv(shader_id, gl::COMPILE_STATUS, &mut success);
match success {
0 => {
let mut log_size: GLint = 0;
gl::GetShaderiv(shader_id, gl::INFO_LOG_LENGTH, &mut log_size);
let mut msg: Vec<u8> = Vec::new();
msg.resize(log_size as usize, 0);
let mut new_length = 0;
gl::GetShaderInfoLog(
shader_id,
log_size,
&mut new_length,
msg.as_ptr() as *mut GLchar,
);
let msg = format!(
"Failed to compile shader : {}",
String::from_utf8(msg).unwrap()
);
Err(From::from(msg))
}
_ => Ok(()), }
}
}
pub fn load_from_file(&mut self, path: &str) -> Result<(), Box<dyn Error> > {
let mut file = File::open(&path)?;
let mut content = String::new();
file.read_to_string(&mut content)
.expect("Failed to read from file");
let c_content: CString = CString::new(content.as_bytes()).unwrap();
match c_content.to_str() {
Ok(v) => {
self.load_from_memory(v)
},
Err(err) => {
Err(From::from(format!("Failed to load shader for path \"{}\": {}", path, err)))
}
}
}
}
#[allow(dead_code)]
pub enum Uniform {
Float(f32),
Int(i32),
Sampler2D(GLuint),
}