Skip to main content

ruckus/
buffers.rs

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    // UByte = gl::UBYTE as isize,
11    Short = gl::SHORT as isize,
12    // UShort = gl::USHORT as isize,
13    Int = gl::INT as isize,
14    // UInt = gl::UINT as isize,
15    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    // TODO :: Ideally we should have this vertex attribute layout
189    //         on a VAO, since its entire purpose is to store layout data for buffers... lol
190    //         Move this to VAO
191    pub layout: Vec<VertexAttribute>
192}
193
194// TODO :: Make this act like more like an actual buffer (have checks for overflow, ect)
195impl VertexBuffer {
196
197
198    /**
199     * Returns VertexBuffer with default quad verts put into an OpenGL VBO instead of a runtime array
200     */
201    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 uv_offset = 
223        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    /**
232     * Uses default Float Datatype
233    */
234    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    /**
251     * Uses default Float Datatype
252    */
253    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}