2020-02-16 23:14:28 +00:00
|
|
|
use std::collections::*;
|
2020-02-16 23:07:32 +00:00
|
|
|
use std::convert::TryInto;
|
2020-02-16 23:14:28 +00:00
|
|
|
use std::ffi::{CStr, CString};
|
2020-02-16 23:07:32 +00:00
|
|
|
|
|
|
|
pub struct ShaderObject {
|
|
|
|
id: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ShaderObject {
|
|
|
|
pub fn id (&self) -> u32 {
|
|
|
|
self.id
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new (shader_type: u32, source: &str) -> Result <ShaderObject, String>
|
|
|
|
{
|
|
|
|
let id = unsafe {
|
|
|
|
gl::CreateShader (shader_type)
|
|
|
|
};
|
|
|
|
|
|
|
|
let sources = [
|
|
|
|
source.as_ptr () as *const i8,
|
|
|
|
];
|
|
|
|
|
|
|
|
let lengths = [
|
|
|
|
source.len ().try_into ().unwrap (),
|
|
|
|
];
|
|
|
|
|
|
|
|
let success = unsafe {
|
|
|
|
gl::ShaderSource (id, sources.len ().try_into ().unwrap (), sources.as_ptr (), lengths.as_ptr ());
|
|
|
|
gl::CompileShader (id);
|
|
|
|
|
|
|
|
let mut success = 0;
|
|
|
|
gl::GetShaderiv (id, gl::COMPILE_STATUS, &mut success);
|
|
|
|
success == 1
|
|
|
|
};
|
|
|
|
|
|
|
|
if success {
|
|
|
|
Ok (ShaderObject {
|
|
|
|
id,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let mut info_log = vec! [0u8; 4096];
|
|
|
|
let mut log_length = 0;
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
gl::GetShaderInfoLog (id, (info_log.len () - 1).try_into ().unwrap (), &mut log_length, info_log.as_mut_ptr () as *mut i8);
|
|
|
|
}
|
|
|
|
|
|
|
|
info_log.truncate (log_length.try_into ().unwrap ());
|
|
|
|
|
|
|
|
let info = String::from_utf8 (info_log).unwrap ();
|
|
|
|
|
|
|
|
Err (info)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for ShaderObject {
|
|
|
|
fn drop (&mut self) {
|
|
|
|
unsafe {
|
|
|
|
gl::DeleteShader (self.id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct ShaderProgram {
|
|
|
|
id: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ShaderProgram {
|
|
|
|
pub fn new (vert: &ShaderObject, frag: &ShaderObject)
|
|
|
|
-> Result <ShaderProgram, String>
|
|
|
|
{
|
|
|
|
let id = unsafe {
|
|
|
|
gl::CreateProgram ()
|
|
|
|
};
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
gl::AttachShader (id, vert.id ());
|
|
|
|
gl::AttachShader (id, frag.id ());
|
|
|
|
|
|
|
|
gl::LinkProgram (id);
|
|
|
|
}
|
|
|
|
|
|
|
|
let success = unsafe {
|
|
|
|
let mut success = 0;
|
|
|
|
gl::GetProgramiv (id, gl::LINK_STATUS, &mut success);
|
|
|
|
success == 1
|
|
|
|
};
|
|
|
|
|
|
|
|
if success {
|
|
|
|
Ok (ShaderProgram {
|
|
|
|
id,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let mut info_log = vec! [0u8; 4096];
|
|
|
|
let mut log_length = 0;
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
gl::GetProgramInfoLog (id, (info_log.len () - 1).try_into ().unwrap (), &mut log_length, info_log.as_mut_ptr () as *mut i8);
|
|
|
|
}
|
|
|
|
|
|
|
|
info_log.truncate (log_length.try_into ().unwrap ());
|
|
|
|
|
|
|
|
let info = String::from_utf8 (info_log).unwrap ();
|
|
|
|
|
|
|
|
Err (info)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_uniform_location (&self, name: &CStr) -> i32 {
|
|
|
|
unsafe {
|
|
|
|
gl::UseProgram (self.id);
|
|
|
|
gl::GetUniformLocation (self.id, name.as_ptr ())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-16 23:14:28 +00:00
|
|
|
pub fn get_uniform_locations <'a, I> (&self, names: I)
|
|
|
|
-> HashMap <String, i32>
|
|
|
|
where I: Iterator <Item = &'a str>
|
|
|
|
{
|
|
|
|
unsafe {
|
|
|
|
gl::UseProgram (self.id);
|
|
|
|
}
|
|
|
|
|
|
|
|
names
|
|
|
|
.map (|name| {
|
|
|
|
let mut s = String::from ("uni_");
|
|
|
|
s.push_str (name);
|
|
|
|
|
|
|
|
let c_str = CString::new (s.as_bytes ()).unwrap ();
|
|
|
|
let loc = unsafe {
|
|
|
|
gl::GetUniformLocation (self.id, c_str.as_ptr ())
|
|
|
|
};
|
|
|
|
|
|
|
|
(String::from (name), loc)
|
|
|
|
})
|
|
|
|
.collect ()
|
|
|
|
}
|
|
|
|
|
2020-02-16 23:07:32 +00:00
|
|
|
pub fn get_attribute_location (&self, name: &CStr) -> i32 {
|
|
|
|
unsafe {
|
|
|
|
gl::UseProgram (self.id);
|
|
|
|
gl::GetAttribLocation (self.id, name.as_ptr ())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for ShaderProgram {
|
|
|
|
fn drop (&mut self) {
|
|
|
|
unsafe {
|
|
|
|
gl::DeleteProgram (self.id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|