2013-12-22 14:04:33 +00:00
|
|
|
#include "OpenGLVariable.h"
|
|
|
|
|
2013-12-23 09:26:29 +00:00
|
|
|
#include <cassert>
|
2015-12-07 22:32:55 +00:00
|
|
|
#include <QOpenGLShaderProgram>
|
|
|
|
#include <QImage>
|
|
|
|
#include "Logs.h"
|
2015-12-03 22:04:50 +00:00
|
|
|
#include "OpenGLFunctions.h"
|
2013-12-22 17:05:11 +00:00
|
|
|
#include "OpenGLRenderer.h"
|
2013-12-22 14:04:33 +00:00
|
|
|
#include "OpenGLShaderProgram.h"
|
|
|
|
#include "Vector3.h"
|
2013-12-22 16:30:48 +00:00
|
|
|
#include "Matrix4.h"
|
2013-12-22 14:04:33 +00:00
|
|
|
#include "Color.h"
|
2013-12-22 17:05:11 +00:00
|
|
|
#include "Texture2D.h"
|
|
|
|
#include "Texture3D.h"
|
|
|
|
#include "Texture4D.h"
|
2015-12-24 00:21:12 +00:00
|
|
|
#include "FractalNoise.h"
|
2013-12-22 14:04:33 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
typedef enum {
|
|
|
|
TYPE_NONE,
|
|
|
|
TYPE_TEXTURE_2D,
|
|
|
|
TYPE_TEXTURE_3D,
|
|
|
|
TYPE_TEXTURE_4D,
|
|
|
|
TYPE_INTEGER,
|
|
|
|
TYPE_FLOAT,
|
|
|
|
TYPE_VECTOR3,
|
|
|
|
TYPE_MATRIX4,
|
2015-12-24 00:21:12 +00:00
|
|
|
TYPE_NOISE,
|
2015-12-23 22:40:19 +00:00
|
|
|
TYPE_COLOR
|
|
|
|
} OpenGLVariableType;
|
|
|
|
|
|
|
|
class OpenGLVariable::pimpl {
|
|
|
|
public:
|
|
|
|
pimpl(const string &name) : name(name) {
|
|
|
|
type = TYPE_NONE;
|
|
|
|
texture_toupload = false;
|
|
|
|
texture_id = 0;
|
|
|
|
}
|
2015-12-07 22:32:55 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
string name;
|
|
|
|
OpenGLVariableType type;
|
|
|
|
|
|
|
|
int value_int;
|
|
|
|
float value_float;
|
|
|
|
unique_ptr<Color> value_color;
|
|
|
|
unique_ptr<Vector3> value_vector3;
|
|
|
|
unique_ptr<float[]> value_array_float;
|
|
|
|
|
|
|
|
int texture_size_x;
|
|
|
|
int texture_size_y;
|
|
|
|
int texture_size_z;
|
|
|
|
bool texture_toupload;
|
|
|
|
bool texture_repeat;
|
|
|
|
bool texture_color;
|
|
|
|
unsigned int texture_id;
|
|
|
|
};
|
|
|
|
|
|
|
|
OpenGLVariable::OpenGLVariable(const string &name) : impl(new pimpl(name)) {
|
2015-12-07 22:32:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
OpenGLVariable::~OpenGLVariable() {
|
2015-12-23 22:40:19 +00:00
|
|
|
if (impl->texture_id) {
|
|
|
|
Logs::warning("OpenGL") << "Texture ID " << impl->texture_id << " not freed in variable " << impl->name << endl;
|
2015-12-07 22:32:55 +00:00
|
|
|
}
|
2013-12-22 14:04:33 +00:00
|
|
|
}
|
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
void OpenGLVariable::apply(OpenGLShaderProgram *program, unsigned int &texture_unit) {
|
|
|
|
assert(program->isBound());
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
OpenGLFunctions *functions = program->getRenderer()->getOpenGlFunctions();
|
2013-12-22 17:05:11 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
if (impl->texture_toupload) {
|
|
|
|
uploadTexture(functions);
|
|
|
|
impl->texture_toupload = false;
|
2013-12-22 17:05:11 +00:00
|
|
|
}
|
2013-12-22 14:04:33 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
int loc = functions->glGetUniformLocation(program->getId(), impl->name.c_str());
|
|
|
|
if (loc >= 0) {
|
|
|
|
switch (impl->type) {
|
|
|
|
case TYPE_INTEGER:
|
|
|
|
functions->glUniform1i(loc, impl->value_int);
|
|
|
|
break;
|
|
|
|
case TYPE_FLOAT:
|
|
|
|
functions->glUniform1f(loc, impl->value_float);
|
|
|
|
break;
|
|
|
|
case TYPE_COLOR:
|
|
|
|
functions->glUniform4f(loc, to_float(impl->value_color->r), to_float(impl->value_color->g),
|
|
|
|
to_float(impl->value_color->b), to_float(impl->value_color->a));
|
|
|
|
break;
|
|
|
|
case TYPE_VECTOR3:
|
|
|
|
functions->glUniform3f(loc, to_float(impl->value_vector3->x), to_float(impl->value_vector3->y),
|
|
|
|
to_float(impl->value_vector3->z));
|
|
|
|
break;
|
|
|
|
case TYPE_MATRIX4:
|
|
|
|
functions->glUniformMatrix4fv(loc, 1, true, impl->value_array_float.get());
|
|
|
|
break;
|
|
|
|
case TYPE_TEXTURE_2D:
|
|
|
|
functions->glActiveTexture(GL_TEXTURE0 + texture_unit);
|
|
|
|
functions->glBindTexture(GL_TEXTURE_2D, impl->texture_id);
|
|
|
|
functions->glUniform1i(loc, static_cast<int>(texture_unit));
|
|
|
|
texture_unit++;
|
|
|
|
break;
|
|
|
|
case TYPE_TEXTURE_3D:
|
|
|
|
case TYPE_TEXTURE_4D:
|
|
|
|
functions->glActiveTexture(GL_TEXTURE0 + texture_unit);
|
|
|
|
functions->glBindTexture(GL_TEXTURE_3D, impl->texture_id);
|
|
|
|
functions->glUniform1i(loc, static_cast<int>(texture_unit));
|
|
|
|
texture_unit++;
|
|
|
|
break;
|
2015-12-24 00:21:12 +00:00
|
|
|
case TYPE_NOISE:
|
|
|
|
functions->glUniform1fv(loc, impl->value_int, impl->value_array_float.get());
|
|
|
|
break;
|
2015-12-23 22:40:19 +00:00
|
|
|
case TYPE_NONE:
|
|
|
|
break;
|
|
|
|
}
|
2013-12-22 14:04:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-10 22:41:42 +00:00
|
|
|
void OpenGLVariable::destroy(OpenGLFunctions *functions) {
|
2015-12-23 22:40:19 +00:00
|
|
|
if (impl->texture_id) {
|
|
|
|
functions->glDeleteTextures(1, &(impl->texture_id));
|
|
|
|
impl->texture_id = 0;
|
2015-12-10 22:41:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLVariable::set(const Texture2D *texture, bool repeat, bool color) {
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->type = TYPE_TEXTURE_2D;
|
2015-12-07 22:32:55 +00:00
|
|
|
|
|
|
|
int sx, sy;
|
|
|
|
texture->getSize(&sx, &sy);
|
2015-12-23 22:40:19 +00:00
|
|
|
float *pixels = new float[to_size(sx * sy * 4)];
|
2015-12-07 22:32:55 +00:00
|
|
|
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);
|
2015-12-23 22:40:19 +00:00
|
|
|
pixel[0] = to_float(col.r);
|
|
|
|
pixel[1] = to_float(col.g);
|
|
|
|
pixel[2] = to_float(col.b);
|
|
|
|
pixel[3] = to_float(col.a);
|
2015-12-07 22:32:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->value_array_float = unique_ptr<float[]>(pixels);
|
2015-12-07 22:32:55 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->texture_size_x = sx;
|
|
|
|
impl->texture_size_y = sy;
|
|
|
|
impl->texture_size_z = 0;
|
2015-12-07 22:32:55 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->texture_toupload = true;
|
|
|
|
impl->texture_repeat = repeat;
|
|
|
|
impl->texture_color = color;
|
2015-12-07 22:32:55 +00:00
|
|
|
}
|
|
|
|
|
2015-12-10 22:41:42 +00:00
|
|
|
void OpenGLVariable::set(const QImage &texture, bool repeat, bool color) {
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->type = TYPE_TEXTURE_2D;
|
2015-12-07 22:32:55 +00:00
|
|
|
|
|
|
|
int sx = texture.width(), sy = texture.height();
|
2015-12-23 22:40:19 +00:00
|
|
|
float *pixels = new float[to_size(sx * sy * 4)];
|
2015-12-07 22:32:55 +00:00
|
|
|
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));
|
2015-12-23 22:40:19 +00:00
|
|
|
pixel[0] = to_float(col.r);
|
|
|
|
pixel[1] = to_float(col.g);
|
|
|
|
pixel[2] = to_float(col.b);
|
|
|
|
pixel[3] = to_float(col.a);
|
2015-12-07 22:32:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->value_array_float = unique_ptr<float[]>(pixels);
|
2015-12-07 22:32:55 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->texture_size_x = sx;
|
|
|
|
impl->texture_size_y = sy;
|
|
|
|
impl->texture_size_z = 0;
|
2015-12-07 22:32:55 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->texture_toupload = true;
|
|
|
|
impl->texture_repeat = repeat;
|
|
|
|
impl->texture_color = color;
|
2013-12-22 17:05:11 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLVariable::set(const Texture3D *texture, bool repeat, bool color) {
|
2015-12-07 22:32:55 +00:00
|
|
|
int sx, sy, sz;
|
|
|
|
texture->getSize(&sx, &sy, &sz);
|
2015-12-23 22:40:19 +00:00
|
|
|
float *pixels = new float[to_size(sx * sy * sz * 4)];
|
2015-12-07 22:32:55 +00:00
|
|
|
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);
|
2015-12-23 22:40:19 +00:00
|
|
|
pixel[0] = to_float(col.r);
|
|
|
|
pixel[1] = to_float(col.g);
|
|
|
|
pixel[2] = to_float(col.b);
|
|
|
|
pixel[3] = to_float(col.a);
|
2015-12-07 22:32:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->value_array_float = unique_ptr<float[]>(pixels);
|
2015-12-07 22:32:55 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->texture_size_x = sx;
|
|
|
|
impl->texture_size_y = sy;
|
|
|
|
impl->texture_size_z = sz;
|
2015-12-07 22:32:55 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->type = TYPE_TEXTURE_3D;
|
|
|
|
impl->texture_toupload = true;
|
|
|
|
impl->texture_repeat = repeat;
|
|
|
|
impl->texture_color = color;
|
2013-12-22 17:05:11 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLVariable::set(const Texture4D *texture, bool repeat, bool color) {
|
2015-12-07 22:32:55 +00:00
|
|
|
int sx, sy, sz, sw;
|
|
|
|
texture->getSize(&sx, &sy, &sz, &sw);
|
2015-12-23 22:40:19 +00:00
|
|
|
float *pixels = new float[to_size(sx * sy * sz * sw * 4)];
|
2015-12-07 22:32:55 +00:00
|
|
|
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);
|
2015-12-23 22:40:19 +00:00
|
|
|
pixel[0] = to_float(col.r);
|
|
|
|
pixel[1] = to_float(col.g);
|
|
|
|
pixel[2] = to_float(col.b);
|
|
|
|
pixel[3] = to_float(col.a);
|
2015-12-07 22:32:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->value_array_float = unique_ptr<float[]>(pixels);
|
2015-12-07 22:32:55 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->texture_size_x = sx;
|
|
|
|
impl->texture_size_y = sy;
|
|
|
|
impl->texture_size_z = sz * sw;
|
2015-12-07 22:32:55 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->type = TYPE_TEXTURE_4D;
|
|
|
|
impl->texture_toupload = true;
|
|
|
|
impl->texture_repeat = repeat;
|
|
|
|
impl->texture_color = color;
|
2013-12-22 17:05:11 +00:00
|
|
|
}
|
|
|
|
|
2015-11-29 18:18:36 +00:00
|
|
|
void OpenGLVariable::set(int value) {
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->type = TYPE_INTEGER;
|
|
|
|
impl->value_int = value;
|
2015-11-25 22:15:58 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLVariable::set(float value) {
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->type = TYPE_FLOAT;
|
|
|
|
impl->value_float = value;
|
2013-12-22 14:04:33 +00:00
|
|
|
}
|
|
|
|
|
2015-12-24 00:21:12 +00:00
|
|
|
void OpenGLVariable::set(const FractalNoise &noise) {
|
|
|
|
impl->type = TYPE_NOISE;
|
|
|
|
|
|
|
|
impl->value_int = 4;
|
|
|
|
|
|
|
|
float *data = new float[4];
|
|
|
|
data[0] = to_float(noise.getScaling());
|
|
|
|
data[1] = to_float(noise.getHeight());
|
|
|
|
data[2] = to_float(noise.getStepScaling());
|
|
|
|
data[3] = to_float(noise.getStepHeight());
|
|
|
|
impl->value_array_float = unique_ptr<float[]>(data);
|
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLVariable::set(const Vector3 &vector) {
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->type = TYPE_VECTOR3;
|
|
|
|
impl->value_vector3 = make_unique<Vector3>(vector);
|
2013-12-22 16:30:48 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLVariable::set(const Matrix4 &matrix) {
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->type = TYPE_MATRIX4;
|
|
|
|
|
|
|
|
float *data = new float[16];
|
|
|
|
data[0] = to_float(matrix.getA());
|
|
|
|
data[1] = to_float(matrix.getB());
|
|
|
|
data[2] = to_float(matrix.getC());
|
|
|
|
data[3] = to_float(matrix.getD());
|
|
|
|
data[4] = to_float(matrix.getE());
|
|
|
|
data[5] = to_float(matrix.getF());
|
|
|
|
data[6] = to_float(matrix.getG());
|
|
|
|
data[7] = to_float(matrix.getH());
|
|
|
|
data[8] = to_float(matrix.getI());
|
|
|
|
data[9] = to_float(matrix.getJ());
|
|
|
|
data[10] = to_float(matrix.getK());
|
|
|
|
data[11] = to_float(matrix.getL());
|
|
|
|
data[12] = to_float(matrix.getM());
|
|
|
|
data[13] = to_float(matrix.getN());
|
|
|
|
data[14] = to_float(matrix.getO());
|
|
|
|
data[15] = to_float(matrix.getP());
|
|
|
|
|
|
|
|
impl->value_array_float = unique_ptr<float[]>(data);
|
2013-12-22 14:04:33 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void OpenGLVariable::set(const Color &color) {
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->type = TYPE_COLOR;
|
|
|
|
impl->value_color = make_unique<Color>(color);
|
|
|
|
}
|
2013-12-22 14:04:33 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
int OpenGLVariable::getIntValue() const {
|
|
|
|
return impl->value_int;
|
2013-12-22 14:04:33 +00:00
|
|
|
}
|
2013-12-22 17:05:11 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
float OpenGLVariable::getFloatValue() const {
|
|
|
|
return impl->value_float;
|
|
|
|
}
|
2013-12-22 17:05:11 +00:00
|
|
|
|
2015-12-24 00:21:12 +00:00
|
|
|
float OpenGLVariable::getFloatArrayValue(unsigned int index) const {
|
|
|
|
return impl->value_array_float[index];
|
|
|
|
}
|
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
void OpenGLVariable::uploadTexture(OpenGLFunctions *functions) {
|
|
|
|
assert(impl->type == TYPE_TEXTURE_2D or impl->type == TYPE_TEXTURE_3D or impl->type == TYPE_TEXTURE_4D);
|
2013-12-22 17:05:11 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
if (impl->texture_id == 0) {
|
2013-12-22 17:05:11 +00:00
|
|
|
GLuint texid;
|
|
|
|
functions->glGenTextures(1, &texid);
|
2015-12-23 22:40:19 +00:00
|
|
|
impl->texture_id = texid;
|
2013-12-22 17:05:11 +00:00
|
|
|
}
|
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
GLenum textype = (impl->type == TYPE_TEXTURE_2D) ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
2013-12-22 17:05:11 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
functions->glBindTexture(textype, impl->texture_id);
|
2013-12-22 17:05:11 +00:00
|
|
|
functions->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
functions->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
2015-12-23 22:40:19 +00:00
|
|
|
functions->glTexParameteri(textype, GL_TEXTURE_WRAP_S, impl->texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
|
|
|
functions->glTexParameteri(textype, GL_TEXTURE_WRAP_T, impl->texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
2015-11-09 21:30:46 +00:00
|
|
|
if (textype == GL_TEXTURE_3D) {
|
2015-12-23 22:40:19 +00:00
|
|
|
functions->glTexParameteri(textype, GL_TEXTURE_WRAP_R, impl->texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
2013-12-22 17:05:11 +00:00
|
|
|
}
|
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
int dest_format = impl->texture_color ? GL_RGBA : GL_RED;
|
2014-01-05 19:37:51 +00:00
|
|
|
|
2015-12-23 22:40:19 +00:00
|
|
|
if (impl->type == TYPE_TEXTURE_2D) {
|
|
|
|
functions->glTexImage2D(GL_TEXTURE_2D, 0, dest_format, impl->texture_size_x, impl->texture_size_y, 0, GL_RGBA,
|
|
|
|
GL_FLOAT, impl->value_array_float.get());
|
2015-11-09 21:30:46 +00:00
|
|
|
} else {
|
2015-12-23 22:40:19 +00:00
|
|
|
functions->glTexImage3D(GL_TEXTURE_3D, 0, dest_format, impl->texture_size_x, impl->texture_size_y,
|
|
|
|
impl->texture_size_z, 0, GL_RGBA, GL_FLOAT, impl->value_array_float.get());
|
2013-12-22 17:05:11 +00:00
|
|
|
}
|
|
|
|
}
|