#include "OpenGLVariable.h" #include #include #include #include #include #include #include "Logs.h" #include "OpenGLFunctions.h" #include "OpenGLRenderer.h" #include "OpenGLShaderProgram.h" #include "Vector3.h" #include "Matrix4.h" #include "Color.h" #include "Texture2D.h" #include "Texture3D.h" #include "Texture4D.h" OpenGLVariable::OpenGLVariable(const std::string &name) : name(name) { type = TYPE_NONE; texture_toupload = false; texture_id = 0; value_color = new QColor; value_matrix4 = new QMatrix4x4; value_vector3 = new QVector3D; value_texture_data = new float[1]; } OpenGLVariable::~OpenGLVariable() { delete value_color; delete value_matrix4; delete value_vector3; delete[] value_texture_data; if (texture_id) { Logs::warning() << "[OpenGL] Texture ID not freed " << texture_id << std::endl; } } void OpenGLVariable::apply(OpenGLShaderProgram *program, int &texture_unit) { QOpenGLShaderProgram *pr = program->getProgram(); OpenGLFunctions *functions = program->getRenderer()->getOpenGlFunctions(); if (texture_toupload) { uploadTexture(program->getRenderer()); texture_toupload = false; } switch (type) { case TYPE_INTEGER: pr->setUniformValue(name.c_str(), value_int); break; case TYPE_FLOAT: pr->setUniformValue(name.c_str(), value_float); break; case TYPE_COLOR: pr->setUniformValue(name.c_str(), *value_color); break; case TYPE_VECTOR3: pr->setUniformValue(name.c_str(), *value_vector3); break; case TYPE_MATRIX4: pr->setUniformValue(name.c_str(), *value_matrix4); break; case TYPE_TEXTURE_2D: functions->glActiveTexture(GL_TEXTURE0 + texture_unit); functions->glBindTexture(GL_TEXTURE_2D, texture_id); pr->setUniformValue(name.c_str(), texture_unit); texture_unit++; break; case TYPE_TEXTURE_3D: case TYPE_TEXTURE_4D: functions->glActiveTexture(GL_TEXTURE0 + texture_unit); functions->glBindTexture(GL_TEXTURE_3D, texture_id); pr->setUniformValue(name.c_str(), texture_unit); texture_unit++; break; case TYPE_NONE: break; } } void OpenGLVariable::set(const Texture2D *texture, bool repeat, bool color) { assert(type == TYPE_NONE or type == TYPE_TEXTURE_2D); type = TYPE_TEXTURE_2D; int sx, sy; texture->getSize(&sx, &sy); float *pixels = new float[sx * sy * 4]; for (int x = 0; x < sx; x++) { for (int y = 0; y < sy; y++) { float *pixel = pixels + (y * sx + x) * 4; Color col = texture->getPixel(x, y); pixel[0] = (float)col.r; pixel[1] = (float)col.g; pixel[2] = (float)col.b; pixel[3] = (float)col.a; } } float *old_pixels = value_texture_data; value_texture_data = pixels; delete[] old_pixels; texture_size_x = sx; texture_size_y = sy; texture_size_z = 0; texture_toupload = true; texture_repeat = repeat; texture_color = color; } void OpenGLVariable::set(const QImage &texture, bool repeat, bool color) { assert(type == TYPE_NONE or type == TYPE_TEXTURE_2D); type = TYPE_TEXTURE_2D; int sx = texture.width(), sy = texture.height(); float *pixels = new float[sx * sy * 4]; for (int x = 0; x < sx; x++) { for (int y = 0; y < sy; y++) { float *pixel = pixels + (y * sx + x) * 4; Color col = Color::from32BitRGBA(texture.pixel(x, y)); pixel[0] = (float)col.r; pixel[1] = (float)col.g; pixel[2] = (float)col.b; pixel[3] = (float)col.a; } } float *old_pixels = value_texture_data; value_texture_data = pixels; delete[] old_pixels; texture_size_x = sx; texture_size_y = sy; texture_size_z = 0; texture_toupload = true; texture_repeat = repeat; texture_color = color; } void OpenGLVariable::set(const Texture3D *texture, bool repeat, bool color) { assert(type == TYPE_NONE or type == TYPE_TEXTURE_3D); int sx, sy, sz; texture->getSize(&sx, &sy, &sz); float *pixels = new float[sx * sy * sz * 4]; for (int x = 0; x < sx; x++) { for (int y = 0; y < sy; y++) { for (int z = 0; z < sz; z++) { float *pixel = pixels + (z * (sx * sy) + y * sx + x) * 4; Color col = texture->getPixel(x, y, z); pixel[0] = (float)col.r; pixel[1] = (float)col.g; pixel[2] = (float)col.b; pixel[3] = (float)col.a; } } } float *old_pixels = value_texture_data; value_texture_data = pixels; delete[] old_pixels; texture_size_x = sx; texture_size_y = sy; texture_size_z = sz; type = TYPE_TEXTURE_3D; texture_toupload = true; texture_repeat = repeat; texture_color = color; } void OpenGLVariable::set(const Texture4D *texture, bool repeat, bool color) { assert(type == TYPE_NONE or type == TYPE_TEXTURE_4D); int sx, sy, sz, sw; texture->getSize(&sx, &sy, &sz, &sw); float *pixels = new float[sx * sy * sz * sw * 4]; for (int x = 0; x < sx; x++) { for (int y = 0; y < sy; y++) { for (int z = 0; z < sz; z++) { for (int w = 0; w < sw; w++) { float *pixel = pixels + (w * (sx * sy * sz) + z * (sx * sy) + y * sx + x) * 4; Color col = texture->getPixel(x, y, z, w); pixel[0] = (float)col.r; pixel[1] = (float)col.g; pixel[2] = (float)col.b; pixel[3] = (float)col.a; } } } } float *old_pixels = value_texture_data; value_texture_data = pixels; delete[] old_pixels; texture_size_x = sx; texture_size_y = sy; texture_size_z = sz * sw; type = TYPE_TEXTURE_4D; texture_toupload = true; texture_repeat = repeat; texture_color = color; } void OpenGLVariable::set(int value) { assert(type == TYPE_NONE or type == TYPE_INTEGER); type = TYPE_INTEGER; value_int = value; } void OpenGLVariable::set(float value) { assert(type == TYPE_NONE or type == TYPE_FLOAT); type = TYPE_FLOAT; value_float = value; } void OpenGLVariable::set(const Vector3 &vector) { set(QVector3D(vector.x, vector.y, vector.z)); } void OpenGLVariable::set(const QVector3D &vector) { assert(type == TYPE_NONE or type == TYPE_VECTOR3); type = TYPE_VECTOR3; *value_vector3 = vector; } void OpenGLVariable::set(const Matrix4 &matrix) { set(matrix.toQMatrix()); } void OpenGLVariable::set(const QMatrix4x4 &matrix) { assert(type == TYPE_NONE or type == TYPE_MATRIX4); type = TYPE_MATRIX4; *value_matrix4 = matrix; } void OpenGLVariable::set(const Color &color) { assert(type == TYPE_NONE or type == TYPE_COLOR); type = TYPE_COLOR; *value_color = QColor::fromRgbF(color.r, color.g, color.b); } void OpenGLVariable::uploadTexture(OpenGLRenderer *renderer) { OpenGLFunctions *functions = renderer->getOpenGlFunctions(); assert(type == TYPE_TEXTURE_2D or type == TYPE_TEXTURE_3D or type == TYPE_TEXTURE_4D); if (texture_id == 0) { GLuint texid; functions->glGenTextures(1, &texid); texture_id = texid; } GLenum textype = (type == TYPE_TEXTURE_2D) ? GL_TEXTURE_2D : GL_TEXTURE_3D; functions->glBindTexture(textype, texture_id); functions->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_LINEAR); functions->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_LINEAR); functions->glTexParameteri(textype, GL_TEXTURE_WRAP_S, texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE); functions->glTexParameteri(textype, GL_TEXTURE_WRAP_T, texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE); if (textype == GL_TEXTURE_3D) { functions->glTexParameteri(textype, GL_TEXTURE_WRAP_R, texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE); } int dest_format = texture_color ? GL_RGBA : GL_RED; if (type == TYPE_TEXTURE_2D) { functions->glTexImage2D(GL_TEXTURE_2D, 0, dest_format, texture_size_x, texture_size_y, 0, GL_RGBA, GL_FLOAT, value_texture_data); } else { functions->glTexImage3D(GL_TEXTURE_3D, 0, dest_format, texture_size_x, texture_size_y, texture_size_z, 0, GL_RGBA, GL_FLOAT, value_texture_data); } }