From d0e18bdb7924c71cdca8dd983711171d87ef28be Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Mon, 17 Jan 2022 23:12:32 -0500 Subject: glplanet, an OpenGL-based planetary renderer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit glplanet draws Earth like it currently appears from space, putting nighttime areas in shadow and daytime areas in light. It’s modeled after Xplanet (http://xplanet.sourceforge.net/), but whereas Xplanet is entirely a CPU-resident program, glplanet draws using OpenGL. It’s thus much less resource-intensive, particularly when using high-resolution textures. --- src/gl/buffer.h | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 src/gl/buffer.h (limited to 'src/gl/buffer.h') diff --git a/src/gl/buffer.h b/src/gl/buffer.h new file mode 100644 index 0000000..439533b --- /dev/null +++ b/src/gl/buffer.h @@ -0,0 +1,206 @@ +// 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. + +// Buffer objects. + +#ifndef GLPLANET_SRC_GL_BUFFER_H_ +#define GLPLANET_SRC_GL_BUFFER_H_ + +#include +#include + +#include +#include +#include + +#include "src/gl/error.h" +#include "third_party/abseil/absl/types/span.h" +#include "third_party/glew/include/GL/glew.h" + +namespace gl { + +// A byte buffer in GPU memory. +class Buffer final { + public: + // The frequency with which data in the buffer will be accessed. + enum class AccessFrequency : uint8_t { kStatic, kStream, kDynamic }; + + // The type of that access. + enum class AccessNature : uint8_t { kDraw, kRead, kCopy }; + + explicit Buffer() noexcept(!(gl_internal::kThreadSafetyChecks || + gl_internal::kAggressiveErrorChecking)) + : size_bytes_(0), + frequency_(AccessFrequency::kStatic), + nature_(AccessNature::kDraw) { + gl_internal::CheckThreadSafety(); + glCreateBuffers(1, &buffer_); + gl_internal::UnnecessaryErrorCheck(); + } + + Buffer(const Buffer&); + + Buffer& operator=(const Buffer& other) { + if (this != &other) { + Buffer other2(other); + swap(*this, other2); + } + return *this; + } + + Buffer(Buffer&& other) noexcept + : buffer_(0), + size_bytes_(0), + frequency_(AccessFrequency::kStatic), + nature_(AccessNature::kDraw) { + *this = std::move(other); + } + + Buffer& operator=(Buffer&& other) noexcept { + swap(*this, other); + return *this; + } + + ~Buffer() noexcept(!(gl_internal::kThreadSafetyChecks || + gl_internal::kAggressiveErrorChecking)) { + gl_internal::CheckThreadSafety(); + glDeleteBuffers(1, &buffer_); + gl_internal::UnnecessaryErrorCheck(); + } + + friend void swap(Buffer& left, Buffer& right) noexcept { + using ::std::swap; + swap(left.buffer_, right.buffer_); + swap(left.size_bytes_, right.size_bytes_); + swap(left.frequency_, right.frequency_); + swap(left.nature_, right.nature_); + } + + // Loads data into the buffer. + void SetData(const void*, int size_bytes, AccessFrequency, AccessNature); + + int size() const noexcept { return size_bytes_; } + + // The GL identifier for this buffer. + unsigned int id() const noexcept { return buffer_; } + + private: + GLuint buffer_; + int size_bytes_; + AccessFrequency frequency_; + AccessNature nature_; +}; + +// A vertex buffer object. +class VertexBuffer final { + public: + explicit VertexBuffer() noexcept(!(gl_internal::kThreadSafetyChecks || + gl_internal::kAggressiveErrorChecking)) = + default; + + // A shorthand to construct the buffer and load data into it in one step. + template + explicit VertexBuffer(absl::Span data, + Buffer::AccessFrequency frequency, + Buffer::AccessNature nature) { + SetData(data, frequency, nature); + } + + VertexBuffer(const VertexBuffer&) = default; + VertexBuffer& operator=(const VertexBuffer&) = default; + VertexBuffer(VertexBuffer&&) = default; + VertexBuffer& operator=(VertexBuffer&&) = default; + + // Loads data into the buffer. + template + void SetData(absl::Span data, Buffer::AccessFrequency frequency, + Buffer::AccessNature nature) { + buffer_.SetData(data.data(), data.size() * sizeof(T), frequency, nature); + element_size_ = sizeof(T); + } + + // The number of vertices in this buffer. + int size() const noexcept { + assert(buffer_.size() % element_size() == 0); + return buffer_.size() / element_size(); + } + + // The size, in bytes, of an individual vertex. + int element_size() const noexcept { return element_size_; } + + // The GL identifier for this buffer. + unsigned int id() const noexcept { return buffer_.id(); } + + private: + Buffer buffer_; + int element_size_; +}; + +// The types that can go in an element buffer. +template +concept IsElement = std::same_as || std::same_as || + std::same_as; + +// An element buffer. +class ElementBuffer final { + public: + explicit ElementBuffer() noexcept(!(gl_internal::kThreadSafetyChecks || + gl_internal::kAggressiveErrorChecking)) = + default; + + // Constructs an element buffer containing the specified data. + template + explicit ElementBuffer(absl::Span data, + Buffer::AccessFrequency frequency, + Buffer::AccessNature nature) { + SetData(data, frequency, nature); + } + + ElementBuffer(const ElementBuffer&) = default; + ElementBuffer& operator=(const ElementBuffer&) = default; + ElementBuffer(ElementBuffer&&) noexcept = default; + ElementBuffer& operator=(ElementBuffer&&) noexcept = default; + + // Loads data into the buffer. + template + void SetData(absl::Span data, Buffer::AccessFrequency frequency, + Buffer::AccessNature nature) { + buffer_.SetData(data.data(), data.size() * sizeof(T), frequency, nature); + element_size_ = sizeof(T); + } + + // The number of elements in this buffer. + int size() const noexcept { + assert(buffer_.size() % element_size() == 0); + return buffer_.size() / element_size(); + } + + // The size, in bytes, of an individual element. This will always be 1, 2, + // or 4. + int element_size() const noexcept { + assert(element_size_ == 1 || element_size_ == 2 || element_size_ == 4); + return element_size_; + } + + // The GL identifier for this buffer. + unsigned int id() const noexcept { return buffer_.id(); } + + private: + Buffer buffer_; + int element_size_; +}; + +} // namespace gl + +#endif // GLPLANET_SRC_GL_BUFFER_H_ -- cgit v1.2.3