1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use super::*;
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 \"{}\": \n{}", path, err)))
}
}
}
}
#[allow(dead_code)]
pub enum Uniform {
Float(f32),
Int(i32),
Vec2(f32,f32),
Sampler2D(GLuint),
}