From 992089f0ef4efa84958b451cc20ad2a0f8c72579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 22 Dec 2013 18:05:11 +0100 Subject: [PATCH] Added textures to OpenGLSharedState --- src/basics/Texture2D.cpp | 18 +-- src/basics/Texture2D.h | 14 +- src/basics/Texture3D.cpp | 18 +-- src/basics/Texture3D.h | 14 +- src/basics/Texture4D.cpp | 18 +-- src/basics/Texture4D.h | 14 +- src/render/opengl/OpenGLShaderProgram.cpp | 149 +-------------------- src/render/opengl/OpenGLShaderProgram.h | 11 +- src/render/opengl/OpenGLSharedState.cpp | 4 +- src/render/opengl/OpenGLSharedState.h | 2 +- src/render/opengl/OpenGLSkybox.cpp | 4 +- src/render/opengl/OpenGLVariable.cpp | 154 +++++++++++++++++++++- src/render/opengl/OpenGLVariable.h | 11 +- 13 files changed, 219 insertions(+), 212 deletions(-) diff --git a/src/basics/Texture2D.cpp b/src/basics/Texture2D.cpp index 5950490..13e71e7 100644 --- a/src/basics/Texture2D.cpp +++ b/src/basics/Texture2D.cpp @@ -19,7 +19,7 @@ Texture2D::~Texture2D() delete[] data; } -void Texture2D::getSize(int* xsize, int* ysize) +void Texture2D::getSize(int* xsize, int* ysize) const { *xsize = this->xsize; *ysize = this->ysize; @@ -33,7 +33,7 @@ void Texture2D::setPixel(int x, int y, Color col) data[y * xsize + x] = col; } -Color Texture2D::getPixel(int x, int y) +Color Texture2D::getPixel(int x, int y) const { assert(x >= 0 && x < xsize); assert(y >= 0 && y < ysize); @@ -41,7 +41,7 @@ Color Texture2D::getPixel(int x, int y) return data[y * xsize + x]; } -Color Texture2D::getNearest(double dx, double dy) +Color Texture2D::getNearest(double dx, double dy) const { if (dx < 0.0) dx = 0.0; if (dx > 1.0) dx = 1.0; @@ -57,7 +57,7 @@ Color Texture2D::getNearest(double dx, double dy) return this->data[iy * this->xsize + ix]; } -Color Texture2D::getLinear(double dx, double dy) +Color Texture2D::getLinear(double dx, double dy) const { if (dx < 0.0) dx = 0.0; if (dx > 1.0) dx = 1.0; @@ -89,7 +89,7 @@ Color Texture2D::getLinear(double dx, double dy) return c1.lerp(c2, dy); } -Color Texture2D::getCubic(double dx, double dy) +Color Texture2D::getCubic(double dx, double dy) const { /* TODO */ return getLinear(dx, dy); @@ -122,7 +122,7 @@ void Texture2D::add(Texture2D* source) } } -void Texture2D::save(PackStream* stream) +void Texture2D::save(PackStream* stream) const { int i, n; stream->write(&this->xsize); @@ -151,17 +151,17 @@ void Texture2D::load(PackStream* stream) class Texture2DWriter:public PictureWriter { public: - Texture2DWriter(Texture2D *tex): tex(tex) {} + Texture2DWriter(const Texture2D *tex): tex(tex) {} virtual unsigned int getPixel(int x, int y) override { return tex->getPixel(x, y).to32BitBGRA(); } private: - Texture2D *tex; + const Texture2D *tex; }; -void Texture2D::saveToFile(const std::string &filepath) +void Texture2D::saveToFile(const std::string &filepath) const { Texture2DWriter writer(this); writer.save(filepath, xsize, ysize); diff --git a/src/basics/Texture2D.h b/src/basics/Texture2D.h index 94bc39f..67d1649 100644 --- a/src/basics/Texture2D.h +++ b/src/basics/Texture2D.h @@ -12,17 +12,17 @@ public: Texture2D(int xsize, int ysize); ~Texture2D(); - void getSize(int* xsize, int* ysize); + void getSize(int* xsize, int* ysize) const; void setPixel(int x, int y, Color col); - Color getPixel(int x, int y); - Color getNearest(double dx, double dy); - Color getLinear(double dx, double dy); - Color getCubic(double dx, double dy); + Color getPixel(int x, int y) const; + Color getNearest(double dx, double dy) const; + Color getLinear(double dx, double dy) const; + Color getCubic(double dx, double dy) const; void fill(Color col); void add(Texture2D* other); - void save(PackStream* stream); + void save(PackStream* stream) const; void load(PackStream* stream); - void saveToFile(const std::string &filepath); + void saveToFile(const std::string &filepath) const; private: int xsize; diff --git a/src/basics/Texture3D.cpp b/src/basics/Texture3D.cpp index bca20a7..55400e2 100644 --- a/src/basics/Texture3D.cpp +++ b/src/basics/Texture3D.cpp @@ -20,7 +20,7 @@ Texture3D::~Texture3D() delete[] data; } -void Texture3D::getSize(int* xsize, int* ysize, int* zsize) +void Texture3D::getSize(int* xsize, int* ysize, int* zsize) const { *xsize = this->xsize; *ysize = this->ysize; @@ -36,7 +36,7 @@ void Texture3D::setPixel(int x, int y, int z, Color col) this->data[z * this->xsize * this->ysize + y * this->xsize + x] = col; } -Color Texture3D::getPixel(int x, int y, int z) +Color Texture3D::getPixel(int x, int y, int z) const { assert(x >= 0 && x < this->xsize); assert(y >= 0 && y < this->ysize); @@ -45,7 +45,7 @@ Color Texture3D::getPixel(int x, int y, int z) return this->data[z * this->xsize * this->ysize + y * this->xsize + x]; } -Color Texture3D::getNearest(double dx, double dy, double dz) +Color Texture3D::getNearest(double dx, double dy, double dz) const { if (dx < 0.0) dx = 0.0; if (dx > 1.0) dx = 1.0; @@ -65,7 +65,7 @@ Color Texture3D::getNearest(double dx, double dy, double dz) return this->data[iz * this->xsize * this->ysize + iy * this->xsize + ix]; } -Color Texture3D::getLinear(double dx, double dy, double dz) +Color Texture3D::getLinear(double dx, double dy, double dz) const { if (dx < 0.0) dx = 0.0; if (dx > 1.0) dx = 1.0; @@ -112,7 +112,7 @@ Color Texture3D::getLinear(double dx, double dy, double dz) return cy1.lerp(cy2, dz); } -Color Texture3D::getCubic(double dx, double dy, double dz) +Color Texture3D::getCubic(double dx, double dy, double dz) const { /* TODO */ return getLinear(dx, dy, dz); @@ -146,7 +146,7 @@ void Texture3D::add(Texture3D* source) } } -void Texture3D::save(PackStream* stream) +void Texture3D::save(PackStream* stream) const { int i, n; stream->write(&this->xsize); @@ -177,7 +177,7 @@ void Texture3D::load(PackStream* stream) class Texture3DWriter:public PictureWriter { public: - Texture3DWriter(Texture3D *tex): tex(tex) {} + Texture3DWriter(const Texture3D *tex): tex(tex) {} virtual unsigned int getPixel(int x, int y) override { @@ -190,10 +190,10 @@ public: return tex->getPixel(x, y, z).to32BitBGRA(); } private: - Texture3D *tex; + const Texture3D *tex; }; -void Texture3D::saveToFile(const std::string &filepath) +void Texture3D::saveToFile(const std::string &filepath) const { Texture3DWriter writer(this); writer.save(filepath, xsize, ysize * zsize); diff --git a/src/basics/Texture3D.h b/src/basics/Texture3D.h index 3c40f16..8a68208 100644 --- a/src/basics/Texture3D.h +++ b/src/basics/Texture3D.h @@ -12,17 +12,17 @@ public: Texture3D(int xsize, int ysize, int zsize); ~Texture3D(); - void getSize(int* xsize, int* ysize, int* zsize); + void getSize(int* xsize, int* ysize, int* zsize) const; void setPixel(int x, int y, int z, Color col); - Color getPixel(int x, int y, int z); - Color getNearest(double dx, double dy, double dz); - Color getLinear(double dx, double dy, double dz); - Color getCubic(double dx, double dy, double dz); + Color getPixel(int x, int y, int z) const; + Color getNearest(double dx, double dy, double dz) const; + Color getLinear(double dx, double dy, double dz) const; + Color getCubic(double dx, double dy, double dz) const; void fill(Color col); void add(Texture3D* other); - void save(PackStream* stream); + void save(PackStream* stream) const; void load(PackStream* stream); - void saveToFile(const std::string &filepath); + void saveToFile(const std::string &filepath) const; private: int xsize; diff --git a/src/basics/Texture4D.cpp b/src/basics/Texture4D.cpp index 8700ecd..877ea4b 100644 --- a/src/basics/Texture4D.cpp +++ b/src/basics/Texture4D.cpp @@ -21,7 +21,7 @@ Texture4D::~Texture4D() delete[] data; } -void Texture4D::getSize(int* xsize, int* ysize, int* zsize, int* wsize) +void Texture4D::getSize(int* xsize, int* ysize, int* zsize, int* wsize) const { *xsize = this->xsize; *ysize = this->ysize; @@ -39,7 +39,7 @@ void Texture4D::setPixel(int x, int y, int z, int w, Color col) this->data[w * this->xsize * this->ysize * this->zsize + z * this->xsize * this->ysize + y * this->xsize + x] = col; } -Color Texture4D::getPixel(int x, int y, int z, int w) +Color Texture4D::getPixel(int x, int y, int z, int w) const { assert(x >= 0 && x < this->xsize); assert(y >= 0 && y < this->ysize); @@ -49,7 +49,7 @@ Color Texture4D::getPixel(int x, int y, int z, int w) return this->data[w * this->xsize * this->ysize * this->zsize + z * this->xsize * this->ysize + y * this->xsize + x]; } -Color Texture4D::getNearest(double dx, double dy, double dz, double dw) +Color Texture4D::getNearest(double dx, double dy, double dz, double dw) const { if (dx < 0.0) dx = 0.0; if (dx > 1.0) dx = 1.0; @@ -73,7 +73,7 @@ Color Texture4D::getNearest(double dx, double dy, double dz, double dw) return this->data[iw * this->xsize * this->ysize * this->zsize + iz * this->xsize * this->ysize + iy * this->xsize + ix]; } -Color Texture4D::getLinear(double dx, double dy, double dz, double dw) +Color Texture4D::getLinear(double dx, double dy, double dz, double dw) const { if (dx < 0.0) dx = 0.0; if (dx > 1.0) dx = 1.0; @@ -143,7 +143,7 @@ Color Texture4D::getLinear(double dx, double dy, double dz, double dw) return cz1.lerp(cz2, dw); } -Color Texture4D::getCubic(double dx, double dy, double dz, double dw) +Color Texture4D::getCubic(double dx, double dy, double dz, double dw) const { /* TODO */ return getLinear(dx, dy, dz, dw); @@ -178,7 +178,7 @@ void Texture4D::add(Texture4D* source) } } -void Texture4D::save(PackStream* stream) +void Texture4D::save(PackStream* stream) const { int i, n; stream->write(&this->xsize); @@ -212,7 +212,7 @@ void Texture4D::load(PackStream* stream) class Texture4DWriter:public PictureWriter { public: - Texture4DWriter(Texture4D *tex): tex(tex) {} + Texture4DWriter(const Texture4D *tex): tex(tex) {} virtual unsigned int getPixel(int x, int y) override { @@ -228,10 +228,10 @@ public: return tex->getPixel(x, y, z, w).to32BitBGRA(); } private: - Texture4D *tex; + const Texture4D *tex; }; -void Texture4D::saveToFile(const std::string &filepath) +void Texture4D::saveToFile(const std::string &filepath) const { Texture4DWriter writer(this); writer.save(filepath, xsize * wsize, ysize * zsize); diff --git a/src/basics/Texture4D.h b/src/basics/Texture4D.h index 3657951..6b53580 100644 --- a/src/basics/Texture4D.h +++ b/src/basics/Texture4D.h @@ -12,17 +12,17 @@ public: Texture4D(int xsize, int ysize, int zsize, int wsize); ~Texture4D(); - void getSize(int* xsize, int* ysize, int* zsize, int* wsize); + void getSize(int* xsize, int* ysize, int* zsize, int* wsize) const; void setPixel(int x, int y, int z, int w, Color col); - Color getPixel(int x, int y, int z, int w); - Color getNearest(double dx, double dy, double dz, double dw); - Color getLinear(double dx, double dy, double dz, double dw); - Color getCubic(double dx, double dy, double dz, double dw); + Color getPixel(int x, int y, int z, int w) const; + Color getNearest(double dx, double dy, double dz, double dw) const; + Color getLinear(double dx, double dy, double dz, double dw) const; + Color getCubic(double dx, double dy, double dz, double dw) const; void fill(Color col); void add(Texture4D* other); - void save(PackStream* stream); + void save(PackStream* stream) const; void load(PackStream* stream); - void saveToFile(const std::string &filepath); + void saveToFile(const std::string &filepath) const; private: int xsize; diff --git a/src/render/opengl/OpenGLShaderProgram.cpp b/src/render/opengl/OpenGLShaderProgram.cpp index 9023b4d..03289a3 100644 --- a/src/render/opengl/OpenGLShaderProgram.cpp +++ b/src/render/opengl/OpenGLShaderProgram.cpp @@ -44,157 +44,12 @@ void OpenGLShaderProgram::compile() } } -void OpenGLShaderProgram::addTexture(QString sampler_name, Texture2D* texture) -{ - GLuint texid; - - if (textures.contains(sampler_name)) - { - texid = textures[sampler_name].second; - } - else - { - functions->glGenTextures(1, &texid); - textures[sampler_name] = QPair(GL_TEXTURE_2D, texid); - } - - functions->glBindTexture(GL_TEXTURE_2D, texid); - functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - 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; - } - } - - functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sx, sy, 0, GL_RGBA, GL_FLOAT, pixels); - delete[] pixels; -} - -void OpenGLShaderProgram::addTexture(QString sampler_name, Texture3D* texture) -{ - GLuint texid; - - if (textures.contains(sampler_name)) - { - texid = textures[sampler_name].second; - } - else - { - functions->glGenTextures(1, &texid); - textures[sampler_name] = QPair(GL_TEXTURE_3D, texid); - } - - functions->glBindTexture(GL_TEXTURE_3D, texid); - functions->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - functions->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - functions->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - functions->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - functions->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - 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; - } - } - } - - functions->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, sx, sy, sz, 0, GL_RGBA, GL_FLOAT, pixels); - delete[] pixels; -} - -void OpenGLShaderProgram::addTexture(QString sampler_name, Texture4D* texture) -{ - GLuint texid; - - if (textures.contains(sampler_name)) - { - texid = textures[sampler_name].second; - } - else - { - functions->glGenTextures(1, &texid); - textures[sampler_name] = QPair(GL_TEXTURE_3D, texid); - } - - functions->glBindTexture(GL_TEXTURE_3D, texid); - functions->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - functions->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - functions->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - functions->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - functions->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - 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; - } - } - } - } - - functions->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, sx, sy, sz * sw, 0, GL_RGBA, GL_FLOAT, pixels); - delete[] pixels; -} - void OpenGLShaderProgram::bind() { program->bind(); - renderer->getSharedState()->apply(this); - - QMapIterator > iter(textures); - int i = 0; - while (iter.hasNext()) - { - iter.next(); - int textureSampler = program->uniformLocation(iter.key()); - if (textureSampler >= 0) - { - functions->glActiveTexture(GL_TEXTURE0 + i); - functions->glBindTexture(iter.value().first, iter.value().second); - program->setUniformValue(textureSampler, i); - i++; - } - } + int texture_unit = 0; + renderer->getSharedState()->apply(this, texture_unit); } void OpenGLShaderProgram::release() diff --git a/src/render/opengl/OpenGLShaderProgram.h b/src/render/opengl/OpenGLShaderProgram.h index 0f23c2a..fa4d5c1 100644 --- a/src/render/opengl/OpenGLShaderProgram.h +++ b/src/render/opengl/OpenGLShaderProgram.h @@ -4,10 +4,6 @@ #include "opengl_global.h" #include -#include -#include -#include -#include class QOpenGLShaderProgram; class QOpenGLFunctions_3_2_Core; @@ -25,15 +21,12 @@ public: void addFragmentSource(QString path); void compile(); - void addTexture(QString sampler_name, Texture2D* texture); - void addTexture(QString sampler_name, Texture3D* texture); - void addTexture(QString sampler_name, Texture4D* texture); - void drawTriangles(float* vertices, int triangle_count); void drawTriangleStrip(float* vertices, int vertex_count); protected: inline QOpenGLShaderProgram* getProgram() const {return program;} + inline OpenGLRenderer* getRenderer() const {return renderer;} friend class OpenGLVariable; private: @@ -45,8 +38,6 @@ private: QString name; QOpenGLShaderProgram* program; QOpenGLFunctions_3_2_Core* functions; - - QMap > textures; }; } diff --git a/src/render/opengl/OpenGLSharedState.cpp b/src/render/opengl/OpenGLSharedState.cpp index a504fd8..b59951d 100644 --- a/src/render/opengl/OpenGLSharedState.cpp +++ b/src/render/opengl/OpenGLSharedState.cpp @@ -4,11 +4,11 @@ OpenGLSharedState::OpenGLSharedState() { } -void OpenGLSharedState::apply(OpenGLShaderProgram *program) +void OpenGLSharedState::apply(OpenGLShaderProgram *program, int &texture_unit) { for (const auto &pair : variables) { - pair.second->apply(program); + pair.second->apply(program, texture_unit); } } diff --git a/src/render/opengl/OpenGLSharedState.h b/src/render/opengl/OpenGLSharedState.h index 8ce3d00..afe8817 100644 --- a/src/render/opengl/OpenGLSharedState.h +++ b/src/render/opengl/OpenGLSharedState.h @@ -20,7 +20,7 @@ public: /*! * \brief Apply the stored variables to the bound program. */ - void apply(OpenGLShaderProgram* program); + void apply(OpenGLShaderProgram* program, int &texture_unit); /*! * \brief Get or create a variable in the state. diff --git a/src/render/opengl/OpenGLSkybox.cpp b/src/render/opengl/OpenGLSkybox.cpp index 11773b0..bc6376a 100644 --- a/src/render/opengl/OpenGLSkybox.cpp +++ b/src/render/opengl/OpenGLSkybox.cpp @@ -59,8 +59,8 @@ void OpenGLSkybox::update() renderer->getSharedState()->set("sunColor", sun_color); SoftwareBrunetonAtmosphereRenderer* bruneton = (SoftwareBrunetonAtmosphereRenderer*)renderer->getAtmosphereRenderer(); - program->addTexture("transmittanceTexture", bruneton->getModel()->getTextureTransmittance()); - program->addTexture("inscatterTexture", bruneton->getModel()->getTextureInscatter()); + renderer->getSharedState()->set("transmittanceTexture", bruneton->getModel()->getTextureTransmittance()); + renderer->getSharedState()->set("inscatterTexture", bruneton->getModel()->getTextureInscatter()); } void OpenGLSkybox::render() diff --git a/src/render/opengl/OpenGLVariable.cpp b/src/render/opengl/OpenGLVariable.cpp index b7d864e..11e97a5 100644 --- a/src/render/opengl/OpenGLVariable.cpp +++ b/src/render/opengl/OpenGLVariable.cpp @@ -2,20 +2,33 @@ #include #include +#include +#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; } -void OpenGLVariable::apply(OpenGLShaderProgram *program) +void OpenGLVariable::apply(OpenGLShaderProgram *program, int &texture_unit) { QOpenGLShaderProgram* pr = program->getProgram(); + QOpenGLFunctions_3_2_Core* functions = program->getRenderer()->getOpenGlFunctions(); + + if (texture_toupload) + { + uploadTexture(program->getRenderer()); + texture_toupload = false; + } switch (type) { @@ -31,11 +44,51 @@ void OpenGLVariable::apply(OpenGLShaderProgram *program) 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) +{ + assert(type == TYPE_NONE or type == TYPE_TEXTURE_2D); + + type = TYPE_TEXTURE_2D; + value_tex2d = texture; + texture_toupload = true; +} + +void OpenGLVariable::set(const Texture3D *texture) +{ + assert(type == TYPE_NONE or type == TYPE_TEXTURE_3D); + + type = TYPE_TEXTURE_3D; + value_tex3d = texture; + texture_toupload = true; +} + +void OpenGLVariable::set(const Texture4D *texture) +{ + assert(type == TYPE_NONE or type == TYPE_TEXTURE_4D); + + type = TYPE_TEXTURE_4D; + value_tex4d = texture; + texture_toupload = true; +} + void OpenGLVariable::set(float value) { assert(type == TYPE_NONE or type == TYPE_FLOAT); @@ -77,3 +130,102 @@ void OpenGLVariable::set(const Color &color) type = TYPE_COLOR; value_color = QColor(color.r, color.g, color.b); } + +void OpenGLVariable::uploadTexture(OpenGLRenderer* renderer) +{ + QOpenGLFunctions_3_2_Core* 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, GL_CLAMP_TO_EDGE); + functions->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (textype == GL_TEXTURE_3D) + { + functions->glTexParameteri(textype, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + } + + if (type == TYPE_TEXTURE_2D) + { + int sx, sy; + value_tex2d->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 = value_tex2d->getPixel(x, y); + pixel[0] = (float)col.r; + pixel[1] = (float)col.g; + pixel[2] = (float)col.b; + pixel[3] = (float)col.a; + } + } + + functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sx, sy, 0, GL_RGBA, GL_FLOAT, pixels); + delete[] pixels; + } + else if (type == TYPE_TEXTURE_3D) + { + int sx, sy, sz; + value_tex3d->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 = value_tex3d->getPixel(x, y, z); + pixel[0] = (float)col.r; + pixel[1] = (float)col.g; + pixel[2] = (float)col.b; + pixel[3] = (float)col.a; + } + } + } + + functions->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, sx, sy, sz, 0, GL_RGBA, GL_FLOAT, pixels); + delete[] pixels; + } + else + { + int sx, sy, sz, sw; + value_tex4d->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 = value_tex4d->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; + } + } + } + } + + functions->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, sx, sy, sz * sw, 0, GL_RGBA, GL_FLOAT, pixels); + delete[] pixels; + } +} diff --git a/src/render/opengl/OpenGLVariable.h b/src/render/opengl/OpenGLVariable.h index 0fc633c..07a7f29 100644 --- a/src/render/opengl/OpenGLVariable.h +++ b/src/render/opengl/OpenGLVariable.h @@ -30,7 +30,7 @@ public: public: OpenGLVariable(const std::string &name); - void apply(OpenGLShaderProgram *program); + void apply(OpenGLShaderProgram *program, int &texture_unit); void set(const Texture2D *texture); void set(const Texture3D *texture); @@ -42,6 +42,9 @@ public: void set(const QMatrix4x4 &matrix); void set(const Color &color); +protected: + void uploadTexture(OpenGLRenderer* renderer); + private: std::string name; OpenGLVariableType type; @@ -50,6 +53,12 @@ private: QColor value_color; QVector3D value_vector3; QMatrix4x4 value_matrix4; + const Texture2D* value_tex2d; + const Texture3D* value_tex3d; + const Texture4D* value_tex4d; + + bool texture_toupload; + unsigned int texture_id; }; }