Refactored OpenGLVariable with pimpl and smart pointers
This commit is contained in:
parent
3934077552
commit
d88cb29f4c
13 changed files with 306 additions and 233 deletions
|
@ -10,6 +10,11 @@ Matrix4::Matrix4(bool identity) {
|
|||
a = f = k = p = (identity ? 1.0 : 0.0);
|
||||
}
|
||||
|
||||
Matrix4::Matrix4(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j,
|
||||
double k, double l, double m, double n, double o, double p)
|
||||
: a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h), i(i), j(j), k(k), l(l), m(m), n(n), o(o), p(p) {
|
||||
}
|
||||
|
||||
void Matrix4::save(PackStream *stream) const {
|
||||
stream->write(&a);
|
||||
stream->write(&b);
|
||||
|
@ -221,7 +226,7 @@ Matrix4 Matrix4::newLookAt(const Vector3 &eye, const Vector3 &at, const Vector3
|
|||
|
||||
Matrix4 Matrix4::newPerspective(double fov_y, double aspect, double near, double far) {
|
||||
Matrix4 result;
|
||||
double fo = 1 / tan(fov_y / 2.0);
|
||||
double fo = 1.0 / tan(fov_y / 2.0);
|
||||
result.a = fo / aspect;
|
||||
result.f = fo;
|
||||
result.k = (far + near) / (near - far);
|
||||
|
|
|
@ -3,16 +3,14 @@
|
|||
|
||||
#include "basics_global.h"
|
||||
|
||||
#ifdef QT_GUI_LIB
|
||||
#include <QMatrix4x4>
|
||||
#endif
|
||||
|
||||
namespace paysages {
|
||||
namespace basics {
|
||||
|
||||
class BASICSSHARED_EXPORT Matrix4 {
|
||||
public:
|
||||
Matrix4(bool identity = true);
|
||||
Matrix4(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j,
|
||||
double k, double l, double m, double n, double o, double p);
|
||||
|
||||
void save(PackStream *stream) const;
|
||||
void load(PackStream *stream);
|
||||
|
@ -36,11 +34,54 @@ class BASICSSHARED_EXPORT Matrix4 {
|
|||
|
||||
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);
|
||||
inline double getA() const {
|
||||
return a;
|
||||
}
|
||||
inline double getB() const {
|
||||
return b;
|
||||
}
|
||||
inline double getC() const {
|
||||
return c;
|
||||
}
|
||||
inline double getD() const {
|
||||
return d;
|
||||
}
|
||||
inline double getE() const {
|
||||
return e;
|
||||
}
|
||||
inline double getF() const {
|
||||
return f;
|
||||
}
|
||||
inline double getG() const {
|
||||
return g;
|
||||
}
|
||||
inline double getH() const {
|
||||
return h;
|
||||
}
|
||||
inline double getI() const {
|
||||
return i;
|
||||
}
|
||||
inline double getJ() const {
|
||||
return j;
|
||||
}
|
||||
inline double getK() const {
|
||||
return k;
|
||||
}
|
||||
inline double getL() const {
|
||||
return l;
|
||||
}
|
||||
inline double getM() const {
|
||||
return m;
|
||||
}
|
||||
inline double getN() const {
|
||||
return n;
|
||||
}
|
||||
inline double getO() const {
|
||||
return o;
|
||||
}
|
||||
inline double getP() const {
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
double a;
|
||||
|
|
|
@ -249,6 +249,7 @@ bool CameraDefinition::transitionToAnother(const CameraDefinition *wanted, doubl
|
|||
dy = wanted->location.y - location.y;
|
||||
dz = wanted->location.z - location.z;
|
||||
dr = wanted->direction.r - direction.r;
|
||||
// TODO pi-modulo nearest
|
||||
dphi = wanted->direction.phi - direction.phi;
|
||||
dtheta = wanted->direction.theta - direction.theta;
|
||||
droll = wanted->roll - roll;
|
||||
|
|
|
@ -73,9 +73,10 @@ void ModelerCameras::endTool() {
|
|||
}
|
||||
|
||||
void ModelerCameras::timerEvent(QTimerEvent *) {
|
||||
current->transitionToAnother(active, 0.5);
|
||||
parent->getScenery()->keepCameraAboveGround(current);
|
||||
parent->getRenderer()->setCamera(current);
|
||||
if (current->transitionToAnother(active, 0.5)) {
|
||||
parent->getScenery()->keepCameraAboveGround(current);
|
||||
parent->getRenderer()->setCamera(current);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelerCameras::nodeChanged(const DefinitionNode *node, const DefinitionDiff *) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "OpenGLRenderer.h"
|
||||
|
||||
#include <QMatrix4x4>
|
||||
#include "OpenGLFunctions.h"
|
||||
#include "CameraDefinition.h"
|
||||
#include "OpenGLSharedState.h"
|
||||
|
@ -38,7 +39,7 @@ OpenGLRenderer::OpenGLRenderer(Scenery *scenery) : SoftwareRenderer(scenery) {
|
|||
shared_state = new OpenGLSharedState();
|
||||
|
||||
shared_state->set("viewDistance", 300.0);
|
||||
shared_state->set("exposure", 1.2);
|
||||
shared_state->set("exposure", to_float(1.2));
|
||||
|
||||
parts.push_back(skybox = new OpenGLSkybox(this));
|
||||
parts.push_back(water = new OpenGLWater(this));
|
||||
|
@ -72,7 +73,7 @@ void OpenGLRenderer::prepare() {
|
|||
}
|
||||
|
||||
void OpenGLRenderer::checkForErrors(const string &domain) {
|
||||
int error_code;
|
||||
unsigned int error_code;
|
||||
while ((error_code = functions->glGetError()) != GL_NO_ERROR) {
|
||||
Logs::warning("OpenGL") << "Error in " << domain << " : " << error_code << endl;
|
||||
}
|
||||
|
@ -236,6 +237,7 @@ void OpenGLRenderer::cameraChangeEvent(CameraDefinition *camera) {
|
|||
CameraPerspective perspective = camera->getPerspective();
|
||||
|
||||
// Compute matrix
|
||||
// TODO Switch to CameraDefinition raw transformation matrix (currently produces strange results)
|
||||
QMatrix4x4 transform;
|
||||
transform.setToIdentity();
|
||||
transform.lookAt(QVector3D(location.x, location.y, location.z), QVector3D(target.x, target.y, target.z),
|
||||
|
@ -249,7 +251,8 @@ void OpenGLRenderer::cameraChangeEvent(CameraDefinition *camera) {
|
|||
|
||||
// Set in shaders
|
||||
shared_state->set("cameraLocation", location);
|
||||
shared_state->set("viewMatrix", *view_matrix);
|
||||
float *matdata = view_matrix->transposed().data();
|
||||
shared_state->set("viewMatrix", Matrix4(matdata[0], matdata[1], matdata[2], matdata[3], matdata[4], matdata[5], matdata[6], matdata[7], matdata[8], matdata[9], matdata[10], matdata[11], matdata[12], matdata[13], matdata[14], matdata[15]));
|
||||
|
||||
// Broadcast to parts
|
||||
vegetation->cameraChanged(camera);
|
||||
|
@ -267,7 +270,7 @@ void OpenGLRenderer::updateMouseProjection() {
|
|||
GLfloat z;
|
||||
functions->glReadPixels(mouse_x, mouse_y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
|
||||
|
||||
QVector4D located(mouse_x / render_camera->getWidth(), mouse_y / render_camera->getHeight(), z, 1.0);
|
||||
QVector4D located(to_float(mouse_x / render_camera->getWidth()), to_float(mouse_y / render_camera->getHeight()), z, 1.0);
|
||||
QVector4D unprojected = view_matrix->inverted() * 2.0 * (located - QVector4D(0.5, 0.5, 0.5, 0.5));
|
||||
*mouse_projected = Vector3(unprojected.x() / unprojected.w(), unprojected.y() / unprojected.w(),
|
||||
unprojected.z() / unprojected.w());
|
||||
|
|
|
@ -18,6 +18,7 @@ OpenGLShaderProgram::OpenGLShaderProgram(const string &name, OpenGLRenderer *ren
|
|||
functions = renderer->getOpenGlFunctions();
|
||||
state = new OpenGLSharedState();
|
||||
compiled = false;
|
||||
bound = false;
|
||||
}
|
||||
|
||||
OpenGLShaderProgram::~OpenGLShaderProgram() {
|
||||
|
@ -28,7 +29,7 @@ OpenGLShaderProgram::~OpenGLShaderProgram() {
|
|||
void OpenGLShaderProgram::addVertexSource(const string &path) {
|
||||
QFile file(QString(":/shaders/%1.vert").arg(QString::fromStdString(path)));
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
source_vertex += QString(file.readAll()).toStdString();
|
||||
source_vertex += QString(file.readAll()).toStdString() + "\n";
|
||||
} else {
|
||||
Logs::error("OpenGL") << "Can't open vertex file " << file.fileName().toStdString() << endl;
|
||||
}
|
||||
|
@ -37,7 +38,7 @@ void OpenGLShaderProgram::addVertexSource(const string &path) {
|
|||
void OpenGLShaderProgram::addFragmentSource(const string &path) {
|
||||
QFile file(QString(":/shaders/%1.frag").arg(QString::fromStdString(path)));
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
source_fragment += QString(file.readAll()).toStdString();
|
||||
source_fragment += QString(file.readAll()).toStdString() + "\n";
|
||||
} else {
|
||||
Logs::error("OpenGL") << "Can't open fragment file " << file.fileName().toStdString() << endl;
|
||||
}
|
||||
|
@ -74,11 +75,14 @@ bool OpenGLShaderProgram::bind(OpenGLSharedState *state) {
|
|||
}
|
||||
|
||||
if (program->bind()) {
|
||||
int texture_unit = 0;
|
||||
bound = true;
|
||||
|
||||
unsigned int texture_unit = 0;
|
||||
renderer->getSharedState()->apply(this, texture_unit);
|
||||
if (state) {
|
||||
state->apply(this, texture_unit);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -86,6 +90,7 @@ bool OpenGLShaderProgram::bind(OpenGLSharedState *state) {
|
|||
}
|
||||
|
||||
void OpenGLShaderProgram::release() {
|
||||
bound = false;
|
||||
program->release();
|
||||
}
|
||||
|
||||
|
@ -96,3 +101,7 @@ void OpenGLShaderProgram::draw(OpenGLVertexArray *vertices, OpenGLSharedState *s
|
|||
release();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int OpenGLShaderProgram::getId() const {
|
||||
return program->programId();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,20 @@ class OPENGLSHARED_EXPORT OpenGLShaderProgram {
|
|||
*/
|
||||
void draw(OpenGLVertexArray *vertices, OpenGLSharedState *state = NULL, int start = 0, int count = -1);
|
||||
|
||||
/**
|
||||
* Check if the program is currently bound to OpenGL context.
|
||||
*
|
||||
* This does not really check the OpenGL context, just check we are between bind() and release() calls.
|
||||
*/
|
||||
inline bool isBound() const {
|
||||
return bound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the OpenGL ID for this program.
|
||||
*/
|
||||
unsigned int getId() const;
|
||||
|
||||
inline QOpenGLShaderProgram *getProgram() const {
|
||||
return program;
|
||||
}
|
||||
|
@ -55,6 +69,7 @@ class OPENGLSHARED_EXPORT OpenGLShaderProgram {
|
|||
void compile();
|
||||
|
||||
bool compiled;
|
||||
bool bound;
|
||||
|
||||
OpenGLRenderer *renderer;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ OpenGLSharedState::~OpenGLSharedState() {
|
|||
}
|
||||
}
|
||||
|
||||
void OpenGLSharedState::apply(OpenGLShaderProgram *program, int &texture_unit) {
|
||||
void OpenGLSharedState::apply(OpenGLShaderProgram *program, unsigned int &texture_unit) {
|
||||
for (const auto &pair : variables) {
|
||||
pair.second->apply(program, texture_unit);
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
#include <map>
|
||||
#include "OpenGLVariable.h"
|
||||
|
||||
class QImage;
|
||||
|
||||
namespace paysages {
|
||||
namespace opengl {
|
||||
|
||||
|
@ -22,7 +20,7 @@ class OPENGLSHARED_EXPORT OpenGLSharedState {
|
|||
/**
|
||||
* Apply the stored variables to the bound program.
|
||||
*/
|
||||
void apply(OpenGLShaderProgram *program, int &texture_unit);
|
||||
void apply(OpenGLShaderProgram *program, unsigned int &texture_unit);
|
||||
|
||||
/**
|
||||
* Release any allocated resource in the opengl context.
|
||||
|
@ -58,15 +56,9 @@ class OPENGLSHARED_EXPORT OpenGLSharedState {
|
|||
inline void set(const string &name, const Vector3 &vector) {
|
||||
get(name)->set(vector);
|
||||
}
|
||||
inline void set(const string &name, const QVector3D &vector) {
|
||||
get(name)->set(vector);
|
||||
}
|
||||
inline void set(const string &name, const Matrix4 &matrix) {
|
||||
get(name)->set(matrix);
|
||||
}
|
||||
inline void set(const string &name, const QMatrix4x4 &matrix) {
|
||||
get(name)->set(matrix);
|
||||
}
|
||||
inline void set(const string &name, const Color &color) {
|
||||
get(name)->set(color);
|
||||
}
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
#include <cassert>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QColor>
|
||||
#include <QVector3D>
|
||||
#include <QMatrix4x4>
|
||||
#include <QImage>
|
||||
#include "Logs.h"
|
||||
#include "OpenGLFunctions.h"
|
||||
|
@ -17,281 +14,303 @@
|
|||
#include "Texture3D.h"
|
||||
#include "Texture4D.h"
|
||||
|
||||
OpenGLVariable::OpenGLVariable(const string &name) : name(name) {
|
||||
type = TYPE_NONE;
|
||||
texture_toupload = false;
|
||||
texture_id = 0;
|
||||
typedef enum {
|
||||
TYPE_NONE,
|
||||
TYPE_TEXTURE_2D,
|
||||
TYPE_TEXTURE_3D,
|
||||
TYPE_TEXTURE_4D,
|
||||
TYPE_INTEGER,
|
||||
TYPE_FLOAT,
|
||||
TYPE_VECTOR3,
|
||||
TYPE_MATRIX4,
|
||||
TYPE_COLOR
|
||||
} OpenGLVariableType;
|
||||
|
||||
value_color = new QColor;
|
||||
value_matrix4 = new QMatrix4x4;
|
||||
value_vector3 = new QVector3D;
|
||||
value_texture_data = new float[1];
|
||||
class OpenGLVariable::pimpl {
|
||||
public:
|
||||
pimpl(const string &name) : name(name) {
|
||||
type = TYPE_NONE;
|
||||
texture_toupload = false;
|
||||
texture_id = 0;
|
||||
}
|
||||
|
||||
string name;
|
||||
OpenGLVariableType type;
|
||||
|
||||
int value_int;
|
||||
float value_float;
|
||||
unique_ptr<Color> value_color;
|
||||
unique_ptr<Vector3> value_vector3;
|
||||
unique_ptr<float[]> value_array_float;
|
||||
|
||||
int texture_size_x;
|
||||
int texture_size_y;
|
||||
int texture_size_z;
|
||||
bool texture_toupload;
|
||||
bool texture_repeat;
|
||||
bool texture_color;
|
||||
unsigned int texture_id;
|
||||
};
|
||||
|
||||
OpenGLVariable::OpenGLVariable(const string &name) : impl(new pimpl(name)) {
|
||||
}
|
||||
|
||||
OpenGLVariable::~OpenGLVariable() {
|
||||
delete value_color;
|
||||
delete value_matrix4;
|
||||
delete value_vector3;
|
||||
delete[] value_texture_data;
|
||||
|
||||
if (texture_id) {
|
||||
Logs::warning("OpenGL") << "Texture ID not freed " << texture_id << endl;
|
||||
if (impl->texture_id) {
|
||||
Logs::warning("OpenGL") << "Texture ID " << impl->texture_id << " not freed in variable " << impl->name << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLVariable::apply(OpenGLShaderProgram *program, int &texture_unit) {
|
||||
QOpenGLShaderProgram *pr = program->getProgram();
|
||||
void OpenGLVariable::apply(OpenGLShaderProgram *program, unsigned int &texture_unit) {
|
||||
assert(program->isBound());
|
||||
|
||||
OpenGLFunctions *functions = program->getRenderer()->getOpenGlFunctions();
|
||||
|
||||
if (texture_toupload) {
|
||||
uploadTexture(program->getRenderer());
|
||||
texture_toupload = false;
|
||||
if (impl->texture_toupload) {
|
||||
uploadTexture(functions);
|
||||
impl->texture_toupload = false;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case TYPE_INTEGER:
|
||||
pr->setUniformValue(name.c_str(), value_int);
|
||||
break;
|
||||
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;
|
||||
int loc = functions->glGetUniformLocation(program->getId(), impl->name.c_str());
|
||||
if (loc >= 0) {
|
||||
switch (impl->type) {
|
||||
case TYPE_INTEGER:
|
||||
functions->glUniform1i(loc, impl->value_int);
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
functions->glUniform1f(loc, impl->value_float);
|
||||
break;
|
||||
case TYPE_COLOR:
|
||||
functions->glUniform4f(loc, to_float(impl->value_color->r), to_float(impl->value_color->g),
|
||||
to_float(impl->value_color->b), to_float(impl->value_color->a));
|
||||
break;
|
||||
case TYPE_VECTOR3:
|
||||
functions->glUniform3f(loc, to_float(impl->value_vector3->x), to_float(impl->value_vector3->y),
|
||||
to_float(impl->value_vector3->z));
|
||||
break;
|
||||
case TYPE_MATRIX4:
|
||||
functions->glUniformMatrix4fv(loc, 1, true, impl->value_array_float.get());
|
||||
break;
|
||||
case TYPE_TEXTURE_2D:
|
||||
functions->glActiveTexture(GL_TEXTURE0 + texture_unit);
|
||||
functions->glBindTexture(GL_TEXTURE_2D, impl->texture_id);
|
||||
functions->glUniform1i(loc, static_cast<int>(texture_unit));
|
||||
texture_unit++;
|
||||
break;
|
||||
case TYPE_TEXTURE_3D:
|
||||
case TYPE_TEXTURE_4D:
|
||||
functions->glActiveTexture(GL_TEXTURE0 + texture_unit);
|
||||
functions->glBindTexture(GL_TEXTURE_3D, impl->texture_id);
|
||||
functions->glUniform1i(loc, static_cast<int>(texture_unit));
|
||||
texture_unit++;
|
||||
break;
|
||||
case TYPE_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLVariable::destroy(OpenGLFunctions *functions) {
|
||||
if (texture_id) {
|
||||
functions->glDeleteTextures(1, &texture_id);
|
||||
texture_id = 0;
|
||||
if (impl->texture_id) {
|
||||
functions->glDeleteTextures(1, &(impl->texture_id));
|
||||
impl->texture_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLVariable::set(const Texture2D *texture, bool repeat, bool color) {
|
||||
assert(type == TYPE_NONE or type == TYPE_TEXTURE_2D);
|
||||
|
||||
type = TYPE_TEXTURE_2D;
|
||||
impl->type = TYPE_TEXTURE_2D;
|
||||
|
||||
int sx, sy;
|
||||
texture->getSize(&sx, &sy);
|
||||
float *pixels = new float[sx * sy * 4];
|
||||
float *pixels = new float[to_size(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 = texture->getPixel(x, y);
|
||||
pixel[0] = (float)col.r;
|
||||
pixel[1] = (float)col.g;
|
||||
pixel[2] = (float)col.b;
|
||||
pixel[3] = (float)col.a;
|
||||
pixel[0] = to_float(col.r);
|
||||
pixel[1] = to_float(col.g);
|
||||
pixel[2] = to_float(col.b);
|
||||
pixel[3] = to_float(col.a);
|
||||
}
|
||||
}
|
||||
|
||||
float *old_pixels = value_texture_data;
|
||||
value_texture_data = pixels;
|
||||
delete[] old_pixels;
|
||||
impl->value_array_float = unique_ptr<float[]>(pixels);
|
||||
|
||||
texture_size_x = sx;
|
||||
texture_size_y = sy;
|
||||
texture_size_z = 0;
|
||||
impl->texture_size_x = sx;
|
||||
impl->texture_size_y = sy;
|
||||
impl->texture_size_z = 0;
|
||||
|
||||
texture_toupload = true;
|
||||
texture_repeat = repeat;
|
||||
texture_color = color;
|
||||
impl->texture_toupload = true;
|
||||
impl->texture_repeat = repeat;
|
||||
impl->texture_color = color;
|
||||
}
|
||||
|
||||
void OpenGLVariable::set(const QImage &texture, bool repeat, bool color) {
|
||||
assert(type == TYPE_NONE or type == TYPE_TEXTURE_2D);
|
||||
|
||||
type = TYPE_TEXTURE_2D;
|
||||
impl->type = TYPE_TEXTURE_2D;
|
||||
|
||||
int sx = texture.width(), sy = texture.height();
|
||||
float *pixels = new float[sx * sy * 4];
|
||||
float *pixels = new float[to_size(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 = Color::from32BitRGBA(texture.pixel(x, y));
|
||||
pixel[0] = (float)col.r;
|
||||
pixel[1] = (float)col.g;
|
||||
pixel[2] = (float)col.b;
|
||||
pixel[3] = (float)col.a;
|
||||
pixel[0] = to_float(col.r);
|
||||
pixel[1] = to_float(col.g);
|
||||
pixel[2] = to_float(col.b);
|
||||
pixel[3] = to_float(col.a);
|
||||
}
|
||||
}
|
||||
|
||||
float *old_pixels = value_texture_data;
|
||||
value_texture_data = pixels;
|
||||
delete[] old_pixels;
|
||||
impl->value_array_float = unique_ptr<float[]>(pixels);
|
||||
|
||||
texture_size_x = sx;
|
||||
texture_size_y = sy;
|
||||
texture_size_z = 0;
|
||||
impl->texture_size_x = sx;
|
||||
impl->texture_size_y = sy;
|
||||
impl->texture_size_z = 0;
|
||||
|
||||
texture_toupload = true;
|
||||
texture_repeat = repeat;
|
||||
texture_color = color;
|
||||
impl->texture_toupload = true;
|
||||
impl->texture_repeat = repeat;
|
||||
impl->texture_color = color;
|
||||
}
|
||||
|
||||
void OpenGLVariable::set(const Texture3D *texture, bool repeat, bool color) {
|
||||
assert(type == TYPE_NONE or type == TYPE_TEXTURE_3D);
|
||||
|
||||
int sx, sy, sz;
|
||||
texture->getSize(&sx, &sy, &sz);
|
||||
float *pixels = new float[sx * sy * sz * 4];
|
||||
float *pixels = new float[to_size(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 = texture->getPixel(x, y, z);
|
||||
pixel[0] = (float)col.r;
|
||||
pixel[1] = (float)col.g;
|
||||
pixel[2] = (float)col.b;
|
||||
pixel[3] = (float)col.a;
|
||||
pixel[0] = to_float(col.r);
|
||||
pixel[1] = to_float(col.g);
|
||||
pixel[2] = to_float(col.b);
|
||||
pixel[3] = to_float(col.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float *old_pixels = value_texture_data;
|
||||
value_texture_data = pixels;
|
||||
delete[] old_pixels;
|
||||
impl->value_array_float = unique_ptr<float[]>(pixels);
|
||||
|
||||
texture_size_x = sx;
|
||||
texture_size_y = sy;
|
||||
texture_size_z = sz;
|
||||
impl->texture_size_x = sx;
|
||||
impl->texture_size_y = sy;
|
||||
impl->texture_size_z = sz;
|
||||
|
||||
type = TYPE_TEXTURE_3D;
|
||||
texture_toupload = true;
|
||||
texture_repeat = repeat;
|
||||
texture_color = color;
|
||||
impl->type = TYPE_TEXTURE_3D;
|
||||
impl->texture_toupload = true;
|
||||
impl->texture_repeat = repeat;
|
||||
impl->texture_color = color;
|
||||
}
|
||||
|
||||
void OpenGLVariable::set(const Texture4D *texture, bool repeat, bool color) {
|
||||
assert(type == TYPE_NONE or type == TYPE_TEXTURE_4D);
|
||||
|
||||
int sx, sy, sz, sw;
|
||||
texture->getSize(&sx, &sy, &sz, &sw);
|
||||
float *pixels = new float[sx * sy * sz * sw * 4];
|
||||
float *pixels = new float[to_size(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 = texture->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;
|
||||
pixel[0] = to_float(col.r);
|
||||
pixel[1] = to_float(col.g);
|
||||
pixel[2] = to_float(col.b);
|
||||
pixel[3] = to_float(col.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float *old_pixels = value_texture_data;
|
||||
value_texture_data = pixels;
|
||||
delete[] old_pixels;
|
||||
impl->value_array_float = unique_ptr<float[]>(pixels);
|
||||
|
||||
texture_size_x = sx;
|
||||
texture_size_y = sy;
|
||||
texture_size_z = sz * sw;
|
||||
impl->texture_size_x = sx;
|
||||
impl->texture_size_y = sy;
|
||||
impl->texture_size_z = sz * sw;
|
||||
|
||||
type = TYPE_TEXTURE_4D;
|
||||
texture_toupload = true;
|
||||
texture_repeat = repeat;
|
||||
texture_color = color;
|
||||
impl->type = TYPE_TEXTURE_4D;
|
||||
impl->texture_toupload = true;
|
||||
impl->texture_repeat = repeat;
|
||||
impl->texture_color = color;
|
||||
}
|
||||
|
||||
void OpenGLVariable::set(int value) {
|
||||
assert(type == TYPE_NONE or type == TYPE_INTEGER);
|
||||
|
||||
type = TYPE_INTEGER;
|
||||
value_int = value;
|
||||
impl->type = TYPE_INTEGER;
|
||||
impl->value_int = value;
|
||||
}
|
||||
|
||||
void OpenGLVariable::set(float value) {
|
||||
assert(type == TYPE_NONE or type == TYPE_FLOAT);
|
||||
|
||||
type = TYPE_FLOAT;
|
||||
value_float = value;
|
||||
impl->type = TYPE_FLOAT;
|
||||
impl->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;
|
||||
impl->type = TYPE_VECTOR3;
|
||||
impl->value_vector3 = make_unique<Vector3>(vector);
|
||||
}
|
||||
|
||||
void OpenGLVariable::set(const Matrix4 &matrix) {
|
||||
set(matrix.toQMatrix());
|
||||
}
|
||||
impl->type = TYPE_MATRIX4;
|
||||
|
||||
void OpenGLVariable::set(const QMatrix4x4 &matrix) {
|
||||
assert(type == TYPE_NONE or type == TYPE_MATRIX4);
|
||||
float *data = new float[16];
|
||||
data[0] = to_float(matrix.getA());
|
||||
data[1] = to_float(matrix.getB());
|
||||
data[2] = to_float(matrix.getC());
|
||||
data[3] = to_float(matrix.getD());
|
||||
data[4] = to_float(matrix.getE());
|
||||
data[5] = to_float(matrix.getF());
|
||||
data[6] = to_float(matrix.getG());
|
||||
data[7] = to_float(matrix.getH());
|
||||
data[8] = to_float(matrix.getI());
|
||||
data[9] = to_float(matrix.getJ());
|
||||
data[10] = to_float(matrix.getK());
|
||||
data[11] = to_float(matrix.getL());
|
||||
data[12] = to_float(matrix.getM());
|
||||
data[13] = to_float(matrix.getN());
|
||||
data[14] = to_float(matrix.getO());
|
||||
data[15] = to_float(matrix.getP());
|
||||
|
||||
type = TYPE_MATRIX4;
|
||||
*value_matrix4 = matrix;
|
||||
impl->value_array_float = unique_ptr<float[]>(data);
|
||||
}
|
||||
|
||||
void OpenGLVariable::set(const Color &color) {
|
||||
assert(type == TYPE_NONE or type == TYPE_COLOR);
|
||||
|
||||
type = TYPE_COLOR;
|
||||
*value_color = QColor::fromRgbF(color.r, color.g, color.b);
|
||||
impl->type = TYPE_COLOR;
|
||||
impl->value_color = make_unique<Color>(color);
|
||||
}
|
||||
|
||||
void OpenGLVariable::uploadTexture(OpenGLRenderer *renderer) {
|
||||
OpenGLFunctions *functions = renderer->getOpenGlFunctions();
|
||||
int OpenGLVariable::getIntValue() const {
|
||||
return impl->value_int;
|
||||
}
|
||||
|
||||
assert(type == TYPE_TEXTURE_2D or type == TYPE_TEXTURE_3D or type == TYPE_TEXTURE_4D);
|
||||
float OpenGLVariable::getFloatValue() const {
|
||||
return impl->value_float;
|
||||
}
|
||||
|
||||
if (texture_id == 0) {
|
||||
void OpenGLVariable::uploadTexture(OpenGLFunctions *functions) {
|
||||
assert(impl->type == TYPE_TEXTURE_2D or impl->type == TYPE_TEXTURE_3D or impl->type == TYPE_TEXTURE_4D);
|
||||
|
||||
if (impl->texture_id == 0) {
|
||||
GLuint texid;
|
||||
functions->glGenTextures(1, &texid);
|
||||
texture_id = texid;
|
||||
impl->texture_id = texid;
|
||||
}
|
||||
|
||||
GLenum textype = (type == TYPE_TEXTURE_2D) ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
||||
GLenum textype = (impl->type == TYPE_TEXTURE_2D) ? GL_TEXTURE_2D : GL_TEXTURE_3D;
|
||||
|
||||
functions->glBindTexture(textype, texture_id);
|
||||
functions->glBindTexture(textype, impl->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, texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
functions->glTexParameteri(textype, GL_TEXTURE_WRAP_T, texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
functions->glTexParameteri(textype, GL_TEXTURE_WRAP_S, impl->texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
functions->glTexParameteri(textype, GL_TEXTURE_WRAP_T, impl->texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
if (textype == GL_TEXTURE_3D) {
|
||||
functions->glTexParameteri(textype, GL_TEXTURE_WRAP_R, texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
functions->glTexParameteri(textype, GL_TEXTURE_WRAP_R, impl->texture_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
int dest_format = texture_color ? GL_RGBA : GL_RED;
|
||||
int dest_format = impl->texture_color ? GL_RGBA : GL_RED;
|
||||
|
||||
if (type == TYPE_TEXTURE_2D) {
|
||||
functions->glTexImage2D(GL_TEXTURE_2D, 0, dest_format, texture_size_x, texture_size_y, 0, GL_RGBA, GL_FLOAT,
|
||||
value_texture_data);
|
||||
if (impl->type == TYPE_TEXTURE_2D) {
|
||||
functions->glTexImage2D(GL_TEXTURE_2D, 0, dest_format, impl->texture_size_x, impl->texture_size_y, 0, GL_RGBA,
|
||||
GL_FLOAT, impl->value_array_float.get());
|
||||
} else {
|
||||
functions->glTexImage3D(GL_TEXTURE_3D, 0, dest_format, texture_size_x, texture_size_y, texture_size_z, 0,
|
||||
GL_RGBA, GL_FLOAT, value_texture_data);
|
||||
functions->glTexImage3D(GL_TEXTURE_3D, 0, dest_format, impl->texture_size_x, impl->texture_size_y,
|
||||
impl->texture_size_z, 0, GL_RGBA, GL_FLOAT, impl->value_array_float.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
|
||||
#include "opengl_global.h"
|
||||
|
||||
class QColor;
|
||||
class QVector3D;
|
||||
class QMatrix4x4;
|
||||
#include <memory>
|
||||
|
||||
class QImage;
|
||||
|
||||
namespace paysages {
|
||||
|
@ -14,7 +13,7 @@ namespace opengl {
|
|||
/*!
|
||||
* \brief OpenGL variable that can be bound to a uniform for shaders.
|
||||
*/
|
||||
class OpenGLVariable {
|
||||
class OpenGLVariable final {
|
||||
public:
|
||||
typedef enum {
|
||||
TYPE_NONE,
|
||||
|
@ -32,7 +31,14 @@ class OpenGLVariable {
|
|||
OpenGLVariable(const string &name);
|
||||
~OpenGLVariable();
|
||||
|
||||
void apply(OpenGLShaderProgram *program, int &texture_unit);
|
||||
/**
|
||||
* Apply the variable to the bound shader program.
|
||||
*
|
||||
* *texture_unit* will be used and updated accordingly.
|
||||
*
|
||||
* This must be called from the rendering thread, with the shader program bound.
|
||||
*/
|
||||
void apply(OpenGLShaderProgram *program, unsigned int &texture_unit);
|
||||
|
||||
/**
|
||||
* Release any allocated resource in the opengl context.
|
||||
|
@ -48,39 +54,18 @@ class OpenGLVariable {
|
|||
void set(int value);
|
||||
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);
|
||||
|
||||
inline int getIntValue() const {
|
||||
return value_int;
|
||||
}
|
||||
inline float getFloatValue() const {
|
||||
return value_float;
|
||||
}
|
||||
int getIntValue() const;
|
||||
float getFloatValue() const;
|
||||
|
||||
protected:
|
||||
void uploadTexture(OpenGLRenderer *renderer);
|
||||
void uploadTexture(OpenGLFunctions *renderer);
|
||||
|
||||
private:
|
||||
string name;
|
||||
OpenGLVariableType type;
|
||||
|
||||
int value_int;
|
||||
float value_float;
|
||||
QColor *value_color;
|
||||
QVector3D *value_vector3;
|
||||
QMatrix4x4 *value_matrix4;
|
||||
float *value_texture_data;
|
||||
|
||||
int texture_size_x;
|
||||
int texture_size_y;
|
||||
int texture_size_z;
|
||||
bool texture_toupload;
|
||||
bool texture_repeat;
|
||||
bool texture_color;
|
||||
unsigned int texture_id;
|
||||
class pimpl;
|
||||
unique_ptr<pimpl> impl;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ using namespace std;
|
|||
|
||||
// Some useful casts
|
||||
#define to_double(_x_) (static_cast<double>(_x_))
|
||||
#define to_float(_x_) (static_cast<float>(_x_))
|
||||
#define trunc_to_int(_x_) (static_cast<int>(_x_))
|
||||
#define round_to_int(_x_) (static_cast<int>(round(_x_)))
|
||||
#define floor_to_int(_x_) (static_cast<int>(floor(_x_)))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "CameraDefinition.h"
|
||||
|
||||
TEST(Camera, Definition) {
|
||||
TEST(CameraDefinition, constructor) {
|
||||
CameraDefinition cam;
|
||||
|
||||
cam.setLocationCoords(0.0, 1.0, 1.0);
|
||||
|
@ -12,14 +12,15 @@ TEST(Camera, Definition) {
|
|||
EXPECT_VECTOR3_COORDS(cam.getTarget(), 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
TEST(Camera, Projection) {
|
||||
TEST(CameraDefinition, unproject) {
|
||||
CameraDefinition cam;
|
||||
Vector3 point;
|
||||
|
||||
cam.setLocationCoords(0.0, 1.0, 1.0);
|
||||
cam.setTargetCoords(0.0, 0.0, 0.0);
|
||||
|
||||
/* Test the reversibility of projection */
|
||||
Vector3 point = cam.project(Vector3(12.0, 5.2, -6.3));
|
||||
// Test the reversibility of projection
|
||||
point = cam.project(Vector3(12.0, 5.2, -6.3));
|
||||
point = cam.unproject(point);
|
||||
EXPECT_VECTOR3_COORDS(point, 12.0, 5.2, -6.3);
|
||||
point = cam.project(Vector3(-25.1, 8.3, 1.3));
|
||||
|
@ -27,13 +28,13 @@ TEST(Camera, Projection) {
|
|||
EXPECT_VECTOR3_COORDS(point, -25.1, 8.3, 1.3);
|
||||
}
|
||||
|
||||
TEST(Camera, Depth) {
|
||||
TEST(CameraDefinition, getRealDepth) {
|
||||
CameraDefinition cam;
|
||||
|
||||
cam.setLocationCoords(0.0, 0.0, 0.0);
|
||||
cam.setTargetCoords(1.0, 0.0, 0.0);
|
||||
|
||||
/* Test the real depth getter */
|
||||
// Test the real depth getter
|
||||
Vector3 point = cam.project(Vector3(12.5, 0.0, 0.0));
|
||||
ASSERT_DOUBLE_EQ(cam.getRealDepth(point), 12.5);
|
||||
point = cam.project(Vector3(12.5, 8.0, -3.0));
|
Loading…
Reference in a new issue