reverie_engine_opengl/
vao.rs

1//! Vertex Array Object
2pub mod buffer;
3pub mod color_vao;
4pub mod config;
5pub mod renderer;
6pub mod texture_vao;
7pub mod vertex;
8
9use std::mem;
10use std::os::raw::c_void;
11
12use crate::gl;
13use crate::gl::types::{GLenum, GLfloat, GLint, GLsizei, GLsizeiptr};
14use crate::gl::Gl;
15use crate::shader::UniformVariables;
16
17pub use {
18    buffer::VaoBuffer,
19    color_vao::VaoBuilder3DGeometryOutline,
20    config::{VaoConfig, VaoConfigBuilder},
21    renderer::{
22        Color3DRenderer, Color3DRenderingInfo, Phong3DRenderer, Phong3DRenderingInfo,
23        PhongRenderingInfo, Renderer,
24    },
25    texture_vao::builder::{CuboidTextures, VaoBuilder3DGeometry},
26    vertex::{VertexType, VertexWithColor, VertexWithNormUv},
27};
28
29/// OpenGLのVertex Array ObjectとVertex Buffer Objectに対応する構造体
30#[derive(Debug)]
31pub struct Vao<'a> {
32    gl: Gl,
33    vao: u32,
34    vbo: u32,
35    vertex_num: i32,
36    config: &'a VaoConfig,
37}
38
39impl<'a> Vao<'a> {
40    #[allow(clippy::too_many_arguments)]
41    /// ## Safety
42    ///
43    /// `data` が有効なポインタであること
44    unsafe fn new(
45        gl: Gl,
46        size: GLsizeiptr,
47        data: *const c_void,
48        usage: GLenum,
49        num_attributes: usize,
50        attribute_types: &'static [GLenum],
51        attribute_sizes: &'static [GLint],
52        stride: GLsizei,
53        vertex_num: i32,
54        config: &'a VaoConfig,
55    ) -> Self {
56        debug_assert_eq!(num_attributes, attribute_types.len());
57        debug_assert_eq!(num_attributes, attribute_sizes.len());
58
59        let mut vao = 0;
60        let mut vbo = 0;
61
62        unsafe {
63            // create vertex array object and vertex buffer object
64            gl.GenVertexArrays(1, &mut vao);
65            gl.GenBuffers(1, &mut vbo);
66
67            // bind buffer
68            gl.BindVertexArray(vao);
69            gl.BindBuffer(gl::ARRAY_BUFFER, vbo);
70            gl.BufferData(gl::ARRAY_BUFFER, size, data, usage);
71
72            let mut offset = 0;
73            for i in 0..num_attributes {
74                gl.EnableVertexAttribArray(i as u32);
75                gl.VertexAttribPointer(
76                    i as u32,
77                    attribute_sizes[i],
78                    attribute_types[i],
79                    gl::FALSE,
80                    stride,
81                    (offset * mem::size_of::<GLfloat>()) as *const c_void,
82                );
83                offset += attribute_sizes[i] as usize;
84            }
85
86            // unbind
87            gl.BindBuffer(gl::ARRAY_BUFFER, 0);
88            gl.BindVertexArray(0);
89        }
90
91        Vao {
92            gl,
93            vao,
94            vbo,
95            vertex_num,
96            config,
97        }
98    }
99
100    fn draw(&self, _uniforms: &UniformVariables, draw_mode: GLenum) {
101        unsafe {
102            if self.config.depth_test {
103                self.gl.Enable(gl::DEPTH_TEST);
104            } else {
105                self.gl.Disable(gl::DEPTH_TEST);
106            }
107
108            if self.config.blend {
109                self.gl.Enable(gl::BLEND);
110                self.gl.BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
111            } else {
112                self.gl.Disable(gl::BLEND);
113            }
114
115            if self.config.wireframe {
116                self.gl.PolygonMode(gl::FRONT_AND_BACK, gl::LINE);
117            } else {
118                self.gl.PolygonMode(gl::FRONT_AND_BACK, gl::FILL);
119            }
120
121            if self.config.culling {
122                self.gl.Enable(gl::CULL_FACE);
123            } else {
124                self.gl.Disable(gl::CULL_FACE);
125            }
126
127            self.gl.BindVertexArray(self.vao);
128            self.gl.DrawArrays(draw_mode, 0, self.vertex_num);
129            self.gl.BindVertexArray(0);
130            self.gl.BindTexture(gl::TEXTURE_2D, 0);
131        }
132    }
133
134    /// ポリゴンを描画する
135    fn draw_triangles(&self, uniforms: &UniformVariables) {
136        self.draw(uniforms, gl::TRIANGLES);
137    }
138}
139
140impl<'a> Drop for Vao<'a> {
141    fn drop(&mut self) {
142        unsafe {
143            if self.vbo > 0 {
144                self.gl.DeleteBuffers(1, &self.vbo as _);
145            }
146            if self.vao > 0 {
147                self.gl.DeleteVertexArrays(1, &self.vao as _);
148            }
149        }
150    }
151}