Rendering terrain chunks with new shader system

This commit is contained in:
Michaël Lemaire 2013-12-24 11:44:39 +01:00 committed by Michael Lemaire
parent f97823604e
commit bf47e058ee
11 changed files with 115 additions and 61 deletions

View file

@ -3,7 +3,6 @@
#include OPENGL_FUNCTIONS_INCLUDE #include OPENGL_FUNCTIONS_INCLUDE
#include <cmath> #include <cmath>
#include <QImage> #include <QImage>
#include <QOpenGLTexture>
#include "ColorProfile.h" #include "ColorProfile.h"
#include "CameraDefinition.h" #include "CameraDefinition.h"
#include "OpenGLRenderer.h" #include "OpenGLRenderer.h"
@ -13,13 +12,13 @@
ExplorerChunkTerrain::ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, double z, double size, int nbchunks, double water_height): ExplorerChunkTerrain::ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, double z, double size, int nbchunks, double water_height):
_renderer(renderer) _renderer(renderer)
{ {
_color_profile = new ColorProfile; _color_profile = new ColorProfile(ColorProfile::TONE_MAPPING_REIHNARD, 2.0);
priority = 0.0; priority = 0.0;
_reset_needed = false; _reset_needed = false;
_texture = new QImage(1, 1, QImage::Format_ARGB32); _texture = new QImage(1, 1, QImage::Format_RGBA8888);
texture = new QOpenGLTexture(*_texture); texture_id = 0;
_texture_changed = false; _texture_changed = false;
_texture_current_size = 0; _texture_current_size = 0;
_texture_max_size = 0; _texture_max_size = 0;
@ -52,7 +51,6 @@ ExplorerChunkTerrain::~ExplorerChunkTerrain()
_lock_data.lock(); _lock_data.lock();
delete _color_profile; delete _color_profile;
delete _texture; delete _texture;
delete texture;
delete tessellated; delete tessellated;
_lock_data.unlock(); _lock_data.unlock();
} }
@ -85,9 +83,9 @@ bool ExplorerChunkTerrain::maintain()
if (_texture_current_size <= 1 || i % 2 != 0 || j % 2 != 0) 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 = 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(); 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(); _lock_data.unlock();
} }
void ExplorerChunkTerrain::render(OpenGLFunctions* functions) void ExplorerChunkTerrain::render(QOpenGLShaderProgram* program, OpenGLFunctions* functions)
{ {
// Put texture in place // Put texture in place
_lock_data.lock(); _lock_data.lock();
if (_texture_changed) if (_texture_changed)
{ {
_texture_changed = false; _texture_changed = false;
texture->destroy();
// TODO Only do the scale if not power-of-two textures are unsupported by GPU // 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)); QImage tex = _texture->scaled(_texture_current_size, _texture_current_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
//texture->setData(*_texture);
texture->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge); if (texture_id == 0)
texture->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge); {
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(); _lock_data.unlock();
// Delegate poly rendering to subclass // Render tessellated mesh
if (!_reset_needed) if (!_reset_needed)
{ {
_lock_data.lock(); _lock_data.lock();
@ -243,15 +251,12 @@ void ExplorerChunkTerrain::render(OpenGLFunctions* functions)
} }
_lock_data.lock(); // TEMP _lock_data.lock(); // TEMP
int n = tessellated->getIndexCount(); // TEMP
functions->glBegin(GL_TRIANGLES); functions->glActiveTexture(GL_TEXTURE0 + 3);
for (int i = 0; i < n; i++) functions->glBindTexture(GL_TEXTURE_2D, texture_id);
{ program->setUniformValue("groundTexture", 3);
TerrainVertex v = tessellated->getVertexByIndex(i);
functions->glTexCoord2d(v.uv[0], v.uv[1]); tessellated->render(program, functions);
functions->glVertex3d(v.location[0], v.location[1], v.location[2]);
}
functions->glEnd();
_lock_data.unlock(); // TEMP _lock_data.unlock(); // TEMP
} }
} }

View file

@ -5,7 +5,7 @@
#include <QMutex> #include <QMutex>
class QImage; class QImage;
class QOpenGLTexture; class QOpenGLShaderProgram;
namespace paysages { namespace paysages {
namespace opengl { namespace opengl {
@ -25,7 +25,7 @@ public:
bool maintain(); bool maintain();
void updatePriority(CameraDefinition* camera); void updatePriority(CameraDefinition* camera);
void render(OpenGLFunctions* functions); void render(QOpenGLShaderProgram* program, OpenGLFunctions* functions);
void askReset(); void askReset();
void setMaxTextureSize(int size); void setMaxTextureSize(int size);
@ -62,7 +62,7 @@ private:
bool _reset_needed; bool _reset_needed;
QImage* _texture; QImage* _texture;
QOpenGLTexture* texture; unsigned int texture_id;
bool _texture_changed; bool _texture_changed;
int _texture_current_size; int _texture_current_size;
int _texture_max_size; int _texture_max_size;

View file

@ -46,7 +46,7 @@ void OpenGLShaderProgram::addFragmentSource(QString path)
} }
else else
{ {
logError("Can't open fragment file %s", file.fileName().toStdString().c_str()); logError() << "Can't open fragment file " << file.fileName();
} }
} }

View file

@ -22,15 +22,17 @@ public:
void drawTriangles(float* vertices, int triangle_count); void drawTriangles(float* vertices, int triangle_count);
void drawTriangleStrip(float* vertices, int vertex_count); void drawTriangleStrip(float* vertices, int vertex_count);
protected: void bind();
void release();
inline QOpenGLShaderProgram* getProgram() const {return program;} inline QOpenGLShaderProgram* getProgram() const {return program;}
inline OpenGLRenderer* getRenderer() const {return renderer;} inline OpenGLRenderer* getRenderer() const {return renderer;}
protected:
friend class OpenGLVariable; friend class OpenGLVariable;
private: private:
void compile(); void compile();
void bind();
void release();
bool compiled; bool compiled;

View file

@ -80,33 +80,16 @@ void OpenGLTerrain::update()
{ {
} }
// TEMP
#include "GL/gl.h"
#include "GL/glu.h"
void OpenGLTerrain::render() 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++) for (int i = 0; i < _chunks.count(); i++)
{ {
glColor3f(1.0, 1.0, 1.0); _chunks[i]->render(program->getProgram(), renderer->getOpenGlFunctions());
_chunks[i]->render(renderer->getOpenGlFunctions());
} }
program->release();
} }
static bool _cmpChunks(const ExplorerChunkTerrain* c1, const ExplorerChunkTerrain* c2) static bool _cmpChunks(const ExplorerChunkTerrain* c1, const ExplorerChunkTerrain* c2)

View file

@ -1 +0,0 @@
#include "VertexArray.h"

View file

@ -3,7 +3,9 @@
#include "opengl_global.h" #include "opengl_global.h"
#include OPENGL_FUNCTIONS_INCLUDE
#include <cassert> #include <cassert>
#include <QOpenGLShaderProgram>
namespace paysages { namespace paysages {
namespace opengl { namespace opengl {
@ -21,7 +23,7 @@ public:
vertex_count = 1; vertex_count = 1;
vertices = new Vertex[1]; vertices = new Vertex[1];
index_count = 1; index_count = 1;
indices = new int[1]; indices = new unsigned short[1];
} }
~VertexArray() ~VertexArray()
@ -74,7 +76,7 @@ public:
int cell_count = edge_vertex_count - 1; int cell_count = edge_vertex_count - 1;
index_count = (cell_count / stride) * (cell_count / stride) * 6; index_count = (cell_count / stride) * (cell_count / stride) * 6;
indices = new int[index_count]; indices = new unsigned short[index_count];
int idx = 0; int idx = 0;
for (int y = 0; y < cell_count; y += stride) for (int y = 0; y < cell_count; y += stride)
@ -99,7 +101,7 @@ public:
return vertices[position]; return vertices[position];
} }
Vertex getVertexByIndex(int index) Vertex getVertexByIndex(unsigned short index)
{ {
assert(index >= 0 and index < index_count); assert(index >= 0 and index < index_count);
@ -111,13 +113,31 @@ public:
return getVertex(y * edge_vertex_count + x); return getVertex(y * edge_vertex_count + x);
} }
int getIndex(int position) unsigned short getIndex(int position)
{ {
assert(position >= 0 and position < index_count); assert(position >= 0 and position < index_count);
return indices[position]; 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: private:
bool ready; bool ready;
bool changed; bool changed;
@ -126,7 +146,7 @@ private:
Vertex* vertices; Vertex* vertices;
int index_count; int index_count;
int* indices; unsigned short* indices;
}; };
} }

View file

@ -23,8 +23,7 @@ SOURCES += \
OpenGLWater.cpp \ OpenGLWater.cpp \
OpenGLSharedState.cpp \ OpenGLSharedState.cpp \
OpenGLVariable.cpp \ OpenGLVariable.cpp \
OpenGLTerrain.cpp \ OpenGLTerrain.cpp
VertexArray.cpp
HEADERS +=\ HEADERS +=\
opengl_global.h \ opengl_global.h \
@ -83,4 +82,6 @@ OTHER_FILES += \
shaders/water.frag \ shaders/water.frag \
shaders/bruneton.frag \ shaders/bruneton.frag \
shaders/bruneton.frag \ shaders/bruneton.frag \
shaders/tonemapping.frag shaders/tonemapping.frag \
shaders/terrain.frag \
shaders/terrain.vert

View file

@ -6,5 +6,7 @@
<file>water.vert</file> <file>water.vert</file>
<file>bruneton.frag</file> <file>bruneton.frag</file>
<file>tonemapping.frag</file> <file>tonemapping.frag</file>
<file>terrain.frag</file>
<file>terrain.vert</file>
</qresource> </qresource>
</RCC> </RCC>

View file

@ -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);
}

View file

@ -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;
}