summaryrefslogtreecommitdiff
path: root/src/gl/draw.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gl/draw.h')
-rw-r--r--src/gl/draw.h217
1 files changed, 217 insertions, 0 deletions
diff --git a/src/gl/draw.h b/src/gl/draw.h
new file mode 100644
index 0000000..13deb43
--- /dev/null
+++ b/src/gl/draw.h
@@ -0,0 +1,217 @@
+// Copyright 2021, 2022 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.
+
+// Drawing to the framebuffer.
+
+#ifndef GLPLANET_SRC_GL_DRAW_H_
+#define GLPLANET_SRC_GL_DRAW_H_
+
+#include <Eigen/Core>
+#include <initializer_list>
+#include <stdexcept>
+
+#include "src/gl/buffer.h"
+#include "src/gl/error.h"
+#include "src/gl/shader.h"
+#include "src/gl/texture.h"
+#include "src/gl/vertex_array.h"
+#include "third_party/glew/include/GL/glew.h"
+
+namespace gl {
+
+// Makes the specified shader program active.
+inline void SetActiveShaderProgram(ShaderProgram& program) {
+ gl_internal::CheckThreadSafety();
+ glUseProgram(program.id());
+ // This error check is necessary because glUseProgram can fail.
+ gl_internal::ErrorCheck();
+}
+
+// RAII version of the above: While live, makes the specified shader program
+// active.
+class ActiveShaderProgram final {
+ public:
+ explicit ActiveShaderProgram(ShaderProgram& program) {
+ gl_internal::CheckThreadSafety();
+ glGetIntegerv(GL_CURRENT_PROGRAM, &old_);
+ gl_internal::UnnecessaryErrorCheck();
+ SetActiveShaderProgram(program);
+ }
+
+ ActiveShaderProgram(const ActiveShaderProgram&) = delete;
+ ActiveShaderProgram& operator=(const ActiveShaderProgram&) = delete;
+
+ ~ActiveShaderProgram() {
+ gl_internal::CheckThreadSafety();
+ glUseProgram(old_);
+ // This error check is necessary because glUseProgram can fail.
+ gl_internal::ErrorCheck();
+ }
+
+ private:
+ GLint old_;
+};
+
+// Sets the specified uniform in the active shader. Throws std::logic_error in
+// the event of a type error (e.g., you set a mat4 uniform to a single integer).
+inline void SetActiveShaderUniform(int index, int v0) {
+ gl_internal::CheckThreadSafety();
+ glUniform1i(index, v0);
+ // This error check is necessary because the shader variable might have a
+ // different type than was passed in.
+ gl_internal::ErrorCheck();
+}
+inline void SetActiveShaderUniform(int index, const Eigen::Vector2f& value) {
+ gl_internal::CheckThreadSafety();
+ glUniform2fv(index, /*count=*/1, value.data());
+ // This error check is necessary because the shader variable might have a
+ // different type than was passed in.
+ gl_internal::ErrorCheck();
+}
+inline void SetActiveShaderUniform(int index, const Eigen::Vector3f& value) {
+ gl_internal::CheckThreadSafety();
+ glUniform3fv(index, /*count=*/1, value.data());
+ // This error check is necessary because the shader variable might have a
+ // different type than was passed in.
+ gl_internal::ErrorCheck();
+}
+inline void SetActiveShaderUniform(int index, const Eigen::Matrix4f& value) {
+ gl_internal::CheckThreadSafety();
+ glUniformMatrix4fv(index, /*count=*/1, /*transpose=*/GL_FALSE, value.data());
+ // This error check is necessary because the shader variable might have a
+ // different type than was passed in.
+ gl_internal::ErrorCheck();
+}
+
+// Binds the specified VAO.
+inline void BindVertexArray(const VertexArray& vao) noexcept(
+ !(gl_internal::kThreadSafetyChecks ||
+ gl_internal::kAggressiveErrorChecking)) {
+ gl_internal::CheckThreadSafety();
+ glBindVertexArray(vao.id());
+ gl_internal::UnnecessaryErrorCheck();
+}
+
+// RAII version of the above: While live, binds the specified VAO.
+class BoundVertexArray final {
+ public:
+ explicit BoundVertexArray(const VertexArray& vao) noexcept(
+ !(gl_internal::kThreadSafetyChecks ||
+ gl_internal::kAggressiveErrorChecking)) {
+ gl_internal::CheckThreadSafety();
+ glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &old_);
+ gl_internal::UnnecessaryErrorCheck();
+ BindVertexArray(vao);
+ }
+
+ BoundVertexArray(const BoundVertexArray&) = delete;
+ BoundVertexArray& operator=(const BoundVertexArray&) = delete;
+
+ ~BoundVertexArray() noexcept(!(gl_internal::kThreadSafetyChecks ||
+ gl_internal::kAggressiveErrorChecking)) {
+ gl_internal::CheckThreadSafety();
+ glBindVertexArray(old_);
+ gl_internal::UnnecessaryErrorCheck();
+ }
+
+ private:
+ GLint old_;
+};
+
+// Sets the current texture unit.
+inline void UseTextureUnit(int unit) {
+ gl_internal::CheckThreadSafety();
+ glActiveTexture(GL_TEXTURE0 + unit);
+ // This error check is necessary because the user might have passed in a
+ // too-large index for the texture unit.
+ gl_internal::ErrorCheck();
+}
+
+// Binds the specified 2D texture.
+inline void BindTexture2d(const Texture2d& tex) noexcept(
+ !(gl_internal::kThreadSafetyChecks ||
+ gl_internal::kAggressiveErrorChecking)) {
+ gl_internal::CheckThreadSafety();
+ glBindTexture(GL_TEXTURE_2D, tex.id());
+ gl_internal::UnnecessaryErrorCheck();
+}
+
+// RAII version of the above: While live, binds the specified 2D texture.
+class BoundTexture2d final {
+ public:
+ explicit BoundTexture2d(const Texture2d& tex) noexcept(
+ !(gl_internal::kThreadSafetyChecks ||
+ gl_internal::kAggressiveErrorChecking)) {
+ gl_internal::CheckThreadSafety();
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_);
+ gl_internal::UnnecessaryErrorCheck();
+ BindTexture2d(tex);
+ }
+
+ BoundTexture2d(const BoundTexture2d&) = delete;
+ BoundTexture2d& operator=(const BoundTexture2d&) = delete;
+
+ ~BoundTexture2d() noexcept(!(gl_internal::kThreadSafetyChecks ||
+ gl_internal::kAggressiveErrorChecking)) {
+ gl_internal::CheckThreadSafety();
+ glBindTexture(GL_TEXTURE_2D, old_);
+ gl_internal::UnnecessaryErrorCheck();
+ }
+
+ private:
+ GLint old_;
+};
+
+enum class GlBuffer : GLenum {
+ kColor = GL_COLOR_BUFFER_BIT,
+ kDepth = GL_DEPTH_BUFFER_BIT,
+ kStencil = GL_STENCIL_BUFFER_BIT,
+};
+
+inline void Clear(const std::initializer_list<GlBuffer>& buffers) noexcept(
+ !(gl_internal::kThreadSafetyChecks ||
+ gl_internal::kAggressiveErrorChecking)) {
+ gl_internal::CheckThreadSafety();
+
+ GLenum mask = 0;
+ for (GlBuffer b : buffers) {
+ mask |= FromEnum(b);
+ }
+ glClear(mask);
+ gl_internal::UnnecessaryErrorCheck();
+}
+
+enum class Primitive : GLenum {
+ kPoints = GL_POINTS,
+ kLineStrip = GL_LINE_STRIP,
+ kLineLoop = GL_LINE_LOOP,
+ kLines = GL_LINES,
+ kLineStripAdjacency = GL_LINE_STRIP_ADJACENCY,
+ kLinesAdjacency = GL_LINES_ADJACENCY,
+ kTriangleStrip = GL_TRIANGLE_STRIP,
+ kTriangleFan = GL_TRIANGLE_FAN,
+ kTriangles = GL_TRIANGLES,
+ kTriangleStripAdjacency = GL_TRIANGLE_STRIP_ADJACENCY,
+ kTrianglesAdjacency = GL_TRIANGLES_ADJACENCY,
+ kPatches = GL_PATCHES,
+};
+
+// Draws the elements from the specified VAO. The VAO must already be bound.
+void DrawElements(const gl::VertexArray&, Primitive);
+
+void SetViewport(int x, int y, int width, int height);
+
+} // namespace gl
+
+#endif // GLPLANET_SRC_GL_DRAW_H_