paysages3d/src/render/opengl/OpenGLRenderer.cpp

244 lines
6.3 KiB
C++
Raw Normal View History

#include "OpenGLRenderer.h"
#include "OpenGLFunctions.h"
#include "CameraDefinition.h"
#include "OpenGLSharedState.h"
2013-12-21 22:48:54 +00:00
#include "OpenGLSkybox.h"
2013-12-21 23:41:19 +00:00
#include "OpenGLWater.h"
#include "OpenGLTerrain.h"
#include "CloudsRenderer.h"
#include "Color.h"
#include "Scenery.h"
#include "LightingManager.h"
#include "GodRaysSampler.h"
#include "Logs.h"
#include "Vector3.h"
OpenGLRenderer::OpenGLRenderer(Scenery *scenery) : SoftwareRenderer(scenery) {
2013-12-23 09:26:29 +00:00
ready = false;
paused = false;
2015-09-14 17:25:54 +00:00
displayed = false;
2014-08-27 16:19:48 +00:00
vp_width = 1;
vp_height = 1;
2013-12-23 09:26:29 +00:00
mouse_tracking = true;
mouse_x = 0;
mouse_y = 0;
mouse_projected = new Vector3();
view_matrix = new QMatrix4x4;
setQuality(0.3);
2013-12-23 09:26:29 +00:00
functions = new OpenGLFunctions();
shared_state = new OpenGLSharedState();
2013-12-24 14:00:32 +00:00
shared_state->set("viewDistance", 300.0);
2013-12-26 18:03:19 +00:00
shared_state->set("exposure", 1.2);
2013-12-21 22:48:54 +00:00
skybox = new OpenGLSkybox(this);
2013-12-21 23:41:19 +00:00
water = new OpenGLWater(this);
terrain = new OpenGLTerrain(this);
}
OpenGLRenderer::~OpenGLRenderer() {
terrain->interrupt();
water->interrupt();
skybox->interrupt();
delete mouse_projected;
delete view_matrix;
2013-12-21 22:48:54 +00:00
delete skybox;
2013-12-21 23:41:19 +00:00
delete water;
delete terrain;
delete functions;
delete shared_state;
}
void OpenGLRenderer::checkForErrors(const std::string &domain) {
int error_code;
while ((error_code = functions->glGetError()) != GL_NO_ERROR) {
Logs::warning() << "[OpenGL] Error in " << domain << " : " << error_code << std::endl;
}
}
void OpenGLRenderer::initialize() {
2013-12-23 09:26:29 +00:00
ready = functions->initializeOpenGLFunctions();
if (ready) {
Logs::debug() << "[OpenGL] renderer started (version " << functions->glGetString(GL_VERSION)
<< ", glsl version " << functions->glGetString(GL_SHADING_LANGUAGE_VERSION) << ")" << std::endl;
2014-08-27 16:19:48 +00:00
prepareOpenGLState();
2013-12-21 22:48:54 +00:00
2013-12-23 09:26:29 +00:00
prepare();
2013-12-21 22:48:54 +00:00
getCloudsRenderer()->setEnabled(false);
getLightingManager()->setSpecularity(false);
getGodRaysSampler()->setEnabled(false);
2013-12-24 14:00:32 +00:00
2013-12-23 09:26:29 +00:00
skybox->initialize();
skybox->updateScenery();
2013-12-21 23:41:19 +00:00
2013-12-23 09:26:29 +00:00
water->initialize();
water->updateScenery();
terrain->initialize();
terrain->updateScenery();
2015-08-18 20:47:18 +00:00
cameraChangeEvent(render_camera);
checkForErrors("initialize");
} else {
Logs::error() << "[OpenGL] Failed to initialize api bindings" << std::endl;
2013-12-23 09:26:29 +00:00
}
}
void OpenGLRenderer::prepareOpenGLState() {
if (ready) {
2014-08-27 16:19:48 +00:00
functions->glDisable(GL_LIGHTING);
functions->glFrontFace(GL_CCW);
functions->glCullFace(GL_BACK);
functions->glEnable(GL_CULL_FACE);
functions->glDepthFunc(GL_LESS);
functions->glDepthMask(1);
functions->glEnable(GL_DEPTH_TEST);
functions->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
functions->glEnable(GL_LINE_SMOOTH);
functions->glLineWidth(1.0);
functions->glDisable(GL_FOG);
functions->glEnable(GL_BLEND);
functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
functions->glClearColor(0.0, 0.0, 0.0, 0.0);
functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
functions->glViewport(0, 0, vp_width, vp_height);
2013-12-23 09:26:29 +00:00
}
2014-08-27 16:19:48 +00:00
}
void OpenGLRenderer::setCamera(CameraDefinition *camera) {
camera->copy(render_camera);
2015-08-18 20:47:18 +00:00
getScenery()->keepCameraAboveGround(render_camera);
render_camera->setRenderSize(vp_width, vp_height);
2015-08-18 20:47:18 +00:00
cameraChangeEvent(render_camera);
}
void OpenGLRenderer::resize(int width, int height) {
if (ready) {
vp_width = width;
vp_height = height;
render_camera->setRenderSize(width, height);
cameraChangeEvent(render_camera);
2014-08-27 16:19:48 +00:00
prepareOpenGLState();
checkForErrors("resize");
}
}
void OpenGLRenderer::paint() {
if (ready and not paused) {
checkForErrors("before_paint");
2013-12-23 09:26:29 +00:00
functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
skybox->render();
checkForErrors("skybox");
terrain->render();
checkForErrors("terrain");
2013-12-23 09:26:29 +00:00
water->render();
checkForErrors("water");
if (mouse_tracking) {
updateMouseProjection();
checkForErrors("mouse_tracking");
}
2015-09-14 17:25:54 +00:00
displayed = true;
2013-12-23 09:26:29 +00:00
}
2013-12-21 22:48:54 +00:00
}
void OpenGLRenderer::reset() {
if (ready) {
skybox->updateScenery();
water->updateScenery();
terrain->updateScenery();
cameraChangeEvent(render_camera);
}
}
void OpenGLRenderer::pause() {
paused = true;
terrain->pause();
}
void OpenGLRenderer::resume() {
paused = false;
terrain->resume();
}
void OpenGLRenderer::setMouseLocation(int x, int y) {
mouse_x = x;
mouse_y = y;
}
const Vector3 &OpenGLRenderer::getMouseProjection() {
return *mouse_projected;
}
void OpenGLRenderer::cameraChangeEvent(CameraDefinition *camera) {
2013-12-22 16:30:48 +00:00
// 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));
2013-12-22 16:30:48 +00:00
QMatrix4x4 projection;
projection.setToIdentity();
projection.perspective(perspective.yfov * 180.0 / M_PI, perspective.xratio, perspective.znear, perspective.zfar);
*view_matrix = projection *transform;
2013-12-22 16:30:48 +00:00
// Set in shaders
shared_state->set("cameraLocation", location);
shared_state->set("viewMatrix", *view_matrix);
}
2013-12-15 14:06:43 +00:00
double OpenGLRenderer::getPrecision(const Vector3 &) {
return 0.0000001;
}
Color OpenGLRenderer::applyMediumTraversal(const Vector3 &, const Color &color) {
2013-12-15 14:06:43 +00:00
return color;
}
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 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());
shared_state->set("mouseProjection", *mouse_projected);
}