// Copyright 2021 Benjamin Barenblat // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy of // the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. // Vertex array objects. #ifndef GLPLANET_SRC_GL_VERTEX_ARRAY_H_ #define GLPLANET_SRC_GL_VERTEX_ARRAY_H_ #include #include #include "src/gl/buffer.h" #include "src/gl/error.h" #include "third_party/abseil/absl/types/optional.h" #include "third_party/glew/include/GL/glew.h" namespace gl { enum class VertexAttributeType : GLenum { kByte = GL_BYTE, kShort = GL_SHORT, kInt = GL_INT, kFixed = GL_FIXED, kFloat = GL_FLOAT, kHalfFloat = GL_HALF_FLOAT, kDouble = GL_DOUBLE, kUnsignedByte = GL_UNSIGNED_BYTE, kUnsignedShort = GL_UNSIGNED_SHORT, kUnsignedInt = GL_UNSIGNED_INT, kInt2x10x10x10Rev = GL_INT_2_10_10_10_REV, kUnsignedInt2x10x10x10Rev = GL_UNSIGNED_INT_2_10_10_10_REV, kUnsignedInt10f11f11fRev = GL_UNSIGNED_INT_10F_11F_11F_REV, }; // A VAO. class VertexArray final { public: explicit VertexArray() noexcept(!(gl_internal::kThreadSafetyChecks || gl_internal::kAggressiveErrorChecking)) { gl_internal::CheckThreadSafety(); glCreateVertexArrays(1, &array_); gl_internal::UnnecessaryErrorCheck(); } VertexArray(VertexArray&&) noexcept = default; VertexArray& operator=(VertexArray&&) noexcept = default; ~VertexArray() noexcept(!(gl_internal::kThreadSafetyChecks || gl_internal::kAggressiveErrorChecking)) { gl_internal::CheckThreadSafety(); glDeleteVertexArrays(1, &array_); gl_internal::UnnecessaryErrorCheck(); } // Attaches the specified vertex buffer to the VAO. void SetVertexBuffer(VertexBuffer vertices) { gl_internal::CheckThreadSafety(); glVertexArrayVertexBuffer(array_, /*bindingindex=*/0, vertices.id(), /*offset=*/0, vertices.element_size()); // This error check is necessary because the elements of the VBO might be // too large for the implementation to handle. gl_internal::ErrorCheck(); vertices_ = std::move(vertices); } // Specifies the organization of data in the attached VAO. void SetVertexAttributeFormat(int index, int size, VertexAttributeType type, int offset, bool normalized = false); // Attaches the specified element buffer to the VAO. The element buffer must // outlive this VAO. void SetElementBuffer(ElementBuffer elements) noexcept( !(gl_internal::kThreadSafetyChecks || gl_internal::kAggressiveErrorChecking)) { gl_internal::CheckThreadSafety(); glVertexArrayElementBuffer(array_, elements.id()); gl_internal::UnnecessaryErrorCheck(); elements_ = std::move(elements); } // Returns the element buffer attached to this VAO. const ElementBuffer& element_buffer() const noexcept { return elements_; } // The GL identifier for this VAO. unsigned int id() const noexcept { return array_; } private: GLuint array_; VertexBuffer vertices_; ElementBuffer elements_; }; } // namespace gl #endif // GLPLANET_SRC_GL_VERTEX_ARRAY_H_