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 <cmath>
#include <QImage>
#include <QOpenGLTexture>
#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
}
}

View file

@ -5,7 +5,7 @@
#include <QMutex>
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;

View file

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

View file

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

View file

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

View file

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

View file

@ -3,7 +3,9 @@
#include "opengl_global.h"
#include OPENGL_FUNCTIONS_INCLUDE
#include <cassert>
#include <QOpenGLShaderProgram>
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;
};
}

View file

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

View file

@ -6,5 +6,7 @@
<file>water.vert</file>
<file>bruneton.frag</file>
<file>tonemapping.frag</file>
<file>terrain.frag</file>
<file>terrain.vert</file>
</qresource>
</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;
}