From bf47e058ee071862ba218a7c080675554bafbef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Tue, 24 Dec 2013 11:44:39 +0100 Subject: [PATCH] Rendering terrain chunks with new shader system --- src/render/opengl/ExplorerChunkTerrain.cpp | 53 ++++++++++++---------- src/render/opengl/ExplorerChunkTerrain.h | 6 +-- src/render/opengl/OpenGLShaderProgram.cpp | 2 +- src/render/opengl/OpenGLShaderProgram.h | 8 ++-- src/render/opengl/OpenGLTerrain.cpp | 25 ++-------- src/render/opengl/VertexArray.cpp | 1 - src/render/opengl/VertexArray.h | 30 ++++++++++-- src/render/opengl/opengl.pro | 7 +-- src/render/opengl/shaders/resources.qrc | 2 + src/render/opengl/shaders/terrain.frag | 30 ++++++++++++ src/render/opengl/shaders/terrain.vert | 12 +++++ 11 files changed, 115 insertions(+), 61 deletions(-) delete mode 100644 src/render/opengl/VertexArray.cpp create mode 100644 src/render/opengl/shaders/terrain.frag create mode 100644 src/render/opengl/shaders/terrain.vert diff --git a/src/render/opengl/ExplorerChunkTerrain.cpp b/src/render/opengl/ExplorerChunkTerrain.cpp index 5d5fd90..05edbba 100644 --- a/src/render/opengl/ExplorerChunkTerrain.cpp +++ b/src/render/opengl/ExplorerChunkTerrain.cpp @@ -3,7 +3,6 @@ #include OPENGL_FUNCTIONS_INCLUDE #include #include -#include #include "ColorProfile.h" #include "CameraDefinition.h" #include "OpenGLRenderer.h" @@ -13,13 +12,13 @@ ExplorerChunkTerrain::ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, double z, double size, int nbchunks, double water_height): _renderer(renderer) { - _color_profile = new ColorProfile; + _color_profile = new ColorProfile(ColorProfile::TONE_MAPPING_REIHNARD, 2.0); priority = 0.0; _reset_needed = false; - _texture = new QImage(1, 1, QImage::Format_ARGB32); - texture = new QOpenGLTexture(*_texture); + _texture = new QImage(1, 1, QImage::Format_RGBA8888); + texture_id = 0; _texture_changed = false; _texture_current_size = 0; _texture_max_size = 0; @@ -52,7 +51,6 @@ ExplorerChunkTerrain::~ExplorerChunkTerrain() _lock_data.lock(); delete _color_profile; delete _texture; - delete texture; delete tessellated; _lock_data.unlock(); } @@ -85,9 +83,9 @@ bool ExplorerChunkTerrain::maintain() if (_texture_current_size <= 1 || i % 2 != 0 || j % 2 != 0) { Color color = getTextureColor((double)i / (double)new_texture_size, (double)j / (double)new_texture_size); - color = _color_profile->apply(color); + //color = _color_profile->apply(color); color.normalize(); - new_image->setPixel(i, j, color.to32BitBGRA()); + new_image->setPixel(i, j, color.to32BitRGBA()); } } } @@ -213,24 +211,34 @@ void ExplorerChunkTerrain::updatePriority(CameraDefinition* camera) _lock_data.unlock(); } -void ExplorerChunkTerrain::render(OpenGLFunctions* functions) +void ExplorerChunkTerrain::render(QOpenGLShaderProgram* program, OpenGLFunctions* functions) { // Put texture in place _lock_data.lock(); if (_texture_changed) { _texture_changed = false; - texture->destroy(); + // TODO Only do the scale if not power-of-two textures are unsupported by GPU - texture->setData(_texture->scaled(_texture_current_size, _texture_current_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - //texture->setData(*_texture); - texture->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge); - texture->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge); + QImage tex = _texture->scaled(_texture_current_size, _texture_current_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + + if (texture_id == 0) + { + GLuint texid; + functions->glGenTextures(1, &texid); + texture_id = texid; + } + + functions->glBindTexture(GL_TEXTURE_2D, texture_id); + 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); + functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits()); } - texture->bind(); _lock_data.unlock(); - // Delegate poly rendering to subclass + // Render tessellated mesh if (!_reset_needed) { _lock_data.lock(); @@ -243,15 +251,12 @@ void ExplorerChunkTerrain::render(OpenGLFunctions* functions) } _lock_data.lock(); // TEMP - int n = tessellated->getIndexCount(); - functions->glBegin(GL_TRIANGLES); - for (int i = 0; i < n; i++) - { - TerrainVertex v = tessellated->getVertexByIndex(i); - functions->glTexCoord2d(v.uv[0], v.uv[1]); - functions->glVertex3d(v.location[0], v.location[1], v.location[2]); - } - functions->glEnd(); + // TEMP + functions->glActiveTexture(GL_TEXTURE0 + 3); + functions->glBindTexture(GL_TEXTURE_2D, texture_id); + program->setUniformValue("groundTexture", 3); + + tessellated->render(program, functions); _lock_data.unlock(); // TEMP } } diff --git a/src/render/opengl/ExplorerChunkTerrain.h b/src/render/opengl/ExplorerChunkTerrain.h index 1de8355..c1ae2ca 100644 --- a/src/render/opengl/ExplorerChunkTerrain.h +++ b/src/render/opengl/ExplorerChunkTerrain.h @@ -5,7 +5,7 @@ #include class QImage; -class QOpenGLTexture; +class QOpenGLShaderProgram; namespace paysages { namespace opengl { @@ -25,7 +25,7 @@ public: bool maintain(); void updatePriority(CameraDefinition* camera); - void render(OpenGLFunctions* functions); + void render(QOpenGLShaderProgram* program, OpenGLFunctions* functions); void askReset(); void setMaxTextureSize(int size); @@ -62,7 +62,7 @@ private: bool _reset_needed; QImage* _texture; - QOpenGLTexture* texture; + unsigned int texture_id; bool _texture_changed; int _texture_current_size; int _texture_max_size; diff --git a/src/render/opengl/OpenGLShaderProgram.cpp b/src/render/opengl/OpenGLShaderProgram.cpp index 6df6534..1b07d7d 100644 --- a/src/render/opengl/OpenGLShaderProgram.cpp +++ b/src/render/opengl/OpenGLShaderProgram.cpp @@ -46,7 +46,7 @@ void OpenGLShaderProgram::addFragmentSource(QString path) } else { - logError("Can't open fragment file %s", file.fileName().toStdString().c_str()); + logError() << "Can't open fragment file " << file.fileName(); } } diff --git a/src/render/opengl/OpenGLShaderProgram.h b/src/render/opengl/OpenGLShaderProgram.h index 9a00bef..5caabf5 100644 --- a/src/render/opengl/OpenGLShaderProgram.h +++ b/src/render/opengl/OpenGLShaderProgram.h @@ -22,15 +22,17 @@ public: void drawTriangles(float* vertices, int triangle_count); void drawTriangleStrip(float* vertices, int vertex_count); -protected: + void bind(); + void release(); + inline QOpenGLShaderProgram* getProgram() const {return program;} inline OpenGLRenderer* getRenderer() const {return renderer;} + +protected: friend class OpenGLVariable; private: void compile(); - void bind(); - void release(); bool compiled; diff --git a/src/render/opengl/OpenGLTerrain.cpp b/src/render/opengl/OpenGLTerrain.cpp index 5d083f0..73b29c5 100644 --- a/src/render/opengl/OpenGLTerrain.cpp +++ b/src/render/opengl/OpenGLTerrain.cpp @@ -80,33 +80,16 @@ void OpenGLTerrain::update() { } -// TEMP -#include "GL/gl.h" -#include "GL/glu.h" - void OpenGLTerrain::render() { - CameraDefinition* camera = renderer->getScenery()->getCamera(); + program->bind(); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - CameraPerspective perspective = camera->getPerspective(); - gluPerspective(perspective.yfov * 180.0 / M_PI, perspective.xratio, perspective.znear, perspective.zfar); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - Vector3 camera_location = camera->getLocation(); - Vector3 camera_target = camera->getTarget(); - Vector3 camera_up = camera->getUpVector(); - gluLookAt(camera_location.x, camera_location.y, camera_location.z, camera_target.x, camera_target.y, camera_target.z, camera_up.x, camera_up.y, camera_up.z); - - // Render chunks - glEnable(GL_TEXTURE_2D); for (int i = 0; i < _chunks.count(); i++) { - glColor3f(1.0, 1.0, 1.0); - _chunks[i]->render(renderer->getOpenGlFunctions()); + _chunks[i]->render(program->getProgram(), renderer->getOpenGlFunctions()); } + + program->release(); } static bool _cmpChunks(const ExplorerChunkTerrain* c1, const ExplorerChunkTerrain* c2) diff --git a/src/render/opengl/VertexArray.cpp b/src/render/opengl/VertexArray.cpp deleted file mode 100644 index 96d7d79..0000000 --- a/src/render/opengl/VertexArray.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "VertexArray.h" diff --git a/src/render/opengl/VertexArray.h b/src/render/opengl/VertexArray.h index ffc289f..66300d6 100644 --- a/src/render/opengl/VertexArray.h +++ b/src/render/opengl/VertexArray.h @@ -3,7 +3,9 @@ #include "opengl_global.h" +#include OPENGL_FUNCTIONS_INCLUDE #include +#include namespace paysages { namespace opengl { @@ -21,7 +23,7 @@ public: vertex_count = 1; vertices = new Vertex[1]; index_count = 1; - indices = new int[1]; + indices = new unsigned short[1]; } ~VertexArray() @@ -74,7 +76,7 @@ public: int cell_count = edge_vertex_count - 1; index_count = (cell_count / stride) * (cell_count / stride) * 6; - indices = new int[index_count]; + indices = new unsigned short[index_count]; int idx = 0; for (int y = 0; y < cell_count; y += stride) @@ -99,7 +101,7 @@ public: return vertices[position]; } - Vertex getVertexByIndex(int index) + Vertex getVertexByIndex(unsigned short index) { assert(index >= 0 and index < index_count); @@ -111,13 +113,31 @@ public: return getVertex(y * edge_vertex_count + x); } - int getIndex(int position) + unsigned short getIndex(int position) { assert(position >= 0 and position < index_count); return indices[position]; } + void render(QOpenGLShaderProgram* program, OpenGLFunctions* functions) + { + size_t ptr = (size_t)vertices; + + GLuint vertex = program->attributeLocation("vertex"); + program->setAttributeArray(vertex, GL_FLOAT, (void*)(ptr + offsetof(Vertex, location)), 3, sizeof(Vertex)); + program->enableAttributeArray(vertex); + + GLuint uv = program->attributeLocation("uv"); + program->setAttributeArray(uv, GL_FLOAT, (void*)(ptr + offsetof(Vertex, uv)), 2, sizeof(Vertex)); + program->enableAttributeArray(uv); + + functions->glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_SHORT, indices); + + program->disableAttributeArray(vertex); + program->disableAttributeArray(uv); + } + private: bool ready; bool changed; @@ -126,7 +146,7 @@ private: Vertex* vertices; int index_count; - int* indices; + unsigned short* indices; }; } diff --git a/src/render/opengl/opengl.pro b/src/render/opengl/opengl.pro index 47594ae..30e51d5 100644 --- a/src/render/opengl/opengl.pro +++ b/src/render/opengl/opengl.pro @@ -23,8 +23,7 @@ SOURCES += \ OpenGLWater.cpp \ OpenGLSharedState.cpp \ OpenGLVariable.cpp \ - OpenGLTerrain.cpp \ - VertexArray.cpp + OpenGLTerrain.cpp HEADERS +=\ opengl_global.h \ @@ -83,4 +82,6 @@ OTHER_FILES += \ shaders/water.frag \ shaders/bruneton.frag \ shaders/bruneton.frag \ - shaders/tonemapping.frag + shaders/tonemapping.frag \ + shaders/terrain.frag \ + shaders/terrain.vert diff --git a/src/render/opengl/shaders/resources.qrc b/src/render/opengl/shaders/resources.qrc index 761c28b..d73512f 100644 --- a/src/render/opengl/shaders/resources.qrc +++ b/src/render/opengl/shaders/resources.qrc @@ -6,5 +6,7 @@ water.vert bruneton.frag tonemapping.frag + terrain.frag + terrain.vert diff --git a/src/render/opengl/shaders/terrain.frag b/src/render/opengl/shaders/terrain.frag new file mode 100644 index 0000000..77054be --- /dev/null +++ b/src/render/opengl/shaders/terrain.frag @@ -0,0 +1,30 @@ +uniform sampler2D groundTexture; +varying vec2 texcoord; + +void main(void) +{ + gl_FragColor = texture2D(groundTexture, texcoord); + + float yoffset = GROUND_OFFSET - waterHeight; + vec3 camera = vec3(cameraLocation.x, max(cameraLocation.y + yoffset, 0.0), cameraLocation.z); + vec3 location = vec3(unprojected.x, max(unprojected.y + yoffset, 0.0), unprojected.z); + vec3 x = vec3(0.0, Rg + camera.y * WORLD_SCALING, 0.0); + vec3 v = normalize(location - camera); + vec3 s = normalize(sunDirection * SUN_DISTANCE_SCALED - x); + + if (v.y == 0.0) + { + v.y = -0.000001; + } + + float r = length(x); + float mu = dot(x, v) / r; + float t = length(location - camera) * WORLD_SCALING; + + vec3 attenuation; + vec3 inscattering = _getInscatterColor(x, t, v, s, r, mu, attenuation); + + gl_FragColor = gl_FragColor * vec4(attenuation, 0.0) + vec4(inscattering, 0.0); + + gl_FragColor = _toneMappingUncharted(gl_FragColor, 2.0); +} diff --git a/src/render/opengl/shaders/terrain.vert b/src/render/opengl/shaders/terrain.vert new file mode 100644 index 0000000..c4fd270 --- /dev/null +++ b/src/render/opengl/shaders/terrain.vert @@ -0,0 +1,12 @@ +attribute highp vec4 vertex; +attribute highp vec2 uv; +uniform highp mat4 viewMatrix; +varying vec3 unprojected; +varying vec2 texcoord; + +void main(void) +{ + unprojected = vertex.xyz; + texcoord = uv; + gl_Position = viewMatrix * vertex; +}