use gl;
use std::ops::{Deref};
use std::ffi::{CString};
pub enum GlShaderType {
Vertex,
Fragment
}
pub struct Shader {
shader: gl::types::GLuint,
attributes: Vec<CString>
}
impl Shader {
pub fn compile<'a, AttributeIter: IntoIterator<Item=&'a str>>(program: &str, shader_type: GlShaderType, attributes: AttributeIter) -> Shader {
unsafe {
let shader_type = match shader_type {
GlShaderType::Vertex => gl::VERTEX_SHADER,
GlShaderType::Fragment => gl::FRAGMENT_SHADER
};
let shader = gl::CreateShader(shader_type);
let mut length = [ program.len() as i32 ];
let program = program.as_bytes().as_ptr() as *const gl::types::GLchar;
let program = [ program ];
gl::ShaderSource(shader, 1, &program[0], &mut length[0]);
gl::CompileShader(shader);
let mut is_compiled = 0;
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut is_compiled);
if is_compiled == gl::FALSE.into() {
let mut logs: Vec<gl::types::GLchar> = vec![0; 8192];
let mut len = 0;
gl::GetShaderInfoLog(shader, 8192, &mut len, logs.as_mut_ptr());
let len = len as usize;
let logs = logs[0..len].into_iter().map(|c| *c as u8).collect::<Vec<_>>();
let logs = String::from_utf8_lossy(&logs);
println!("=== Shader errors\n {}\n===", logs);
panic!("Could not compile shader");
}
let attributes = attributes.into_iter()
.map(|attr| CString::new(attr).unwrap())
.collect();
Shader {
shader: shader,
attributes: attributes
}
}
}
pub (super) fn attributes(&self) -> &Vec<CString> {
&self.attributes
}
}
impl Drop for Shader {
fn drop(&mut self) {
unsafe {
gl::DeleteShader(self.shader);
}
}
}
impl Deref for Shader {
type Target = gl::types::GLuint;
fn deref(&self) -> &gl::types::GLuint {
&self.shader
}
}