13 | 13 |
use std::marker::PhantomData;
|
14 | 14 |
use std::os::raw::c_void;
|
15 | 15 |
|
16 | |
//
|
17 | |
|
| 16 |
/// Clear the screen to a generic color
|
18 | 17 |
pub fn clear() {
|
19 | 18 |
unsafe {
|
20 | 19 |
gl::ClearColor(0.3, 0.3, 0.3, 1.0);
|
|
22 | 21 |
}
|
23 | 22 |
}
|
24 | 23 |
|
| 24 |
/// Abstract over an OpenGL context as well as a basic event loop
|
25 | 25 |
pub struct Window {
|
26 | 26 |
events: glutin::EventsLoop,
|
27 | 27 |
gl_window: glutin::GlWindow,
|
28 | 28 |
}
|
29 | 29 |
|
30 | 30 |
impl Window {
|
| 31 |
/// Attempt to create a new window, and load all the relevant
|
| 32 |
/// OpenGL symbols in the process
|
31 | 33 |
pub fn create() -> Result<Window, Error> {
|
32 | 34 |
use glutin::GlContext;
|
33 | 35 |
let events = glutin::EventsLoop::new();
|
|
42 | 44 |
Ok(Window { events, gl_window })
|
43 | 45 |
}
|
44 | 46 |
|
| 47 |
/// Run the main event loop, calling the supplied callback with
|
| 48 |
/// every event
|
45 | 49 |
pub fn run<F>(self, mut cb: F) -> Result<(), Error>
|
46 | 50 |
where F: FnMut(glutin::Event) -> glutin::ControlFlow
|
47 | 51 |
{
|
|
66 | 70 |
|
67 | 71 |
}
|
68 | 72 |
|
| 73 |
/// Wrap an OpenGL shader. This will automatically be cleaned up from
|
| 74 |
/// the OpenGL state machine when it is dropped.
|
69 | 75 |
pub struct Shader {
|
70 | 76 |
pub n: gl::GLuint,
|
71 | 77 |
}
|
|
76 | 82 |
}
|
77 | 83 |
}
|
78 | 84 |
|
| 85 |
/// Right now, we're only concerned with either Fragment or Vertex
|
| 86 |
/// shaders. We might eventually want Geometry shaders, as well.
|
79 | 87 |
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
80 | 88 |
pub enum ShaderType {
|
81 | 89 |
Fragment,
|
|
83 | 91 |
}
|
84 | 92 |
|
85 | 93 |
impl ShaderType {
|
| 94 |
/// Convert a ShaderType value to OpenGL's enum value for the same
|
86 | 95 |
fn to_glenum(&self) -> gl::GLenum {
|
87 | 96 |
match *self {
|
88 | 97 |
ShaderType::Fragment => gl::FRAGMENT_SHADER,
|
|
92 | 101 |
}
|
93 | 102 |
|
94 | 103 |
impl Shader {
|
| 104 |
/// Compile a shade string and provide our Rust-level handle to it
|
95 | 105 |
pub fn compile(ty: ShaderType, src: &str) -> Result<Shader, Error> {
|
| 106 |
// this structure is gonna repeat a few times but also can't
|
| 107 |
// really get abstracted over in a clean way, so this comment
|
| 108 |
// could be consulted for the other functions, too.
|
96 | 109 |
let shader;
|
97 | 110 |
unsafe {
|
| 111 |
// we start by getting a new shader from OpenGL
|
98 | 112 |
shader = gl::CreateShader(ty.to_glenum());
|
| 113 |
// and also get the C string version of the source code
|
99 | 114 |
let c_str = ffi::CString::new(src.as_bytes())?;
|
| 115 |
|
| 116 |
// and then we compile it!
|
100 | 117 |
gl::ShaderSource(shader, 1, &c_str.as_ptr(), ptr::null());
|
101 | 118 |
gl::CompileShader(shader);
|
102 | 119 |
|
| 120 |
// this is the common part: we now ask OpenGL for the
|
| 121 |
// status of that compile, which OpenGL gives us by
|
| 122 |
// updating a pointer
|
103 | 123 |
let mut status = gl::FALSE as gl::GLint;
|
104 | 124 |
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
|
105 | 125 |
|
| 126 |
// If it's not good...
|
106 | 127 |
if status != (gl::TRUE as gl::GLint) {
|
| 128 |
// then then need to get the length of the error
|
| 129 |
// message, which, again we fetch via pointer
|
107 | 130 |
let mut len = 0;
|
108 | 131 |
gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
|
| 132 |
|
| 133 |
// create the buffer that's big enough for that
|
| 134 |
// message
|
109 | 135 |
let mut buf = Vec::with_capacity(len as usize);
|
110 | 136 |
buf.set_len((len as usize) - 1);
|
| 137 |
// and then fill it in via OpenGL's mechanisms
|
111 | 138 |
gl::GetShaderInfoLog(
|
112 | 139 |
shader,
|
113 | 140 |
len,
|
114 | 141 |
ptr::null_mut(),
|
115 | 142 |
buf.as_mut_ptr() as *mut gl::GLchar
|
116 | 143 |
);
|
| 144 |
// and finally return it!
|
117 | 145 |
return Err(Error::CompileError(String::from_utf8(buf)?));
|
118 | 146 |
}
|
119 | 147 |
}
|
| 148 |
|
120 | 149 |
Ok(Shader { n: shader })
|
121 | 150 |
}
|
122 | 151 |
}
|
|
124 | 153 |
|
125 | 154 |
//
|
126 | 155 |
|
| 156 |
/// Represents a linked set of OpenGL shaders.
|
127 | 157 |
pub struct Program {
|
128 | 158 |
pub p: gl::GLuint,
|
129 | 159 |
pub shaders: Vec<Shader>,
|
|
139 | 169 |
}
|
140 | 170 |
|
141 | 171 |
impl Program {
|
| 172 |
/// Link several existing shaders into a single Program
|
142 | 173 |
pub fn link(shaders: Vec<Shader>) -> Result<Program, Error> {
|
| 174 |
// the stuff in here looks a lot like Shader::compile, so
|
| 175 |
// consult the inline docs for that to figure out what's going on
|
143 | 176 |
unsafe {
|
144 | 177 |
let program = gl::CreateProgram();
|
145 | 178 |
for s in shaders.iter() {
|