#define GLEW_STATIC #include #include #include #include "utils/Array.h" #include "utils/Logger.h" #include "wrapper/GL.h" static_assert(std::is_same::value, "shader has invalid type"); static_assert(std::is_same::value, "p has invalid type"); static_assert(std::is_same::value, "char has invalid type"); static_assert(std::is_same::value, "int has invalid type"); static_assert(std::is_same::value, "float has invalid type"); static_assert(std::is_same::value, "shader type has invalid type"); static_assert(std::is_same::value, "texture has invalid type"); static_assert(std::is_same::value, "framebuffer has invalid type"); static_assert(std::is_same::value, "color attachment has invalid type"); static_assert(std::is_same::value, "vertex array has invalid type"); static_assert(std::is_same::value, "buffer has invalid type"); GL::ShaderType GL::VERTEX_SHADER = GL_VERTEX_SHADER; GL::ShaderType GL::FRAGMENT_SHADER = GL_FRAGMENT_SHADER; GL::ShaderType GL::GEOMETRY_SHADER = GL_GEOMETRY_SHADER; GL::Attribute::Attribute(int count, int size, int type, bool normalized) : count(count), size(size), type(type), normalized(normalized) { } GL::Attribute GL::Attribute::newFloat(int count) { return GL::Attribute(count, sizeof(float), GL_FLOAT, false); } GL::Attribute GL::Attribute::newColor(int count) { return GL::Attribute(count, sizeof(unsigned char), GL_UNSIGNED_BYTE, true); } GL::Attribute GL::Attribute::newDummy() { return GL::Attribute(0, 0, -1, false); } bool GL::Attribute::isDummy() const { return type == -1; } int GL::Attribute::getSize() const { return count * size; } GL::TextureFormat::TextureFormat(int internalformat, int format, int type) : internalformat(internalformat), format(format), type(type) { } GL::TextureFormat GL::TextureFormat::color8(int channels) { switch(channels) { case 1: return TextureFormat(GL_RED, GL_RED, GL_UNSIGNED_BYTE); case 2: return TextureFormat(GL_RG, GL_RG, GL_UNSIGNED_BYTE); case 3: return TextureFormat(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE); case 4: return TextureFormat(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); } LOG_ERROR(StringBuffer<50>(channels).append( " is not a valid amount of channels")); return unknown(); } GL::TextureFormat GL::TextureFormat::float16(int channels) { switch(channels) { case 1: return TextureFormat(GL_R16F, GL_RED, GL_FLOAT); case 2: return TextureFormat(GL_RG16F, GL_RG, GL_FLOAT); case 3: return TextureFormat(GL_RGB16F, GL_RGB, GL_FLOAT); case 4: return TextureFormat(GL_RGBA16F, GL_RGBA, GL_FLOAT); } LOG_ERROR(StringBuffer<50>(channels).append( " is not a valid amount of channels")); return unknown(); } GL::TextureFormat GL::TextureFormat::float32(int channels) { switch(channels) { case 1: return TextureFormat(GL_R32F, GL_RED, GL_FLOAT); case 2: return TextureFormat(GL_RG32F, GL_RG, GL_FLOAT); case 3: return TextureFormat(GL_RGB32F, GL_RGB, GL_FLOAT); case 4: return TextureFormat(GL_RGBA32F, GL_RGBA, GL_FLOAT); } LOG_ERROR(StringBuffer<50>(channels).append( " is not a valid amount of channels")); return unknown(); } GL::TextureFormat GL::TextureFormat::depth16() { return TextureFormat(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_FLOAT); } GL::TextureFormat GL::TextureFormat::depth32() { return TextureFormat(GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT); } GL::TextureFormat GL::TextureFormat::unknown() { return TextureFormat(-1, -1, -1); } bool GL::printError(const char* message) { GLenum error = glGetError(); if(error != GL_NO_ERROR) { LOG_ERROR(StringBuffer<100>(message).append(": ").append( gluErrorString(error))); return true; } return false; } Error GL::getError(const char* message) { GLenum error = glGetError(); if(error != GL_NO_ERROR) { Error e = {message}; e.message.append(": ").append(gluErrorString(error)); return e; } return {}; } void GL::enableDepthTesting() { glEnable(GL_DEPTH_TEST); } void GL::disableDepthTesting() { glDisable(GL_DEPTH_TEST); } void GL::bindMainFramebuffer() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } void GL::clear() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void GL::enableBlending() { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); } void GL::disableBlending() { glDisable(GL_BLEND); } void GL::setViewport(int width, int height) { glViewport(0, 0, width, height); } void GL::vertexAttribPointer(int index, const Attribute& a, int stride, int offset) { glVertexAttribPointer(index, a.count, a.type, a.normalized, stride, static_cast(0) + offset); glEnableVertexAttribArray(index); } GL::Program GL::createProgram() { return glCreateProgram(); } void GL::attachShader(Program p, Shader s) { glAttachShader(p, s); } void GL::linkProgram(Program p) { glLinkProgram(p); } Error GL::getLinkerError(Program p) { GLint linked; glGetProgramiv(p, GL_LINK_STATUS, &linked); if(!linked) { Array log; glGetProgramInfoLog(p, log.getLength(), nullptr, log.begin()); Error e = {"linker log: "}; e.message.append(static_cast(log.begin())); return e; } return {}; } void GL::deleteShader(Shader s) { glDeleteShader(s); } void GL::deleteProgram(Program p) { glDeleteProgram(p); } GL::Shader GL::createShader(ShaderType type) { return glCreateShader(type); } void GL::compileShader(Shader s, const char* code) { glShaderSource(s, 1, &code, nullptr); glCompileShader(s); } Error GL::getCompileError(Shader s) { GLint compiled; glGetShaderiv(s, GL_COMPILE_STATUS, &compiled); if(!compiled) { Array log; glGetShaderInfoLog(s, log.getLength(), nullptr, log.begin()); Error e = {"compiler log: "}; e.message.append(static_cast(log.begin())); return e; } return {}; } void GL::useProgram(Program p) { glUseProgram(p); } void GL::setMatrix(Program p, const char* name, const float* data) { glUniformMatrix4fv(glGetUniformLocation(p, name), 1, GL_TRUE, data); } void GL::setInt(Program p, const char* name, int data) { glUniform1i(glGetUniformLocation(p, name), data); } void GL::setFloat(Program p, const char* name, float data) { glUniform1f(glGetUniformLocation(p, name), data); } void GL::set2Float(Program p, const char* name, const float* data) { glUniform2fv(glGetUniformLocation(p, name), 1, data); } void GL::set3Float(Program p, const char* name, const float* data) { glUniform3fv(glGetUniformLocation(p, name), 1, data); } void GL::set4Float(Program p, const char* name, const float* data) { glUniform4fv(glGetUniformLocation(p, name), 1, data); } void GL::texImage2D(const TextureFormat& tf, int width, int height, const void* data, int level) { glTexImage2D(GL_TEXTURE_2D, level, tf.internalformat, width, height, 0, tf.format, tf.type, data); } GL::Texture GL::genTexture() { Texture t; glGenTextures(1, &t); return t; } void GL::deleteTexture(Texture t) { glDeleteTextures(1, &t); } void GL::setNearFilter2D() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } void GL::setMipMapNearFilter2D() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } void GL::setLinearFilter2D() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } void GL::setMipMapLinearFilter2D() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } void GL::setClampWrap2D() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } void GL::setRepeatWrap2D() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } void GL::bindTexture2D(Texture t) { glBindTexture(GL_TEXTURE_2D, t); } void GL::activeTexture(int index) { glActiveTexture(GL_TEXTURE0 + index); } void GL::generateMipmap2D(int maxLevels) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevels); glGenerateMipmap(GL_TEXTURE_2D); } void GL::deleteFramebuffers(Framebuffer fb) { glDeleteFramebuffers(1, &fb); } GL::Framebuffer GL::genFramebuffer() { Framebuffer fb; glGenFramebuffers(1, &fb); return fb; } void GL::bindFramebuffer(Framebuffer fb) { glBindFramebuffer(GL_FRAMEBUFFER, fb); } void GL::framebufferDepthTexture2D(Texture t) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, t, 0); } GL::ColorAttachment GL::framebufferColorTexture2D(Texture t, int index) { GLenum c = GL_COLOR_ATTACHMENT0 + index; glFramebufferTexture2D(GL_FRAMEBUFFER, c, GL_TEXTURE_2D, t, 0); return c; } void GL::drawBuffers(int length, ColorAttachment* c) { glDrawBuffers(length, c); } Error GL::getFramebufferError() { GLenum error = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(error != GL_FRAMEBUFFER_COMPLETE) { Error e = {"framebuffer error: "}; e.message.append(error); return e; } return {}; } GL::VertexArray GL::genVertexArray() { VertexArray va; glGenVertexArrays(1, &va); return va; } GL::Buffer GL::genBuffer() { Buffer b; glGenBuffers(1, &b); return b; } void GL::deleteBuffer(Buffer b) { glDeleteBuffers(1, &b); } void GL::deleteVertexArray(VertexArray va) { glDeleteVertexArrays(1, &va); } void GL::bindVertexArray(VertexArray va) { glBindVertexArray(va); } void GL::bindBuffer(Buffer b) { glBindBuffer(GL_ARRAY_BUFFER, b); } void GL::bufferDataStatic(int size, const void* data) { glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); } void GL::bufferDataStream(int size, const void* data) { glBufferData(GL_ARRAY_BUFFER, size, data, GL_STREAM_DRAW); } void GL::bufferDataDynamic(int size, const void* data) { glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW); } void GL::bufferSubData(int offset, int size, const void* data) { glBufferSubData(GL_ARRAY_BUFFER, offset, size, data); } void GL::drawTriangles(int offset, int vertices) { glDrawArrays(GL_TRIANGLES, offset, vertices); } void GL::drawTriangleStrip(int offset, int vertices) { glDrawArrays(GL_TRIANGLE_STRIP, offset, vertices); } void GL::drawPoints(int offset, int vertices) { glDrawArrays(GL_POINTS, offset, vertices); }