paysages3d/src/render/opengl/OpenGLVariable.cpp
Michaël Lemaire 9196be4c05 Merge branch 'master' into vegetation
Conflicts:
	src/render/opengl/OpenGLShaderProgram.cpp
	src/render/opengl/OpenGLShaderProgram.h
	src/render/opengl/opengl_global.h
2015-12-08 01:28:15 +01:00

290 lines
8.4 KiB
C++

#include "OpenGLVariable.h"
#include <cassert>
#include <QOpenGLShaderProgram>
#include <QColor>
#include <QVector3D>
#include <QMatrix4x4>
#include <QImage>
#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);
}
}