Merge branch 'opengl_shaders'
This commit is contained in:
commit
7d2d022a98
60 changed files with 2207 additions and 763 deletions
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
ColorProfile::ColorProfile()
|
ColorProfile::ColorProfile()
|
||||||
{
|
{
|
||||||
setToneMapping(TONE_MAPPING_UNCHARTED, 2.0);
|
setToneMapping(TONE_MAPPING_UNCHARTED, 1.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorProfile::ColorProfile(ToneMappingOperator tonemapper, double exposure)
|
ColorProfile::ColorProfile(ToneMappingOperator tonemapper, double exposure)
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#include "basics_global.h"
|
#include "basics_global.h"
|
||||||
|
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
#ifdef QT_GUI_LIB
|
||||||
|
#include <QMatrix4x4>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
@ -35,6 +38,15 @@ public:
|
||||||
|
|
||||||
double getDeterminant() const;
|
double getDeterminant() const;
|
||||||
|
|
||||||
|
#ifdef QT_GUI_LIB
|
||||||
|
inline QMatrix4x4 toQMatrix() const {
|
||||||
|
return QMatrix4x4(a, b, c, d,
|
||||||
|
e, f, g, h,
|
||||||
|
i, j, k, l,
|
||||||
|
m, n, o, p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double a;
|
double a;
|
||||||
double b;
|
double b;
|
||||||
|
|
|
@ -19,7 +19,7 @@ Texture2D::~Texture2D()
|
||||||
delete[] data;
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture2D::getSize(int* xsize, int* ysize)
|
void Texture2D::getSize(int* xsize, int* ysize) const
|
||||||
{
|
{
|
||||||
*xsize = this->xsize;
|
*xsize = this->xsize;
|
||||||
*ysize = this->ysize;
|
*ysize = this->ysize;
|
||||||
|
@ -33,7 +33,7 @@ void Texture2D::setPixel(int x, int y, Color col)
|
||||||
data[y * xsize + x] = col;
|
data[y * xsize + x] = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture2D::getPixel(int x, int y)
|
Color Texture2D::getPixel(int x, int y) const
|
||||||
{
|
{
|
||||||
assert(x >= 0 && x < xsize);
|
assert(x >= 0 && x < xsize);
|
||||||
assert(y >= 0 && y < ysize);
|
assert(y >= 0 && y < ysize);
|
||||||
|
@ -41,7 +41,7 @@ Color Texture2D::getPixel(int x, int y)
|
||||||
return data[y * xsize + x];
|
return data[y * xsize + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture2D::getNearest(double dx, double dy)
|
Color Texture2D::getNearest(double dx, double dy) const
|
||||||
{
|
{
|
||||||
if (dx < 0.0) dx = 0.0;
|
if (dx < 0.0) dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0) dx = 1.0;
|
||||||
|
@ -57,7 +57,7 @@ Color Texture2D::getNearest(double dx, double dy)
|
||||||
return this->data[iy * this->xsize + ix];
|
return this->data[iy * this->xsize + ix];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture2D::getLinear(double dx, double dy)
|
Color Texture2D::getLinear(double dx, double dy) const
|
||||||
{
|
{
|
||||||
if (dx < 0.0) dx = 0.0;
|
if (dx < 0.0) dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0) dx = 1.0;
|
||||||
|
@ -89,7 +89,7 @@ Color Texture2D::getLinear(double dx, double dy)
|
||||||
return c1.lerp(c2, dy);
|
return c1.lerp(c2, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture2D::getCubic(double dx, double dy)
|
Color Texture2D::getCubic(double dx, double dy) const
|
||||||
{
|
{
|
||||||
/* TODO */
|
/* TODO */
|
||||||
return getLinear(dx, dy);
|
return getLinear(dx, dy);
|
||||||
|
@ -122,7 +122,7 @@ void Texture2D::add(Texture2D* source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture2D::save(PackStream* stream)
|
void Texture2D::save(PackStream* stream) const
|
||||||
{
|
{
|
||||||
int i, n;
|
int i, n;
|
||||||
stream->write(&this->xsize);
|
stream->write(&this->xsize);
|
||||||
|
@ -151,17 +151,17 @@ void Texture2D::load(PackStream* stream)
|
||||||
class Texture2DWriter:public PictureWriter
|
class Texture2DWriter:public PictureWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Texture2DWriter(Texture2D *tex): tex(tex) {}
|
Texture2DWriter(const Texture2D *tex): tex(tex) {}
|
||||||
|
|
||||||
virtual unsigned int getPixel(int x, int y) override
|
virtual unsigned int getPixel(int x, int y) override
|
||||||
{
|
{
|
||||||
return tex->getPixel(x, y).to32BitBGRA();
|
return tex->getPixel(x, y).to32BitBGRA();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Texture2D *tex;
|
const Texture2D *tex;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Texture2D::saveToFile(const std::string &filepath)
|
void Texture2D::saveToFile(const std::string &filepath) const
|
||||||
{
|
{
|
||||||
Texture2DWriter writer(this);
|
Texture2DWriter writer(this);
|
||||||
writer.save(filepath, xsize, ysize);
|
writer.save(filepath, xsize, ysize);
|
||||||
|
|
|
@ -12,17 +12,17 @@ public:
|
||||||
Texture2D(int xsize, int ysize);
|
Texture2D(int xsize, int ysize);
|
||||||
~Texture2D();
|
~Texture2D();
|
||||||
|
|
||||||
void getSize(int* xsize, int* ysize);
|
void getSize(int* xsize, int* ysize) const;
|
||||||
void setPixel(int x, int y, Color col);
|
void setPixel(int x, int y, Color col);
|
||||||
Color getPixel(int x, int y);
|
Color getPixel(int x, int y) const;
|
||||||
Color getNearest(double dx, double dy);
|
Color getNearest(double dx, double dy) const;
|
||||||
Color getLinear(double dx, double dy);
|
Color getLinear(double dx, double dy) const;
|
||||||
Color getCubic(double dx, double dy);
|
Color getCubic(double dx, double dy) const;
|
||||||
void fill(Color col);
|
void fill(Color col);
|
||||||
void add(Texture2D* other);
|
void add(Texture2D* other);
|
||||||
void save(PackStream* stream);
|
void save(PackStream* stream) const;
|
||||||
void load(PackStream* stream);
|
void load(PackStream* stream);
|
||||||
void saveToFile(const std::string &filepath);
|
void saveToFile(const std::string &filepath) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int xsize;
|
int xsize;
|
||||||
|
|
|
@ -20,7 +20,7 @@ Texture3D::~Texture3D()
|
||||||
delete[] data;
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture3D::getSize(int* xsize, int* ysize, int* zsize)
|
void Texture3D::getSize(int* xsize, int* ysize, int* zsize) const
|
||||||
{
|
{
|
||||||
*xsize = this->xsize;
|
*xsize = this->xsize;
|
||||||
*ysize = this->ysize;
|
*ysize = this->ysize;
|
||||||
|
@ -36,7 +36,7 @@ void Texture3D::setPixel(int x, int y, int z, Color col)
|
||||||
this->data[z * this->xsize * this->ysize + y * this->xsize + x] = col;
|
this->data[z * this->xsize * this->ysize + y * this->xsize + x] = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture3D::getPixel(int x, int y, int z)
|
Color Texture3D::getPixel(int x, int y, int z) const
|
||||||
{
|
{
|
||||||
assert(x >= 0 && x < this->xsize);
|
assert(x >= 0 && x < this->xsize);
|
||||||
assert(y >= 0 && y < this->ysize);
|
assert(y >= 0 && y < this->ysize);
|
||||||
|
@ -45,7 +45,7 @@ Color Texture3D::getPixel(int x, int y, int z)
|
||||||
return this->data[z * this->xsize * this->ysize + y * this->xsize + x];
|
return this->data[z * this->xsize * this->ysize + y * this->xsize + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture3D::getNearest(double dx, double dy, double dz)
|
Color Texture3D::getNearest(double dx, double dy, double dz) const
|
||||||
{
|
{
|
||||||
if (dx < 0.0) dx = 0.0;
|
if (dx < 0.0) dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0) dx = 1.0;
|
||||||
|
@ -65,7 +65,7 @@ Color Texture3D::getNearest(double dx, double dy, double dz)
|
||||||
return this->data[iz * this->xsize * this->ysize + iy * this->xsize + ix];
|
return this->data[iz * this->xsize * this->ysize + iy * this->xsize + ix];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture3D::getLinear(double dx, double dy, double dz)
|
Color Texture3D::getLinear(double dx, double dy, double dz) const
|
||||||
{
|
{
|
||||||
if (dx < 0.0) dx = 0.0;
|
if (dx < 0.0) dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0) dx = 1.0;
|
||||||
|
@ -112,7 +112,7 @@ Color Texture3D::getLinear(double dx, double dy, double dz)
|
||||||
return cy1.lerp(cy2, dz);
|
return cy1.lerp(cy2, dz);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture3D::getCubic(double dx, double dy, double dz)
|
Color Texture3D::getCubic(double dx, double dy, double dz) const
|
||||||
{
|
{
|
||||||
/* TODO */
|
/* TODO */
|
||||||
return getLinear(dx, dy, dz);
|
return getLinear(dx, dy, dz);
|
||||||
|
@ -146,7 +146,7 @@ void Texture3D::add(Texture3D* source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture3D::save(PackStream* stream)
|
void Texture3D::save(PackStream* stream) const
|
||||||
{
|
{
|
||||||
int i, n;
|
int i, n;
|
||||||
stream->write(&this->xsize);
|
stream->write(&this->xsize);
|
||||||
|
@ -177,7 +177,7 @@ void Texture3D::load(PackStream* stream)
|
||||||
class Texture3DWriter:public PictureWriter
|
class Texture3DWriter:public PictureWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Texture3DWriter(Texture3D *tex): tex(tex) {}
|
Texture3DWriter(const Texture3D *tex): tex(tex) {}
|
||||||
|
|
||||||
virtual unsigned int getPixel(int x, int y) override
|
virtual unsigned int getPixel(int x, int y) override
|
||||||
{
|
{
|
||||||
|
@ -190,10 +190,10 @@ public:
|
||||||
return tex->getPixel(x, y, z).to32BitBGRA();
|
return tex->getPixel(x, y, z).to32BitBGRA();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Texture3D *tex;
|
const Texture3D *tex;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Texture3D::saveToFile(const std::string &filepath)
|
void Texture3D::saveToFile(const std::string &filepath) const
|
||||||
{
|
{
|
||||||
Texture3DWriter writer(this);
|
Texture3DWriter writer(this);
|
||||||
writer.save(filepath, xsize, ysize * zsize);
|
writer.save(filepath, xsize, ysize * zsize);
|
||||||
|
|
|
@ -12,17 +12,17 @@ public:
|
||||||
Texture3D(int xsize, int ysize, int zsize);
|
Texture3D(int xsize, int ysize, int zsize);
|
||||||
~Texture3D();
|
~Texture3D();
|
||||||
|
|
||||||
void getSize(int* xsize, int* ysize, int* zsize);
|
void getSize(int* xsize, int* ysize, int* zsize) const;
|
||||||
void setPixel(int x, int y, int z, Color col);
|
void setPixel(int x, int y, int z, Color col);
|
||||||
Color getPixel(int x, int y, int z);
|
Color getPixel(int x, int y, int z) const;
|
||||||
Color getNearest(double dx, double dy, double dz);
|
Color getNearest(double dx, double dy, double dz) const;
|
||||||
Color getLinear(double dx, double dy, double dz);
|
Color getLinear(double dx, double dy, double dz) const;
|
||||||
Color getCubic(double dx, double dy, double dz);
|
Color getCubic(double dx, double dy, double dz) const;
|
||||||
void fill(Color col);
|
void fill(Color col);
|
||||||
void add(Texture3D* other);
|
void add(Texture3D* other);
|
||||||
void save(PackStream* stream);
|
void save(PackStream* stream) const;
|
||||||
void load(PackStream* stream);
|
void load(PackStream* stream);
|
||||||
void saveToFile(const std::string &filepath);
|
void saveToFile(const std::string &filepath) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int xsize;
|
int xsize;
|
||||||
|
|
|
@ -21,7 +21,7 @@ Texture4D::~Texture4D()
|
||||||
delete[] data;
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture4D::getSize(int* xsize, int* ysize, int* zsize, int* wsize)
|
void Texture4D::getSize(int* xsize, int* ysize, int* zsize, int* wsize) const
|
||||||
{
|
{
|
||||||
*xsize = this->xsize;
|
*xsize = this->xsize;
|
||||||
*ysize = this->ysize;
|
*ysize = this->ysize;
|
||||||
|
@ -39,7 +39,7 @@ void Texture4D::setPixel(int x, int y, int z, int w, Color col)
|
||||||
this->data[w * this->xsize * this->ysize * this->zsize + z * this->xsize * this->ysize + y * this->xsize + x] = col;
|
this->data[w * this->xsize * this->ysize * this->zsize + z * this->xsize * this->ysize + y * this->xsize + x] = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture4D::getPixel(int x, int y, int z, int w)
|
Color Texture4D::getPixel(int x, int y, int z, int w) const
|
||||||
{
|
{
|
||||||
assert(x >= 0 && x < this->xsize);
|
assert(x >= 0 && x < this->xsize);
|
||||||
assert(y >= 0 && y < this->ysize);
|
assert(y >= 0 && y < this->ysize);
|
||||||
|
@ -49,7 +49,7 @@ Color Texture4D::getPixel(int x, int y, int z, int w)
|
||||||
return this->data[w * this->xsize * this->ysize * this->zsize + z * this->xsize * this->ysize + y * this->xsize + x];
|
return this->data[w * this->xsize * this->ysize * this->zsize + z * this->xsize * this->ysize + y * this->xsize + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture4D::getNearest(double dx, double dy, double dz, double dw)
|
Color Texture4D::getNearest(double dx, double dy, double dz, double dw) const
|
||||||
{
|
{
|
||||||
if (dx < 0.0) dx = 0.0;
|
if (dx < 0.0) dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0) dx = 1.0;
|
||||||
|
@ -73,7 +73,7 @@ Color Texture4D::getNearest(double dx, double dy, double dz, double dw)
|
||||||
return this->data[iw * this->xsize * this->ysize * this->zsize + iz * this->xsize * this->ysize + iy * this->xsize + ix];
|
return this->data[iw * this->xsize * this->ysize * this->zsize + iz * this->xsize * this->ysize + iy * this->xsize + ix];
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture4D::getLinear(double dx, double dy, double dz, double dw)
|
Color Texture4D::getLinear(double dx, double dy, double dz, double dw) const
|
||||||
{
|
{
|
||||||
if (dx < 0.0) dx = 0.0;
|
if (dx < 0.0) dx = 0.0;
|
||||||
if (dx > 1.0) dx = 1.0;
|
if (dx > 1.0) dx = 1.0;
|
||||||
|
@ -143,7 +143,7 @@ Color Texture4D::getLinear(double dx, double dy, double dz, double dw)
|
||||||
return cz1.lerp(cz2, dw);
|
return cz1.lerp(cz2, dw);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Texture4D::getCubic(double dx, double dy, double dz, double dw)
|
Color Texture4D::getCubic(double dx, double dy, double dz, double dw) const
|
||||||
{
|
{
|
||||||
/* TODO */
|
/* TODO */
|
||||||
return getLinear(dx, dy, dz, dw);
|
return getLinear(dx, dy, dz, dw);
|
||||||
|
@ -178,7 +178,7 @@ void Texture4D::add(Texture4D* source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture4D::save(PackStream* stream)
|
void Texture4D::save(PackStream* stream) const
|
||||||
{
|
{
|
||||||
int i, n;
|
int i, n;
|
||||||
stream->write(&this->xsize);
|
stream->write(&this->xsize);
|
||||||
|
@ -212,7 +212,7 @@ void Texture4D::load(PackStream* stream)
|
||||||
class Texture4DWriter:public PictureWriter
|
class Texture4DWriter:public PictureWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Texture4DWriter(Texture4D *tex): tex(tex) {}
|
Texture4DWriter(const Texture4D *tex): tex(tex) {}
|
||||||
|
|
||||||
virtual unsigned int getPixel(int x, int y) override
|
virtual unsigned int getPixel(int x, int y) override
|
||||||
{
|
{
|
||||||
|
@ -228,10 +228,10 @@ public:
|
||||||
return tex->getPixel(x, y, z, w).to32BitBGRA();
|
return tex->getPixel(x, y, z, w).to32BitBGRA();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Texture4D *tex;
|
const Texture4D *tex;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Texture4D::saveToFile(const std::string &filepath)
|
void Texture4D::saveToFile(const std::string &filepath) const
|
||||||
{
|
{
|
||||||
Texture4DWriter writer(this);
|
Texture4DWriter writer(this);
|
||||||
writer.save(filepath, xsize * wsize, ysize * zsize);
|
writer.save(filepath, xsize * wsize, ysize * zsize);
|
||||||
|
|
|
@ -12,17 +12,17 @@ public:
|
||||||
Texture4D(int xsize, int ysize, int zsize, int wsize);
|
Texture4D(int xsize, int ysize, int zsize, int wsize);
|
||||||
~Texture4D();
|
~Texture4D();
|
||||||
|
|
||||||
void getSize(int* xsize, int* ysize, int* zsize, int* wsize);
|
void getSize(int* xsize, int* ysize, int* zsize, int* wsize) const;
|
||||||
void setPixel(int x, int y, int z, int w, Color col);
|
void setPixel(int x, int y, int z, int w, Color col);
|
||||||
Color getPixel(int x, int y, int z, int w);
|
Color getPixel(int x, int y, int z, int w) const;
|
||||||
Color getNearest(double dx, double dy, double dz, double dw);
|
Color getNearest(double dx, double dy, double dz, double dw) const;
|
||||||
Color getLinear(double dx, double dy, double dz, double dw);
|
Color getLinear(double dx, double dy, double dz, double dw) const;
|
||||||
Color getCubic(double dx, double dy, double dz, double dw);
|
Color getCubic(double dx, double dy, double dz, double dw) const;
|
||||||
void fill(Color col);
|
void fill(Color col);
|
||||||
void add(Texture4D* other);
|
void add(Texture4D* other);
|
||||||
void save(PackStream* stream);
|
void save(PackStream* stream) const;
|
||||||
void load(PackStream* stream);
|
void load(PackStream* stream);
|
||||||
void saveToFile(const std::string &filepath);
|
void saveToFile(const std::string &filepath) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int xsize;
|
int xsize;
|
||||||
|
|
|
@ -20,6 +20,9 @@ namespace basics {
|
||||||
class NoiseGenerator;
|
class NoiseGenerator;
|
||||||
class Curve;
|
class Curve;
|
||||||
class ColorProfile;
|
class ColorProfile;
|
||||||
|
class Texture2D;
|
||||||
|
class Texture3D;
|
||||||
|
class Texture4D;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
using namespace paysages::basics;
|
using namespace paysages::basics;
|
||||||
|
|
|
@ -36,6 +36,7 @@ public:
|
||||||
inline double getRoll() const {return roll;}
|
inline double getRoll() const {return roll;}
|
||||||
inline Vector3 getDirection() const {return Vector3(direction);}
|
inline Vector3 getDirection() const {return Vector3(direction);}
|
||||||
inline Vector3 getDirectionNormalized() const {return forward;}
|
inline Vector3 getDirectionNormalized() const {return forward;}
|
||||||
|
inline const Matrix4 &getTransformationMatrix() const {return projector;}
|
||||||
inline VectorSpherical getDirectionSpherical() const {return direction;}
|
inline VectorSpherical getDirectionSpherical() const {return direction;}
|
||||||
inline CameraPerspective getPerspective() const {return perspective;}
|
inline CameraPerspective getPerspective() const {return perspective;}
|
||||||
|
|
||||||
|
|
|
@ -199,8 +199,8 @@ void Scenery::getWater(WaterDefinition* water)
|
||||||
void Scenery::checkCameraAboveGround()
|
void Scenery::checkCameraAboveGround()
|
||||||
{
|
{
|
||||||
Vector3 camera_location = camera->getLocation();
|
Vector3 camera_location = camera->getLocation();
|
||||||
double terrain_height = terrain->getInterpolatedHeight(camera_location.x, camera_location.z, 1, 1) + 0.5;
|
double terrain_height = terrain->getInterpolatedHeight(camera_location.x, camera_location.z, 1, 1) + 2.0;
|
||||||
double water_height = terrain->getWaterHeight() + 0.5;
|
double water_height = terrain->getWaterHeight() + 1.5;
|
||||||
if (camera_location.y < water_height || camera_location.y < terrain_height)
|
if (camera_location.y < water_height || camera_location.y < terrain_height)
|
||||||
{
|
{
|
||||||
double diff = ((water_height > terrain_height) ? water_height : terrain_height) - camera_location.y;
|
double diff = ((water_height > terrain_height) ? water_height : terrain_height) - camera_location.y;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define DEFINITION_GLOBAL_H
|
#define DEFINITION_GLOBAL_H
|
||||||
|
|
||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
|
|
||||||
#if defined(DEFINITION_LIBRARY)
|
#if defined(DEFINITION_LIBRARY)
|
||||||
# define DEFINITIONSHARED_EXPORT Q_DECL_EXPORT
|
# define DEFINITIONSHARED_EXPORT Q_DECL_EXPORT
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -1,170 +0,0 @@
|
||||||
#include "BaseExplorerChunk.h"
|
|
||||||
|
|
||||||
#include <QImage>
|
|
||||||
#include <QGLWidget>
|
|
||||||
#include "ColorProfile.h"
|
|
||||||
|
|
||||||
#ifndef GL_CLAMP_TO_EDGE
|
|
||||||
#define GL_CLAMP_TO_EDGE 0x812F
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BaseExplorerChunk::BaseExplorerChunk(SoftwareRenderer* renderer)
|
|
||||||
{
|
|
||||||
_renderer = renderer;
|
|
||||||
_color_profile = new ColorProfile;
|
|
||||||
|
|
||||||
priority = 0.0;
|
|
||||||
_reset_needed = false;
|
|
||||||
|
|
||||||
_texture = new QImage(1, 1, QImage::Format_ARGB32);
|
|
||||||
_texture_id = 0;
|
|
||||||
_texture_changed = false;
|
|
||||||
_texture_current_size = 0;
|
|
||||||
_texture_max_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseExplorerChunk::~BaseExplorerChunk()
|
|
||||||
{
|
|
||||||
_lock_data.lock();
|
|
||||||
delete _color_profile;
|
|
||||||
delete _texture;
|
|
||||||
_lock_data.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseExplorerChunk::maintain()
|
|
||||||
{
|
|
||||||
bool subchanged;
|
|
||||||
|
|
||||||
_lock_data.lock();
|
|
||||||
if (_reset_needed)
|
|
||||||
{
|
|
||||||
_reset_needed = false;
|
|
||||||
_texture_current_size = 0;
|
|
||||||
onResetEvent();
|
|
||||||
}
|
|
||||||
_lock_data.unlock();
|
|
||||||
|
|
||||||
subchanged = onMaintainEvent();
|
|
||||||
|
|
||||||
// Improve texture resolution
|
|
||||||
if (_texture_current_size < _texture_max_size)
|
|
||||||
{
|
|
||||||
int new_texture_size = _texture_current_size ? _texture_current_size * 2 : 1;
|
|
||||||
QImage* new_image = new QImage(_texture->scaled(new_texture_size + 1, new_texture_size + 1, Qt::IgnoreAspectRatio, Qt::FastTransformation));
|
|
||||||
for (int j = 0; j <= new_texture_size; j++)
|
|
||||||
{
|
|
||||||
for (int i = 0; i <= new_texture_size; i++)
|
|
||||||
{
|
|
||||||
if (_texture_current_size <= 1 || i % 2 != 0 || j % 2 != 0)
|
|
||||||
{
|
|
||||||
Color color = getTextureColor((double)i / (double)new_texture_size, 1.0 - (double)j / (double)new_texture_size);
|
|
||||||
color = _color_profile->apply(color);
|
|
||||||
color.normalize();
|
|
||||||
new_image->setPixel(i, j, color.to32BitBGRA());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_lock_data.lock();
|
|
||||||
delete _texture;
|
|
||||||
_texture = new_image;
|
|
||||||
_texture_current_size = new_texture_size;
|
|
||||||
_texture_changed = true;
|
|
||||||
_lock_data.unlock();
|
|
||||||
|
|
||||||
/*if (_texture_current_size < 4 && _texture_current_size < _texture_max_size)
|
|
||||||
{
|
|
||||||
maintain();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return subchanged;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseExplorerChunk::updatePriority(CameraDefinition* camera)
|
|
||||||
{
|
|
||||||
if (_reset_needed || (_texture_max_size > 1 && _texture_current_size <= 1))
|
|
||||||
{
|
|
||||||
priority = 1000.0;
|
|
||||||
}
|
|
||||||
else if (_texture_current_size == _texture_max_size)
|
|
||||||
{
|
|
||||||
priority = -1000.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
priority = getDisplayedSizeHint(camera) - _texture_current_size;
|
|
||||||
}
|
|
||||||
onCameraEvent(camera);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseExplorerChunk::render(QGLWidget* widget)
|
|
||||||
{
|
|
||||||
// Put texture in place
|
|
||||||
_lock_data.lock();
|
|
||||||
if (_texture_changed)
|
|
||||||
{
|
|
||||||
_texture_changed = false;
|
|
||||||
if (_texture_id)
|
|
||||||
{
|
|
||||||
widget->deleteTexture(_texture_id);
|
|
||||||
}
|
|
||||||
// TODO Only do the scale if not power-of-two textures are unsupported by GPU
|
|
||||||
_texture_id = widget->bindTexture(_texture->scaled(_texture_current_size, _texture_current_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
|
||||||
//_texture_id = widget->bindTexture(*_texture);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_2D, _texture_id);
|
|
||||||
}
|
|
||||||
_lock_data.unlock();
|
|
||||||
|
|
||||||
// Delegate poly rendering to subclass
|
|
||||||
if (!_reset_needed)
|
|
||||||
{
|
|
||||||
onRenderEvent(widget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseExplorerChunk::askReset()
|
|
||||||
{
|
|
||||||
_reset_needed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseExplorerChunk::setMaxTextureSize(int size)
|
|
||||||
{
|
|
||||||
_texture_max_size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseExplorerChunk::onCameraEvent(CameraDefinition*)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseExplorerChunk::onResetEvent()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseExplorerChunk::onMaintainEvent()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseExplorerChunk::onRenderEvent(QGLWidget*)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
double BaseExplorerChunk::getDisplayedSizeHint(CameraDefinition*)
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color BaseExplorerChunk::getTextureColor(double, double)
|
|
||||||
{
|
|
||||||
return COLOR_TRANSPARENT;
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
#ifndef BASEEXPLORERCHUNK_H
|
|
||||||
#define BASEEXPLORERCHUNK_H
|
|
||||||
|
|
||||||
#include "opengl_global.h"
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include "Color.h"
|
|
||||||
|
|
||||||
class QImage;
|
|
||||||
class QGLWidget;
|
|
||||||
|
|
||||||
namespace paysages {
|
|
||||||
namespace opengl {
|
|
||||||
|
|
||||||
class BaseExplorerChunk
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~BaseExplorerChunk();
|
|
||||||
|
|
||||||
bool maintain();
|
|
||||||
void updatePriority(CameraDefinition* camera);
|
|
||||||
void render(QGLWidget* widget);
|
|
||||||
|
|
||||||
double priority;
|
|
||||||
protected:
|
|
||||||
BaseExplorerChunk(SoftwareRenderer* renderer);
|
|
||||||
|
|
||||||
inline SoftwareRenderer* renderer() {return _renderer;}
|
|
||||||
|
|
||||||
void askReset();
|
|
||||||
void setMaxTextureSize(int size);
|
|
||||||
|
|
||||||
virtual void onCameraEvent(CameraDefinition* camera);
|
|
||||||
virtual void onResetEvent();
|
|
||||||
virtual bool onMaintainEvent();
|
|
||||||
virtual void onRenderEvent(QGLWidget* widget);
|
|
||||||
virtual double getDisplayedSizeHint(CameraDefinition* camera);
|
|
||||||
virtual Color getTextureColor(double x, double y);
|
|
||||||
|
|
||||||
QMutex _lock_data;
|
|
||||||
|
|
||||||
private:
|
|
||||||
SoftwareRenderer* _renderer;
|
|
||||||
ColorProfile* _color_profile;
|
|
||||||
|
|
||||||
bool _reset_needed;
|
|
||||||
|
|
||||||
QImage* _texture;
|
|
||||||
unsigned int _texture_id;
|
|
||||||
bool _texture_changed;
|
|
||||||
int _texture_current_size;
|
|
||||||
int _texture_max_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // BASEEXPLORERCHUNK_H
|
|
|
@ -1,148 +0,0 @@
|
||||||
#include "ExplorerChunkSky.h"
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#include "CameraDefinition.h"
|
|
||||||
#include "SoftwareRenderer.h"
|
|
||||||
#include "AtmosphereRenderer.h"
|
|
||||||
#include "AtmosphereResult.h"
|
|
||||||
|
|
||||||
ExplorerChunkSky::ExplorerChunkSky(SoftwareRenderer* renderer, double size, SkyboxOrientation orientation) : BaseExplorerChunk(renderer)
|
|
||||||
{
|
|
||||||
_box_size = size;
|
|
||||||
_orientation = orientation;
|
|
||||||
_center = VECTOR_ZERO;
|
|
||||||
|
|
||||||
setMaxTextureSize(256);
|
|
||||||
maintain();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExplorerChunkSky::onCameraEvent(CameraDefinition* camera)
|
|
||||||
{
|
|
||||||
_center = camera->getLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExplorerChunkSky::onRenderEvent(QGLWidget*)
|
|
||||||
{
|
|
||||||
double size = _box_size;
|
|
||||||
Vector3 camera = _center;
|
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
switch (_orientation)
|
|
||||||
{
|
|
||||||
case SKYBOX_NORTH:
|
|
||||||
glTexCoord2d(0.0, 0.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y + size, camera.z - size);
|
|
||||||
glTexCoord2d(0.0, 1.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y - size, camera.z - size);
|
|
||||||
glTexCoord2d(1.0, 1.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y - size, camera.z - size);
|
|
||||||
glTexCoord2d(1.0, 0.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y + size, camera.z - size);
|
|
||||||
break;
|
|
||||||
case SKYBOX_SOUTH:
|
|
||||||
glTexCoord2d(0.0, 0.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y + size, camera.z + size);
|
|
||||||
glTexCoord2d(0.0, 1.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y - size, camera.z + size);
|
|
||||||
glTexCoord2d(1.0, 1.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y - size, camera.z + size);
|
|
||||||
glTexCoord2d(1.0, 0.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y + size, camera.z + size);
|
|
||||||
break;
|
|
||||||
case SKYBOX_EAST:
|
|
||||||
glTexCoord2d(0.0, 0.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y + size, camera.z - size);
|
|
||||||
glTexCoord2d(0.0, 1.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y - size, camera.z - size);
|
|
||||||
glTexCoord2d(1.0, 1.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y - size, camera.z + size);
|
|
||||||
glTexCoord2d(1.0, 0.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y + size, camera.z + size);
|
|
||||||
break;
|
|
||||||
case SKYBOX_WEST:
|
|
||||||
glTexCoord2d(0.0, 0.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y + size, camera.z + size);
|
|
||||||
glTexCoord2d(0.0, 1.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y - size, camera.z + size);
|
|
||||||
glTexCoord2d(1.0, 1.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y - size, camera.z - size);
|
|
||||||
glTexCoord2d(1.0, 0.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y + size, camera.z - size);
|
|
||||||
break;
|
|
||||||
case SKYBOX_TOP:
|
|
||||||
glTexCoord2d(0.0, 0.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y + size, camera.z + size);
|
|
||||||
glTexCoord2d(0.0, 1.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y + size, camera.z - size);
|
|
||||||
glTexCoord2d(1.0, 1.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y + size, camera.z - size);
|
|
||||||
glTexCoord2d(1.0, 0.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y + size, camera.z + size);
|
|
||||||
break;
|
|
||||||
case SKYBOX_BOTTOM:
|
|
||||||
/*glTexCoord2d(0.0, 0.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y - size, camera.z - size);
|
|
||||||
glTexCoord2d(0.0, 1.0);
|
|
||||||
glVertex3d(camera.x - size, camera.y - size, camera.z + size);
|
|
||||||
glTexCoord2d(1.0, 1.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y - size, camera.z + size);
|
|
||||||
glTexCoord2d(1.0, 0.0);
|
|
||||||
glVertex3d(camera.x + size, camera.y - size, camera.z - size);*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
double ExplorerChunkSky::getDisplayedSizeHint(CameraDefinition*)
|
|
||||||
{
|
|
||||||
return 1000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color ExplorerChunkSky::getTextureColor(double x, double y)
|
|
||||||
{
|
|
||||||
Vector3 location;
|
|
||||||
|
|
||||||
x -= 0.5;
|
|
||||||
y -= 0.5;
|
|
||||||
|
|
||||||
switch (_orientation)
|
|
||||||
{
|
|
||||||
case SKYBOX_NORTH:
|
|
||||||
location.x = x;
|
|
||||||
location.y = -y;
|
|
||||||
location.z = -0.5;
|
|
||||||
break;
|
|
||||||
case SKYBOX_SOUTH:
|
|
||||||
location.x = -x;
|
|
||||||
location.y = -y;
|
|
||||||
location.z = 0.5;
|
|
||||||
break;
|
|
||||||
case SKYBOX_EAST:
|
|
||||||
location.x = 0.5;
|
|
||||||
location.y = -y;
|
|
||||||
location.z = x;
|
|
||||||
break;
|
|
||||||
case SKYBOX_WEST:
|
|
||||||
location.x = -0.5;
|
|
||||||
location.y = -y;
|
|
||||||
location.z = -x;
|
|
||||||
break;
|
|
||||||
case SKYBOX_TOP:
|
|
||||||
location.x = x;
|
|
||||||
location.y = 0.5;
|
|
||||||
location.z = -y;
|
|
||||||
break;
|
|
||||||
case SKYBOX_BOTTOM:
|
|
||||||
location.x = x;
|
|
||||||
location.y = -0.5;
|
|
||||||
location.z = y;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
location = location.normalize();
|
|
||||||
if (location.y < 0.0)
|
|
||||||
{
|
|
||||||
location.y = 0.0;
|
|
||||||
}
|
|
||||||
return renderer()->getAtmosphereRenderer()->getSkyColor(location).final;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
#ifndef EXPLORERCHUNKSKY_H
|
|
||||||
#define EXPLORERCHUNKSKY_H
|
|
||||||
|
|
||||||
#include "opengl_global.h"
|
|
||||||
|
|
||||||
#include "BaseExplorerChunk.h"
|
|
||||||
|
|
||||||
#include "Vector3.h"
|
|
||||||
|
|
||||||
namespace paysages {
|
|
||||||
namespace opengl {
|
|
||||||
|
|
||||||
enum SkyboxOrientation
|
|
||||||
{
|
|
||||||
SKYBOX_NORTH,
|
|
||||||
SKYBOX_SOUTH,
|
|
||||||
SKYBOX_WEST,
|
|
||||||
SKYBOX_EAST,
|
|
||||||
SKYBOX_TOP,
|
|
||||||
SKYBOX_BOTTOM
|
|
||||||
};
|
|
||||||
|
|
||||||
class OPENGLSHARED_EXPORT ExplorerChunkSky:public BaseExplorerChunk
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ExplorerChunkSky(SoftwareRenderer* renderer, double size, SkyboxOrientation orientation);
|
|
||||||
|
|
||||||
void onCameraEvent(CameraDefinition* camera);
|
|
||||||
void onRenderEvent(QGLWidget* widget);
|
|
||||||
double getDisplayedSizeHint(CameraDefinition* camera);
|
|
||||||
Color getTextureColor(double x, double y);
|
|
||||||
|
|
||||||
private:
|
|
||||||
SkyboxOrientation _orientation;
|
|
||||||
double _box_size;
|
|
||||||
Vector3 _center;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // EXPLORERCHUNKSKY_H
|
|
|
@ -1,13 +1,28 @@
|
||||||
#include "ExplorerChunkTerrain.h"
|
#include "ExplorerChunkTerrain.h"
|
||||||
|
|
||||||
|
#include OPENGL_FUNCTIONS_INCLUDE
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <GL/gl.h>
|
#include <QImage>
|
||||||
|
#include "ColorProfile.h"
|
||||||
#include "CameraDefinition.h"
|
#include "CameraDefinition.h"
|
||||||
#include "SoftwareRenderer.h"
|
#include "OpenGLRenderer.h"
|
||||||
#include "TerrainRenderer.h"
|
#include "TerrainRenderer.h"
|
||||||
|
#include "VertexArray.h"
|
||||||
|
|
||||||
ExplorerChunkTerrain::ExplorerChunkTerrain(SoftwareRenderer* renderer, double x, double z, double size, int nbchunks, double water_height) : BaseExplorerChunk(renderer)
|
ExplorerChunkTerrain::ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, double z, double size, int nbchunks, double water_height):
|
||||||
|
_renderer(renderer)
|
||||||
{
|
{
|
||||||
|
_color_profile = new ColorProfile(ColorProfile::TONE_MAPPING_REIHNARD, 2.0);
|
||||||
|
|
||||||
|
priority = 0.0;
|
||||||
|
_reset_needed = false;
|
||||||
|
|
||||||
|
_texture = new QImage(1, 1, QImage::Format_RGBA8888);
|
||||||
|
texture_id = 0;
|
||||||
|
_texture_changed = false;
|
||||||
|
_texture_current_size = 0;
|
||||||
|
_texture_max_size = 0;
|
||||||
|
|
||||||
_startx = x;
|
_startx = x;
|
||||||
_startz = z;
|
_startz = z;
|
||||||
_size = size;
|
_size = size;
|
||||||
|
@ -18,8 +33,11 @@ ExplorerChunkTerrain::ExplorerChunkTerrain(SoftwareRenderer* renderer, double x,
|
||||||
_water_height = water_height;
|
_water_height = water_height;
|
||||||
_overwater = false;
|
_overwater = false;
|
||||||
|
|
||||||
_tessellation_max_size = 32;
|
tessellation_count = 33;
|
||||||
_tessellation = new double[(_tessellation_max_size + 1) * (_tessellation_max_size + 1)];
|
tessellated = new VertexArray<TerrainVertex>();
|
||||||
|
tessellated->setGridSize(tessellation_count);
|
||||||
|
tessellated->setAutoGridIndices(tessellation_count);
|
||||||
|
_tessellation_max_size = tessellation_count - 1;
|
||||||
_tessellation_current_size = 0;
|
_tessellation_current_size = 0;
|
||||||
_tessellation_step = _size / (double) _tessellation_max_size;
|
_tessellation_step = _size / (double) _tessellation_max_size;
|
||||||
|
|
||||||
|
@ -31,44 +49,108 @@ ExplorerChunkTerrain::ExplorerChunkTerrain(SoftwareRenderer* renderer, double x,
|
||||||
ExplorerChunkTerrain::~ExplorerChunkTerrain()
|
ExplorerChunkTerrain::~ExplorerChunkTerrain()
|
||||||
{
|
{
|
||||||
_lock_data.lock();
|
_lock_data.lock();
|
||||||
delete [] _tessellation;
|
delete _color_profile;
|
||||||
|
delete _texture;
|
||||||
|
delete tessellated;
|
||||||
_lock_data.unlock();
|
_lock_data.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExplorerChunkTerrain::onResetEvent()
|
bool ExplorerChunkTerrain::maintain()
|
||||||
{
|
{
|
||||||
|
bool subchanged;
|
||||||
|
|
||||||
|
_lock_data.lock();
|
||||||
|
if (_reset_needed)
|
||||||
|
{
|
||||||
|
_reset_needed = false;
|
||||||
|
_texture_current_size = 0;
|
||||||
_tessellation_current_size = 0;
|
_tessellation_current_size = 0;
|
||||||
_overwater = false;
|
_overwater = false;
|
||||||
}
|
}
|
||||||
|
_lock_data.unlock();
|
||||||
|
|
||||||
|
subchanged = onMaintainEvent();
|
||||||
|
|
||||||
|
// Improve texture resolution
|
||||||
|
if (_texture_current_size < _texture_max_size)
|
||||||
|
{
|
||||||
|
int new_texture_size = _texture_current_size ? _texture_current_size * 2 : 1;
|
||||||
|
QImage* new_image = new QImage(_texture->scaled(new_texture_size + 1, new_texture_size + 1, Qt::IgnoreAspectRatio, Qt::FastTransformation));
|
||||||
|
for (int j = 0; j <= new_texture_size; j++)
|
||||||
|
{
|
||||||
|
for (int i = 0; i <= new_texture_size; i++)
|
||||||
|
{
|
||||||
|
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.normalize();
|
||||||
|
new_image->setPixel(i, j, color.to32BitRGBA());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_lock_data.lock();
|
||||||
|
delete _texture;
|
||||||
|
_texture = new_image;
|
||||||
|
_texture_current_size = new_texture_size;
|
||||||
|
_texture_changed = true;
|
||||||
|
_lock_data.unlock();
|
||||||
|
|
||||||
|
/*if (_texture_current_size < 4 && _texture_current_size < _texture_max_size)
|
||||||
|
{
|
||||||
|
maintain();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return subchanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ExplorerChunkTerrain::onMaintainEvent()
|
bool ExplorerChunkTerrain::onMaintainEvent()
|
||||||
{
|
{
|
||||||
SoftwareRenderer* renderer = this->renderer();
|
|
||||||
|
|
||||||
// Improve heightmap resolution
|
// Improve heightmap resolution
|
||||||
if (_tessellation_current_size < _tessellation_max_size)
|
if (_tessellation_current_size < _tessellation_max_size)
|
||||||
{
|
{
|
||||||
int new_tessellation_size = _tessellation_current_size ? _tessellation_current_size * 4 : 2;
|
int new_tessellation_size = _tessellation_current_size ? _tessellation_current_size * 4 : 2;
|
||||||
int old_tessellation_inc = _tessellation_current_size ? _tessellation_max_size / _tessellation_current_size : 1;
|
int old_tessellation_inc = _tessellation_current_size ? _tessellation_max_size / _tessellation_current_size : 1;
|
||||||
int new_tessellation_inc = _tessellation_max_size / new_tessellation_size;
|
int new_tessellation_inc = _tessellation_max_size / new_tessellation_size;
|
||||||
|
float internal_step = 1.0f / (float)_tessellation_max_size;
|
||||||
for (int j = 0; j <= _tessellation_max_size; j += new_tessellation_inc)
|
for (int j = 0; j <= _tessellation_max_size; j += new_tessellation_inc)
|
||||||
{
|
{
|
||||||
for (int i = 0; i <= _tessellation_max_size; i += new_tessellation_inc)
|
for (int i = 0; i <= _tessellation_max_size; i += new_tessellation_inc)
|
||||||
{
|
{
|
||||||
if (_tessellation_current_size == 0 || i % old_tessellation_inc != 0 || j % old_tessellation_inc != 0)
|
if (_tessellation_current_size == 0 || i % old_tessellation_inc != 0 || j % old_tessellation_inc != 0)
|
||||||
{
|
{
|
||||||
double height = renderer->getTerrainRenderer()->getHeight(_startx + _tessellation_step * (double) i, _startz + _tessellation_step * (double) j, 1);
|
double x = _startx + _tessellation_step * (float)i;
|
||||||
|
double z = _startz + _tessellation_step * (float)j;
|
||||||
|
|
||||||
|
double height = _renderer->getTerrainRenderer()->getHeight(x, z, 1);
|
||||||
if (height >= _water_height)
|
if (height >= _water_height)
|
||||||
{
|
{
|
||||||
_overwater = true;
|
_overwater = true;
|
||||||
}
|
}
|
||||||
_tessellation[j * (_tessellation_max_size + 1) + i] = height;
|
|
||||||
|
TerrainVertex v;
|
||||||
|
|
||||||
|
v.uv[0] = internal_step * (float)i;
|
||||||
|
v.uv[1] = internal_step * (float)j;
|
||||||
|
|
||||||
|
v.location[0] = x;
|
||||||
|
v.location[1] = height;
|
||||||
|
v.location[2] = z;
|
||||||
|
|
||||||
|
tessellated->setGridVertex(tessellation_count, i, j, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_lock_data.lock();
|
_lock_data.lock();
|
||||||
_tessellation_current_size = new_tessellation_size;
|
_tessellation_current_size = new_tessellation_size;
|
||||||
|
tessellated->setAutoGridIndices(tessellation_count, new_tessellation_inc);
|
||||||
_lock_data.unlock();
|
_lock_data.unlock();
|
||||||
|
|
||||||
if (_tessellation_current_size < 4 && _tessellation_current_size < _tessellation_max_size)
|
if (_tessellation_current_size < 4 && _tessellation_current_size < _tessellation_max_size)
|
||||||
|
@ -84,8 +166,21 @@ bool ExplorerChunkTerrain::onMaintainEvent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExplorerChunkTerrain::onCameraEvent(CameraDefinition* camera)
|
void ExplorerChunkTerrain::updatePriority(CameraDefinition* camera)
|
||||||
{
|
{
|
||||||
|
if (_reset_needed || (_texture_max_size > 1 && _texture_current_size <= 1))
|
||||||
|
{
|
||||||
|
priority = 1000.0;
|
||||||
|
}
|
||||||
|
else if (_texture_current_size == _texture_max_size)
|
||||||
|
{
|
||||||
|
priority = -1000.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priority = getDisplayedSizeHint(camera) - _texture_current_size;
|
||||||
|
}
|
||||||
|
|
||||||
Vector3 camera_location = camera->getLocation();
|
Vector3 camera_location = camera->getLocation();
|
||||||
|
|
||||||
// Handle position
|
// Handle position
|
||||||
|
@ -116,11 +211,38 @@ void ExplorerChunkTerrain::onCameraEvent(CameraDefinition* camera)
|
||||||
_lock_data.unlock();
|
_lock_data.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExplorerChunkTerrain::onRenderEvent(QGLWidget*)
|
void ExplorerChunkTerrain::render(QOpenGLShaderProgram* program, OpenGLFunctions* functions)
|
||||||
|
{
|
||||||
|
// Put texture in place
|
||||||
|
_lock_data.lock();
|
||||||
|
if (_texture_changed)
|
||||||
|
{
|
||||||
|
_texture_changed = false;
|
||||||
|
|
||||||
|
// TODO Only do the scale if not power-of-two textures are unsupported by GPU
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
_lock_data.unlock();
|
||||||
|
|
||||||
|
// Render tessellated mesh
|
||||||
|
if (!_reset_needed)
|
||||||
{
|
{
|
||||||
_lock_data.lock();
|
_lock_data.lock();
|
||||||
int tessellation_size = _tessellation_current_size;
|
int tessellation_size = _tessellation_current_size;
|
||||||
double tsize = 1.0 / (double) _tessellation_max_size;
|
|
||||||
_lock_data.unlock();
|
_lock_data.unlock();
|
||||||
|
|
||||||
if (tessellation_size <= 1 or not _overwater)
|
if (tessellation_size <= 1 or not _overwater)
|
||||||
|
@ -128,19 +250,25 @@ void ExplorerChunkTerrain::onRenderEvent(QGLWidget*)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tessellation_inc = _tessellation_max_size / (double) tessellation_size;
|
_lock_data.lock(); // TEMP
|
||||||
for (int j = 0; j < _tessellation_max_size; j += tessellation_inc)
|
// TEMP
|
||||||
{
|
functions->glActiveTexture(GL_TEXTURE0 + 3);
|
||||||
glBegin(GL_QUAD_STRIP);
|
functions->glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||||
for (int i = 0; i <= _tessellation_max_size; i += tessellation_inc)
|
program->setUniformValue("groundTexture", 3);
|
||||||
{
|
|
||||||
glTexCoord2d(tsize * (double) i, tsize * (double) j);
|
tessellated->render(program, functions);
|
||||||
glVertex3d(_startx + _tessellation_step * (double) i, _tessellation[j * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double) j);
|
_lock_data.unlock(); // TEMP
|
||||||
glTexCoord2d(tsize * (double) i, tsize * (double) (j + tessellation_inc));
|
|
||||||
glVertex3d(_startx + _tessellation_step * (double) i, _tessellation[(j + tessellation_inc) * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double) (j + tessellation_inc));
|
|
||||||
}
|
}
|
||||||
glEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExplorerChunkTerrain::askReset()
|
||||||
|
{
|
||||||
|
_reset_needed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExplorerChunkTerrain::setMaxTextureSize(int size)
|
||||||
|
{
|
||||||
|
_texture_max_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
double ExplorerChunkTerrain::getDisplayedSizeHint(CameraDefinition* camera)
|
double ExplorerChunkTerrain::getDisplayedSizeHint(CameraDefinition* camera)
|
||||||
|
@ -170,7 +298,7 @@ double ExplorerChunkTerrain::getDisplayedSizeHint(CameraDefinition* camera)
|
||||||
Color ExplorerChunkTerrain::getTextureColor(double x, double y)
|
Color ExplorerChunkTerrain::getTextureColor(double x, double y)
|
||||||
{
|
{
|
||||||
Vector3 location = {_startx + x * _size, 0.0, _startz + y * _size};
|
Vector3 location = {_startx + x * _size, 0.0, _startz + y * _size};
|
||||||
return renderer()->getTerrainRenderer()->getFinalColor(location, 0.01);
|
return _renderer->getTerrainRenderer()->getFinalColor(location, 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 ExplorerChunkTerrain::getCenter()
|
Vector3 ExplorerChunkTerrain::getCenter()
|
||||||
|
|
|
@ -1,26 +1,41 @@
|
||||||
#ifndef EXPLORERCHUNKTERRAIN_H
|
#ifndef EXPLORERCHUNKTERRAIN_H
|
||||||
#define EXPLORERCHUNKTERRAIN_H
|
#define EXPLORERCHUNKTERRAIN_H
|
||||||
|
|
||||||
#include "BaseExplorerChunk.h"
|
#include "opengl_global.h"
|
||||||
|
|
||||||
#include "Vector3.h"
|
#include <QMutex>
|
||||||
|
class QImage;
|
||||||
|
class QOpenGLShaderProgram;
|
||||||
|
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace opengl {
|
namespace opengl {
|
||||||
|
|
||||||
class OPENGLSHARED_EXPORT ExplorerChunkTerrain:public BaseExplorerChunk
|
class OPENGLSHARED_EXPORT ExplorerChunkTerrain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ExplorerChunkTerrain(SoftwareRenderer* renderer, double x, double z, double size, int nbchunks, double water_height);
|
typedef struct
|
||||||
|
{
|
||||||
|
float location[3];
|
||||||
|
float uv[2];
|
||||||
|
} TerrainVertex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ExplorerChunkTerrain(OpenGLRenderer* renderer, double x, double z, double size, int nbchunks, double water_height);
|
||||||
~ExplorerChunkTerrain();
|
~ExplorerChunkTerrain();
|
||||||
|
|
||||||
void onCameraEvent(CameraDefinition* camera);
|
bool maintain();
|
||||||
void onResetEvent();
|
void updatePriority(CameraDefinition* camera);
|
||||||
|
void render(QOpenGLShaderProgram* program, OpenGLFunctions* functions);
|
||||||
|
|
||||||
|
void askReset();
|
||||||
|
void setMaxTextureSize(int size);
|
||||||
|
|
||||||
bool onMaintainEvent();
|
bool onMaintainEvent();
|
||||||
void onRenderEvent(QGLWidget* widget);
|
|
||||||
double getDisplayedSizeHint(CameraDefinition* camera);
|
double getDisplayedSizeHint(CameraDefinition* camera);
|
||||||
Color getTextureColor(double x, double y);
|
Color getTextureColor(double x, double y);
|
||||||
|
|
||||||
|
double priority;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3 getCenter();
|
Vector3 getCenter();
|
||||||
|
|
||||||
|
@ -33,11 +48,24 @@ private:
|
||||||
double _water_height;
|
double _water_height;
|
||||||
bool _overwater;
|
bool _overwater;
|
||||||
|
|
||||||
double* _tessellation;
|
int tessellation_count;
|
||||||
|
VertexArray<TerrainVertex> *tessellated;
|
||||||
int _tessellation_max_size;
|
int _tessellation_max_size;
|
||||||
int _tessellation_current_size;
|
int _tessellation_current_size;
|
||||||
double _tessellation_step;
|
double _tessellation_step;
|
||||||
|
|
||||||
|
QMutex _lock_data;
|
||||||
|
|
||||||
|
OpenGLRenderer* _renderer;
|
||||||
|
ColorProfile* _color_profile;
|
||||||
|
|
||||||
|
bool _reset_needed;
|
||||||
|
|
||||||
|
QImage* _texture;
|
||||||
|
unsigned int texture_id;
|
||||||
|
bool _texture_changed;
|
||||||
|
int _texture_current_size;
|
||||||
|
int _texture_max_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
49
src/render/opengl/OpenGLPart.cpp
Normal file
49
src/render/opengl/OpenGLPart.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include "OpenGLPart.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <cmath>
|
||||||
|
#include "OpenGLRenderer.h"
|
||||||
|
#include "OpenGLShaderProgram.h"
|
||||||
|
#include "CameraDefinition.h"
|
||||||
|
#include "AtmosphereDefinition.h"
|
||||||
|
#include "AtmosphereRenderer.h"
|
||||||
|
#include "Scenery.h"
|
||||||
|
|
||||||
|
OpenGLPart::OpenGLPart(OpenGLRenderer* renderer):
|
||||||
|
renderer(renderer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLPart::~OpenGLPart()
|
||||||
|
{
|
||||||
|
QMapIterator<QString, OpenGLShaderProgram*> i(shaders);
|
||||||
|
while (i.hasNext())
|
||||||
|
{
|
||||||
|
i.next();
|
||||||
|
delete i.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLShaderProgram* OpenGLPart::createShader(QString name)
|
||||||
|
{
|
||||||
|
OpenGLShaderProgram* program = new OpenGLShaderProgram(name, renderer);
|
||||||
|
|
||||||
|
if (!shaders.contains(name))
|
||||||
|
{
|
||||||
|
shaders[name] = program;
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLPart::updateScenery(bool onlyCommon)
|
||||||
|
{
|
||||||
|
// Let subclass do its own collecting
|
||||||
|
if (not onlyCommon)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
44
src/render/opengl/OpenGLPart.h
Normal file
44
src/render/opengl/OpenGLPart.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef OPENGLPART_H
|
||||||
|
#define OPENGLPART_H
|
||||||
|
|
||||||
|
#include "opengl_global.h"
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace opengl {
|
||||||
|
|
||||||
|
// Class that can be inherited by scenery parts, to use OpenGL features
|
||||||
|
|
||||||
|
class OPENGLSHARED_EXPORT OpenGLPart
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenGLPart(OpenGLRenderer* renderer);
|
||||||
|
virtual ~OpenGLPart();
|
||||||
|
|
||||||
|
// Initialize the part rendering (create shaders, prepare static textures...)
|
||||||
|
virtual void initialize() = 0;
|
||||||
|
|
||||||
|
// Update parameters from scenery
|
||||||
|
virtual void update() = 0;
|
||||||
|
|
||||||
|
// Do the rendering
|
||||||
|
virtual void render() = 0;
|
||||||
|
|
||||||
|
void updateScenery(bool onlyCommon=false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Create a shader program
|
||||||
|
OpenGLShaderProgram* createShader(QString name);
|
||||||
|
|
||||||
|
// Access to the main scenery renderer
|
||||||
|
OpenGLRenderer* renderer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMap<QString, OpenGLShaderProgram*> shaders;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENGLPART_H
|
|
@ -1,62 +1,147 @@
|
||||||
#include "OpenGLRenderer.h"
|
#include "OpenGLRenderer.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include OPENGL_FUNCTIONS_INCLUDE
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <GL/glu.h>
|
|
||||||
#include "Scenery.h"
|
|
||||||
#include "CameraDefinition.h"
|
#include "CameraDefinition.h"
|
||||||
|
#include "OpenGLSharedState.h"
|
||||||
|
#include "OpenGLSkybox.h"
|
||||||
|
#include "OpenGLWater.h"
|
||||||
|
#include "OpenGLTerrain.h"
|
||||||
|
#include "Scenery.h"
|
||||||
|
#include "LightingManager.h"
|
||||||
|
#include "Logs.h"
|
||||||
|
|
||||||
|
#include "GL/glu.h" // TEMP
|
||||||
|
|
||||||
OpenGLRenderer::OpenGLRenderer(Scenery* scenery):
|
OpenGLRenderer::OpenGLRenderer(Scenery* scenery):
|
||||||
SoftwareRenderer(scenery)
|
SoftwareRenderer(scenery)
|
||||||
{
|
{
|
||||||
|
ready = false;
|
||||||
|
|
||||||
|
functions = new OpenGLFunctions();
|
||||||
|
shared_state = new OpenGLSharedState();
|
||||||
|
|
||||||
|
shared_state->set("viewDistance", 300.0);
|
||||||
|
shared_state->set("exposure", 1.6);
|
||||||
|
|
||||||
|
skybox = new OpenGLSkybox(this);
|
||||||
|
water = new OpenGLWater(this);
|
||||||
|
terrain = new OpenGLTerrain(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLRenderer::~OpenGLRenderer()
|
OpenGLRenderer::~OpenGLRenderer()
|
||||||
{
|
{
|
||||||
|
delete skybox;
|
||||||
|
delete water;
|
||||||
|
delete terrain;
|
||||||
|
|
||||||
|
delete functions;
|
||||||
|
delete shared_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderer::initialize()
|
void OpenGLRenderer::initialize()
|
||||||
{
|
{
|
||||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
ready = functions->initializeOpenGLFunctions();
|
||||||
|
|
||||||
glDisable(GL_LIGHTING);
|
if (ready)
|
||||||
|
{
|
||||||
|
functions->glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
|
|
||||||
glFrontFace(GL_CCW);
|
functions->glDisable(GL_LIGHTING);
|
||||||
glCullFace(GL_BACK);
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
|
|
||||||
glDepthFunc(GL_LESS);
|
functions->glFrontFace(GL_CCW);
|
||||||
glDepthMask(1);
|
functions->glCullFace(GL_BACK);
|
||||||
glEnable(GL_DEPTH_TEST);
|
functions->glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
functions->glDepthFunc(GL_LESS);
|
||||||
glEnable(GL_LINE_SMOOTH);
|
functions->glDepthMask(1);
|
||||||
glLineWidth(1.0);
|
functions->glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
glDisable(GL_FOG);
|
functions->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
functions->glEnable(GL_LINE_SMOOTH);
|
||||||
|
functions->glLineWidth(1.0);
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
functions->glDisable(GL_FOG);
|
||||||
|
|
||||||
|
functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
prepare();
|
prepare();
|
||||||
|
|
||||||
|
disableClouds();
|
||||||
|
getLightingManager()->setSpecularity(false);
|
||||||
|
|
||||||
|
skybox->initialize();
|
||||||
|
skybox->updateScenery();
|
||||||
|
|
||||||
|
water->initialize();
|
||||||
|
water->updateScenery();
|
||||||
|
|
||||||
|
terrain->initialize();
|
||||||
|
terrain->updateScenery();
|
||||||
|
|
||||||
|
cameraChangeEvent(getScenery()->getCamera());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logError("Failed to initialize OpenGL bindings");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderer::resize(int width, int height)
|
void OpenGLRenderer::resize(int width, int height)
|
||||||
{
|
{
|
||||||
CameraPerspective perspective;
|
if (ready)
|
||||||
|
{
|
||||||
|
functions->glViewport(0, 0, width, height);
|
||||||
|
}
|
||||||
|
getScenery()->getCamera()->setRenderSize(width, height);
|
||||||
|
render_camera->setRenderSize(width, height);
|
||||||
|
|
||||||
glViewport(0, 0, width, height);
|
cameraChangeEvent(getScenery()->getCamera());
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
perspective = render_camera->getPerspective();
|
|
||||||
gluPerspective(perspective.yfov * 180.0 / M_PI, perspective.xratio, perspective.znear, perspective.zfar);
|
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderer::paint()
|
void OpenGLRenderer::paint()
|
||||||
{
|
{
|
||||||
|
if (ready)
|
||||||
|
{
|
||||||
|
functions->glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
|
functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
functions->glEnable(GL_BLEND);
|
||||||
|
functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
skybox->render();
|
||||||
|
terrain->render();
|
||||||
|
water->render();
|
||||||
|
|
||||||
|
int error_code;
|
||||||
|
while ((error_code = glGetError()) != GL_NO_ERROR)
|
||||||
|
{
|
||||||
|
logWarning("[OpenGL] ERROR : %s", (const char*)gluErrorString(error_code));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLRenderer::cameraChangeEvent(CameraDefinition *camera)
|
||||||
|
{
|
||||||
|
// Get camera info
|
||||||
|
Vector3 location = camera->getLocation();
|
||||||
|
Vector3 target = camera->getTarget();
|
||||||
|
Vector3 up = camera->getUpVector();
|
||||||
|
CameraPerspective perspective = camera->getPerspective();
|
||||||
|
|
||||||
|
// Compute matrix
|
||||||
|
QMatrix4x4 transform;
|
||||||
|
transform.setToIdentity();
|
||||||
|
transform.lookAt(QVector3D(location.x, location.y, location.z),
|
||||||
|
QVector3D(target.x, target.y, target.z),
|
||||||
|
QVector3D(up.x, up.y, up.z));
|
||||||
|
|
||||||
|
QMatrix4x4 projection;
|
||||||
|
projection.setToIdentity();
|
||||||
|
projection.perspective(perspective.yfov * 180.0 / M_PI, perspective.xratio, perspective.znear, perspective.zfar);
|
||||||
|
|
||||||
|
// Set in shaders
|
||||||
|
shared_state->set("cameraLocation", location);
|
||||||
|
shared_state->set("viewMatrix", projection * transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
double OpenGLRenderer::getPrecision(const Vector3 &)
|
double OpenGLRenderer::getPrecision(const Vector3 &)
|
||||||
|
|
|
@ -21,8 +21,23 @@ public:
|
||||||
void resize(int width, int height);
|
void resize(int width, int height);
|
||||||
void paint();
|
void paint();
|
||||||
|
|
||||||
|
void cameraChangeEvent(CameraDefinition* camera);
|
||||||
|
|
||||||
|
inline OpenGLFunctions* getOpenGlFunctions() const {return functions;}
|
||||||
|
inline OpenGLSharedState* getSharedState() const {return shared_state;}
|
||||||
|
|
||||||
virtual double getPrecision(const Vector3 &location) override;
|
virtual double getPrecision(const Vector3 &location) override;
|
||||||
virtual Color applyMediumTraversal(Vector3 location, Color color) override;
|
virtual Color applyMediumTraversal(Vector3 location, Color color) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool ready;
|
||||||
|
|
||||||
|
OpenGLFunctions* functions;
|
||||||
|
OpenGLSharedState* shared_state;
|
||||||
|
|
||||||
|
OpenGLSkybox* skybox;
|
||||||
|
OpenGLWater* water;
|
||||||
|
OpenGLTerrain* terrain;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
115
src/render/opengl/OpenGLShaderProgram.cpp
Normal file
115
src/render/opengl/OpenGLShaderProgram.cpp
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
#include "OpenGLShaderProgram.h"
|
||||||
|
|
||||||
|
#include OPENGL_FUNCTIONS_INCLUDE
|
||||||
|
#include <QOpenGLShaderProgram>
|
||||||
|
#include <QDir>
|
||||||
|
#include "OpenGLRenderer.h"
|
||||||
|
#include "OpenGLSharedState.h"
|
||||||
|
#include "Texture2D.h"
|
||||||
|
#include "Texture3D.h"
|
||||||
|
#include "Texture4D.h"
|
||||||
|
#include "Color.h"
|
||||||
|
#include "Logs.h"
|
||||||
|
|
||||||
|
OpenGLShaderProgram::OpenGLShaderProgram(QString name, OpenGLRenderer* renderer):
|
||||||
|
renderer(renderer), name(name)
|
||||||
|
{
|
||||||
|
program = new QOpenGLShaderProgram();
|
||||||
|
functions = renderer->getOpenGlFunctions();
|
||||||
|
compiled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLShaderProgram::~OpenGLShaderProgram()
|
||||||
|
{
|
||||||
|
delete program;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderProgram::addVertexSource(QString path)
|
||||||
|
{
|
||||||
|
QFile file(QString(":/shaders/%1.vert").arg(path));
|
||||||
|
if (file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
source_vertex += QString(file.readAll()).toStdString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logError() << "Can't open vertex file " << file.fileName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderProgram::addFragmentSource(QString path)
|
||||||
|
{
|
||||||
|
QFile file(QString(":/shaders/%1.frag").arg(path));
|
||||||
|
if (file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
source_fragment += QString(file.readAll()).toStdString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logError() << "Can't open fragment file " << file.fileName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderProgram::compile()
|
||||||
|
{
|
||||||
|
program->addShaderFromSourceCode(QOpenGLShader::Vertex, QString::fromStdString(source_vertex));
|
||||||
|
program->addShaderFromSourceCode(QOpenGLShader::Fragment, QString::fromStdString(source_fragment));
|
||||||
|
|
||||||
|
if (not program->link())
|
||||||
|
{
|
||||||
|
qWarning() << "Error while compiling shader " << name << "\n" << program->log() << "\n";
|
||||||
|
}
|
||||||
|
else if (program->log().length() > 0)
|
||||||
|
{
|
||||||
|
qDebug() << "Shader " << name << " compilation output:\n" << program->log() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderProgram::bind()
|
||||||
|
{
|
||||||
|
if (not compiled)
|
||||||
|
{
|
||||||
|
compile();
|
||||||
|
compiled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
program->bind();
|
||||||
|
|
||||||
|
int texture_unit = 0;
|
||||||
|
renderer->getSharedState()->apply(this, texture_unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderProgram::release()
|
||||||
|
{
|
||||||
|
program->release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderProgram::drawTriangles(float* vertices, int triangle_count)
|
||||||
|
{
|
||||||
|
bind();
|
||||||
|
|
||||||
|
GLuint vertex = program->attributeLocation("vertex");
|
||||||
|
program->setAttributeArray(vertex, GL_FLOAT, vertices, 3);
|
||||||
|
program->enableAttributeArray(vertex);
|
||||||
|
|
||||||
|
functions->glDrawArrays(GL_TRIANGLES, 0, triangle_count * 3);
|
||||||
|
|
||||||
|
program->disableAttributeArray(vertex);
|
||||||
|
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderProgram::drawTriangleStrip(float* vertices, int vertex_count)
|
||||||
|
{
|
||||||
|
bind();
|
||||||
|
|
||||||
|
GLuint vertex = program->attributeLocation("vertex");
|
||||||
|
program->setAttributeArray(vertex, GL_FLOAT, vertices, 3);
|
||||||
|
program->enableAttributeArray(vertex);
|
||||||
|
|
||||||
|
functions->glDrawArrays(GL_TRIANGLE_STRIP, 0, vertex_count);
|
||||||
|
|
||||||
|
program->disableAttributeArray(vertex);
|
||||||
|
|
||||||
|
release();
|
||||||
|
}
|
52
src/render/opengl/OpenGLShaderProgram.h
Normal file
52
src/render/opengl/OpenGLShaderProgram.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef OPENGLSHADERPROGRAM_H
|
||||||
|
#define OPENGLSHADERPROGRAM_H
|
||||||
|
|
||||||
|
#include "opengl_global.h"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class QOpenGLShaderProgram;
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace opengl {
|
||||||
|
|
||||||
|
class OPENGLSHARED_EXPORT OpenGLShaderProgram
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenGLShaderProgram(QString name, OpenGLRenderer* renderer);
|
||||||
|
~OpenGLShaderProgram();
|
||||||
|
|
||||||
|
void addVertexSource(QString path);
|
||||||
|
void addFragmentSource(QString path);
|
||||||
|
|
||||||
|
void drawTriangles(float* vertices, int triangle_count);
|
||||||
|
void drawTriangleStrip(float* vertices, int vertex_count);
|
||||||
|
|
||||||
|
void bind();
|
||||||
|
void release();
|
||||||
|
|
||||||
|
inline QOpenGLShaderProgram* getProgram() const {return program;}
|
||||||
|
inline OpenGLRenderer* getRenderer() const {return renderer;}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class OpenGLVariable;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void compile();
|
||||||
|
|
||||||
|
bool compiled;
|
||||||
|
|
||||||
|
OpenGLRenderer* renderer;
|
||||||
|
|
||||||
|
QString name;
|
||||||
|
QOpenGLShaderProgram* program;
|
||||||
|
OpenGLFunctions* functions;
|
||||||
|
|
||||||
|
std::string source_vertex;
|
||||||
|
std::string source_fragment;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENGLSHADERPROGRAM_H
|
23
src/render/opengl/OpenGLSharedState.cpp
Normal file
23
src/render/opengl/OpenGLSharedState.cpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#include "OpenGLSharedState.h"
|
||||||
|
|
||||||
|
OpenGLSharedState::OpenGLSharedState()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLSharedState::apply(OpenGLShaderProgram *program, int &texture_unit)
|
||||||
|
{
|
||||||
|
for (const auto &pair : variables)
|
||||||
|
{
|
||||||
|
pair.second->apply(program, texture_unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLVariable *OpenGLSharedState::get(const std::string &name)
|
||||||
|
{
|
||||||
|
OpenGLVariable*& var = variables[name];
|
||||||
|
if (var == 0)
|
||||||
|
{
|
||||||
|
var = new OpenGLVariable(name);
|
||||||
|
}
|
||||||
|
return var;
|
||||||
|
}
|
48
src/render/opengl/OpenGLSharedState.h
Normal file
48
src/render/opengl/OpenGLSharedState.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef OPENGLSHAREDSTATE_H
|
||||||
|
#define OPENGLSHAREDSTATE_H
|
||||||
|
|
||||||
|
#include "opengl_global.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#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, int &texture_unit);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \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 QVector3D &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 QMatrix4x4 &matrix) {get(name)->set(matrix);}
|
||||||
|
inline void set(const std::string &name, const Color &color) {get(name)->set(color);}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, OpenGLVariable*> variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENGLSHAREDSTATE_H
|
104
src/render/opengl/OpenGLSkybox.cpp
Normal file
104
src/render/opengl/OpenGLSkybox.cpp
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
#include "OpenGLSkybox.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include "OpenGLRenderer.h"
|
||||||
|
#include "OpenGLShaderProgram.h"
|
||||||
|
#include "OpenGLSharedState.h"
|
||||||
|
#include "Scenery.h"
|
||||||
|
#include "AtmosphereDefinition.h"
|
||||||
|
#include "AtmosphereRenderer.h"
|
||||||
|
#include "AtmosphereModelBruneton.h"
|
||||||
|
|
||||||
|
OpenGLSkybox::OpenGLSkybox(OpenGLRenderer* renderer):
|
||||||
|
OpenGLPart(renderer)
|
||||||
|
{
|
||||||
|
vertices = new float[14 * 3];
|
||||||
|
daytime = renderer->getScenery()->getAtmosphere()->_daytime;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLSkybox::~OpenGLSkybox()
|
||||||
|
{
|
||||||
|
delete[] vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLSkybox::initialize()
|
||||||
|
{
|
||||||
|
program = createShader("skybox");
|
||||||
|
program->addVertexSource("skybox");
|
||||||
|
program->addFragmentSource("bruneton");
|
||||||
|
program->addFragmentSource("tonemapping");
|
||||||
|
program->addFragmentSource("skybox");
|
||||||
|
|
||||||
|
setVertex(0, 1.0f, 1.0f, 1.0f);
|
||||||
|
setVertex(12, 1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
setVertex(1, 1.0f, -1.0f, 1.0f);
|
||||||
|
setVertex(5, 1.0f, -1.0f, 1.0f);
|
||||||
|
setVertex(13, 1.0f, -1.0f, 1.0f);
|
||||||
|
|
||||||
|
setVertex(2, -1.0f, 1.0f, 1.0f);
|
||||||
|
setVertex(10, -1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
setVertex(3, -1.0f, -1.0f, 1.0f);
|
||||||
|
|
||||||
|
setVertex(4, -1.0f, -1.0f, -1.0f);
|
||||||
|
setVertex(8, -1.0f, -1.0f, -1.0f);
|
||||||
|
|
||||||
|
setVertex(6, 1.0f, -1.0f, -1.0f);
|
||||||
|
|
||||||
|
setVertex(7, 1.0f, 1.0f, -1.0f);
|
||||||
|
setVertex(11, 1.0f, 1.0f, -1.0f);
|
||||||
|
|
||||||
|
setVertex(9, -1.0f, 1.0f, -1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLSkybox::update()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
renderer->getSharedState()->set("transmittanceTexture", bruneton->getModel()->getTextureTransmittance());
|
||||||
|
renderer->getSharedState()->set("inscatterTexture", bruneton->getModel()->getTextureInscatter());
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLSkybox::render()
|
||||||
|
{
|
||||||
|
program->drawTriangleStrip(vertices, 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLSkybox::alterDayTime(double delta)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
Scenery* scenery = renderer->getScenery();
|
||||||
|
AtmosphereDefinition* definition = scenery->getAtmosphere()->definition;
|
||||||
|
daytime = fmod(daytime + delta * 0.001, 1.0);
|
||||||
|
// TEMP
|
||||||
|
if (daytime > 0.8)
|
||||||
|
{
|
||||||
|
daytime -= 0.6;
|
||||||
|
}
|
||||||
|
if (daytime < 0.2)
|
||||||
|
{
|
||||||
|
daytime += 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
definition->hour = (int)(daytime * 24.0);
|
||||||
|
definition->minute = (int)((daytime - (((double)definition->hour) / 24.0)) * 1440.0);
|
||||||
|
|
||||||
|
AtmosphereDefinitionClass.validate(definition);
|
||||||
|
|
||||||
|
// TODO Update only the sun
|
||||||
|
updateScenery(scenery, true);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLSkybox::setVertex(int i, float x, float y, float z)
|
||||||
|
{
|
||||||
|
vertices[i * 3] = x;
|
||||||
|
vertices[i * 3 + 1] = y;
|
||||||
|
vertices[i * 3 + 2] = z;
|
||||||
|
}
|
35
src/render/opengl/OpenGLSkybox.h
Normal file
35
src/render/opengl/OpenGLSkybox.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef OPENGLSKYBOX_H
|
||||||
|
#define OPENGLSKYBOX_H
|
||||||
|
|
||||||
|
#include "opengl_global.h"
|
||||||
|
|
||||||
|
#include "OpenGLPart.h"
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace opengl {
|
||||||
|
|
||||||
|
class OPENGLSHARED_EXPORT OpenGLSkybox: public OpenGLPart
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenGLSkybox(OpenGLRenderer* renderer);
|
||||||
|
virtual ~OpenGLSkybox();
|
||||||
|
|
||||||
|
virtual void initialize() override;
|
||||||
|
virtual void update() override;
|
||||||
|
virtual void render() override;
|
||||||
|
|
||||||
|
void alterDayTime(double delta);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setVertex(int i, float x, float y, float z);
|
||||||
|
|
||||||
|
OpenGLShaderProgram* program;
|
||||||
|
float* vertices;
|
||||||
|
|
||||||
|
double daytime;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENGLSKYBOX_H
|
128
src/render/opengl/OpenGLTerrain.cpp
Normal file
128
src/render/opengl/OpenGLTerrain.cpp
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
#include "OpenGLTerrain.h"
|
||||||
|
|
||||||
|
#include OPENGL_FUNCTIONS_INCLUDE
|
||||||
|
#include "OpenGLRenderer.h"
|
||||||
|
#include "OpenGLShaderProgram.h"
|
||||||
|
#include "ParallelPool.h"
|
||||||
|
#include "Thread.h"
|
||||||
|
#include "ExplorerChunkTerrain.h"
|
||||||
|
#include "WaterRenderer.h"
|
||||||
|
#include "CameraDefinition.h"
|
||||||
|
#include "Scenery.h"
|
||||||
|
|
||||||
|
class ChunkMaintenanceThreads:public ParallelPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ChunkMaintenanceThreads(OpenGLTerrain* terrain):
|
||||||
|
terrain(terrain)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void work() override
|
||||||
|
{
|
||||||
|
while (running)
|
||||||
|
{
|
||||||
|
terrain->performChunksMaintenance();
|
||||||
|
Thread::timeSleepMs(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
OpenGLTerrain* terrain;
|
||||||
|
};
|
||||||
|
|
||||||
|
OpenGLTerrain::OpenGLTerrain(OpenGLRenderer *renderer):
|
||||||
|
OpenGLPart(renderer)
|
||||||
|
{
|
||||||
|
work = new ChunkMaintenanceThreads(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLTerrain::~OpenGLTerrain()
|
||||||
|
{
|
||||||
|
delete work;
|
||||||
|
|
||||||
|
for (int i = 0; i < _chunks.count(); i++)
|
||||||
|
{
|
||||||
|
delete _chunks[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLTerrain::initialize()
|
||||||
|
{
|
||||||
|
// Prepare shader programs
|
||||||
|
program = createShader("terrain");
|
||||||
|
program->addVertexSource("terrain");
|
||||||
|
program->addFragmentSource("bruneton");
|
||||||
|
program->addFragmentSource("tonemapping");
|
||||||
|
program->addFragmentSource("fadeout");
|
||||||
|
program->addFragmentSource("terrain");
|
||||||
|
|
||||||
|
// Add terrain chunks
|
||||||
|
int chunks = 25;
|
||||||
|
double size = 800.0;
|
||||||
|
double chunksize = size / (double) chunks;
|
||||||
|
double start = -size / 2.0;
|
||||||
|
double water_height = renderer->getWaterRenderer()->getHeightInfo().base_height;
|
||||||
|
for (int i = 0; i < chunks; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < chunks; j++)
|
||||||
|
{
|
||||||
|
ExplorerChunkTerrain* chunk = new ExplorerChunkTerrain(renderer, start + chunksize * (double) i, start + chunksize * (double) j, chunksize, chunks, water_height);
|
||||||
|
_chunks.append(chunk);
|
||||||
|
_updateQueue.append(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start chunks maintenance
|
||||||
|
work->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLTerrain::update()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLTerrain::render()
|
||||||
|
{
|
||||||
|
program->bind();
|
||||||
|
|
||||||
|
for (int i = 0; i < _chunks.count(); i++)
|
||||||
|
{
|
||||||
|
_chunks[i]->render(program->getProgram(), renderer->getOpenGlFunctions());
|
||||||
|
}
|
||||||
|
|
||||||
|
program->release();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _cmpChunks(const ExplorerChunkTerrain* c1, const ExplorerChunkTerrain* c2)
|
||||||
|
{
|
||||||
|
return c1->priority > c2->priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLTerrain::performChunksMaintenance()
|
||||||
|
{
|
||||||
|
CameraDefinition* camera = renderer->getScenery()->getCamera();
|
||||||
|
ExplorerChunkTerrain* chunk;
|
||||||
|
|
||||||
|
_lock_chunks.lock();
|
||||||
|
if (_updateQueue.count() > 0)
|
||||||
|
{
|
||||||
|
chunk = _updateQueue.takeFirst();
|
||||||
|
_lock_chunks.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_lock_chunks.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk->maintain();
|
||||||
|
|
||||||
|
_lock_chunks.lock();
|
||||||
|
_updateQueue.append(chunk);
|
||||||
|
for (int i = 0; i < _chunks.count(); i++)
|
||||||
|
{
|
||||||
|
_chunks[i]->updatePriority(camera);
|
||||||
|
}
|
||||||
|
qSort(_updateQueue.begin(), _updateQueue.end(), _cmpChunks);
|
||||||
|
_lock_chunks.unlock();
|
||||||
|
}
|
40
src/render/opengl/OpenGLTerrain.h
Normal file
40
src/render/opengl/OpenGLTerrain.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef OPENGLTERRAIN_H
|
||||||
|
#define OPENGLTERRAIN_H
|
||||||
|
|
||||||
|
#include "opengl_global.h"
|
||||||
|
|
||||||
|
#include "OpenGLPart.h"
|
||||||
|
|
||||||
|
#include <QVector>
|
||||||
|
#include <QList>
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace opengl {
|
||||||
|
|
||||||
|
class OPENGLSHARED_EXPORT OpenGLTerrain:public OpenGLPart
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenGLTerrain(OpenGLRenderer* renderer);
|
||||||
|
virtual ~OpenGLTerrain();
|
||||||
|
|
||||||
|
virtual void initialize() override;
|
||||||
|
virtual void update() override;
|
||||||
|
virtual void render() override;
|
||||||
|
|
||||||
|
void performChunksMaintenance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
OpenGLShaderProgram* program;
|
||||||
|
|
||||||
|
ParallelPool* work;
|
||||||
|
|
||||||
|
QVector<ExplorerChunkTerrain*> _chunks;
|
||||||
|
QList<ExplorerChunkTerrain*> _updateQueue;
|
||||||
|
QMutex _lock_chunks;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENGLTERRAIN_H
|
231
src/render/opengl/OpenGLVariable.cpp
Normal file
231
src/render/opengl/OpenGLVariable.cpp
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
#include "OpenGLVariable.h"
|
||||||
|
|
||||||
|
#include OPENGL_FUNCTIONS_INCLUDE
|
||||||
|
#include <QOpenGLShaderProgram>
|
||||||
|
#include <cassert>
|
||||||
|
#include "OpenGLRenderer.h"
|
||||||
|
#include "OpenGLShaderProgram.h"
|
||||||
|
#include "Vector3.h"
|
||||||
|
#include "Matrix4.h"
|
||||||
|
#include "Color.h"
|
||||||
|
#include "Texture2D.h"
|
||||||
|
#include "Texture3D.h"
|
||||||
|
#include "Texture4D.h"
|
||||||
|
|
||||||
|
OpenGLVariable::OpenGLVariable(const std::string &name):
|
||||||
|
name(name)
|
||||||
|
{
|
||||||
|
type = TYPE_NONE;
|
||||||
|
texture_toupload = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLVariable::apply(OpenGLShaderProgram *program, int &texture_unit)
|
||||||
|
{
|
||||||
|
QOpenGLShaderProgram* pr = program->getProgram();
|
||||||
|
OpenGLFunctions* functions = program->getRenderer()->getOpenGlFunctions();
|
||||||
|
|
||||||
|
if (texture_toupload)
|
||||||
|
{
|
||||||
|
uploadTexture(program->getRenderer());
|
||||||
|
texture_toupload = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_MATRIX4:
|
||||||
|
pr->setUniformValue(name.c_str(), value_matrix4);
|
||||||
|
break;
|
||||||
|
case TYPE_TEXTURE_2D:
|
||||||
|
functions->glActiveTexture(GL_TEXTURE0 + texture_unit);
|
||||||
|
functions->glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||||
|
pr->setUniformValue(name.c_str(), texture_unit);
|
||||||
|
texture_unit++;
|
||||||
|
break;
|
||||||
|
case TYPE_TEXTURE_3D:
|
||||||
|
case TYPE_TEXTURE_4D:
|
||||||
|
functions->glActiveTexture(GL_TEXTURE0 + texture_unit);
|
||||||
|
functions->glBindTexture(GL_TEXTURE_3D, texture_id);
|
||||||
|
pr->setUniformValue(name.c_str(), texture_unit);
|
||||||
|
texture_unit++;
|
||||||
|
break;
|
||||||
|
case TYPE_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLVariable::set(const Texture2D *texture)
|
||||||
|
{
|
||||||
|
assert(type == TYPE_NONE or type == TYPE_TEXTURE_2D);
|
||||||
|
|
||||||
|
type = TYPE_TEXTURE_2D;
|
||||||
|
value_tex2d = texture;
|
||||||
|
texture_toupload = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLVariable::set(const Texture3D *texture)
|
||||||
|
{
|
||||||
|
assert(type == TYPE_NONE or type == TYPE_TEXTURE_3D);
|
||||||
|
|
||||||
|
type = TYPE_TEXTURE_3D;
|
||||||
|
value_tex3d = texture;
|
||||||
|
texture_toupload = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLVariable::set(const Texture4D *texture)
|
||||||
|
{
|
||||||
|
assert(type == TYPE_NONE or type == TYPE_TEXTURE_4D);
|
||||||
|
|
||||||
|
type = TYPE_TEXTURE_4D;
|
||||||
|
value_tex4d = texture;
|
||||||
|
texture_toupload = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
set(QVector3D(vector.x, vector.y, vector.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLVariable::set(const QVector3D &vector)
|
||||||
|
{
|
||||||
|
assert(type == TYPE_NONE or type == TYPE_VECTOR3);
|
||||||
|
|
||||||
|
type = TYPE_VECTOR3;
|
||||||
|
value_vector3 = vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLVariable::set(const Matrix4 &matrix)
|
||||||
|
{
|
||||||
|
set(matrix.toQMatrix());
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLVariable::set(const QMatrix4x4 &matrix)
|
||||||
|
{
|
||||||
|
assert(type == TYPE_NONE or type == TYPE_MATRIX4);
|
||||||
|
|
||||||
|
type = TYPE_MATRIX4;
|
||||||
|
value_matrix4 = matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLVariable::uploadTexture(OpenGLRenderer* renderer)
|
||||||
|
{
|
||||||
|
OpenGLFunctions* functions = renderer->getOpenGlFunctions();
|
||||||
|
|
||||||
|
assert(type == TYPE_TEXTURE_2D or type == TYPE_TEXTURE_3D or type == TYPE_TEXTURE_4D);
|
||||||
|
|
||||||
|
if (texture_id == 0)
|
||||||
|
{
|
||||||
|
GLuint texid;
|
||||||
|
functions->glGenTextures(1, &texid);
|
||||||
|
texture_id = texid;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum textype = (type == TYPE_TEXTURE_2D) ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
||||||
|
|
||||||
|
functions->glBindTexture(textype, texture_id);
|
||||||
|
functions->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
functions->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
functions->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
functions->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
if (textype == GL_TEXTURE_3D)
|
||||||
|
{
|
||||||
|
functions->glTexParameteri(textype, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == TYPE_TEXTURE_2D)
|
||||||
|
{
|
||||||
|
int sx, sy;
|
||||||
|
value_tex2d->getSize(&sx, &sy);
|
||||||
|
float* pixels = new float[sx * sy * 4];
|
||||||
|
for (int x = 0; x < sx; x++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < sy; y++)
|
||||||
|
{
|
||||||
|
float* pixel = pixels + (y * sx + x) * 4;
|
||||||
|
Color col = value_tex2d->getPixel(x, y);
|
||||||
|
pixel[0] = (float)col.r;
|
||||||
|
pixel[1] = (float)col.g;
|
||||||
|
pixel[2] = (float)col.b;
|
||||||
|
pixel[3] = (float)col.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sx, sy, 0, GL_RGBA, GL_FLOAT, pixels);
|
||||||
|
delete[] pixels;
|
||||||
|
}
|
||||||
|
else if (type == TYPE_TEXTURE_3D)
|
||||||
|
{
|
||||||
|
int sx, sy, sz;
|
||||||
|
value_tex3d->getSize(&sx, &sy, &sz);
|
||||||
|
float* pixels = new float[sx * sy * sz * 4];
|
||||||
|
for (int x = 0; x < sx; x++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < sy; y++)
|
||||||
|
{
|
||||||
|
for (int z = 0; z < sz; z++)
|
||||||
|
{
|
||||||
|
float* pixel = pixels + (z * (sx * sy) + y * sx + x) * 4;
|
||||||
|
Color col = value_tex3d->getPixel(x, y, z);
|
||||||
|
pixel[0] = (float)col.r;
|
||||||
|
pixel[1] = (float)col.g;
|
||||||
|
pixel[2] = (float)col.b;
|
||||||
|
pixel[3] = (float)col.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
functions->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, sx, sy, sz, 0, GL_RGBA, GL_FLOAT, pixels);
|
||||||
|
delete[] pixels;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int sx, sy, sz, sw;
|
||||||
|
value_tex4d->getSize(&sx, &sy, &sz, &sw);
|
||||||
|
float* pixels = new float[sx * sy * sz * sw * 4];
|
||||||
|
for (int x = 0; x < sx; x++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < sy; y++)
|
||||||
|
{
|
||||||
|
for (int z = 0; z < sz; z++)
|
||||||
|
{
|
||||||
|
for (int w = 0; w < sw; w++)
|
||||||
|
{
|
||||||
|
float* pixel = pixels + (w * (sx * sy * sz) + z * (sx * sy) + y * sx + x) * 4;
|
||||||
|
Color col = value_tex4d->getPixel(x, y, z, w);
|
||||||
|
pixel[0] = (float)col.r;
|
||||||
|
pixel[1] = (float)col.g;
|
||||||
|
pixel[2] = (float)col.b;
|
||||||
|
pixel[3] = (float)col.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
functions->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, sx, sy, sz * sw, 0, GL_RGBA, GL_FLOAT, pixels);
|
||||||
|
delete[] pixels;
|
||||||
|
}
|
||||||
|
}
|
67
src/render/opengl/OpenGLVariable.h
Normal file
67
src/render/opengl/OpenGLVariable.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef OPENGLVARIABLE_H
|
||||||
|
#define OPENGLVARIABLE_H
|
||||||
|
|
||||||
|
#include "opengl_global.h"
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
#include <QVector3D>
|
||||||
|
#include <QMatrix4x4>
|
||||||
|
|
||||||
|
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, int &texture_unit);
|
||||||
|
|
||||||
|
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 QVector3D &vector);
|
||||||
|
void set(const Matrix4 &matrix);
|
||||||
|
void set(const QMatrix4x4 &matrix);
|
||||||
|
void set(const Color &color);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void uploadTexture(OpenGLRenderer* renderer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
OpenGLVariableType type;
|
||||||
|
|
||||||
|
float value_float;
|
||||||
|
QColor value_color;
|
||||||
|
QVector3D value_vector3;
|
||||||
|
QMatrix4x4 value_matrix4;
|
||||||
|
const Texture2D* value_tex2d;
|
||||||
|
const Texture3D* value_tex3d;
|
||||||
|
const Texture4D* value_tex4d;
|
||||||
|
|
||||||
|
bool texture_toupload;
|
||||||
|
unsigned int texture_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENGLVARIABLE_H
|
56
src/render/opengl/OpenGLWater.cpp
Normal file
56
src/render/opengl/OpenGLWater.cpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#include "OpenGLWater.h"
|
||||||
|
|
||||||
|
#include "OpenGLRenderer.h"
|
||||||
|
#include "OpenGLShaderProgram.h"
|
||||||
|
#include "OpenGLSharedState.h"
|
||||||
|
#include "WaterRenderer.h"
|
||||||
|
#include "Scenery.h"
|
||||||
|
#include "WaterDefinition.h"
|
||||||
|
#include "SurfaceMaterial.h"
|
||||||
|
|
||||||
|
OpenGLWater::OpenGLWater(OpenGLRenderer *renderer):
|
||||||
|
OpenGLPart(renderer)
|
||||||
|
{
|
||||||
|
vertices = new float[4 * 3];
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLWater::~OpenGLWater()
|
||||||
|
{
|
||||||
|
delete[] vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLWater::initialize()
|
||||||
|
{
|
||||||
|
program = createShader("water");
|
||||||
|
program->addVertexSource("water");
|
||||||
|
program->addFragmentSource("bruneton");
|
||||||
|
program->addFragmentSource("tonemapping");
|
||||||
|
program->addFragmentSource("fadeout");
|
||||||
|
program->addFragmentSource("water");
|
||||||
|
|
||||||
|
setVertex(0, -1.0f, 0.0f, -1.0f);
|
||||||
|
setVertex(1, -1.0f, 0.0f, 1.0f);
|
||||||
|
setVertex(2, 1.0f, 0.0f, -1.0f);
|
||||||
|
setVertex(3, 1.0f, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLWater::update()
|
||||||
|
{
|
||||||
|
double water_height = renderer->getWaterRenderer()->getHeightInfo().max_height;
|
||||||
|
renderer->getSharedState()->set("waterHeight", water_height);
|
||||||
|
|
||||||
|
Color water_color = renderer->getScenery()->getWater()->material->_rgb;
|
||||||
|
renderer->getSharedState()->set("waterColor", water_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLWater::render()
|
||||||
|
{
|
||||||
|
program->drawTriangleStrip(vertices, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLWater::setVertex(int i, float x, float y, float z)
|
||||||
|
{
|
||||||
|
vertices[i * 3] = x;
|
||||||
|
vertices[i * 3 + 1] = y;
|
||||||
|
vertices[i * 3 + 2] = z;
|
||||||
|
}
|
31
src/render/opengl/OpenGLWater.h
Normal file
31
src/render/opengl/OpenGLWater.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef OPENGLWATER_H
|
||||||
|
#define OPENGLWATER_H
|
||||||
|
|
||||||
|
#include "opengl_global.h"
|
||||||
|
|
||||||
|
#include "OpenGLPart.h"
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace opengl {
|
||||||
|
|
||||||
|
class OPENGLSHARED_EXPORT OpenGLWater: public OpenGLPart
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenGLWater(OpenGLRenderer* renderer);
|
||||||
|
virtual ~OpenGLWater();
|
||||||
|
|
||||||
|
virtual void initialize() override;
|
||||||
|
virtual void update() override;
|
||||||
|
virtual void render() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setVertex(int i, float x, float y, float z);
|
||||||
|
|
||||||
|
OpenGLShaderProgram* program;
|
||||||
|
float* vertices;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENGLWATER_H
|
155
src/render/opengl/VertexArray.h
Normal file
155
src/render/opengl/VertexArray.h
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
#ifndef VERTEXARRAY_H
|
||||||
|
#define VERTEXARRAY_H
|
||||||
|
|
||||||
|
#include "opengl_global.h"
|
||||||
|
|
||||||
|
#include OPENGL_FUNCTIONS_INCLUDE
|
||||||
|
#include <cassert>
|
||||||
|
#include <QOpenGLShaderProgram>
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace opengl {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Wrapper for OpenGL vertex arrays.
|
||||||
|
*/
|
||||||
|
template <typename Vertex> class VertexArray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VertexArray()
|
||||||
|
{
|
||||||
|
ready = false;
|
||||||
|
changed = false;
|
||||||
|
vertex_count = 1;
|
||||||
|
vertices = new Vertex[1];
|
||||||
|
index_count = 1;
|
||||||
|
indices = new unsigned short[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
~VertexArray()
|
||||||
|
{
|
||||||
|
delete[] vertices;
|
||||||
|
delete[] indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int getVertexCount() {return vertex_count;}
|
||||||
|
inline int getIndexCount() {return index_count;}
|
||||||
|
inline bool isReady() {return ready;}
|
||||||
|
inline bool isChanged() {return changed;}
|
||||||
|
|
||||||
|
void setVertexCount(int count)
|
||||||
|
{
|
||||||
|
assert(count > 0 and count <= 16384);
|
||||||
|
|
||||||
|
delete[] vertices;
|
||||||
|
vertices = new Vertex[count];
|
||||||
|
|
||||||
|
vertex_count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGridSize(int edge_vertex_count)
|
||||||
|
{
|
||||||
|
assert(edge_vertex_count >= 2);
|
||||||
|
|
||||||
|
setVertexCount(edge_vertex_count * edge_vertex_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setVertex(int position, const Vertex &vertex)
|
||||||
|
{
|
||||||
|
assert(position >= 0 and position < vertex_count);
|
||||||
|
|
||||||
|
vertices[position] = vertex;
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGridVertex(int edge_vertex_count, int x, int y, const Vertex &vertex)
|
||||||
|
{
|
||||||
|
setVertex(y * edge_vertex_count + x, vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAutoGridIndices(int edge_vertex_count, int stride=1)
|
||||||
|
{
|
||||||
|
assert(stride >= 1);
|
||||||
|
|
||||||
|
delete[] indices;
|
||||||
|
int cell_count = edge_vertex_count - 1;
|
||||||
|
|
||||||
|
index_count = (cell_count / stride) * (cell_count / stride) * 6;
|
||||||
|
indices = new unsigned short[index_count];
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
for (int y = 0; y < cell_count; y += stride)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < cell_count; x += stride)
|
||||||
|
{
|
||||||
|
int base = y * edge_vertex_count + x;
|
||||||
|
indices[idx++] = base;
|
||||||
|
indices[idx++] = base + edge_vertex_count * stride;
|
||||||
|
indices[idx++] = base + stride;
|
||||||
|
indices[idx++] = base + stride;
|
||||||
|
indices[idx++] = base + edge_vertex_count * stride;
|
||||||
|
indices[idx++] = base + edge_vertex_count * stride + stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vertex getVertex(int position)
|
||||||
|
{
|
||||||
|
assert(position >= 0 and position < vertex_count);
|
||||||
|
|
||||||
|
return vertices[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
Vertex getVertexByIndex(unsigned short index)
|
||||||
|
{
|
||||||
|
assert(index >= 0 and index < index_count);
|
||||||
|
|
||||||
|
return getVertex(indices[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vertex getGridVertex(int edge_vertex_count, int x, int y)
|
||||||
|
{
|
||||||
|
return getVertex(y * edge_vertex_count + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
int vertex_count;
|
||||||
|
Vertex* vertices;
|
||||||
|
|
||||||
|
int index_count;
|
||||||
|
unsigned short* indices;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // VERTEXARRAY_H
|
|
@ -11,51 +11,12 @@
|
||||||
#include "WaterDefinition.h"
|
#include "WaterDefinition.h"
|
||||||
#include "SurfaceMaterial.h"
|
#include "SurfaceMaterial.h"
|
||||||
#include "CameraDefinition.h"
|
#include "CameraDefinition.h"
|
||||||
#include "ExplorerChunkSky.h"
|
|
||||||
#include "ExplorerChunkTerrain.h"
|
#include "ExplorerChunkTerrain.h"
|
||||||
#include "TerrainRenderer.h"
|
#include "TerrainRenderer.h"
|
||||||
#include "WaterRenderer.h"
|
#include "WaterRenderer.h"
|
||||||
#include "Scenery.h"
|
#include "Scenery.h"
|
||||||
#include "LightingManager.h"
|
#include "LightingManager.h"
|
||||||
|
|
||||||
class ChunkMaintenanceThread : public QThread
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
ChunkMaintenanceThread(WidgetExplorer* wanderer)
|
|
||||||
{
|
|
||||||
_wanderer = wanderer;
|
|
||||||
_running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void askStop()
|
|
||||||
{
|
|
||||||
_running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void usleep(unsigned long us)
|
|
||||||
{
|
|
||||||
QThread::usleep(us);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
while (_running)
|
|
||||||
{
|
|
||||||
_wanderer->performChunksMaintenance();
|
|
||||||
QThread::usleep(10000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool _running;
|
|
||||||
WidgetExplorer* _wanderer;
|
|
||||||
};
|
|
||||||
|
|
||||||
static QVector<ChunkMaintenanceThread*> _threads;
|
|
||||||
|
|
||||||
WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera, Scenery* scenery) :
|
WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera, Scenery* scenery) :
|
||||||
QGLWidget(parent)
|
QGLWidget(parent)
|
||||||
{
|
{
|
||||||
|
@ -67,13 +28,6 @@ QGLWidget(parent)
|
||||||
camera->copy(_current_camera);
|
camera->copy(_current_camera);
|
||||||
|
|
||||||
_renderer = new OpenGLRenderer(scenery);
|
_renderer = new OpenGLRenderer(scenery);
|
||||||
_renderer->prepare();
|
|
||||||
_renderer->render_quality = 3;
|
|
||||||
_renderer->getLightingManager()->setSpecularity(false);
|
|
||||||
_renderer->disableClouds();
|
|
||||||
|
|
||||||
_inited = false;
|
|
||||||
_updated = false;
|
|
||||||
|
|
||||||
_average_frame_time = 0.05;
|
_average_frame_time = 0.05;
|
||||||
_quality = 3;
|
_quality = 3;
|
||||||
|
@ -85,111 +39,10 @@ QGLWidget(parent)
|
||||||
|
|
||||||
WidgetExplorer::~WidgetExplorer()
|
WidgetExplorer::~WidgetExplorer()
|
||||||
{
|
{
|
||||||
stopRendering();
|
|
||||||
|
|
||||||
for (int i = 0; i < _chunks.count(); i++)
|
|
||||||
{
|
|
||||||
delete _chunks[i];
|
|
||||||
}
|
|
||||||
delete _current_camera;
|
delete _current_camera;
|
||||||
delete _renderer;
|
delete _renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetExplorer::startRendering()
|
|
||||||
{
|
|
||||||
// Add terrain
|
|
||||||
int chunks = 20;
|
|
||||||
double size = 400.0;
|
|
||||||
double chunksize = size / (double) chunks;
|
|
||||||
double start = -size / 2.0;
|
|
||||||
double water_height = _renderer->getWaterRenderer()->getHeightInfo().base_height;
|
|
||||||
for (int i = 0; i < chunks; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < chunks; j++)
|
|
||||||
{
|
|
||||||
ExplorerChunkTerrain* chunk = new ExplorerChunkTerrain(_renderer, start + chunksize * (double) i, start + chunksize * (double) j, chunksize, chunks, water_height);
|
|
||||||
_chunks.append(chunk);
|
|
||||||
_updateQueue.append(chunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add skybox
|
|
||||||
for (int orientation = 0; orientation < 5; orientation++)
|
|
||||||
{
|
|
||||||
ExplorerChunkSky* chunk = new ExplorerChunkSky(_renderer, 500.0, (SkyboxOrientation) orientation);
|
|
||||||
_chunks.append(chunk);
|
|
||||||
_updateQueue.append(chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start rendering workers
|
|
||||||
int nbcore;
|
|
||||||
_alive = true;
|
|
||||||
|
|
||||||
nbcore = QThread::idealThreadCount();
|
|
||||||
if (nbcore < 1)
|
|
||||||
{
|
|
||||||
nbcore = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < nbcore; i++)
|
|
||||||
{
|
|
||||||
_threads.append(new ChunkMaintenanceThread(this));
|
|
||||||
}
|
|
||||||
for (int i = 0; i < _threads.count(); i++)
|
|
||||||
{
|
|
||||||
_threads[i]->start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WidgetExplorer::stopRendering()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < _threads.count(); i++)
|
|
||||||
{
|
|
||||||
_threads[i]->askStop();
|
|
||||||
}
|
|
||||||
_alive = false;
|
|
||||||
for (int i = 0; i < _threads.count(); i++)
|
|
||||||
{
|
|
||||||
_threads[i]->wait();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _cmpChunks(const BaseExplorerChunk* c1, const BaseExplorerChunk* c2)
|
|
||||||
{
|
|
||||||
return c1->priority > c2->priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WidgetExplorer::performChunksMaintenance()
|
|
||||||
{
|
|
||||||
BaseExplorerChunk* chunk;
|
|
||||||
|
|
||||||
_lock_chunks.lock();
|
|
||||||
if (_updateQueue.count() > 0)
|
|
||||||
{
|
|
||||||
chunk = _updateQueue.takeFirst();
|
|
||||||
_lock_chunks.unlock();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_lock_chunks.unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chunk->maintain())
|
|
||||||
{
|
|
||||||
if (!_alive)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_updated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lock_chunks.lock();
|
|
||||||
_updateQueue.append(chunk);
|
|
||||||
_lock_chunks.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WidgetExplorer::resetCamera()
|
void WidgetExplorer::resetCamera()
|
||||||
{
|
{
|
||||||
_base_camera->copy(_current_camera);
|
_base_camera->copy(_current_camera);
|
||||||
|
@ -332,27 +185,9 @@ void WidgetExplorer::wheelEvent(QWheelEvent* event)
|
||||||
|
|
||||||
void WidgetExplorer::timerEvent(QTimerEvent*)
|
void WidgetExplorer::timerEvent(QTimerEvent*)
|
||||||
{
|
{
|
||||||
if (!_inited)
|
|
||||||
{
|
|
||||||
_inited = true;
|
|
||||||
startRendering();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_updated)
|
|
||||||
{
|
|
||||||
_updated = false;
|
|
||||||
updateGL();
|
updateGL();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _chunks.count(); i++)
|
|
||||||
{
|
|
||||||
_chunks[i]->updatePriority(_current_camera);
|
|
||||||
}
|
|
||||||
_lock_chunks.lock();
|
|
||||||
qSort(_updateQueue.begin(), _updateQueue.end(), _cmpChunks);
|
|
||||||
_lock_chunks.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WidgetExplorer::initializeGL()
|
void WidgetExplorer::initializeGL()
|
||||||
{
|
{
|
||||||
_renderer->initialize();
|
_renderer->initialize();
|
||||||
|
@ -366,46 +201,18 @@ void WidgetExplorer::resizeGL(int w, int h)
|
||||||
|
|
||||||
void WidgetExplorer::paintGL()
|
void WidgetExplorer::paintGL()
|
||||||
{
|
{
|
||||||
GLenum error_code;
|
|
||||||
QTime start_time;
|
QTime start_time;
|
||||||
double frame_time;
|
double frame_time;
|
||||||
WaterDefinition* water = _renderer->getScenery()->getWater();
|
|
||||||
|
|
||||||
// Don't do this at each frame, only on camera change
|
// Don't do this at each frame, only on camera change
|
||||||
_renderer->getScenery()->setCamera(_current_camera);
|
_renderer->getScenery()->setCamera(_current_camera);
|
||||||
_renderer->getScenery()->getCamera(_current_camera);
|
_renderer->getScenery()->getCamera(_current_camera);
|
||||||
|
_renderer->cameraChangeEvent(_current_camera);
|
||||||
|
|
||||||
start_time = QTime::currentTime();
|
start_time = QTime::currentTime();
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadIdentity();
|
|
||||||
Vector3 camera_location = _current_camera->getLocation();
|
|
||||||
Vector3 camera_target = _current_camera->getTarget();
|
|
||||||
Vector3 camera_up = _current_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);
|
|
||||||
|
|
||||||
// Background
|
// Background
|
||||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
_renderer->paint();
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
// Render water
|
|
||||||
double water_height = _renderer->getTerrainRenderer()->getWaterHeight();
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
glColor3f(water->material->_rgb.r, water->material->_rgb.g, water->material->_rgb.b);
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
glVertex3f(camera_location.x - 500.0, water_height, camera_location.z - 500.0);
|
|
||||||
glVertex3f(camera_location.x - 500.0, water_height, camera_location.z + 500.0);
|
|
||||||
glVertex3f(camera_location.x + 500.0, water_height, camera_location.z + 500.0);
|
|
||||||
glVertex3f(camera_location.x + 500.0, water_height, camera_location.z - 500.0);
|
|
||||||
glEnd();
|
|
||||||
|
|
||||||
// Render chunks
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
for (int i = 0; i < _chunks.count(); i++)
|
|
||||||
{
|
|
||||||
glColor3f(1.0, 1.0, 1.0);
|
|
||||||
_chunks[i]->render(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
frame_time = 0.001 * (double) start_time.msecsTo(QTime::currentTime());
|
frame_time = 0.001 * (double) start_time.msecsTo(QTime::currentTime());
|
||||||
|
|
||||||
|
@ -422,16 +229,11 @@ void WidgetExplorer::paintGL()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Messages
|
// Messages
|
||||||
if (!_inited)
|
/*if (!_inited)
|
||||||
{
|
{
|
||||||
glColor3f(0.0, 0.0, 0.0);
|
glColor3f(0.0, 0.0, 0.0);
|
||||||
renderText(6, height() - 10, tr("Please wait while loading scene..."));
|
renderText(6, height() - 10, tr("Please wait while loading scene..."));
|
||||||
glColor3f(1.0, 1.0, 1.0);
|
glColor3f(1.0, 1.0, 1.0);
|
||||||
renderText(5, height() - 9, tr("Please wait while loading scene..."));
|
renderText(5, height() - 9, tr("Please wait while loading scene..."));
|
||||||
}
|
}*/
|
||||||
|
|
||||||
while ((error_code = glGetError()) != GL_NO_ERROR)
|
|
||||||
{
|
|
||||||
qDebug("[OpenGL] ERROR : %s", (const char*)gluErrorString(error_code));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
|
|
||||||
#include <QGLWidget>
|
#include <QGLWidget>
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
|
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace opengl {
|
namespace opengl {
|
||||||
|
|
||||||
|
@ -17,8 +15,6 @@ public:
|
||||||
WidgetExplorer(QWidget* parent, CameraDefinition* camera, Scenery* scenery);
|
WidgetExplorer(QWidget* parent, CameraDefinition* camera, Scenery* scenery);
|
||||||
~WidgetExplorer();
|
~WidgetExplorer();
|
||||||
|
|
||||||
void performChunksMaintenance();
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void resetCamera();
|
void resetCamera();
|
||||||
void validateCamera();
|
void validateCamera();
|
||||||
|
@ -35,20 +31,10 @@ protected:
|
||||||
void paintGL();
|
void paintGL();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startRendering();
|
|
||||||
void stopRendering();
|
|
||||||
|
|
||||||
CameraDefinition* _current_camera;
|
CameraDefinition* _current_camera;
|
||||||
CameraDefinition* _base_camera;
|
CameraDefinition* _base_camera;
|
||||||
|
|
||||||
OpenGLRenderer* _renderer;
|
OpenGLRenderer* _renderer;
|
||||||
bool _inited;
|
|
||||||
bool _updated;
|
|
||||||
|
|
||||||
QVector<BaseExplorerChunk*> _chunks;
|
|
||||||
QList<BaseExplorerChunk*> _updateQueue;
|
|
||||||
bool _alive;
|
|
||||||
QMutex _lock_chunks;
|
|
||||||
|
|
||||||
double _average_frame_time;
|
double _average_frame_time;
|
||||||
int _quality;
|
int _quality;
|
||||||
|
|
|
@ -13,20 +13,33 @@ DEFINES += OPENGL_LIBRARY
|
||||||
|
|
||||||
include(../../common.pri)
|
include(../../common.pri)
|
||||||
|
|
||||||
|
unix:LIBS += -lGLU
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
OpenGLRenderer.cpp \
|
OpenGLRenderer.cpp \
|
||||||
BaseExplorerChunk.cpp \
|
|
||||||
ExplorerChunkSky.cpp \
|
|
||||||
ExplorerChunkTerrain.cpp \
|
ExplorerChunkTerrain.cpp \
|
||||||
WidgetExplorer.cpp
|
WidgetExplorer.cpp \
|
||||||
|
OpenGLShaderProgram.cpp \
|
||||||
|
OpenGLPart.cpp \
|
||||||
|
OpenGLSkybox.cpp \
|
||||||
|
OpenGLWater.cpp \
|
||||||
|
OpenGLSharedState.cpp \
|
||||||
|
OpenGLVariable.cpp \
|
||||||
|
OpenGLTerrain.cpp
|
||||||
|
|
||||||
HEADERS +=\
|
HEADERS +=\
|
||||||
opengl_global.h \
|
opengl_global.h \
|
||||||
OpenGLRenderer.h \
|
OpenGLRenderer.h \
|
||||||
BaseExplorerChunk.h \
|
|
||||||
ExplorerChunkSky.h \
|
|
||||||
ExplorerChunkTerrain.h \
|
ExplorerChunkTerrain.h \
|
||||||
WidgetExplorer.h
|
WidgetExplorer.h \
|
||||||
|
OpenGLShaderProgram.h \
|
||||||
|
OpenGLPart.h \
|
||||||
|
OpenGLSkybox.h \
|
||||||
|
OpenGLWater.h \
|
||||||
|
OpenGLSharedState.h \
|
||||||
|
OpenGLVariable.h \
|
||||||
|
OpenGLTerrain.h \
|
||||||
|
VertexArray.h
|
||||||
|
|
||||||
unix:!symbian {
|
unix:!symbian {
|
||||||
maemo5 {
|
maemo5 {
|
||||||
|
@ -60,3 +73,18 @@ else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../software/debug/
|
||||||
else:unix: LIBS += -L$$OUT_PWD/../software/ -lpaysages_render_software
|
else:unix: LIBS += -L$$OUT_PWD/../software/ -lpaysages_render_software
|
||||||
INCLUDEPATH += $$PWD/../software
|
INCLUDEPATH += $$PWD/../software
|
||||||
DEPENDPATH += $$PWD/../software
|
DEPENDPATH += $$PWD/../software
|
||||||
|
|
||||||
|
RESOURCES += \
|
||||||
|
shaders/resources.qrc
|
||||||
|
|
||||||
|
OTHER_FILES += \
|
||||||
|
shaders/skybox.frag \
|
||||||
|
shaders/skybox.vert \
|
||||||
|
shaders/water.vert \
|
||||||
|
shaders/water.frag \
|
||||||
|
shaders/bruneton.frag \
|
||||||
|
shaders/bruneton.frag \
|
||||||
|
shaders/tonemapping.frag \
|
||||||
|
shaders/terrain.frag \
|
||||||
|
shaders/terrain.vert \
|
||||||
|
shaders/fadeout.frag
|
||||||
|
|
|
@ -15,9 +15,21 @@ namespace paysages {
|
||||||
namespace opengl {
|
namespace opengl {
|
||||||
class WidgetExplorer;
|
class WidgetExplorer;
|
||||||
class OpenGLRenderer;
|
class OpenGLRenderer;
|
||||||
class BaseExplorerChunk;
|
class OpenGLShaderProgram;
|
||||||
|
class OpenGLSharedState;
|
||||||
|
class OpenGLVariable;
|
||||||
|
class OpenGLSkybox;
|
||||||
|
class OpenGLWater;
|
||||||
|
class OpenGLTerrain;
|
||||||
|
class ExplorerChunkTerrain;
|
||||||
|
template <typename Vertex> class VertexArray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
using namespace paysages::opengl;
|
using namespace paysages::opengl;
|
||||||
|
|
||||||
|
//#define OpenGLFunctions QOpenGLFunctions_3_2_Core
|
||||||
|
#define OpenGLFunctions QOpenGLFunctions_3_0
|
||||||
|
#define OPENGL_FUNCTIONS_INCLUDE <OpenGLFunctions>
|
||||||
|
class OpenGLFunctions;
|
||||||
|
|
||||||
#endif // OPENGL_GLOBAL_H
|
#endif // OPENGL_GLOBAL_H
|
||||||
|
|
211
src/render/opengl/shaders/bruneton.frag
Normal file
211
src/render/opengl/shaders/bruneton.frag
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
const float GROUND_OFFSET = 0.5;
|
||||||
|
const float Rg = 6360.0;
|
||||||
|
const float Rt = 6420.0;
|
||||||
|
const float RL = 6421.0;
|
||||||
|
const float ISun = 100.0;
|
||||||
|
const float AVERAGE_GROUND_REFLECTANCE = 0.1;
|
||||||
|
const float HR = 8.0;
|
||||||
|
const vec3 betaR = vec3(5.8e-3, 1.35e-2, 3.31e-2);
|
||||||
|
const float HM = 1.2;
|
||||||
|
const vec3 betaMSca = vec3(4e-3);
|
||||||
|
const vec3 betaMEx = vec3(4e-3 / 0.9);
|
||||||
|
const float mieG = 0.8;
|
||||||
|
const float SPHERE_SIZE = 20000.0;
|
||||||
|
const float WORLD_SCALING = 0.05;
|
||||||
|
const float SUN_DISTANCE = 149597870.0;
|
||||||
|
const float SUN_DISTANCE_SCALED = (SUN_DISTANCE / WORLD_SCALING);
|
||||||
|
const float SUN_RADIUS = 6.955e5;
|
||||||
|
const float SUN_RADIUS_SCALED = (SUN_RADIUS / WORLD_SCALING);
|
||||||
|
const float M_PI = 3.141592657;
|
||||||
|
|
||||||
|
const int RES_MU = 128;
|
||||||
|
const int RES_MU_S = 32;
|
||||||
|
const int RES_R = 32;
|
||||||
|
const int RES_NU = 8;
|
||||||
|
|
||||||
|
uniform float waterHeight;
|
||||||
|
uniform vec3 cameraLocation;
|
||||||
|
uniform vec3 sunDirection;
|
||||||
|
uniform vec4 sunColor;
|
||||||
|
const float sunRadius = 1.0; // TODO -> uniform
|
||||||
|
|
||||||
|
varying vec3 unprojected;
|
||||||
|
|
||||||
|
uniform sampler2D transmittanceTexture;
|
||||||
|
uniform sampler3D inscatterTexture;
|
||||||
|
|
||||||
|
vec4 texture4D(sampler3D tex, float r, float mu, float muS, float nu)
|
||||||
|
{
|
||||||
|
if (r < Rg + 0.00000001) r = Rg + 0.00000001;
|
||||||
|
float H = sqrt(Rt * Rt - Rg * Rg);
|
||||||
|
float rho = sqrt(r * r - Rg * Rg);
|
||||||
|
float rmu = r * mu;
|
||||||
|
float delta = rmu * rmu - r * r + Rg * Rg;
|
||||||
|
vec4 cst = (rmu < 0.0 && delta > 0.0) ? vec4(1.0, 0.0, 0.0, 0.5 - 0.5 / float(RES_MU)) : vec4(-1.0, H * H, H, 0.5 + 0.5 / float(RES_MU));
|
||||||
|
float uR = 0.5 / float(RES_R) + rho / H * (1.0 - 1.0 / float(RES_R));
|
||||||
|
float uMu = cst.a + (rmu * cst.r + sqrt(delta + cst.g)) / (rho + cst.b) * (0.5 - 1.0 / float(RES_MU));
|
||||||
|
float uMuS = 0.5 / float(RES_MU_S) + (atan(max(muS, -0.1975) * tan(1.26 * 1.1)) / 1.1 + (1.0 - 0.26)) * 0.5 * (1.0 - 1.0 / float(RES_MU_S));
|
||||||
|
|
||||||
|
float sr = 1.0 / float(RES_R);
|
||||||
|
int br = int(floor(uR / sr));
|
||||||
|
vec4 r1 = texture3D(tex, vec3(uMu, uMuS, float(br) * sr + nu * sr));
|
||||||
|
vec4 r2 = texture3D(tex, vec3(uMu, uMuS, float(br + 1) * sr + nu * sr));
|
||||||
|
return mix(r1, r2, (uR - float(br) * sr) / sr);
|
||||||
|
}
|
||||||
|
|
||||||
|
float _limit(float r, float mu)
|
||||||
|
{
|
||||||
|
float dout = -r * mu + sqrt(r * r * (mu * mu - 1.0) + RL * RL);
|
||||||
|
float delta2 = r * r * (mu * mu - 1.0) + Rg * Rg;
|
||||||
|
if (delta2 >= 0.0)
|
||||||
|
{
|
||||||
|
float din = -r * mu - sqrt(delta2);
|
||||||
|
if (din >= 0.0) {
|
||||||
|
dout = min(dout, din);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dout;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 _getTransmittanceUV(float r, float mu)
|
||||||
|
{
|
||||||
|
if (r < Rg + 0.00000001) r = Rg + 0.00000001;
|
||||||
|
float dr = (r - Rg) / (Rt - Rg);
|
||||||
|
return vec2(atan((mu + 0.15) / (1.0 + 0.15) * tan(1.5)) / 1.5, sqrt(dr));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 _transmittance(float r, float mu)
|
||||||
|
{
|
||||||
|
vec2 uv = _getTransmittanceUV(r, mu);
|
||||||
|
return texture2D(transmittanceTexture, uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 _transmittanceWithShadow(float r, float mu)
|
||||||
|
{
|
||||||
|
return mu < -sqrt(1.0 - (Rg / r) * (Rg / r)) ? vec4(0.0) : _transmittance(r, mu);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 _sunTransmittance(vec3 v, vec3 s, float r, float mu, float radius)
|
||||||
|
{
|
||||||
|
vec4 transmittance = r <= Rt ? _transmittanceWithShadow(r, mu) : vec4(1.0); /* T(x,xo) */
|
||||||
|
float d = _limit(r, mu);
|
||||||
|
radius *= (1.0 + 25.0 * d / Rt); /* Inflating due to lens effect near horizon */
|
||||||
|
float isun = step(cos(radius * M_PI / 180.0), dot(v, s)) * ISun; /* Lsun */
|
||||||
|
transmittance.r *= isun;
|
||||||
|
transmittance.g *= isun;
|
||||||
|
transmittance.b *= isun;
|
||||||
|
transmittance.a = 1.0;
|
||||||
|
return transmittance; /* Eq (9) */
|
||||||
|
}
|
||||||
|
|
||||||
|
float phaseFunctionR(float mu) {
|
||||||
|
return (3.0 / (16.0 * M_PI)) * (1.0 + mu * mu);
|
||||||
|
}
|
||||||
|
|
||||||
|
float phaseFunctionM(float mu) {
|
||||||
|
return 1.5 * 1.0 / (4.0 * M_PI) * (1.0 - mieG*mieG) * pow(1.0 + (mieG*mieG) - 2.0*mieG*mu, -3.0/2.0) * (1.0 + mu * mu) / (2.0 + mieG*mieG);
|
||||||
|
}
|
||||||
|
|
||||||
|
float opticalDepth(float H, float r, float mu, float d) {
|
||||||
|
float a = sqrt((0.5/H)*r);
|
||||||
|
vec2 a01 = a*vec2(mu, mu + d / r);
|
||||||
|
vec2 a01s = sign(a01);
|
||||||
|
vec2 a01sq = a01*a01;
|
||||||
|
float x = a01s.y > a01s.x ? exp(a01sq.x) : 0.0;
|
||||||
|
vec2 y = a01s / (2.3193*abs(a01) + sqrt(1.52*a01sq + 4.0)) * vec2(1.0, exp(-d/H*(d/(2.0*r)+mu)));
|
||||||
|
return sqrt((6.2831*H)*r) * exp((Rg-r)/H) * (x + dot(y, vec2(1.0, -1.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 analyticTransmittance(float r, float mu, float d) {
|
||||||
|
return exp(- betaR * opticalDepth(HR, r, mu, d) - betaMEx * opticalDepth(HM, r, mu, d));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getMie(vec4 rayMie) { // rayMie.rgb=C*, rayMie.w=Cm,r
|
||||||
|
return rayMie.rgb * rayMie.w / max(rayMie.r, 1e-4) * (betaR.r / betaR);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 _getInscatterColor(inout vec3 x, inout float t, vec3 v, vec3 s, out float r, out float mu, out vec3 attenuation) {
|
||||||
|
vec3 result;
|
||||||
|
r = length(x);
|
||||||
|
mu = dot(x, v) / r;
|
||||||
|
float d = -r * mu - sqrt(r * r * (mu * mu - 1.0) + Rt * Rt);
|
||||||
|
if (d > 0.0) { // if x in space and ray intersects atmosphere
|
||||||
|
// move x to nearest intersection of ray with top atmosphere boundary
|
||||||
|
x += d * v;
|
||||||
|
t -= d;
|
||||||
|
mu = (r * mu + d) / Rt;
|
||||||
|
r = Rt;
|
||||||
|
}
|
||||||
|
if (r <= Rt) { // if ray intersects atmosphere
|
||||||
|
float nu = dot(v, s);
|
||||||
|
float muS = dot(x, s) / r;
|
||||||
|
float phaseR = phaseFunctionR(nu);
|
||||||
|
float phaseM = phaseFunctionM(nu);
|
||||||
|
vec4 inscatter = max(texture4D(inscatterTexture, r, mu, muS, nu), 0.0);
|
||||||
|
if (t > 0.0) {
|
||||||
|
vec3 x0 = x + t * v;
|
||||||
|
float r0 = length(x0);
|
||||||
|
float rMu0 = dot(x0, v);
|
||||||
|
float mu0 = rMu0 / r0;
|
||||||
|
float muS0 = dot(x0, s) / r0;
|
||||||
|
// avoids imprecision problems in transmittance computations based on textures
|
||||||
|
attenuation = analyticTransmittance(r, mu, t);
|
||||||
|
if (r0 > Rg + 0.001) {
|
||||||
|
// computes S[L]-T(x,x0)S[L]|x0
|
||||||
|
inscatter = max(inscatter - attenuation.rgbr * texture4D(inscatterTexture, r0, mu0, muS0, nu), 0.0);
|
||||||
|
// avoids imprecision problems near horizon by interpolating between two points above and below horizon
|
||||||
|
const float EPS = 0.02;
|
||||||
|
float muHoriz = -sqrt(1.0 - (Rg / r) * (Rg / r));
|
||||||
|
if (abs(mu - muHoriz) < EPS) {
|
||||||
|
float a = ((mu - muHoriz) + EPS) / (2.0 * EPS);
|
||||||
|
|
||||||
|
mu = muHoriz - EPS;
|
||||||
|
r0 = sqrt(r * r + t * t + 2.0 * r * t * mu);
|
||||||
|
mu0 = (r * mu + t) / r0;
|
||||||
|
vec4 inScatter0 = texture4D(inscatterTexture, r, mu, muS, nu);
|
||||||
|
vec4 inScatter1 = texture4D(inscatterTexture, r0, mu0, muS0, nu);
|
||||||
|
vec4 inScatterA = max(inScatter0 - attenuation.rgbr * inScatter1, 0.0);
|
||||||
|
|
||||||
|
mu = muHoriz + EPS;
|
||||||
|
r0 = sqrt(r * r + t * t + 2.0 * r * t * mu);
|
||||||
|
mu0 = (r * mu + t) / r0;
|
||||||
|
inScatter0 = texture4D(inscatterTexture, r, mu, muS, nu);
|
||||||
|
inScatter1 = texture4D(inscatterTexture, r0, mu0, muS0, nu);
|
||||||
|
vec4 inScatterB = max(inScatter0 - attenuation.rgbr * inScatter1, 0.0);
|
||||||
|
|
||||||
|
inscatter = mix(inScatterA, inScatterB, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// avoids imprecision problems in Mie scattering when sun is below horizon
|
||||||
|
inscatter.w *= smoothstep(0.00, 0.02, muS);
|
||||||
|
result = max(inscatter.rgb * phaseR + getMie(inscatter) * phaseM, 0.0);
|
||||||
|
} else { // x in space and ray looking in space
|
||||||
|
result = vec3(0.0);
|
||||||
|
}
|
||||||
|
return result * ISun;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 applyAerialPerspective(vec4 base)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
return base * vec4(attenuation, 0.0) + vec4(inscattering, 0.0);
|
||||||
|
}
|
8
src/render/opengl/shaders/fadeout.frag
Normal file
8
src/render/opengl/shaders/fadeout.frag
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
uniform float viewDistance;
|
||||||
|
|
||||||
|
float distanceFadeout()
|
||||||
|
{
|
||||||
|
vec3 camera = vec3(cameraLocation.x, 0.0, cameraLocation.z);
|
||||||
|
vec3 location = vec3(unprojected.x, 0.0, unprojected.z);
|
||||||
|
return mix(1.0, 0.0, clamp((length(location - camera) - viewDistance * 0.8) / (viewDistance * 0.2), 0.0, 1.0));
|
||||||
|
}
|
13
src/render/opengl/shaders/resources.qrc
Normal file
13
src/render/opengl/shaders/resources.qrc
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/shaders">
|
||||||
|
<file>skybox.frag</file>
|
||||||
|
<file>skybox.vert</file>
|
||||||
|
<file>water.frag</file>
|
||||||
|
<file>water.vert</file>
|
||||||
|
<file>bruneton.frag</file>
|
||||||
|
<file>tonemapping.frag</file>
|
||||||
|
<file>terrain.frag</file>
|
||||||
|
<file>terrain.vert</file>
|
||||||
|
<file>fadeout.frag</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
19
src/render/opengl/shaders/skybox.frag
Normal file
19
src/render/opengl/shaders/skybox.frag
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
float r = length(x);
|
||||||
|
float mu = dot(x, v) / r;
|
||||||
|
float t = -r * mu - sqrt(r * r * (mu * mu - 1.0) + Rg * Rg);
|
||||||
|
|
||||||
|
vec4 sunTransmittance = _sunTransmittance(v, s, r, mu, sunRadius);
|
||||||
|
vec3 attenuation;
|
||||||
|
vec3 inscattering = _getInscatterColor(x, t, v, s, r, mu, attenuation);
|
||||||
|
|
||||||
|
gl_FragColor = applyToneMapping(sunTransmittance + vec4(inscattering, 0.0));
|
||||||
|
}
|
10
src/render/opengl/shaders/skybox.vert
Normal file
10
src/render/opengl/shaders/skybox.vert
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
attribute highp vec4 vertex;
|
||||||
|
uniform highp mat4 viewMatrix;
|
||||||
|
uniform vec3 cameraLocation;
|
||||||
|
varying vec3 unprojected;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
unprojected = cameraLocation + vertex.xyz * 500.0;
|
||||||
|
gl_Position = viewMatrix * vec4(unprojected, 1.0);
|
||||||
|
}
|
13
src/render/opengl/shaders/terrain.frag
Normal file
13
src/render/opengl/shaders/terrain.frag
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
uniform sampler2D groundTexture;
|
||||||
|
varying vec2 texcoord;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
gl_FragColor = texture2D(groundTexture, texcoord);
|
||||||
|
|
||||||
|
gl_FragColor = applyAerialPerspective(gl_FragColor);
|
||||||
|
|
||||||
|
gl_FragColor = applyToneMapping(gl_FragColor);
|
||||||
|
|
||||||
|
gl_FragColor.a = distanceFadeout();
|
||||||
|
}
|
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;
|
||||||
|
}
|
32
src/render/opengl/shaders/tonemapping.frag
Normal file
32
src/render/opengl/shaders/tonemapping.frag
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
uniform float exposure;
|
||||||
|
|
||||||
|
float _uncharted2Tonemap(float x)
|
||||||
|
{
|
||||||
|
float A = 0.15;
|
||||||
|
float B = 0.50;
|
||||||
|
float C = 0.10;
|
||||||
|
float D = 0.20;
|
||||||
|
float E = 0.02;
|
||||||
|
float F = 0.30;
|
||||||
|
|
||||||
|
return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 applyToneMapping(vec4 color)
|
||||||
|
{
|
||||||
|
return vec4(((color * exposure) / (1.0 + color * exposure)).rgb, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*vec4 applyToneMapping(vec4 color)
|
||||||
|
{
|
||||||
|
float W = 11.2;
|
||||||
|
float white_scale = 1.0 / _uncharted2Tonemap(W);
|
||||||
|
vec4 result;
|
||||||
|
|
||||||
|
result.r = pow(_uncharted2Tonemap(color.r * exposure) * white_scale, 1.0 / 2.2);
|
||||||
|
result.g = pow(_uncharted2Tonemap(color.g * exposure) * white_scale, 1.0 / 2.2);
|
||||||
|
result.b = pow(_uncharted2Tonemap(color.b * exposure) * white_scale, 1.0 / 2.2);
|
||||||
|
result.a = 1.0;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}*/
|
12
src/render/opengl/shaders/water.frag
Normal file
12
src/render/opengl/shaders/water.frag
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
uniform vec4 waterColor;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
gl_FragColor = waterColor;
|
||||||
|
|
||||||
|
gl_FragColor = applyAerialPerspective(gl_FragColor);
|
||||||
|
|
||||||
|
gl_FragColor = applyToneMapping(gl_FragColor);
|
||||||
|
|
||||||
|
gl_FragColor.a = distanceFadeout();
|
||||||
|
}
|
11
src/render/opengl/shaders/water.vert
Normal file
11
src/render/opengl/shaders/water.vert
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
attribute highp vec4 vertex;
|
||||||
|
uniform highp mat4 viewMatrix;
|
||||||
|
uniform float waterHeight;
|
||||||
|
uniform vec3 cameraLocation;
|
||||||
|
varying vec3 unprojected;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
unprojected = vec3(cameraLocation.x + vertex.x * 500.0, vertex.y + waterHeight, cameraLocation.z + vertex.z * 500.0);
|
||||||
|
gl_Position = viewMatrix * vec4(unprojected, 1.0);
|
||||||
|
}
|
|
@ -934,7 +934,7 @@ static Color _sunColor(Vector3 v, Vector3 s, double r, double mu, double radius)
|
||||||
{
|
{
|
||||||
Color transmittance = r <= Rt ? _transmittanceWithShadow(r, mu) : COLOR_WHITE; /* T(x,xo) */
|
Color transmittance = r <= Rt ? _transmittanceWithShadow(r, mu) : COLOR_WHITE; /* T(x,xo) */
|
||||||
double d = _limit(r, mu);
|
double d = _limit(r, mu);
|
||||||
radius *= (1.0 + 10.0 * d / Rt); /* Inflating due to lens effect near horizon */
|
radius *= (1.0 + 25.0 * d / Rt); /* Inflating due to lens effect near horizon */
|
||||||
double isun = step(cos(radius * M_PI / 180.0), v.dotProduct(s)) * ISun; /* Lsun */
|
double isun = step(cos(radius * M_PI / 180.0), v.dotProduct(s)) * ISun; /* Lsun */
|
||||||
transmittance.r *= isun;
|
transmittance.r *= isun;
|
||||||
transmittance.g *= isun;
|
transmittance.g *= isun;
|
||||||
|
@ -1268,3 +1268,18 @@ void AtmosphereModelBruneton::fillLightingStatus(LightStatus *status, const Vect
|
||||||
|
|
||||||
status->pushComponent(irradiance);
|
status->pushComponent(irradiance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Texture2D *AtmosphereModelBruneton::getTextureTransmittance() const
|
||||||
|
{
|
||||||
|
return _transmittanceTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D *AtmosphereModelBruneton::getTextureIrradiance() const
|
||||||
|
{
|
||||||
|
return _irradianceTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture4D *AtmosphereModelBruneton::getTextureInscatter() const
|
||||||
|
{
|
||||||
|
return _inscatterTexture;
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,11 @@ public:
|
||||||
AtmosphereResult applyAerialPerspective(Vector3 location, const Color &base);
|
AtmosphereResult applyAerialPerspective(Vector3 location, const Color &base);
|
||||||
void fillLightingStatus(LightStatus *status, const Vector3 &normal, int opaque);
|
void fillLightingStatus(LightStatus *status, const Vector3 &normal, int opaque);
|
||||||
|
|
||||||
|
/* Functions to get access to internal textures (for opengl shaders) */
|
||||||
|
Texture2D* getTextureTransmittance() const;
|
||||||
|
Texture2D* getTextureIrradiance() const;
|
||||||
|
Texture4D* getTextureInscatter() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SoftwareRenderer* parent;
|
SoftwareRenderer* parent;
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,6 +39,8 @@ public:
|
||||||
virtual AtmosphereResult applyAerialPerspective(Vector3 location, Color base) override;
|
virtual AtmosphereResult applyAerialPerspective(Vector3 location, Color base) override;
|
||||||
virtual AtmosphereResult getSkyColor(Vector3 direction) override;
|
virtual AtmosphereResult getSkyColor(Vector3 direction) override;
|
||||||
|
|
||||||
|
inline const AtmosphereModelBruneton* getModel() const {return model;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AtmosphereModelBruneton* model;
|
AtmosphereModelBruneton* model;
|
||||||
};
|
};
|
||||||
|
|
1
src/system/Logs.cpp
Normal file
1
src/system/Logs.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "Logs.h"
|
9
src/system/Logs.h
Normal file
9
src/system/Logs.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef LOGS_H
|
||||||
|
#define LOGS_H
|
||||||
|
|
||||||
|
#include "system_global.h"
|
||||||
|
|
||||||
|
#define logWarning qWarning
|
||||||
|
#define logError qCritical
|
||||||
|
|
||||||
|
#endif // LOGS_H
|
55
src/system/ParallelPool.cpp
Normal file
55
src/system/ParallelPool.cpp
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#include "ParallelPool.h"
|
||||||
|
|
||||||
|
#include "System.h"
|
||||||
|
#include "Thread.h"
|
||||||
|
|
||||||
|
static void* _threadFunction(void* data)
|
||||||
|
{
|
||||||
|
ParallelPool* pool = (ParallelPool*)data;
|
||||||
|
pool->work();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParallelPool::ParallelPool()
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParallelPool::~ParallelPool()
|
||||||
|
{
|
||||||
|
if (running)
|
||||||
|
{
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
|
for (auto thread : threads)
|
||||||
|
{
|
||||||
|
thread->join();
|
||||||
|
delete thread;
|
||||||
|
}
|
||||||
|
threads.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParallelPool::start(int thread_count)
|
||||||
|
{
|
||||||
|
if (running)
|
||||||
|
{
|
||||||
|
qCritical("Starting an already started parallel pool !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
running = true;
|
||||||
|
if (thread_count < 0)
|
||||||
|
{
|
||||||
|
thread_count = System::getCoreCount();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < thread_count; i++)
|
||||||
|
{
|
||||||
|
Thread* thread = new Thread(_threadFunction);
|
||||||
|
thread->start(this);
|
||||||
|
threads.push_back(thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParallelPool::interrupt()
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
}
|
43
src/system/ParallelPool.h
Normal file
43
src/system/ParallelPool.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef PARALLELPOOL_H
|
||||||
|
#define PARALLELPOOL_H
|
||||||
|
|
||||||
|
#include "system_global.h"
|
||||||
|
|
||||||
|
namespace paysages {
|
||||||
|
namespace system {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Pool to handle a group of threads doing the same task.
|
||||||
|
*/
|
||||||
|
class ParallelPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ParallelPool();
|
||||||
|
virtual ~ParallelPool();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Start the effective work.
|
||||||
|
*/
|
||||||
|
void start(int thread_count=-1);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Method called from each thread to do actual work.
|
||||||
|
*/
|
||||||
|
virtual void work() = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Method called once to interrupt all threads.
|
||||||
|
*/
|
||||||
|
virtual void interrupt();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool running;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Thread*> threads;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PARALLELPOOL_H
|
|
@ -23,7 +23,9 @@ SOURCES += \
|
||||||
ParallelWork.cpp \
|
ParallelWork.cpp \
|
||||||
ParallelQueue.cpp \
|
ParallelQueue.cpp \
|
||||||
CacheFile.cpp \
|
CacheFile.cpp \
|
||||||
PictureWriter.cpp
|
PictureWriter.cpp \
|
||||||
|
Logs.cpp \
|
||||||
|
ParallelPool.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
system_global.h \
|
system_global.h \
|
||||||
|
@ -36,7 +38,9 @@ HEADERS += \
|
||||||
ParallelWork.h \
|
ParallelWork.h \
|
||||||
ParallelQueue.h \
|
ParallelQueue.h \
|
||||||
CacheFile.h \
|
CacheFile.h \
|
||||||
PictureWriter.h
|
PictureWriter.h \
|
||||||
|
Logs.h \
|
||||||
|
ParallelPool.h
|
||||||
|
|
||||||
unix:!symbian {
|
unix:!symbian {
|
||||||
maemo5 {
|
maemo5 {
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace system {
|
||||||
class PackStream;
|
class PackStream;
|
||||||
class ParallelQueue;
|
class ParallelQueue;
|
||||||
class ParallelWork;
|
class ParallelWork;
|
||||||
|
class ParallelPool;
|
||||||
class Thread;
|
class Thread;
|
||||||
class Mutex;
|
class Mutex;
|
||||||
}
|
}
|
||||||
|
|
100
src/tests/VertexArray_Test.cpp
Normal file
100
src/tests/VertexArray_Test.cpp
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
#include "BaseTestCase.h"
|
||||||
|
|
||||||
|
#include "VertexArray.h"
|
||||||
|
|
||||||
|
class TestVertex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
float uv[2];
|
||||||
|
int loc[3];
|
||||||
|
|
||||||
|
bool operator==(const TestVertex &other) const
|
||||||
|
{
|
||||||
|
return other.uv[0] == uv[0]
|
||||||
|
and other.uv[1] == uv[1]
|
||||||
|
and other.loc[0] == loc[0]
|
||||||
|
and other.loc[1] == loc[1]
|
||||||
|
and other.loc[2] == loc[2];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(VertexArray, grid)
|
||||||
|
{
|
||||||
|
VertexArray<TestVertex> array;
|
||||||
|
|
||||||
|
array.setGridSize(3);
|
||||||
|
|
||||||
|
ASSERT_EQ(9, array.getVertexCount());
|
||||||
|
|
||||||
|
TestVertex v1 = {{0.1, 0.2}, {1, 2, 3}};
|
||||||
|
TestVertex vgot;
|
||||||
|
|
||||||
|
array.setGridVertex(3, 1, 2, v1);
|
||||||
|
vgot = array.getGridVertex(3, 1, 2);
|
||||||
|
EXPECT_EQ(v1, vgot);
|
||||||
|
vgot = array.getVertex(7);
|
||||||
|
EXPECT_EQ(v1, vgot);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VertexArray, gridIndices)
|
||||||
|
{
|
||||||
|
VertexArray<TestVertex> array;
|
||||||
|
|
||||||
|
array.setGridSize(3);
|
||||||
|
|
||||||
|
array.setAutoGridIndices(3);
|
||||||
|
ASSERT_EQ(24, array.getIndexCount());
|
||||||
|
|
||||||
|
EXPECT_EQ(0, array.getIndex(0));
|
||||||
|
EXPECT_EQ(3, array.getIndex(1));
|
||||||
|
EXPECT_EQ(1, array.getIndex(2));
|
||||||
|
|
||||||
|
EXPECT_EQ(1, array.getIndex(3));
|
||||||
|
EXPECT_EQ(3, array.getIndex(4));
|
||||||
|
EXPECT_EQ(4, array.getIndex(5));
|
||||||
|
|
||||||
|
EXPECT_EQ(1, array.getIndex(6));
|
||||||
|
EXPECT_EQ(4, array.getIndex(7));
|
||||||
|
EXPECT_EQ(2, array.getIndex(8));
|
||||||
|
|
||||||
|
EXPECT_EQ(2, array.getIndex(9));
|
||||||
|
EXPECT_EQ(4, array.getIndex(10));
|
||||||
|
EXPECT_EQ(5, array.getIndex(11));
|
||||||
|
|
||||||
|
EXPECT_EQ(3, array.getIndex(12));
|
||||||
|
EXPECT_EQ(6, array.getIndex(13));
|
||||||
|
EXPECT_EQ(4, array.getIndex(14));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VertexArray, gridIndicesStride)
|
||||||
|
{
|
||||||
|
VertexArray<TestVertex> array;
|
||||||
|
|
||||||
|
array.setGridSize(5);
|
||||||
|
|
||||||
|
array.setAutoGridIndices(5, 1);
|
||||||
|
ASSERT_EQ(96, array.getIndexCount());
|
||||||
|
|
||||||
|
array.setAutoGridIndices(5, 2);
|
||||||
|
ASSERT_EQ(24, array.getIndexCount());
|
||||||
|
|
||||||
|
EXPECT_EQ(0, array.getIndex(0));
|
||||||
|
EXPECT_EQ(10, array.getIndex(1));
|
||||||
|
EXPECT_EQ(2, array.getIndex(2));
|
||||||
|
|
||||||
|
EXPECT_EQ(2, array.getIndex(3));
|
||||||
|
EXPECT_EQ(10, array.getIndex(4));
|
||||||
|
EXPECT_EQ(12, array.getIndex(5));
|
||||||
|
|
||||||
|
EXPECT_EQ(2, array.getIndex(6));
|
||||||
|
EXPECT_EQ(12, array.getIndex(7));
|
||||||
|
EXPECT_EQ(4, array.getIndex(8));
|
||||||
|
|
||||||
|
EXPECT_EQ(4, array.getIndex(9));
|
||||||
|
EXPECT_EQ(12, array.getIndex(10));
|
||||||
|
EXPECT_EQ(14, array.getIndex(11));
|
||||||
|
|
||||||
|
EXPECT_EQ(10, array.getIndex(12));
|
||||||
|
EXPECT_EQ(20, array.getIndex(13));
|
||||||
|
EXPECT_EQ(12, array.getIndex(14));
|
||||||
|
}
|
|
@ -17,7 +17,8 @@ SOURCES += main.cpp \
|
||||||
Bruneton_Test.cpp \
|
Bruneton_Test.cpp \
|
||||||
Camera_Test.cpp \
|
Camera_Test.cpp \
|
||||||
Clouds_Test.cpp \
|
Clouds_Test.cpp \
|
||||||
FluidMediumManager_Test.cpp
|
FluidMediumManager_Test.cpp \
|
||||||
|
VertexArray_Test.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
BaseTestCase.h
|
BaseTestCase.h
|
||||||
|
@ -51,3 +52,9 @@ else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../render/software/
|
||||||
else:unix: LIBS += -L$$OUT_PWD/../render/software/ -lpaysages_render_software
|
else:unix: LIBS += -L$$OUT_PWD/../render/software/ -lpaysages_render_software
|
||||||
INCLUDEPATH += $$PWD/../render/software
|
INCLUDEPATH += $$PWD/../render/software
|
||||||
DEPENDPATH += $$PWD/../render/software
|
DEPENDPATH += $$PWD/../render/software
|
||||||
|
|
||||||
|
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../render/opengl/release/ -lpaysages_render_opengl
|
||||||
|
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../render/opengl/debug/ -lpaysages_render_opengl
|
||||||
|
else:unix: LIBS += -L$$OUT_PWD/../render/opengl/ -lpaysages_render_opengl
|
||||||
|
INCLUDEPATH += $$PWD/../render/opengl
|
||||||
|
DEPENDPATH += $$PWD/../render/opengl
|
||||||
|
|
Loading…
Reference in a new issue