gdritter repos panem-nostrum-quotidianum / f1ad093
Move that stuff over from Outlander Getty Ritter 6 years ago
4 changed file(s) with 315 addition(s) and 0 deletion(s). Collapse all Expand all
1
2 /target/
3 **/*.rs.bk
4 Cargo.lock
1 [package]
2 name = "panem-nostrum-quotidianum"
3 version = "0.1.0"
4 authors = ["Getty Ritter <samothes@infinitenegativeutility.com>"]
5
6 [dependencies]
7 gl = "0.6.0"
8 glutin = "*"
1 use glutin;
2 use std::{convert, ffi, string};
3
4 #[derive(Debug)]
5 pub enum Error {
6 BadCString,
7 InvalidShaderLog,
8 CompileError(String),
9 LinkError(String),
10 GlutinCreation(glutin::CreationError),
11 GlutinContext(glutin::ContextError),
12 }
13
14 impl convert::From<glutin::CreationError> for Error {
15 fn from(err: glutin::CreationError) -> Error {
16 Error::GlutinCreation(err)
17 }
18 }
19
20 impl convert::From<glutin::ContextError> for Error {
21 fn from(err: glutin::ContextError) -> Error {
22 Error::GlutinContext(err)
23 }
24 }
25
26 impl convert::From<ffi::NulError> for Error {
27 fn from(_: ffi::NulError) -> Error {
28 Error::BadCString
29 }
30 }
31
32 impl convert::From<string::FromUtf8Error> for Error {
33 fn from(_: string::FromUtf8Error) -> Error {
34 Error::InvalidShaderLog
35 }
36 }
1 extern crate glutin;
2 mod gl {
3 extern crate gl;
4 pub use self::gl::types::*;
5 pub use self::gl::*;
6 }
7 mod errors;
8 pub use errors::Error;
9 use std::{ffi,mem,ptr};
10
11 //
12
13 pub struct Window {
14 events: glutin::EventsLoop,
15 gl_window: glutin::GlWindow,
16 }
17
18 impl Window {
19 pub fn create() -> Result<Window, Error> {
20 use glutin::GlContext;
21 let events = glutin::EventsLoop::new();
22 let window = glutin::WindowBuilder::new();
23 let context = glutin::ContextBuilder::new();
24 let gl_window = glutin::GlWindow::new(window, context, &events)?;
25
26 unsafe { gl_window.make_current() }?;
27
28 gl::load_with(|symbol| gl_window.get_proc_address(symbol) as *const _);
29
30 Ok(Window { events, gl_window })
31 }
32
33 pub fn run<F>(self, mut cb: F) -> Result<(), Error>
34 where F: FnMut(glutin::Event) -> glutin::ControlFlow
35 {
36 use glutin::GlContext;
37 let Window { mut events, gl_window } = self;
38 let mut result = Ok(());
39
40 events.run_forever(|ev| {
41 let r = cb(ev);
42
43 match gl_window.swap_buffers() {
44 Ok(()) => r,
45 Err(ctx) => {
46 result = Err(Error::GlutinContext(ctx));
47 glutin::ControlFlow::Break
48 }
49 }
50 });
51
52 result
53 }
54 }
55
56 pub struct Shader {
57 pub n: gl::GLuint,
58 }
59
60 impl Drop for Shader {
61 fn drop(&mut self) {
62 unsafe { gl::DeleteShader(self.n); }
63 }
64 }
65
66 #[derive(PartialEq, Eq, Debug, Copy, Clone)]
67 pub enum ShaderType {
68 Fragment,
69 Vertex,
70 }
71
72 impl ShaderType {
73 fn to_glenum(&self) -> gl::GLenum {
74 match *self {
75 ShaderType::Fragment => gl::FRAGMENT_SHADER,
76 ShaderType::Vertex => gl::VERTEX_SHADER,
77 }
78 }
79 }
80
81 impl Shader {
82 pub fn compile(ty: ShaderType, src: &str) -> Result<Shader, Error> {
83 let shader;
84 unsafe {
85 shader = gl::CreateShader(ty.to_glenum());
86 let c_str = ffi::CString::new(src.as_bytes())?;
87 gl::ShaderSource(shader, 1, &c_str.as_ptr(), ptr::null());
88 gl::CompileShader(shader);
89
90 let mut status = gl::FALSE as gl::GLint;
91 gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
92
93 if status != (gl::TRUE as gl::GLint) {
94 let mut len = 0;
95 gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
96 let mut buf = Vec::with_capacity(len as usize);
97 buf.set_len((len as usize) - 1);
98 gl::GetShaderInfoLog(
99 shader,
100 len,
101 ptr::null_mut(),
102 buf.as_mut_ptr() as *mut gl::GLchar
103 );
104 return Err(Error::CompileError(String::from_utf8(buf)?));
105 }
106 }
107 Ok(Shader { n: shader })
108 }
109 }
110
111
112 //
113
114 pub struct Program {
115 pub p: gl::GLuint,
116 pub shaders: Vec<Shader>,
117 }
118
119 impl Drop for Program {
120 fn drop(&mut self) {
121 self.shaders = vec![];
122 unsafe {
123 gl::DeleteProgram(self.p)
124 }
125 }
126 }
127
128 impl Program {
129 pub fn link(shaders: Vec<Shader>) -> Result<Program, Error> {
130 unsafe {
131 let program = gl::CreateProgram();
132 for s in shaders.iter() {
133 gl::AttachShader(program, s.n);
134 }
135 gl::LinkProgram(program);
136
137 let mut status = gl::FALSE as gl::GLint;
138 gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
139
140 // Fail on error
141 if status != (gl::TRUE as gl::GLint) {
142 let mut len: gl::GLint = 0;
143 gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
144 let mut buf = Vec::with_capacity(len as usize);
145 buf.set_len((len as usize) - 1);
146 gl::GetProgramInfoLog(
147 program,
148 len,
149 ptr::null_mut(),
150 buf.as_mut_ptr() as *mut gl::GLchar,
151 );
152 return Err(Error::LinkError(String::from_utf8(buf)?));
153 }
154
155 Ok(Program {
156 p: program,
157 shaders: shaders,
158 })
159 }
160 }
161
162 pub fn use_program(&self) {
163 unsafe { gl::UseProgram(self.p); }
164 }
165
166 pub fn bind_frag_data_location(&self, idx: u32, s: &str) -> Result<(), Error> {
167 unsafe {
168 gl::BindFragDataLocation(
169 self.p,
170 idx,
171 ffi::CString::new(s)?.as_ptr(),
172 );
173 }
174 Ok(())
175 }
176
177 pub fn get_attrib_location(&self, s: &str) -> Result<i32, Error> {
178 Ok(unsafe {
179 gl::GetAttribLocation(
180 self.p,
181 ffi::CString::new(s)?.as_ptr(),
182 )
183 })
184 }
185 }
186
187 //
188
189 pub struct VertexArray {
190 idx: u32,
191 }
192
193 impl Drop for VertexArray {
194 fn drop(&mut self) {
195 unsafe { gl::DeleteVertexArrays(1, &self.idx); }
196 }
197 }
198
199 pub struct VertexBuffer {
200 idx: u32,
201 data: VertexArray,
202 }
203
204 impl Drop for VertexBuffer {
205 fn drop(&mut self) {
206 unsafe { gl::DeleteBuffers(1, &self.idx); }
207 }
208 }
209
210 impl VertexArray {
211 pub fn new() -> VertexArray {
212 let mut idx = 0;
213 unsafe {
214 gl::GenVertexArrays(1, &mut idx);
215 gl::BindVertexArray(idx);
216 }
217
218 VertexArray { idx }
219 }
220
221 pub fn bind(&self) {
222 unsafe {
223 gl::BindVertexArray(self.idx);
224 }
225 }
226
227 pub fn unbind(&self) {
228 unsafe {
229 gl::BindVertexArray(0);
230 }
231 }
232 }
233
234 impl VertexBuffer {
235 pub fn new_array_buffer(
236 data: VertexArray,
237 vertex_data: &[gl::GLfloat],
238 ) -> VertexBuffer {
239 let mut idx = 0;
240 unsafe {
241 gl::GenBuffers(1, &mut idx);
242 gl::BindBuffer(gl::ARRAY_BUFFER, idx);
243 gl::BufferData(
244 gl::ARRAY_BUFFER,
245 (vertex_data.len() * mem::size_of::<gl::GLfloat>()) as gl::GLsizeiptr,
246 mem::transmute(&vertex_data[0]),
247 gl::STATIC_DRAW,
248 );
249 }
250
251 VertexBuffer { idx, data }
252 }
253
254 pub fn bind(&self) {
255 unsafe {
256 self.data.bind();
257 gl::BindBuffer(gl::ARRAY_BUFFER, self.idx);
258 }
259 }
260
261 pub fn unbind(&self) {
262 unsafe {
263 gl::BindBuffer(gl::ARRAY_BUFFER, 0);
264 self.data.unbind();
265 }
266 }
267 }