From 666420bbb2f74b4d1625e63ae58deaf78b9d8ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 22 Dec 2013 15:04:33 +0100 Subject: [PATCH] New OpenGLSharedState class to manage shader variables --- src/render/opengl/OpenGLPart.cpp | 22 +-------- src/render/opengl/OpenGLRenderer.cpp | 5 ++ src/render/opengl/OpenGLRenderer.h | 4 +- src/render/opengl/OpenGLShaderProgram.cpp | 38 +++------------ src/render/opengl/OpenGLShaderProgram.h | 15 +++--- src/render/opengl/OpenGLSharedState.cpp | 23 +++++++++ src/render/opengl/OpenGLSharedState.h | 46 ++++++++++++++++++ src/render/opengl/OpenGLSkybox.cpp | 8 +++- src/render/opengl/OpenGLVariable.cpp | 57 +++++++++++++++++++++++ src/render/opengl/OpenGLVariable.h | 54 +++++++++++++++++++++ src/render/opengl/OpenGLWater.cpp | 5 ++ src/render/opengl/opengl.pro | 8 +++- src/render/opengl/opengl_global.h | 2 + src/system/Logs.cpp | 1 + src/system/Logs.h | 9 ++++ src/system/system.pro | 6 ++- 16 files changed, 237 insertions(+), 66 deletions(-) create mode 100644 src/render/opengl/OpenGLSharedState.cpp create mode 100644 src/render/opengl/OpenGLSharedState.h create mode 100644 src/render/opengl/OpenGLVariable.cpp create mode 100644 src/render/opengl/OpenGLVariable.h create mode 100644 src/system/Logs.cpp create mode 100644 src/system/Logs.h diff --git a/src/render/opengl/OpenGLPart.cpp b/src/render/opengl/OpenGLPart.cpp index c2d6d98..4c184d6 100644 --- a/src/render/opengl/OpenGLPart.cpp +++ b/src/render/opengl/OpenGLPart.cpp @@ -7,7 +7,6 @@ #include "CameraDefinition.h" #include "AtmosphereDefinition.h" #include "AtmosphereRenderer.h" -#include "WaterRenderer.h" #include "Scenery.h" OpenGLPart::OpenGLPart(OpenGLRenderer* renderer): @@ -27,7 +26,7 @@ OpenGLPart::~OpenGLPart() OpenGLShaderProgram* OpenGLPart::createShader(QString name) { - OpenGLShaderProgram* program = new OpenGLShaderProgram(name, renderer->getOpenGlFunctions()); + OpenGLShaderProgram* program = new OpenGLShaderProgram(name, renderer); if (!shaders.contains(name)) { @@ -82,25 +81,6 @@ void OpenGLPart::updateCamera(CameraDefinition* camera) void OpenGLPart::updateScenery(bool onlyCommon) { - Scenery* scenery = renderer->getScenery(); - - // Collect common info - double water_height = renderer->getWaterRenderer()->getHeightInfo().max_height; - Vector3 orig_sun_direction = renderer->getAtmosphereRenderer()->getSunDirection(); - QVector3D sun_direction = QVector3D(orig_sun_direction.x, orig_sun_direction.y, orig_sun_direction.z); - Color orig_sun_color = scenery->getAtmosphere()->sun_color; - QColor sun_color = QColor(orig_sun_color.r, orig_sun_color.g, orig_sun_color.b); - - // Update shaders - QMapIterator i(shaders); - while (i.hasNext()) - { - i.next(); - - i.value()->updateWaterHeight(water_height); - i.value()->updateSun(sun_direction, sun_color); - } - // Let subclass do its own collecting if (not onlyCommon) { diff --git a/src/render/opengl/OpenGLRenderer.cpp b/src/render/opengl/OpenGLRenderer.cpp index 65a6b5b..1b326bf 100644 --- a/src/render/opengl/OpenGLRenderer.cpp +++ b/src/render/opengl/OpenGLRenderer.cpp @@ -2,6 +2,7 @@ #include #include "CameraDefinition.h" +#include "OpenGLSharedState.h" #include "OpenGLSkybox.h" #include "OpenGLWater.h" @@ -9,6 +10,8 @@ OpenGLRenderer::OpenGLRenderer(Scenery* scenery): SoftwareRenderer(scenery) { functions = new QOpenGLFunctions_3_2_Core(); + shared_state = new OpenGLSharedState(); + skybox = new OpenGLSkybox(this); water = new OpenGLWater(this); } @@ -17,7 +20,9 @@ OpenGLRenderer::~OpenGLRenderer() { delete skybox; delete water; + delete functions; + delete shared_state; } void OpenGLRenderer::initialize() diff --git a/src/render/opengl/OpenGLRenderer.h b/src/render/opengl/OpenGLRenderer.h index 1021f4c..2069ed1 100644 --- a/src/render/opengl/OpenGLRenderer.h +++ b/src/render/opengl/OpenGLRenderer.h @@ -25,13 +25,15 @@ public: void cameraChangeEvent(CameraDefinition* camera); - inline QOpenGLFunctions_3_2_Core* getOpenGlFunctions() {return functions;} + inline QOpenGLFunctions_3_2_Core* getOpenGlFunctions() const {return functions;} + inline OpenGLSharedState* getSharedState() const {return shared_state;} virtual double getPrecision(const Vector3 &location) override; virtual Color applyMediumTraversal(Vector3 location, Color color) override; private: QOpenGLFunctions_3_2_Core* functions; + OpenGLSharedState* shared_state; OpenGLSkybox* skybox; OpenGLWater* water; diff --git a/src/render/opengl/OpenGLShaderProgram.cpp b/src/render/opengl/OpenGLShaderProgram.cpp index 3caece4..cf34e66 100644 --- a/src/render/opengl/OpenGLShaderProgram.cpp +++ b/src/render/opengl/OpenGLShaderProgram.cpp @@ -3,15 +3,18 @@ #include #include #include +#include "OpenGLRenderer.h" +#include "OpenGLSharedState.h" #include "Texture2D.h" #include "Texture3D.h" #include "Texture4D.h" #include "Color.h" -OpenGLShaderProgram::OpenGLShaderProgram(QString name, QOpenGLFunctions_3_2_Core* functions): - name(name), functions(functions) +OpenGLShaderProgram::OpenGLShaderProgram(QString name, OpenGLRenderer* renderer): + renderer(renderer), name(name) { program = new QOpenGLShaderProgram(); + functions = renderer->getOpenGlFunctions(); } OpenGLShaderProgram::~OpenGLShaderProgram() @@ -47,17 +50,6 @@ void OpenGLShaderProgram::updateCamera(const QVector3D& location, const QMatrix4 this->view = view; } -void OpenGLShaderProgram::updateWaterHeight(double height) -{ - this->water_height = height; -} - -void OpenGLShaderProgram::updateSun(const QVector3D& direction, const QColor& color) -{ - this->sun_direction = direction; - this->sun_color = color; -} - void OpenGLShaderProgram::addTexture(QString sampler_name, Texture2D* texture) { GLuint texid; @@ -193,6 +185,8 @@ void OpenGLShaderProgram::bind() { program->bind(); + renderer->getSharedState()->apply(this); + // TODO Keep locations in cache int viewMatrix = program->uniformLocation("viewMatrix"); @@ -207,24 +201,6 @@ void OpenGLShaderProgram::bind() program->setUniformValue(cameraLocation, camera_location); } - int waterHeight = program->uniformLocation("waterHeight"); - if (waterHeight >= 0) - { - program->setUniformValue(waterHeight, water_height); - } - - int sunDirection = program->uniformLocation("sunDirection"); - if (sunDirection >= 0) - { - program->setUniformValue(sunDirection, sun_direction); - } - - int sunColor = program->uniformLocation("sunColor"); - if (sunColor >= 0) - { - program->setUniformValue(sunColor, sun_color); - } - QMapIterator > iter(textures); int i = 0; while (iter.hasNext()) diff --git a/src/render/opengl/OpenGLShaderProgram.h b/src/render/opengl/OpenGLShaderProgram.h index 773a1e4..7cf9e6b 100644 --- a/src/render/opengl/OpenGLShaderProgram.h +++ b/src/render/opengl/OpenGLShaderProgram.h @@ -18,7 +18,7 @@ namespace opengl { class OPENGLSHARED_EXPORT OpenGLShaderProgram { public: - OpenGLShaderProgram(QString name, QOpenGLFunctions_3_2_Core* functions); + OpenGLShaderProgram(QString name, OpenGLRenderer* renderer); ~OpenGLShaderProgram(); void addVertexSource(QString path); @@ -26,8 +26,6 @@ public: void compile(); void updateCamera(const QVector3D& location, const QMatrix4x4& view); - void updateWaterHeight(double height); - void updateSun(const QVector3D& direction, const QColor& color); void addTexture(QString sampler_name, Texture2D* texture); void addTexture(QString sampler_name, Texture3D* texture); @@ -36,18 +34,19 @@ public: void drawTriangles(float* vertices, int triangle_count); void drawTriangleStrip(float* vertices, int vertex_count); +protected: + inline QOpenGLShaderProgram* getProgram() const {return program;} + friend class OpenGLVariable; + private: void bind(); void release(); + OpenGLRenderer* renderer; + QMatrix4x4 view; QVector3D camera_location; - float water_height; - - QVector3D sun_direction; - QColor sun_color; - QString name; QOpenGLShaderProgram* program; QOpenGLFunctions_3_2_Core* functions; diff --git a/src/render/opengl/OpenGLSharedState.cpp b/src/render/opengl/OpenGLSharedState.cpp new file mode 100644 index 0000000..a504fd8 --- /dev/null +++ b/src/render/opengl/OpenGLSharedState.cpp @@ -0,0 +1,23 @@ +#include "OpenGLSharedState.h" + +OpenGLSharedState::OpenGLSharedState() +{ +} + +void OpenGLSharedState::apply(OpenGLShaderProgram *program) +{ + for (const auto &pair : variables) + { + pair.second->apply(program); + } +} + +OpenGLVariable *OpenGLSharedState::get(const std::string &name) +{ + OpenGLVariable*& var = variables[name]; + if (var == 0) + { + var = new OpenGLVariable(name); + } + return var; +} diff --git a/src/render/opengl/OpenGLSharedState.h b/src/render/opengl/OpenGLSharedState.h new file mode 100644 index 0000000..050f68d --- /dev/null +++ b/src/render/opengl/OpenGLSharedState.h @@ -0,0 +1,46 @@ +#ifndef OPENGLSHAREDSTATE_H +#define OPENGLSHAREDSTATE_H + +#include "opengl_global.h" + +#include +#include "OpenGLVariable.h" + +namespace paysages { +namespace opengl { + +/*! + * \brief OpenGL variables that can be shared between shaders. + */ +class OPENGLSHARED_EXPORT OpenGLSharedState +{ +public: + OpenGLSharedState(); + + /*! + * \brief Apply the stored variables to the bound program. + */ + void apply(OpenGLShaderProgram* program); + + /*! + * \brief Get or create a variable in the state. + */ + OpenGLVariable *get(const std::string &name); + + // Shortcuts + inline void set(const std::string &name, const Texture2D *texture) {get(name)->set(texture);} + inline void set(const std::string &name, const Texture3D *texture) {get(name)->set(texture);} + inline void set(const std::string &name, const Texture4D *texture) {get(name)->set(texture);} + inline void set(const std::string &name, float value) {get(name)->set(value);} + inline void set(const std::string &name, const Vector3 &vector) {get(name)->set(vector);} + inline void set(const std::string &name, const Matrix4 &matrix) {get(name)->set(matrix);} + inline void set(const std::string &name, const Color &color) {get(name)->set(color);} + +private: + std::map variables; +}; + +} +} + +#endif // OPENGLSHAREDSTATE_H diff --git a/src/render/opengl/OpenGLSkybox.cpp b/src/render/opengl/OpenGLSkybox.cpp index 8cfa29a..11773b0 100644 --- a/src/render/opengl/OpenGLSkybox.cpp +++ b/src/render/opengl/OpenGLSkybox.cpp @@ -3,6 +3,7 @@ #include #include "OpenGLRenderer.h" #include "OpenGLShaderProgram.h" +#include "OpenGLSharedState.h" #include "Scenery.h" #include "AtmosphereDefinition.h" #include "AtmosphereRenderer.h" @@ -51,8 +52,13 @@ void OpenGLSkybox::initialize() void OpenGLSkybox::update() { - SoftwareBrunetonAtmosphereRenderer* bruneton = (SoftwareBrunetonAtmosphereRenderer*)renderer->getAtmosphereRenderer(); + Vector3 sun_direction = renderer->getAtmosphereRenderer()->getSunDirection(); + renderer->getSharedState()->set("sunDirection", sun_direction); + Color sun_color = renderer->getScenery()->getAtmosphere()->sun_color; + renderer->getSharedState()->set("sunColor", sun_color); + + SoftwareBrunetonAtmosphereRenderer* bruneton = (SoftwareBrunetonAtmosphereRenderer*)renderer->getAtmosphereRenderer(); program->addTexture("transmittanceTexture", bruneton->getModel()->getTextureTransmittance()); program->addTexture("inscatterTexture", bruneton->getModel()->getTextureInscatter()); } diff --git a/src/render/opengl/OpenGLVariable.cpp b/src/render/opengl/OpenGLVariable.cpp new file mode 100644 index 0000000..5724399 --- /dev/null +++ b/src/render/opengl/OpenGLVariable.cpp @@ -0,0 +1,57 @@ +#include "OpenGLVariable.h" + +#include +#include +#include "OpenGLShaderProgram.h" +#include "Vector3.h" +#include "Color.h" + +OpenGLVariable::OpenGLVariable(const std::string &name): + name(name) +{ + type = TYPE_NONE; +} + +void OpenGLVariable::apply(OpenGLShaderProgram *program) +{ + QOpenGLShaderProgram* pr = program->getProgram(); + + switch (type) + { + 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_NONE: + break; + } +} + +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) +{ + assert(type == TYPE_NONE or type == TYPE_COLOR); + + type = TYPE_VECTOR3; + value_vector3 = QVector3D(vector.x, vector.y, vector.z); +} + +void OpenGLVariable::set(const Color &color) +{ + assert(type == TYPE_NONE or type == TYPE_COLOR); + + type = TYPE_COLOR; + value_color = QColor(color.r, color.g, color.b); +} diff --git a/src/render/opengl/OpenGLVariable.h b/src/render/opengl/OpenGLVariable.h new file mode 100644 index 0000000..102c1ea --- /dev/null +++ b/src/render/opengl/OpenGLVariable.h @@ -0,0 +1,54 @@ +#ifndef OPENGLVARIABLE_H +#define OPENGLVARIABLE_H + +#include "opengl_global.h" + +#include +#include + +namespace paysages { +namespace opengl { + +/*! + * \brief OpenGL variable that can be bound to a uniform for shaders. + */ +class OpenGLVariable +{ +public: + typedef enum { + TYPE_NONE, + TYPE_TEXTURE_2D, + TYPE_TEXTURE_3D, + TYPE_TEXTURE_4D, + TYPE_FLOAT, + TYPE_VECTOR3, + TYPE_MATRIX4, + TYPE_COLOR + } OpenGLVariableType; + +public: + OpenGLVariable(const std::string &name); + + void apply(OpenGLShaderProgram *program); + + void set(const Texture2D *texture); + void set(const Texture3D *texture); + void set(const Texture4D *texture); + void set(float value); + void set(const Vector3 &vector); + void set(const Matrix4 &matrix); + void set(const Color &color); + +private: + std::string name; + OpenGLVariableType type; + + float value_float; + QColor value_color; + QVector3D value_vector3; +}; + +} +} + +#endif // OPENGLVARIABLE_H diff --git a/src/render/opengl/OpenGLWater.cpp b/src/render/opengl/OpenGLWater.cpp index bebef71..3c88c23 100644 --- a/src/render/opengl/OpenGLWater.cpp +++ b/src/render/opengl/OpenGLWater.cpp @@ -1,6 +1,9 @@ #include "OpenGLWater.h" +#include "OpenGLRenderer.h" #include "OpenGLShaderProgram.h" +#include "OpenGLSharedState.h" +#include "WaterRenderer.h" OpenGLWater::OpenGLWater(OpenGLRenderer *renderer): OpenGLPart(renderer) @@ -27,6 +30,8 @@ void OpenGLWater::initialize() void OpenGLWater::update() { + double water_height = renderer->getWaterRenderer()->getHeightInfo().max_height; + renderer->getSharedState()->set("waterHeight", water_height); } void OpenGLWater::render() diff --git a/src/render/opengl/opengl.pro b/src/render/opengl/opengl.pro index fe2ea41..b341939 100644 --- a/src/render/opengl/opengl.pro +++ b/src/render/opengl/opengl.pro @@ -21,7 +21,9 @@ SOURCES += \ OpenGLShaderProgram.cpp \ OpenGLPart.cpp \ OpenGLSkybox.cpp \ - OpenGLWater.cpp + OpenGLWater.cpp \ + OpenGLSharedState.cpp \ + OpenGLVariable.cpp HEADERS +=\ opengl_global.h \ @@ -32,7 +34,9 @@ HEADERS +=\ OpenGLShaderProgram.h \ OpenGLPart.h \ OpenGLSkybox.h \ - OpenGLWater.h + OpenGLWater.h \ + OpenGLSharedState.h \ + OpenGLVariable.h unix:!symbian { maemo5 { diff --git a/src/render/opengl/opengl_global.h b/src/render/opengl/opengl_global.h index b949e60..d8f0cef 100644 --- a/src/render/opengl/opengl_global.h +++ b/src/render/opengl/opengl_global.h @@ -17,6 +17,8 @@ namespace opengl { class OpenGLRenderer; class BaseExplorerChunk; class OpenGLShaderProgram; + class OpenGLSharedState; + class OpenGLVariable; class OpenGLSkybox; class OpenGLWater; } diff --git a/src/system/Logs.cpp b/src/system/Logs.cpp new file mode 100644 index 0000000..eca5c5c --- /dev/null +++ b/src/system/Logs.cpp @@ -0,0 +1 @@ +#include "Logs.h" diff --git a/src/system/Logs.h b/src/system/Logs.h new file mode 100644 index 0000000..a044089 --- /dev/null +++ b/src/system/Logs.h @@ -0,0 +1,9 @@ +#ifndef LOGS_H +#define LOGS_H + +#include "system_global.h" + +#define logWarning qWarning +#define logError qError + +#endif // LOGS_H diff --git a/src/system/system.pro b/src/system/system.pro index 2c6bd99..2aa7ac0 100644 --- a/src/system/system.pro +++ b/src/system/system.pro @@ -23,7 +23,8 @@ SOURCES += \ ParallelWork.cpp \ ParallelQueue.cpp \ CacheFile.cpp \ - PictureWriter.cpp + PictureWriter.cpp \ + Logs.cpp HEADERS += \ system_global.h \ @@ -36,7 +37,8 @@ HEADERS += \ ParallelWork.h \ ParallelQueue.h \ CacheFile.h \ - PictureWriter.h + PictureWriter.h \ + Logs.h unix:!symbian { maemo5 {