gdritter repos chenoska / d62dedf
Switching away from Panem + to specific 2D Vertex type Getty Ritter 6 years ago
5 changed file(s) with 375 addition(s) and 14 deletion(s). Collapse all Expand all
66 [dependencies]
77 gl = "0.6.0"
88 glutin = "*"
9 panem-nostrum-quotidianum = { git = "https://git.gdritter.com/panem-nostrum-quotidianum/" }
9 # panem-nostrum-quotidianum = { path = "../panem-nostrum-quotidianum/" }
10 imagefmt = "*"
1 pub struct Tile {
2 sprite: (u8, u8),
3 }
4
5 pub struct Spritesheet {
6 image: ::imagefmt::Image<u8>,
7 }
8
9 pub struct Board {
10 tiles: Vec<Tile>,
11 }
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 mod gl {
2 pub use gl::types::*;
3 pub use gl::*;
4 }
5 use glutin;
6 mod errors;
7 pub use self::errors::Error;
8 use std::{ffi,mem,ptr};
9
10 //
11
12 pub struct Window {
13 events: glutin::EventsLoop,
14 gl_window: glutin::GlWindow,
15 }
16
17 impl Window {
18 pub fn create() -> Result<Window, Error> {
19 use glutin::GlContext;
20 let events = glutin::EventsLoop::new();
21 let window = glutin::WindowBuilder::new();
22 let context = glutin::ContextBuilder::new();
23 let gl_window = glutin::GlWindow::new(window, context, &events)?;
24
25 unsafe { gl_window.make_current() }?;
26
27 gl::load_with(|symbol| gl_window.get_proc_address(symbol) as *const _);
28
29 Ok(Window { events, gl_window })
30 }
31
32 pub fn run<F>(self, mut cb: F) -> Result<(), Error>
33 where F: FnMut(glutin::Event) -> glutin::ControlFlow
34 {
35 use glutin::GlContext;
36 let Window { mut events, gl_window } = self;
37 let mut result = Ok(());
38
39 events.run_forever(|ev| {
40 let r = cb(ev);
41
42 match gl_window.swap_buffers() {
43 Ok(()) => r,
44 Err(ctx) => {
45 result = Err(Error::GlutinContext(ctx));
46 glutin::ControlFlow::Break
47 }
48 }
49 });
50
51 result
52 }
53 }
54
55 pub struct Shader {
56 pub n: gl::GLuint,
57 }
58
59 impl Drop for Shader {
60 fn drop(&mut self) {
61 unsafe { gl::DeleteShader(self.n); }
62 }
63 }
64
65 #[derive(PartialEq, Eq, Debug, Copy, Clone)]
66 pub enum ShaderType {
67 Fragment,
68 Vertex,
69 }
70
71 impl ShaderType {
72 fn to_glenum(&self) -> gl::GLenum {
73 match *self {
74 ShaderType::Fragment => gl::FRAGMENT_SHADER,
75 ShaderType::Vertex => gl::VERTEX_SHADER,
76 }
77 }
78 }
79
80 impl Shader {
81 pub fn compile(ty: ShaderType, src: &str) -> Result<Shader, Error> {
82 let shader;
83 unsafe {
84 shader = gl::CreateShader(ty.to_glenum());
85 let c_str = ffi::CString::new(src.as_bytes())?;
86 gl::ShaderSource(shader, 1, &c_str.as_ptr(), ptr::null());
87 gl::CompileShader(shader);
88
89 let mut status = gl::FALSE as gl::GLint;
90 gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
91
92 if status != (gl::TRUE as gl::GLint) {
93 let mut len = 0;
94 gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
95 let mut buf = Vec::with_capacity(len as usize);
96 buf.set_len((len as usize) - 1);
97 gl::GetShaderInfoLog(
98 shader,
99 len,
100 ptr::null_mut(),
101 buf.as_mut_ptr() as *mut gl::GLchar
102 );
103 return Err(Error::CompileError(String::from_utf8(buf)?));
104 }
105 }
106 Ok(Shader { n: shader })
107 }
108 }
109
110
111 //
112
113 pub struct Program {
114 pub p: gl::GLuint,
115 pub shaders: Vec<Shader>,
116 }
117
118 impl Drop for Program {
119 fn drop(&mut self) {
120 self.shaders = vec![];
121 unsafe {
122 gl::DeleteProgram(self.p)
123 }
124 }
125 }
126
127 impl Program {
128 pub fn link(shaders: Vec<Shader>) -> Result<Program, Error> {
129 unsafe {
130 let program = gl::CreateProgram();
131 for s in shaders.iter() {
132 gl::AttachShader(program, s.n);
133 }
134 gl::LinkProgram(program);
135
136 let mut status = gl::FALSE as gl::GLint;
137 gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
138
139 // Fail on error
140 if status != (gl::TRUE as gl::GLint) {
141 let mut len: gl::GLint = 0;
142 gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
143 let mut buf = Vec::with_capacity(len as usize);
144 buf.set_len((len as usize) - 1);
145 gl::GetProgramInfoLog(
146 program,
147 len,
148 ptr::null_mut(),
149 buf.as_mut_ptr() as *mut gl::GLchar,
150 );
151 return Err(Error::LinkError(String::from_utf8(buf)?));
152 }
153
154 Ok(Program {
155 p: program,
156 shaders: shaders,
157 })
158 }
159 }
160
161 pub fn use_program(&self) {
162 unsafe { gl::UseProgram(self.p); }
163 }
164
165 pub fn bind_frag_data_location(&self, idx: u32, s: &str) -> Result<(), Error> {
166 unsafe {
167 gl::BindFragDataLocation(
168 self.p,
169 idx,
170 ffi::CString::new(s)?.as_ptr(),
171 );
172 }
173 Ok(())
174 }
175
176 pub fn get_attrib_location(&self, s: &str) -> Result<i32, Error> {
177 Ok(unsafe {
178 gl::GetAttribLocation(
179 self.p,
180 ffi::CString::new(s)?.as_ptr(),
181 )
182 })
183 }
184 }
185
186 //
187
188 pub struct VertexArray {
189 idx: u32,
190 }
191
192 impl Drop for VertexArray {
193 fn drop(&mut self) {
194 unsafe { gl::DeleteVertexArrays(1, &self.idx); }
195 }
196 }
197
198 pub struct VertexBuffer {
199 idx: u32,
200 data: VertexArray,
201 }
202
203 impl Drop for VertexBuffer {
204 fn drop(&mut self) {
205 unsafe { gl::DeleteBuffers(1, &self.idx); }
206 }
207 }
208
209 impl VertexArray {
210 pub fn new() -> VertexArray {
211 let mut idx = 0;
212 unsafe {
213 gl::GenVertexArrays(1, &mut idx);
214 gl::BindVertexArray(idx);
215 }
216
217 VertexArray { idx }
218 }
219
220 pub fn bind(&self) {
221 unsafe {
222 gl::BindVertexArray(self.idx);
223 }
224 }
225
226 pub fn unbind(&self) {
227 unsafe {
228 gl::BindVertexArray(0);
229 }
230 }
231 }
232
233 impl VertexBuffer {
234 pub fn new_array_buffer<Vtx>(
235 data: VertexArray,
236 vertex_data: &[Vtx],
237 ) -> VertexBuffer {
238 let mut idx = 0;
239 unsafe {
240 gl::GenBuffers(1, &mut idx);
241 gl::BindBuffer(gl::ARRAY_BUFFER, idx);
242 gl::BufferData(
243 gl::ARRAY_BUFFER,
244 (vertex_data.len() * mem::size_of::<Vtx>()) as gl::GLsizeiptr,
245 mem::transmute(&vertex_data[0]),
246 gl::STATIC_DRAW,
247 );
248 }
249
250 VertexBuffer { idx, data }
251 }
252
253 pub fn bind(&self) {
254 unsafe {
255 self.data.bind();
256 gl::BindBuffer(gl::ARRAY_BUFFER, self.idx);
257 }
258 }
259
260 pub fn unbind(&self) {
261 unsafe {
262 gl::BindBuffer(gl::ARRAY_BUFFER, 0);
263 self.data.unbind();
264 }
265 }
266 }
1 mod pan {
2 extern crate panem_nostrum_quotidianum;
3 pub use self::panem_nostrum_quotidianum::*;
4 }
1 // mod pan {
2 // extern crate panem_nostrum_quotidianum;
3 // pub use self::panem_nostrum_quotidianum::*;
4 // }
55 mod gl {
66 extern crate gl;
77 pub use self::gl::types::*;
88 pub use self::gl::*;
99 }
1010 extern crate glutin;
11 use std::ptr;
11 extern crate imagefmt;
12 use std::{mem,ptr};
13 use std::os::raw::c_void;
1214
13 static VERTEX_DATA: [gl::GLfloat; 6] = [0.0, 0.5, 0.5, -0.5, -0.5, -0.5];
15 mod board;
16 mod graphics;
17 mod pan {
18 pub use graphics::*;
19 }
1420
21 struct Vertex {
22 x: gl::GLfloat,
23 y: gl::GLfloat,
24 u: gl::GLfloat,
25 v: gl::GLfloat,
26 }
27
28 impl Vertex {
29 fn new(
30 x: gl::GLfloat,
31 y: gl::GLfloat,
32 u: gl::GLfloat,
33 v: gl::GLfloat,
34 ) -> Vertex {
35 Vertex { x, y, u, v }
36 }
37 }
38
39 static TILE_DATA: [Vertex; 4] = [
40 Vertex { x: -0.5, y: -0.5, u: 0.0, v: 0.0 },
41 Vertex { x: 0.5, y: -0.5, u: 1.0, v: 0.0 },
42 Vertex { x: 0.5, y: 0.5, u: 1.0, v: 1.0 },
43 Vertex { x: -0.5, y: 0.5, u: 0.0, v: 1.0 },
44 ];
45
46 static VERTEX_DATA: [Vertex; 3] = [
47 Vertex { x: 0.0, y: 0.5, u: 0.0, v: 0.0 },
48 Vertex { x: 0.5, y: -0.5, u: 0.0, v: 0.0 },
49 Vertex { x: -0.5, y: -0.5, u: 0.0, v: 0.0 },
50 ];
1551
1652 // Shader sources
1753 static VS_SRC: &'static str = "
1854 #version 150
19 in vec3 position;
55 in vec2 position;
56 in vec2 uv;
2057 void main() {
21 gl_Position = vec4(position, 1.0);
58 gl_Position = vec4(position.x, position.y, 0.5, 1.0);
2259 }";
2360
2461 static FS_SRC: &'static str = "
3774
3875 let vbo = pan::VertexBuffer::new_array_buffer(
3976 pan::VertexArray::new(),
40 &VERTEX_DATA,
77 &TILE_DATA,
4178 );
4279
4380 program.use_program();
4481 program.bind_frag_data_location(0, "out_color")?;
4582 let pos_attr = program.get_attrib_location("position")?;
83 let uv_attr = program.get_attrib_location("uv")?;
4684
4785 unsafe {
4886 gl::EnableVertexAttribArray(pos_attr as gl::GLuint);
4987 gl::VertexAttribPointer(
5088 pos_attr as gl::GLuint,
51 3,
89 2,
5290 gl::FLOAT,
5391 gl::FALSE as gl::GLboolean,
54 0,
92 4 * mem::size_of::<gl::GLfloat>() as i32,
5593 ptr::null(),
94 );
95 let off = ptr::null::<u8>().offset((mem::size_of::<gl::GLfloat>() * 2) as isize);
96 gl::EnableVertexAttribArray(uv_attr as gl::GLuint);
97 gl::VertexAttribPointer(
98 uv_attr as gl::GLuint,
99 2,
100 gl::FLOAT,
101 gl::FALSE as gl::GLboolean,
102 4 * mem::size_of::<gl::GLfloat>() as i32,
103 off as *const c_void,
56104 );
57105 }
58106
61109 window.run(|event| {
62110 use glutin::{ControlFlow, Event, WindowEvent, VirtualKeyCode};
63111
64 println!("{:?}", event);
65112 match event {
66113 Event::WindowEvent { event: WindowEvent::Closed, .. } =>
67114 return ControlFlow::Break,
87134
88135 vbo.bind();
89136
90 gl::DrawArrays(gl::TRIANGLES, 0, 3);
137 gl::DrawArrays(gl::TRIANGLES, 0, 4);
91138 }
92139
93140 ControlFlow::Continue