|
|
|
@@ -32,12 +32,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
namespace OpenGL {
|
|
|
|
namespace OpenGL {
|
|
|
|
|
|
|
|
|
|
|
|
// Workaround for using static_assert inside constexpr if
|
|
|
|
// Workaround for using static_assert inside constexpr if
|
|
|
|
// https://stackoverflow.com/questions/53945490/how-to-assert-that-a-constexpr-if-else-clause-never-happen
|
|
|
|
// https://stackoverflow.com/questions/53945490/how-to-assert-that-a-constexpr-if-else-clause-never-happen
|
|
|
|
template <class...>
|
|
|
|
template <class...>
|
|
|
|
constexpr std::false_type AlwaysFalse{};
|
|
|
|
constexpr std::false_type AlwaysFalse{};
|
|
|
|
|
|
|
|
|
|
|
|
struct VertexArray {
|
|
|
|
struct VertexArray {
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
|
|
|
|
|
|
|
|
void create() {
|
|
|
|
void create() {
|
|
|
|
@@ -60,19 +60,26 @@ struct VertexArray {
|
|
|
|
void setAttributeFloat(GLuint index, GLint size, GLsizei stride, const void* offset, bool normalized = false) {
|
|
|
|
void setAttributeFloat(GLuint index, GLint size, GLsizei stride, const void* offset, bool normalized = false) {
|
|
|
|
if constexpr (std::is_same<T, GLfloat>()) {
|
|
|
|
if constexpr (std::is_same<T, GLfloat>()) {
|
|
|
|
glVertexAttribPointer(index, size, GL_FLOAT, normalized, stride, offset);
|
|
|
|
glVertexAttribPointer(index, size, GL_FLOAT, normalized, stride, offset);
|
|
|
|
} else if constexpr (std::is_same<T, GLbyte>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLbyte>()) {
|
|
|
|
glVertexAttribPointer(index, size, GL_BYTE, normalized, stride, offset);
|
|
|
|
glVertexAttribPointer(index, size, GL_BYTE, normalized, stride, offset);
|
|
|
|
} else if constexpr (std::is_same<T, GLubyte>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLubyte>()) {
|
|
|
|
glVertexAttribPointer(index, size, GL_UNSIGNED_BYTE, normalized, stride, offset);
|
|
|
|
glVertexAttribPointer(index, size, GL_UNSIGNED_BYTE, normalized, stride, offset);
|
|
|
|
} else if constexpr (std::is_same<T, GLshort>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLshort>()) {
|
|
|
|
glVertexAttribPointer(index, size, GL_SHORT, normalized, stride, offset);
|
|
|
|
glVertexAttribPointer(index, size, GL_SHORT, normalized, stride, offset);
|
|
|
|
} else if constexpr (std::is_same<T, GLushort>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLushort>()) {
|
|
|
|
glVertexAttribPointer(index, size, GL_UNSIGNED_SHORT, normalized, stride, offset);
|
|
|
|
glVertexAttribPointer(index, size, GL_UNSIGNED_SHORT, normalized, stride, offset);
|
|
|
|
} else if constexpr (std::is_same<T, GLint>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLint>()) {
|
|
|
|
glVertexAttribPointer(index, size, GL_INT, normalized, stride, offset);
|
|
|
|
glVertexAttribPointer(index, size, GL_INT, normalized, stride, offset);
|
|
|
|
} else if constexpr (std::is_same<T, GLuint>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLuint>()) {
|
|
|
|
glVertexAttribPointer(index, size, GL_UNSIGNED_INT, normalized, stride, offset);
|
|
|
|
glVertexAttribPointer(index, size, GL_UNSIGNED_INT, normalized, stride, offset);
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
static_assert(AlwaysFalse<T>, "Unimplemented type for OpenGL::setAttributeFloat");
|
|
|
|
static_assert(AlwaysFalse<T>, "Unimplemented type for OpenGL::setAttributeFloat");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -81,17 +88,23 @@ struct VertexArray {
|
|
|
|
void setAttributeInt(GLuint index, GLint size, GLsizei stride, const void* offset) {
|
|
|
|
void setAttributeInt(GLuint index, GLint size, GLsizei stride, const void* offset) {
|
|
|
|
if constexpr (std::is_same<T, GLbyte>()) {
|
|
|
|
if constexpr (std::is_same<T, GLbyte>()) {
|
|
|
|
glVertexAttribIPointer(index, size, GL_BYTE, stride, offset);
|
|
|
|
glVertexAttribIPointer(index, size, GL_BYTE, stride, offset);
|
|
|
|
} else if constexpr (std::is_same<T, GLubyte>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLubyte>()) {
|
|
|
|
glVertexAttribIPointer(index, size, GL_UNSIGNED_BYTE, stride, offset);
|
|
|
|
glVertexAttribIPointer(index, size, GL_UNSIGNED_BYTE, stride, offset);
|
|
|
|
} else if constexpr (std::is_same<T, GLshort>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLshort>()) {
|
|
|
|
glVertexAttribIPointer(index, size, GL_SHORT, stride, offset);
|
|
|
|
glVertexAttribIPointer(index, size, GL_SHORT, stride, offset);
|
|
|
|
} else if constexpr (std::is_same<T, GLushort>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLushort>()) {
|
|
|
|
glVertexAttribIPointer(index, size, GL_UNSIGNED_SHORT, stride, offset);
|
|
|
|
glVertexAttribIPointer(index, size, GL_UNSIGNED_SHORT, stride, offset);
|
|
|
|
} else if constexpr (std::is_same<T, GLint>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLint>()) {
|
|
|
|
glVertexAttribIPointer(index, size, GL_INT, stride, offset);
|
|
|
|
glVertexAttribIPointer(index, size, GL_INT, stride, offset);
|
|
|
|
} else if constexpr (std::is_same<T, GLuint>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLuint>()) {
|
|
|
|
glVertexAttribIPointer(index, size, GL_UNSIGNED_INT, stride, offset);
|
|
|
|
glVertexAttribIPointer(index, size, GL_UNSIGNED_INT, stride, offset);
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
static_assert(AlwaysFalse<T>, "Unimplemented type for OpenGL::setAttributeInt");
|
|
|
|
static_assert(AlwaysFalse<T>, "Unimplemented type for OpenGL::setAttributeInt");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -108,15 +121,15 @@ struct VertexArray {
|
|
|
|
|
|
|
|
|
|
|
|
void enableAttribute(GLuint index) { glEnableVertexAttribArray(index); }
|
|
|
|
void enableAttribute(GLuint index) { glEnableVertexAttribArray(index); }
|
|
|
|
void disableAttribute(GLuint index) { glDisableVertexAttribArray(index); }
|
|
|
|
void disableAttribute(GLuint index) { glDisableVertexAttribArray(index); }
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
enum FramebufferTypes {
|
|
|
|
enum FramebufferTypes {
|
|
|
|
DrawFramebuffer = GL_DRAW_FRAMEBUFFER,
|
|
|
|
DrawFramebuffer = GL_DRAW_FRAMEBUFFER,
|
|
|
|
ReadFramebuffer = GL_READ_FRAMEBUFFER,
|
|
|
|
ReadFramebuffer = GL_READ_FRAMEBUFFER,
|
|
|
|
DrawAndReadFramebuffer = GL_FRAMEBUFFER
|
|
|
|
DrawAndReadFramebuffer = GL_FRAMEBUFFER
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct Texture {
|
|
|
|
struct Texture {
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
int m_width, m_height;
|
|
|
|
int m_width, m_height;
|
|
|
|
GLenum m_binding;
|
|
|
|
GLenum m_binding;
|
|
|
|
@@ -142,7 +155,8 @@ struct Texture {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalFormat, width, height, GL_TRUE);
|
|
|
|
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalFormat, width, height, GL_TRUE);
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
glTexStorage2D(binding, 1, internalFormat, width, height);
|
|
|
|
glTexStorage2D(binding, 1, internalFormat, width, height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -157,9 +171,9 @@ struct Texture {
|
|
|
|
void bind() { glBindTexture(m_binding, m_handle); }
|
|
|
|
void bind() { glBindTexture(m_binding, m_handle); }
|
|
|
|
int width() { return m_width; }
|
|
|
|
int width() { return m_width; }
|
|
|
|
int height() { return m_height; }
|
|
|
|
int height() { return m_height; }
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct Framebuffer {
|
|
|
|
struct Framebuffer {
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
GLenum m_textureType; // GL_TEXTURE_2D or GL_TEXTURE_2D_MULTISAMPLE
|
|
|
|
GLenum m_textureType; // GL_TEXTURE_2D or GL_TEXTURE_2D_MULTISAMPLE
|
|
|
|
|
|
|
|
|
|
|
|
@@ -201,18 +215,18 @@ struct Framebuffer {
|
|
|
|
bind(mode);
|
|
|
|
bind(mode);
|
|
|
|
glFramebufferTexture2D(mode, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex.handle(), 0);
|
|
|
|
glFramebufferTexture2D(mode, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex.handle(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
enum ShaderType {
|
|
|
|
enum ShaderType {
|
|
|
|
Fragment = GL_FRAGMENT_SHADER,
|
|
|
|
Fragment = GL_FRAGMENT_SHADER,
|
|
|
|
Vertex = GL_VERTEX_SHADER,
|
|
|
|
Vertex = GL_VERTEX_SHADER,
|
|
|
|
Geometry = GL_GEOMETRY_SHADER,
|
|
|
|
Geometry = GL_GEOMETRY_SHADER,
|
|
|
|
Compute = GL_COMPUTE_SHADER,
|
|
|
|
Compute = GL_COMPUTE_SHADER,
|
|
|
|
TessControl = GL_TESS_CONTROL_SHADER,
|
|
|
|
TessControl = GL_TESS_CONTROL_SHADER,
|
|
|
|
TessEvaluation = GL_TESS_EVALUATION_SHADER
|
|
|
|
TessEvaluation = GL_TESS_EVALUATION_SHADER
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct Shader {
|
|
|
|
struct Shader {
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
|
|
|
|
|
|
|
|
Shader() {}
|
|
|
|
Shader() {}
|
|
|
|
@@ -221,14 +235,14 @@ struct Shader {
|
|
|
|
// Returns whether compilation failed or not
|
|
|
|
// Returns whether compilation failed or not
|
|
|
|
bool create(const std::string_view source, GLenum type) {
|
|
|
|
bool create(const std::string_view source, GLenum type) {
|
|
|
|
m_handle = glCreateShader(type);
|
|
|
|
m_handle = glCreateShader(type);
|
|
|
|
const GLchar* const sources[1] = {source.data()};
|
|
|
|
const GLchar* const sources[1] = { source.data() };
|
|
|
|
|
|
|
|
|
|
|
|
glShaderSource(m_handle, 1, sources, nullptr);
|
|
|
|
glShaderSource(m_handle, 1, sources, nullptr);
|
|
|
|
glCompileShader(m_handle);
|
|
|
|
glCompileShader(m_handle);
|
|
|
|
|
|
|
|
|
|
|
|
GLint success;
|
|
|
|
GLint success;
|
|
|
|
glGetShaderiv(m_handle, GL_COMPILE_STATUS, &success);
|
|
|
|
glGetShaderiv(m_handle, GL_COMPILE_STATUS, &success);
|
|
|
|
if (!success) {
|
|
|
|
if (success == GL_FALSE) {
|
|
|
|
char buf[4096];
|
|
|
|
char buf[4096];
|
|
|
|
glGetShaderInfoLog(m_handle, 4096, nullptr, buf);
|
|
|
|
glGetShaderInfoLog(m_handle, 4096, nullptr, buf);
|
|
|
|
fprintf(stderr, "Failed to compile shader\nError: %s\n", buf);
|
|
|
|
fprintf(stderr, "Failed to compile shader\nError: %s\n", buf);
|
|
|
|
@@ -242,9 +256,9 @@ struct Shader {
|
|
|
|
|
|
|
|
|
|
|
|
GLuint handle() { return m_handle; }
|
|
|
|
GLuint handle() { return m_handle; }
|
|
|
|
bool exists() { return m_handle != 0; }
|
|
|
|
bool exists() { return m_handle != 0; }
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct Program {
|
|
|
|
struct Program {
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
|
|
|
|
|
|
|
|
bool create(std::initializer_list<std::reference_wrapper<Shader>> shaders) {
|
|
|
|
bool create(std::initializer_list<std::reference_wrapper<Shader>> shaders) {
|
|
|
|
@@ -272,9 +286,13 @@ struct Program {
|
|
|
|
GLuint handle() { return m_handle; }
|
|
|
|
GLuint handle() { return m_handle; }
|
|
|
|
bool exists() { return m_handle != 0; }
|
|
|
|
bool exists() { return m_handle != 0; }
|
|
|
|
void use() { glUseProgram(m_handle); }
|
|
|
|
void use() { glUseProgram(m_handle); }
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct VertexBuffer {
|
|
|
|
static void dispatchCompute(GLuint groupsX = 1, GLuint groupsY = 1, GLuint groupsZ = 1) {
|
|
|
|
|
|
|
|
glDispatchCompute(groupsX, groupsY, groupsZ);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct VertexBuffer {
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
GLuint m_handle = 0;
|
|
|
|
|
|
|
|
|
|
|
|
void create() {
|
|
|
|
void create() {
|
|
|
|
@@ -311,27 +329,37 @@ struct VertexBuffer {
|
|
|
|
void bufferVertsSub(VertType* vertices, int vertCount, GLintptr offset = 0) {
|
|
|
|
void bufferVertsSub(VertType* vertices, int vertCount, GLintptr offset = 0) {
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(VertType) * vertCount, vertices);
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(VertType) * vertCount, vertices);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void setClearColor(float val) { glClearColor(val, val, val, val); }
|
|
|
|
static void setClearColor(float val) { glClearColor(val, val, val, val); }
|
|
|
|
static void setClearColor(float r, float g, float b, float a) { glClearColor(r, g, b, a); }
|
|
|
|
static void setClearColor(float r, float g, float b, float a) { glClearColor(r, g, b, a); }
|
|
|
|
static void setClearDepth(float depth) { glClearDepthf(depth); }
|
|
|
|
static void setClearDepth(float depth) { glClearDepthf(depth); }
|
|
|
|
static void clearColor() { glClear(GL_COLOR_BUFFER_BIT); }
|
|
|
|
static void setClearStencil(GLint stencil) { glClearStencil(stencil); }
|
|
|
|
static void clearDepth() { glClear(GL_DEPTH_BUFFER_BIT); }
|
|
|
|
static void clearColor() { glClear(GL_COLOR_BUFFER_BIT); }
|
|
|
|
static void clearColorAndDepth() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); }
|
|
|
|
static void clearDepth() { glClear(GL_DEPTH_BUFFER_BIT); }
|
|
|
|
|
|
|
|
static void clearStencil() { glClear(GL_STENCIL_BUFFER_BIT); }
|
|
|
|
|
|
|
|
static void clearColorAndDepth() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); }
|
|
|
|
|
|
|
|
static void clearColorAndStencil() { glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); }
|
|
|
|
|
|
|
|
static void clearDepthAndStencil() { glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); }
|
|
|
|
|
|
|
|
static void clearAll() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); }
|
|
|
|
|
|
|
|
|
|
|
|
static void setViewport(GLsizei width, GLsizei height) { glViewport(0, 0, width, height); }
|
|
|
|
static void setViewport(GLsizei width, GLsizei height) { glViewport(0, 0, width, height); }
|
|
|
|
static void setViewport(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glViewport(x, y, width, height); }
|
|
|
|
static void setViewport(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glViewport(x, y, width, height); }
|
|
|
|
static void setScissor(GLsizei width, GLsizei height) { glScissor(0, 0, width, height); }
|
|
|
|
static void setScissor(GLsizei width, GLsizei height) { glScissor(0, 0, width, height); }
|
|
|
|
static void setScissor(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glScissor(x, y, width, height); }
|
|
|
|
static void setScissor(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glScissor(x, y, width, height); }
|
|
|
|
|
|
|
|
static void setStencilMask(GLuint mask) { glStencilMask(mask); }
|
|
|
|
|
|
|
|
|
|
|
|
static void bindScreenFramebuffer() { glBindFramebuffer(GL_FRAMEBUFFER, 0); }
|
|
|
|
static void bindScreenFramebuffer() { glBindFramebuffer(GL_FRAMEBUFFER, 0); }
|
|
|
|
static void enableScissor() { glEnable(GL_SCISSOR_TEST); }
|
|
|
|
static void enableScissor() { glEnable(GL_SCISSOR_TEST); }
|
|
|
|
static void disableScissor() { glDisable(GL_SCISSOR_TEST); }
|
|
|
|
static void disableScissor() { glDisable(GL_SCISSOR_TEST); }
|
|
|
|
static void enableBlend() { glEnable(GL_BLEND); }
|
|
|
|
static void enableBlend() { glEnable(GL_BLEND); }
|
|
|
|
static void disableBlend() { glDisable(GL_BLEND); }
|
|
|
|
static void disableBlend() { glDisable(GL_BLEND); }
|
|
|
|
|
|
|
|
static void enableDepth() { glEnable(GL_DEPTH_TEST); }
|
|
|
|
|
|
|
|
static void disableDepth() { glDisable(GL_DEPTH_TEST); }
|
|
|
|
|
|
|
|
static void enableStencil() { glEnable(GL_STENCIL_TEST); }
|
|
|
|
|
|
|
|
static void disableStencil() { glDisable(GL_STENCIL_TEST); }
|
|
|
|
|
|
|
|
|
|
|
|
enum Primitives {
|
|
|
|
enum Primitives {
|
|
|
|
Triangle = GL_TRIANGLES,
|
|
|
|
Triangle = GL_TRIANGLES,
|
|
|
|
Triangles = Triangle,
|
|
|
|
Triangles = Triangle,
|
|
|
|
Tri = Triangle,
|
|
|
|
Tri = Triangle,
|
|
|
|
@@ -343,74 +371,78 @@ enum Primitives {
|
|
|
|
LineStrip = GL_LINE_STRIP,
|
|
|
|
LineStrip = GL_LINE_STRIP,
|
|
|
|
Point = GL_POINTS,
|
|
|
|
Point = GL_POINTS,
|
|
|
|
Points = Point
|
|
|
|
Points = Point
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void draw(Primitives prim, GLsizei vertexCount) { glDrawArrays(static_cast<GLenum>(prim), 0, vertexCount); }
|
|
|
|
static void draw(Primitives prim, GLsizei vertexCount) { glDrawArrays(static_cast<GLenum>(prim), 0, vertexCount); }
|
|
|
|
static void draw(Primitives prim, GLint first, GLsizei vertexCount) {
|
|
|
|
static void draw(Primitives prim, GLint first, GLsizei vertexCount) {
|
|
|
|
glDrawArrays(static_cast<GLenum>(prim), first, vertexCount);
|
|
|
|
glDrawArrays(static_cast<GLenum>(prim), first, vertexCount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
enum FillMode { DrawPoints = GL_POINT, DrawWire = GL_LINE, FillPoly = GL_FILL };
|
|
|
|
enum FillMode { DrawPoints = GL_POINT, DrawWire = GL_LINE, FillPoly = GL_FILL };
|
|
|
|
|
|
|
|
|
|
|
|
static void setFillMode(GLenum mode) { glPolygonMode(GL_FRONT_AND_BACK, mode); }
|
|
|
|
static void setFillMode(GLenum mode) { glPolygonMode(GL_FRONT_AND_BACK, mode); }
|
|
|
|
static void setFillMode(FillMode mode) { glPolygonMode(GL_FRONT_AND_BACK, static_cast<GLenum>(mode)); }
|
|
|
|
static void setFillMode(FillMode mode) { glPolygonMode(GL_FRONT_AND_BACK, static_cast<GLenum>(mode)); }
|
|
|
|
static void drawWireframe() { setFillMode(DrawWire); }
|
|
|
|
static void drawWireframe() { setFillMode(DrawWire); }
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
template <typename T>
|
|
|
|
T get(GLenum query) {
|
|
|
|
T get(GLenum query) {
|
|
|
|
T ret{};
|
|
|
|
T ret{};
|
|
|
|
if constexpr (std::is_same<T, GLint>()) {
|
|
|
|
if constexpr (std::is_same<T, GLint>()) {
|
|
|
|
glGetIntegerv(query, &ret);
|
|
|
|
glGetIntegerv(query, &ret);
|
|
|
|
} else if constexpr (std::is_same<T, GLfloat>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLfloat>()) {
|
|
|
|
glGetFloatv(query, &ret);
|
|
|
|
glGetFloatv(query, &ret);
|
|
|
|
} else if constexpr (std::is_same<T, GLdouble>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLdouble>()) {
|
|
|
|
glGetDoublev(query, &ret);
|
|
|
|
glGetDoublev(query, &ret);
|
|
|
|
} else if constexpr (std::is_same<T, GLboolean>()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
else if constexpr (std::is_same<T, GLboolean>()) {
|
|
|
|
glGetBooleanv(query, &ret);
|
|
|
|
glGetBooleanv(query, &ret);
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
static_assert(AlwaysFalse<T>, "Invalid type for OpenGL::get");
|
|
|
|
static_assert(AlwaysFalse<T>, "Invalid type for OpenGL::get");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool isEnabled(GLenum query) { return glIsEnabled(query) != GL_FALSE; }
|
|
|
|
static bool isEnabled(GLenum query) { return glIsEnabled(query) != GL_FALSE; }
|
|
|
|
|
|
|
|
|
|
|
|
static GLint getDrawFramebuffer() { return get<GLint>(GL_DRAW_FRAMEBUFFER_BINDING); }
|
|
|
|
static GLint getDrawFramebuffer() { return get<GLint>(GL_DRAW_FRAMEBUFFER_BINDING); }
|
|
|
|
static GLint maxSamples() { return get<GLint>(GL_MAX_INTEGER_SAMPLES); }
|
|
|
|
static GLint maxSamples() { return get<GLint>(GL_MAX_INTEGER_SAMPLES); }
|
|
|
|
static GLint getTex2D() { return get<GLint>(GL_TEXTURE_BINDING_2D); }
|
|
|
|
static GLint getTex2D() { return get<GLint>(GL_TEXTURE_BINDING_2D); }
|
|
|
|
static GLint getProgram() { return get<GLint>(GL_CURRENT_PROGRAM); }
|
|
|
|
static GLint getProgram() { return get<GLint>(GL_CURRENT_PROGRAM); }
|
|
|
|
static bool scissorEnabled() { return isEnabled(GL_SCISSOR_TEST); }
|
|
|
|
static bool scissorEnabled() { return isEnabled(GL_SCISSOR_TEST); }
|
|
|
|
|
|
|
|
|
|
|
|
static bool versionSupported(int major, int minor) { return gl3wIsSupported(major, minor); }
|
|
|
|
static bool versionSupported(int major, int minor) { return gl3wIsSupported(major, minor); }
|
|
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] static GLint uniformLocation(GLuint program, const char* name) {
|
|
|
|
[[nodiscard]] static GLint uniformLocation(GLuint program, const char* name) {
|
|
|
|
return glGetUniformLocation(program, name);
|
|
|
|
return glGetUniformLocation(program, name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[[nodiscard]] static GLint uniformLocation(Program& program, const char* name) {
|
|
|
|
[[nodiscard]] static GLint uniformLocation(Program& program, const char* name) {
|
|
|
|
return glGetUniformLocation(program.handle(), name);
|
|
|
|
return glGetUniformLocation(program.handle(), name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
enum BlendEquation {
|
|
|
|
enum BlendEquation {
|
|
|
|
Add = GL_FUNC_ADD,
|
|
|
|
Add = GL_FUNC_ADD,
|
|
|
|
Sub = GL_FUNC_SUBTRACT,
|
|
|
|
Sub = GL_FUNC_SUBTRACT,
|
|
|
|
ReverseSub = GL_FUNC_REVERSE_SUBTRACT,
|
|
|
|
ReverseSub = GL_FUNC_REVERSE_SUBTRACT,
|
|
|
|
Min = GL_MIN,
|
|
|
|
Min = GL_MIN,
|
|
|
|
Max = GL_MAX
|
|
|
|
Max = GL_MAX
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void setBlendColor(float r, float g, float b, float a = 1.0) { glBlendColor(r, g, b, a); }
|
|
|
|
static void setBlendColor(float r, float g, float b, float a = 1.0) { glBlendColor(r, g, b, a); }
|
|
|
|
static void setBlendEquation(BlendEquation eq) { glBlendEquation(eq); }
|
|
|
|
static void setBlendEquation(BlendEquation eq) { glBlendEquation(eq); }
|
|
|
|
static void setBlendEquation(BlendEquation eq1, BlendEquation eq2) { glBlendEquationSeparate(eq1, eq2); }
|
|
|
|
static void setBlendEquation(BlendEquation eq1, BlendEquation eq2) { glBlendEquationSeparate(eq1, eq2); }
|
|
|
|
|
|
|
|
|
|
|
|
static void setBlendFactor(GLenum fac1, GLenum fac2) { glBlendFunc(fac1, fac2); }
|
|
|
|
static void setBlendFactor(GLenum fac1, GLenum fac2) { glBlendFunc(fac1, fac2); }
|
|
|
|
static void setBlendFactor(GLenum fac1, GLenum fac2, GLenum fac3, GLenum fac4) {
|
|
|
|
static void setBlendFactor(GLenum fac1, GLenum fac2, GLenum fac3, GLenum fac4) {
|
|
|
|
glBlendFuncSeparate(fac1, fac2, fac3, fac4);
|
|
|
|
glBlendFuncSeparate(fac1, fac2, fac3, fac4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Abstraction for GLSL vectors
|
|
|
|
// Abstraction for GLSL vectors
|
|
|
|
template <typename T, int size>
|
|
|
|
template <typename T, int size>
|
|
|
|
class Vector {
|
|
|
|
class Vector {
|
|
|
|
// A GLSL vector can only have 2, 3 or 4 elements
|
|
|
|
// A GLSL vector can only have 2, 3 or 4 elements
|
|
|
|
static_assert(size == 2 || size == 3 || size == 4);
|
|
|
|
static_assert(size == 2 || size == 3 || size == 4);
|
|
|
|
T m_storage[size];
|
|
|
|
T m_storage[size];
|
|
|
|
@@ -444,30 +476,30 @@ class Vector {
|
|
|
|
Vector(std::array<T, size> list) { std::copy(list.begin(), list.end(), &m_storage[0]); }
|
|
|
|
Vector(std::array<T, size> list) { std::copy(list.begin(), list.end(), &m_storage[0]); }
|
|
|
|
|
|
|
|
|
|
|
|
Vector() {}
|
|
|
|
Vector() {}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
using vec2 = Vector<GLfloat, 2>;
|
|
|
|
using vec2 = Vector<GLfloat, 2>;
|
|
|
|
using vec3 = Vector<GLfloat, 3>;
|
|
|
|
using vec3 = Vector<GLfloat, 3>;
|
|
|
|
using vec4 = Vector<GLfloat, 4>;
|
|
|
|
using vec4 = Vector<GLfloat, 4>;
|
|
|
|
|
|
|
|
|
|
|
|
using dvec2 = Vector<GLdouble, 2>;
|
|
|
|
using dvec2 = Vector<GLdouble, 2>;
|
|
|
|
using dvec3 = Vector<GLdouble, 3>;
|
|
|
|
using dvec3 = Vector<GLdouble, 3>;
|
|
|
|
using dvec4 = Vector<GLdouble, 4>;
|
|
|
|
using dvec4 = Vector<GLdouble, 4>;
|
|
|
|
|
|
|
|
|
|
|
|
using ivec2 = Vector<GLint, 2>;
|
|
|
|
using ivec2 = Vector<GLint, 2>;
|
|
|
|
using ivec3 = Vector<GLint, 3>;
|
|
|
|
using ivec3 = Vector<GLint, 3>;
|
|
|
|
using ivec4 = Vector<GLint, 4>;
|
|
|
|
using ivec4 = Vector<GLint, 4>;
|
|
|
|
|
|
|
|
|
|
|
|
using uvec2 = Vector<GLuint, 2>;
|
|
|
|
using uvec2 = Vector<GLuint, 2>;
|
|
|
|
using uvec3 = Vector<GLuint, 3>;
|
|
|
|
using uvec3 = Vector<GLuint, 3>;
|
|
|
|
using uvec4 = Vector<GLuint, 4>;
|
|
|
|
using uvec4 = Vector<GLuint, 4>;
|
|
|
|
|
|
|
|
|
|
|
|
// A 2D rectangle, meant to be used for stuff like scissor rects or viewport rects
|
|
|
|
// A 2D rectangle, meant to be used for stuff like scissor rects or viewport rects
|
|
|
|
// We're never supporting 3D rectangles, because rectangles were never meant to be 3D in the first place
|
|
|
|
// We're never supporting 3D rectangles, because rectangles were never meant to be 3D in the first place
|
|
|
|
// x, y: Coords of the top left vertex
|
|
|
|
// x, y: Coords of the top left vertex
|
|
|
|
// width, height: Dimensions of the rectangle. Initialized to 0 if not specified.
|
|
|
|
// width, height: Dimensions of the rectangle. Initialized to 0 if not specified.
|
|
|
|
template <typename T>
|
|
|
|
template <typename T>
|
|
|
|
struct Rectangle {
|
|
|
|
struct Rectangle {
|
|
|
|
T x, y, width, height;
|
|
|
|
T x, y, width, height;
|
|
|
|
|
|
|
|
|
|
|
|
std::pair<T, T> topLeft() { return std::make_pair(x, y); }
|
|
|
|
std::pair<T, T> topLeft() { return std::make_pair(x, y); }
|
|
|
|
@@ -482,8 +514,8 @@ struct Rectangle {
|
|
|
|
bool isLine() { return (width == 0 && height != 0) || (width != 0 && height == 0); }
|
|
|
|
bool isLine() { return (width == 0 && height != 0) || (width != 0 && height == 0); }
|
|
|
|
|
|
|
|
|
|
|
|
void setEmpty() { x = y = width = height = 0; }
|
|
|
|
void setEmpty() { x = y = width = height = 0; }
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
using Rect = Rectangle<GLuint>;
|
|
|
|
using Rect = Rectangle<GLuint>;
|
|
|
|
|
|
|
|
|
|
|
|
} // end namespace OpenGL
|
|
|
|
} // end namespace OpenGL
|
|
|
|
|