use super::shader::Shader;
use gfxmath_vec3::Vec3;
use std::collections::HashMap;
pub struct ShaderProgram {
pub (crate) id: u32,
pub (crate) uniforms: HashMap<String, i32>
}
#[allow(dead_code)]
impl ShaderProgram {
pub fn new() -> Option<Self> {
unsafe {
let id: u32 = gl::CreateProgram();
if id != 0 { return Some(Self{ id, uniforms: HashMap::new() }) }
}
None
}
#[inline]
pub fn get_id(&self) -> u32 {
return self.id
}
#[inline]
pub fn activate(&self) -> &Self {
unsafe { gl::UseProgram(self.id); }
return self;
}
#[inline]
pub fn attach(&self, shader: &Shader) -> &Self {
unsafe { gl::AttachShader(self.id, shader.id); }
return self;
}
#[inline]
pub fn detach(&self, shader: &Shader) -> &Self {
unsafe { gl::DetachShader(self.id, shader.id); }
return self;
}
#[inline]
pub fn link(&self) -> bool {
unsafe {
let mut status: i32 = 0;
gl::LinkProgram(self.id);
gl::GetProgramiv(self.id, gl::LINK_STATUS, &mut status);
if status == gl::TRUE.into() { return true; }
return false;
}
}
#[inline]
pub fn add_uniform(&mut self, name: &str) {
if let None = self.uniforms.get(name) {
unsafe {
let n = std::ffi::CString::new(name).expect("malformed uniform name");
let location = gl::GetUniformLocation(self.id, n.as_ptr());
if location >= 0 {
self.uniforms.insert(String::from(name), location);
} else {
println!("Failed to add uniform ({:?}) - location: {:?}", name, location)
}
}
}
}
#[inline]
pub fn set_uniform_1i(&self, name: &str, value: i32) {
if let Some(e) = self.uniforms.get(name) {
unsafe { gl::Uniform1i(*e, value) };
}
}
#[inline]
pub fn set_uniform_1f(&self, name: &str, value: f32) {
if let Some(e) = self.uniforms.get(name) {
unsafe { gl::Uniform1f(*e, value) };
}
}
#[inline]
pub fn set_uniform_2f(&self, name: &str, value: &(f32, f32)) {
if let Some(e) = self.uniforms.get(name) {
unsafe { gl::Uniform2f(*e, value.0, value.1) };
}
}
#[inline]
pub fn set_uniform_2i(&self, name: &str, value: &(i32, i32)) {
if let Some(e) = self.uniforms.get(name) {
unsafe { gl::Uniform2i(*e, value.0, value.1) };
}
}
#[inline]
pub fn set_uniform_3f(&self, name: &str, value: &Vec3<f32>) {
if let Some(e) = self.uniforms.get(name) {
unsafe { gl::Uniform3f(*e, value.x, value.y, value.z) };
}
}
#[inline]
pub fn set_uniform_4f(&self, name: &str, value: &(f32, f32, f32, f32)) {
if let Some(e) = self.uniforms.get(name) {
unsafe { gl::Uniform4f(*e, value.0, value.1, value.2, value.3) };
} else {
println!("failed to set uniform: {:?} = {:?}", name, value)
}
}
#[inline]
pub fn set_uniform_matrix_4fv(&self, name: &str, count: gl::types::GLsizei, transpose: gl::types::GLboolean, value: *const gl::types::GLfloat) {
if let Some(e) = self.uniforms.get(name) {
unsafe { gl::UniformMatrix4fv(*e, count, transpose, value) };
}
}
}
impl Drop for ShaderProgram {
fn drop(&mut self) {
unsafe { gl::DeleteProgram(self.id); }
}
}