1use crate::vertex::Vertex2D;
2use crate::opengl::*;
3use crate::graphics;
4use crate::sys::Quad;
5use std::mem;
6
7#[derive(Debug, Copy, Clone)]
8pub enum DataType {
9 Byte = gl::BYTE as isize,
10 Short = gl::SHORT as isize,
12 Int = gl::INT as isize,
14 Float = gl::FLOAT as isize
16}
17
18#[derive(Debug, Copy, Clone)]
19pub enum DrawPrimitive {
20 Points = gl::POINTS as isize,
21 Lines = gl::LINES as isize,
22 LineLoop = gl::LINE_LOOP as isize,
23 LineStrip = gl::LINE_STRIP as isize,
24 Triangles = gl::TRIANGLES as isize,
25 TriangleStrip = gl::TRIANGLE_STRIP as isize,
26 Quads = gl::QUADS as isize,
27}
28
29#[derive(Debug, Copy, Clone)]
30pub enum DrawUsage {
31 Static = gl::STATIC_DRAW as isize,
32 Dynamic = gl::DYNAMIC_DRAW as isize,
33 Stream = gl::STREAM_DRAW as isize
34}
35
36#[derive(Debug, Copy, Clone)]
37pub enum BufferAccess {
38 ReadOnly = gl::READ_ONLY as isize,
39 WriteOnly = gl::WRITE_ONLY as isize,
40 ReadWrite = gl::READ_WRITE as isize
41}
42
43#[derive(Debug, Copy, Clone)]
44pub struct VertexAttribute {
45 pub buffer_index: u32,
46 pub elem_count: u32,
47 pub is_instanced: bool,
48 pub dtype: DataType,
49 pub offset: usize,
50 pub stride: usize
51}
52
53impl Default for VertexAttribute {
54 fn default() -> Self {
55 VertexAttribute {
56 buffer_index: 0, elem_count: 0, is_instanced: false,
57 dtype: DataType::Float, offset: 0, stride: 0
58 }
59 }
60}
61
62pub struct ElementBuffer {
63 id: u32,
64 pub count: u32
65}
66
67impl ElementBuffer {
68 pub fn new(indicies: &[u32]) -> Self {
69 ElementBuffer::new_with_draw(indicies, DrawUsage::Static)
70 }
71
72 pub fn new_with_draw(indicies: &[u32], usage: DrawUsage) -> Self {
73 let eb = ElementBuffer {
74 id: gl_gen_buffer(),
75 count: indicies.len() as u32
76 };
77 eb.apply();
78
79 unsafe {
80 opengl().BufferData(gl::ELEMENT_ARRAY_BUFFER, (eb.count * mem::size_of::<u32>() as u32) as isize, indicies.as_ptr() as *const _, usage as u32)
81 }
82 eb
83 }
84
85 pub fn new_quad(count: u32) -> Self {
86 let mut indicies: Vec<u32> = vec![0, count];
87 let itr_range = 0..(indicies.len() / 6);
88
89 for i in itr_range {
90 let quad_index = i * 6;
91 let vert_index = (i * 4) as u32;
92
93 indicies[quad_index + 0] = vert_index + 0;
94 indicies[quad_index + 1] = vert_index + 1;
95 indicies[quad_index + 2] = vert_index + 2;
96
97 indicies[quad_index + 3] = vert_index + 3;
98 indicies[quad_index + 4] = vert_index + 4;
99 indicies[quad_index + 5] = vert_index + 5;
100 }
101
102 ElementBuffer::new(indicies.as_slice())
103 }
104
105 pub fn apply(&self) {
106 unsafe {
107 opengl().BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.id)
108 }
109 }
110
111 pub fn unbind(&self) {
112 gl_unbind_element_buffer();
113 }
114}
115
116pub struct RenderBuffer {
117 id: u32
118}
119
120impl RenderBuffer {
121 pub fn new(width: i32, height: i32) -> Self {
122 let id = gl_gen_buffer();
123 let rb = RenderBuffer { id };
124 rb.apply();
125
126 unsafe {
127 opengl().RenderbufferStorage(gl::RENDERBUFFER, gl::DEPTH24_STENCIL8, width, height);
128 };
129 rb
130 }
131
132 pub fn apply(&self) {
133 unsafe { opengl().BindBuffer(gl::RENDERBUFFER, self.id) };
134 }
135}
136
137pub struct FrameBuffer {
138 id: u32
139}
140
141impl FrameBuffer {
142 pub fn new() -> Self {
143 unsafe {
144 let mut id = mem::zeroed();
145 opengl().GenFramebuffers(1, &mut id);
146 let fb = FrameBuffer { id };
147 FrameBuffer::apply(&fb);
148 return fb;
149 }
150 }
151
152 pub fn apply(fb: &FrameBuffer) {
153 unsafe {
154 opengl().BindFramebuffer(gl::FRAMEBUFFER, fb.id)
155 };
156 }
157
158 pub fn unbind() {
159 unsafe {
160 opengl().BindFramebuffer(gl::FRAMEBUFFER, 0)
161 };
162 }
163
164 pub fn attach_render_buffer(&self, rb: &RenderBuffer) {
165 FrameBuffer::apply(self);
166 unsafe {
167 opengl().FramebufferRenderbuffer(gl::FRAMEBUFFER, gl::DEPTH_STENCIL_ATTACHMENT, gl::RENDERBUFFER, rb.id)
168 };
169 }
170
171 pub fn attach_texture(&self, texture: &graphics::Texture) {
172 self.attach_texture_n(texture, 0);
173 }
174
175 pub fn attach_texture_n(&self, texture: &graphics::Texture, attachment_num: u32) {
176 FrameBuffer::apply(self);
177 unsafe {
178 opengl().FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment_num, gl::TEXTURE_2D, texture.id(), 0);
179 }
180 }
181}
182
183pub struct VertexBuffer {
184 id: u32,
185 size_bytes: usize,
186 vert_count: u32,
187 pub draw_prim: DrawPrimitive,
188 pub layout: Vec<VertexAttribute>
192}
193
194impl VertexBuffer {
196
197
198 pub fn new_as_quad(useage: DrawUsage) -> Self {
202 Self::new_with_prim(&Quad::default_verts(), useage, DrawPrimitive::TriangleStrip)
203 }
204
205 pub fn zeroed<T>(count: u32, usage: DrawUsage, draw_prim: DrawPrimitive) -> Self {
206 let type_size = mem::size_of::<T>() as u32;
207 let id = gl_gen_buffer();
208 let size_bytes = (type_size * count) as isize;
209
210 gl_bind_array_buffer(id);
211
212 unsafe { opengl().BufferData(gl::ARRAY_BUFFER, size_bytes, 0 as *const _, usage as u32) };
213
214 VertexBuffer {
215 id, size_bytes: size_bytes as usize, vert_count: count, draw_prim, layout: Self::vertex2d_attributes()
216 }
217 }
218
219 pub fn vertex2d_attributes() -> Vec<VertexAttribute> {
220
221 let vert_size = std::mem::size_of::<Vertex2D>();
222 let mut attr = vec![VertexAttribute::default(); 3];
224 attr[0] = VertexAttribute { buffer_index: 0, elem_count: 3, dtype: DataType::Float, stride: vert_size, offset: 0, is_instanced: false };
225 attr[1] = VertexAttribute { buffer_index: 1, elem_count: 2, dtype: DataType::Float, stride: vert_size, offset: crate::memory_offset!(Vertex2D, text_coord), is_instanced: false };
226 attr[2] = VertexAttribute { buffer_index: 2, elem_count: 4, dtype: DataType::Float, stride: vert_size, offset: crate::memory_offset!(Vertex2D, color), is_instanced: false };
227 attr
228
229 }
230
231 pub fn new<T>(verts: &[T], usage: DrawUsage) -> Self {
235 VertexBuffer::new_with_prim(verts, usage, DrawPrimitive::Triangles)
236 }
237
238 pub fn new_with_prim<T>(verts: &[T], usage: DrawUsage, draw_prim: DrawPrimitive) -> Self {
239 let id = gl_gen_buffer();
240 let size_bytes = mem::size_of::<T>() * verts.len();
241
242 let mut vb = VertexBuffer {
243 id, size_bytes, draw_prim, vert_count: verts.len() as u32, layout: Self::vertex2d_attributes()
244 };
245 vb.alloc(verts, usage);
246
247 vb
248 }
249
250 pub fn alloc<T>(&mut self, verts: &[T], usage: DrawUsage) {
254 self.apply();
255 self.size_bytes = verts.len() * mem::size_of::<T>();
256 self.vert_count = verts.len() as u32;
257
258 unsafe {
259 opengl().BufferData(gl::ARRAY_BUFFER, self.size_bytes as isize, verts.as_ptr() as *const _, usage as u32)
260 };
261 }
262
263 pub fn write<T>(&self, verts: &[T], offset: isize) {
264 self.apply();
265 unsafe {
266 opengl().BufferSubData(gl::ARRAY_BUFFER, offset, (mem::size_of::<T>() * verts.len()) as isize, verts.as_ptr() as *const _)
267 }
268 }
269
270 pub fn copy_data(&self, other: &VertexBuffer, read_offset: isize, write_offset: isize, size: isize) {
271 let gl = opengl();
272 unsafe {
273 gl.BindBuffer(gl::COPY_READ_BUFFER, other.id);
274 gl.BindBuffer(gl::COPY_WRITE_BUFFER, self.id);
275 gl.CopyBufferSubData(gl::COPY_READ_BUFFER, gl::COPY_WRITE_BUFFER, read_offset, write_offset, size);
276 }
277 }
278
279 pub fn vert_count(&self) -> u32 { self.vert_count }
280
281 pub unsafe fn map_buffer(&self, access: BufferAccess) -> *mut std::ffi::c_void {
282 self.apply();
283 opengl().MapBuffer(gl::ARRAY_BUFFER, access as u32)
284 }
285
286 pub unsafe fn unmap(&self) {
287 self.apply();
288 opengl().UnmapBuffer(gl::ARRAY_BUFFER);
289 }
290
291 pub fn apply(&self) {
292 gl_bind_array_buffer(self.id)
293 }
294
295 pub fn unbind(&self) {
296 gl_bind_array_buffer(0);
297 }
298
299}
300
301pub struct VAO {
302 id: u32
303}
304
305impl VAO {
306
307 pub fn new() -> Self {
308 VAO {
309 id: gl_gen_vertex_array()
310 }
311 }
312
313 pub fn set_buffer_layout(&self, buffer: &VertexBuffer) {
314 self.apply();
315 buffer.apply();
316
317 let gl = opengl();
318 for attrib in buffer.layout.iter() {
319 unsafe {
320 gl.VertexAttribPointer(
321 attrib.buffer_index, attrib.elem_count as i32,
322 attrib.dtype as u32, gl::FALSE, attrib.stride as i32,
323 attrib.offset as *const _
324 );
325 gl.EnableVertexAttribArray(attrib.buffer_index);
326 gl.VertexAttribDivisor(attrib.buffer_index, if attrib.is_instanced { 1 } else { 0 });
327 }
328 }
329 buffer.unbind();
330 self.unbind();
331 }
332
333 pub fn apply(&self) {
334 gl_bind_vertex_array(self.id);
335 }
336
337 pub fn unbind(&self) {
338 gl_bind_vertex_array(0);
339 }
340}
341
342impl Drop for ElementBuffer {
343
344 fn drop(&mut self) {
345 gl_delete_buffer(self.id);
346 }
347}
348
349impl Drop for RenderBuffer {
350
351 fn drop(&mut self) {
352 unsafe { opengl().DeleteRenderbuffers(1, &self.id) }
353 }
354}
355
356impl Drop for FrameBuffer {
357
358 fn drop(&mut self) {
359 unsafe { opengl().DeleteFramebuffers(1, &self.id) }
360 }
361}
362
363impl Drop for VertexBuffer {
364
365 fn drop(&mut self) {
366 gl_delete_buffer(self.id)
367 }
368}
369
370impl Drop for VAO {
371
372 fn drop(&mut self) {
373 gl_delete_buffer(self.id)
374 }
375}
376
377pub fn set_vertex_layout(buffer: &VertexBuffer, attribs: &[VertexAttribute]) {
378let gl = opengl();
379 buffer.apply();
380
381
382}