Rendering terrain chunks with new shader system
This commit is contained in:
parent
f97823604e
commit
bf47e058ee
11 changed files with 115 additions and 61 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include "VertexArray.h"
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
30
src/render/opengl/shaders/terrain.frag
Normal file
30
src/render/opengl/shaders/terrain.frag
Normal 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);
|
||||||
|
}
|
12
src/render/opengl/shaders/terrain.vert
Normal file
12
src/render/opengl/shaders/terrain.vert
Normal 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;
|
||||||
|
}
|
Loading…
Reference in a new issue