Antkeeper  0.0.1
vertex-array.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
22 #include <glad/gl.h>
23 #include <stdexcept>
24 
25 namespace {
26 
27  // 0 = unscaled, 1 = normalized, 2 = scaled
28  static constexpr std::uint8_t format_scale_lut[] =
29  {
30  0, // undefined
31  1, // r4g4_unorm_pack8
32  1, // r4g4b4a4_unorm_pack16
33  1, // b4g4r4a4_unorm_pack16
34  1, // r5g6b5_unorm_pack16
35  1, // b5g6r5_unorm_pack16
36  1, // r5g5b5a1_unorm_pack16
37  1, // b5g5r5a1_unorm_pack16
38  1, // a1r5g5b5_unorm_pack16
39  1, // r8_unorm
40  1, // r8_snorm
41  2, // r8_uscaled
42  2, // r8_sscaled
43  0, // r8_uint
44  0, // r8_sint
45  0, // r8_srgb
46  1, // r8g8_unorm
47  1, // r8g8_snorm
48  2, // r8g8_uscaled
49  2, // r8g8_sscaled
50  0, // r8g8_uint
51  0, // r8g8_sint
52  0, // r8g8_srgb
53  1, // r8g8b8_unorm
54  1, // r8g8b8_snorm
55  2, // r8g8b8_uscaled
56  2, // r8g8b8_sscaled
57  0, // r8g8b8_uint
58  0, // r8g8b8_sint
59  0, // r8g8b8_srgb
60  1, // b8g8r8_unorm
61  1, // b8g8r8_snorm
62  2, // b8g8r8_uscaled
63  2, // b8g8r8_sscaled
64  0, // b8g8r8_uint
65  0, // b8g8r8_sint
66  0, // b8g8r8_srgb
67  1, // r8g8b8a8_unorm
68  1, // r8g8b8a8_snorm
69  2, // r8g8b8a8_uscaled
70  2, // r8g8b8a8_sscaled
71  0, // r8g8b8a8_uint
72  0, // r8g8b8a8_sint
73  0, // r8g8b8a8_srgb
74  1, // b8g8r8a8_unorm
75  1, // b8g8r8a8_snorm
76  2, // b8g8r8a8_uscaled
77  2, // b8g8r8a8_sscaled
78  0, // b8g8r8a8_uint
79  0, // b8g8r8a8_sint
80  0, // b8g8r8a8_srgb
81  1, // a8b8g8r8_unorm_pack32
82  1, // a8b8g8r8_snorm_pack32
83  2, // a8b8g8r8_uscaled_pack32
84  2, // a8b8g8r8_sscaled_pack32
85  0, // a8b8g8r8_uint_pack32
86  0, // a8b8g8r8_sint_pack32
87  0, // a8b8g8r8_srgb_pack32
88  1, // a2r10g10b10_unorm_pack32
89  1, // a2r10g10b10_snorm_pack32
90  2, // a2r10g10b10_uscaled_pack32
91  2, // a2r10g10b10_sscaled_pack32
92  0, // a2r10g10b10_uint_pack32
93  0, // a2r10g10b10_sint_pack32
94  1, // a2b10g10r10_unorm_pack32
95  1, // a2b10g10r10_snorm_pack32
96  2, // a2b10g10r10_uscaled_pack32
97  2, // a2b10g10r10_sscaled_pack32
98  0, // a2b10g10r10_uint_pack32
99  0, // a2b10g10r10_sint_pack32
100  1, // r16_unorm
101  1, // r16_snorm
102  2, // r16_uscaled
103  2, // r16_sscaled
104  0, // r16_uint
105  0, // r16_sint
106  0, // r16_sfloat
107  1, // r16g16_unorm
108  1, // r16g16_snorm
109  2, // r16g16_uscaled
110  2, // r16g16_sscaled
111  0, // r16g16_uint
112  0, // r16g16_sint
113  0, // r16g16_sfloat
114  1, // r16g16b16_unorm
115  1, // r16g16b16_snorm
116  2, // r16g16b16_uscaled
117  2, // r16g16b16_sscaled
118  0, // r16g16b16_uint
119  0, // r16g16b16_sint
120  0, // r16g16b16_sfloat
121  1, // r16g16b16a16_unorm
122  1, // r16g16b16a16_snorm
123  2, // r16g16b16a16_uscaled
124  2, // r16g16b16a16_sscaled
125  0, // r16g16b16a16_uint
126  0, // r16g16b16a16_sint
127  0, // r16g16b16a16_sfloat
128  0, // r32_uint
129  0, // r32_sint
130  0, // r32_sfloat
131  0, // r32g32_uint
132  0, // r32g32_sint
133  0, // r32g32_sfloat
134  0, // r32g32b32_uint
135  0, // r32g32b32_sint
136  0, // r32g32b32_sfloat
137  0, // r32g32b32a32_uint
138  0, // r32g32b32a32_sint
139  0, // r32g32b32a32_sfloat
140  0, // r64_uint
141  0, // r64_sint
142  0, // r64_sfloat
143  0, // r64g64_uint
144  0, // r64g64_sint
145  0, // r64g64_sfloat
146  0, // r64g64b64_uint
147  0, // r64g64b64_sint
148  0, // r64g64b64_sfloat
149  0, // r64g64b64a64_uint
150  0, // r64g64b64a64_sint
151  0, // r64g64b64a64_sfloat
152  0, // b10g11r11_ufloat_pack32
153  0, // e5b9g9r9_ufloat_pack32
154  1, // d16_unorm
155  1, // x8_d24_unorm_pack32
156  0, // d32_sfloat
157  0, // s8_uint
158  1, // d16_unorm_s8_uint
159  1, // d24_unorm_s8_uint
160  0, // d32_sfloat_s8_uint
161  1, // bc1_rgb_unorm_block,
162  0, // bc1_rgb_srgb_block,
163  1, // bc1_rgba_unorm_block,
164  0, // bc1_rgba_srgb_block,
165  1, // bc2_unorm_block,
166  0, // bc2_srgb_block,
167  1, // bc3_unorm_block,
168  0, // bc3_srgb_block,
169  1, // bc4_unorm_block,
170  1, // bc4_snorm_block,
171  1, // bc5_unorm_block,
172  1, // bc5_snorm_block,
173  2, // bc6h_ufloat_block,
174  2, // bc6h_sfloat_block,
175  1, // bc7_unorm_block,
176  0, // bc7_srgb_block,
177  1, // etc2_r8g8b8_unorm_block,
178  0, // etc2_r8g8b8_srgb_block,
179  1, // etc2_r8g8b8a1_unorm_block,
180  0, // etc2_r8g8b8a1_srgb_block,
181  1, // etc2_r8g8b8a8_unorm_block,
182  0, // etc2_r8g8b8a8_srgb_block,
183  1, // eac_r11_unorm_block,
184  1, // eac_r11_snorm_block,
185  1, // eac_r11g11_unorm_block,
186  1, // eac_r11g11_snorm_block,
187  1, // astc_4x4_unorm_block,
188  0, // astc_4x4_srgb_block,
189  1, // astc_5x4_unorm_block,
190  0, // astc_5x4_srgb_block,
191  1, // astc_5x5_unorm_block,
192  0, // astc_5x5_srgb_block,
193  1, // astc_6x5_unorm_block,
194  0, // astc_6x5_srgb_block,
195  1, // astc_6x6_unorm_block,
196  0, // astc_6x6_srgb_block,
197  1, // astc_8x5_unorm_block,
198  0, // astc_8x5_srgb_block,
199  1, // astc_8x6_unorm_block,
200  0, // astc_8x6_srgb_block,
201  1, // astc_8x8_unorm_block,
202  0, // astc_8x8_srgb_block,
203  1, // astc_10x5_unorm_block,
204  0, // astc_10x5_srgb_block,
205  1, // astc_10x6_unorm_block,
206  0, // astc_10x6_srgb_block,
207  1, // astc_10x8_unorm_block,
208  0, // astc_10x8_srgb_block,
209  1, // astc_10x10_unorm_block,
210  0, // astc_10x10_srgb_block,
211  1, // astc_12x10_unorm_block,
212  0, // astc_12x10_srgb_block,
213  1, // astc_12x12_unorm_block,
214  0, // astc_12x12_srgb_block
215  };
216 }
217 
218 namespace gl {
219 
220 vertex_array::vertex_array(std::span<const vertex_input_attribute> attributes)
221 {
222  m_attributes.assign(attributes.begin(), attributes.end());
223 
224  glCreateVertexArrays(1, &m_gl_named_array);
225 
226  for (const auto& attribute: m_attributes)
227  {
228  // Enable attribute
229  glEnableVertexArrayAttrib(m_gl_named_array, static_cast<GLuint>(attribute.location));
230 
231  // Set attribute vertex binding index
232  glVertexArrayAttribBinding
233  (
234  m_gl_named_array,
235  static_cast<GLuint>(attribute.location),
236  static_cast<GLuint>(attribute.binding)
237  );
238 
239  const auto format_index = std::to_underlying(attribute.format);
240  const auto gl_base_format = gl_format_lut[format_index][1];
241  const auto gl_type = gl_format_lut[format_index][2];
242  const auto format_scale = format_scale_lut[format_index];
243 
244  // Determine number of values per vertex
245  GLint gl_size;
246  switch (gl_base_format)
247  {
248  case GL_RED:
249  case GL_RED_INTEGER:
250  case GL_DEPTH_COMPONENT:
251  case GL_STENCIL_INDEX:
252  gl_size = 1;
253  break;
254 
255  case GL_RG:
256  case GL_RG_INTEGER:
257  case GL_DEPTH_STENCIL:
258  gl_size = 2;
259  break;
260 
261  case GL_BGR:
262  case GL_BGR_INTEGER:
263  case GL_RGB:
264  case GL_RGB_INTEGER:
265  gl_size = 3;
266  break;
267 
268  case GL_BGRA:
269  case GL_BGRA_INTEGER:
270  case GL_RGBA:
271  case GL_RGBA_INTEGER:
272  gl_size = 4;
273  break;
274 
275  default:
276  gl_size = 0;
277  break;
278  }
279 
280  if (gl_size == 0 || gl_type == 0)
281  {
282  throw std::invalid_argument("Vertex input attribute has unsupported format.");
283  }
284 
285  if (format_scale > 0 || gl_type == GL_FLOAT || gl_type == GL_HALF_FLOAT)
286  {
287  glVertexArrayAttribFormat
288  (
289  m_gl_named_array,
290  static_cast<GLuint>(attribute.location),
291  gl_size,
292  gl_type,
293  (format_scale == 1),
294  static_cast<GLuint>(attribute.offset)
295  );
296  }
297  else if (gl_type == GL_DOUBLE)
298  {
299  glVertexArrayAttribLFormat
300  (
301  m_gl_named_array,
302  static_cast<GLuint>(attribute.location),
303  gl_size,
304  gl_type,
305  static_cast<GLuint>(attribute.offset)
306  );
307  }
308  else
309  {
310  glVertexArrayAttribIFormat
311  (
312  m_gl_named_array,
313  static_cast<GLuint>(attribute.location),
314  gl_size,
315  gl_type,
316  static_cast<GLuint>(attribute.offset)
317  );
318  }
319  }
320 }
321 
323 {
324  glCreateVertexArrays(1, &m_gl_named_array);
325 }
326 
328 {
329  glDeleteVertexArrays(1, &m_gl_named_array);
330 }
331 
332 } // namespace gl
~vertex_array()
Destructs a vertex array.
constexpr const std::vector< vertex_input_attribute > & attributes() const noexcept
Returns the vertex array's vertex input attributes.
vertex_array()
Constructs a vertex array.
Graphics library interface.
Definition: window.hpp:28
constexpr GLenum gl_format_lut[][3]
Maps gl::format to OpenGL internal format, base format, and pixel type.