Move deferred lighting into its own class.

This commit is contained in:
Andrzej Kapolka 2014-09-11 16:39:17 -07:00
parent 1c50b32400
commit c2b58c9781
6 changed files with 219 additions and 172 deletions

View file

@ -1735,6 +1735,7 @@ void Application::init() {
_environment.init();
_deferredLightingEffect.init();
_glowEffect.init();
_ambientOcclusionEffect.init();
_voxelShader.init();
@ -2842,11 +2843,13 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
}
// Draw voxels
bool deferredLightingRequired = false;
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
PerformanceTimer perfTimer("voxels");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... voxels...");
_voxels.render();
deferredLightingRequired = true;
}
// also, metavoxels
@ -2855,6 +2858,11 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... metavoxels...");
_metavoxels.render();
deferredLightingRequired = true;
}
if (deferredLightingRequired) {
_deferredLightingEffect.render();
}
if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {

View file

@ -68,6 +68,7 @@
#include "entities/EntityTreeRenderer.h"
#include "particles/ParticleTreeRenderer.h"
#include "renderer/AmbientOcclusionEffect.h"
#include "renderer/DeferredLightingEffect.h"
#include "renderer/GeometryCache.h"
#include "renderer/GlowEffect.h"
#include "renderer/PointShader.h"
@ -556,6 +557,7 @@ private:
AnimationCache _animationCache;
TextureCache _textureCache;
DeferredLightingEffect _deferredLightingEffect;
GlowEffect _glowEffect;
AmbientOcclusionEffect _ambientOcclusionEffect;
VoxelShader _voxelShader;

View file

@ -51,12 +51,6 @@ void MetavoxelSystem::init() {
new BufferDataAttribute("voxelBuffer"));
_voxelBufferAttribute->setLODThresholdMultiplier(
AttributeRegistry::getInstance()->getVoxelColorAttribute()->getLODThresholdMultiplier());
loadLightProgram("shaders/directional_light.frag", _directionalLight, _directionalLightLocations);
loadLightProgram("shaders/directional_light_shadow_map.frag", _directionalLightShadowMap,
_directionalLightShadowMapLocations);
loadLightProgram("shaders/directional_light_cascaded_shadow_map.frag", _directionalLightCascadedShadowMap,
_directionalLightCascadedShadowMapLocations);
}
MetavoxelLOD MetavoxelSystem::getLOD() {
@ -138,8 +132,6 @@ void MetavoxelSystem::render() {
viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(),
viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight());
_needToLight = false;
// clear the normal buffer
glDrawBuffers(sizeof(NORMAL_DRAW_BUFFERS) / sizeof(NORMAL_DRAW_BUFFERS[0]), NORMAL_DRAW_BUFFERS);
glClear(GL_COLOR_BUFFER_BIT);
@ -151,126 +143,6 @@ void MetavoxelSystem::render() {
// give external parties a chance to join in
emit rendering();
if (!_needToLight) {
return; // skip lighting if not needed
}
// perform deferred lighting, rendering to free fbo
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glDisable(GL_BLEND);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();
primaryFBO->release();
QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject();
freeFBO->bind();
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, primaryFBO->texture());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryNormalTextureID());
// get the viewport side (left, right, both)
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
const int VIEWPORT_X_INDEX = 0;
const int VIEWPORT_WIDTH_INDEX = 2;
float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width();
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width();
if (Menu::getInstance()->getShadowsEnabled()) {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID());
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID());
ProgramObject* program = &_directionalLightShadowMap;
const LightLocations* locations = &_directionalLightShadowMapLocations;
if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
program = &_directionalLightCascadedShadowMap;
locations = &_directionalLightCascadedShadowMapLocations;
_directionalLightCascadedShadowMap.bind();
_directionalLightCascadedShadowMap.setUniform(locations->shadowDistances,
Application::getInstance()->getShadowDistances());
} else {
program->bind();
}
program->setUniformValue(locations->shadowScale,
1.0f / Application::getInstance()->getTextureCache()->getShadowFramebufferObject()->width());
float left, right, bottom, top, nearVal, farVal;
glm::vec4 nearClipPlane, farClipPlane;
Application::getInstance()->computeOffAxisFrustum(
left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
program->setUniformValue(locations->nearLocation, nearVal);
program->setUniformValue(locations->depthScale, (farVal - nearVal) / farVal);
float nearScale = -1.0f / nearVal;
float sScale = 1.0f / sWidth;
float depthTexCoordScaleS = (right - left) * nearScale * sScale;
program->setUniformValue(locations->depthTexCoordOffset, left * nearScale - sMin * depthTexCoordScaleS,
bottom * nearScale);
program->setUniformValue(locations->depthTexCoordScale, depthTexCoordScaleS, (top - bottom) * nearScale);
renderFullscreenQuad(sMin, sMin + sWidth);
program->release();
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1);
} else {
_directionalLight.bind();
renderFullscreenQuad(sMin, sMin + sWidth);
_directionalLight.release();
}
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
freeFBO->release();
// now transfer the lit region to the primary fbo
glEnable(GL_BLEND);
primaryFBO->bind();
glBindTexture(GL_TEXTURE_2D, freeFBO->texture());
glEnable(GL_TEXTURE_2D);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
renderFullscreenQuad(sMin, sMin + sWidth);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
glDisable(GL_ALPHA_TEST);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
class RayHeightfieldIntersectionVisitor : public RayIntersectionVisitor {
@ -630,24 +502,6 @@ void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) {
}
}
void MetavoxelSystem::loadLightProgram(const char* name, ProgramObject& program, LightLocations& locations) {
program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + name);
program.link();
program.bind();
program.setUniformValue("diffuseMap", 0);
program.setUniformValue("normalMap", 1);
program.setUniformValue("depthMap", 2);
program.setUniformValue("shadowMap", 3);
locations.shadowDistances = program.uniformLocation("shadowDistances");
locations.shadowScale = program.uniformLocation("shadowScale");
locations.nearLocation = program.uniformLocation("near");
locations.depthScale = program.uniformLocation("depthScale");
locations.depthTexCoordOffset = program.uniformLocation("depthTexCoordOffset");
locations.depthTexCoordScale = program.uniformLocation("depthTexCoordScale");
program.release();
}
MetavoxelSystemClient::MetavoxelSystemClient(const SharedNodePointer& node, MetavoxelUpdater* updater) :
MetavoxelClient(node, updater) {
}
@ -1077,8 +931,6 @@ void HeightfieldBuffer::render(bool cursor) {
bufferPair.first.release();
bufferPair.second.release();
Application::getInstance()->getMetavoxels()->noteNeedToLight();
}
QHash<int, HeightfieldBuffer::BufferPair> HeightfieldBuffer::_bufferPairs;
@ -1245,8 +1097,6 @@ void VoxelBuffer::render(bool cursor) {
_vertexBuffer.release();
_indexBuffer.release();
Application::getInstance()->getMetavoxels()->noteNeedToLight();
}
BufferDataAttribute::BufferDataAttribute(const QString& name) :

View file

@ -52,8 +52,6 @@ public:
Q_INVOKABLE void deleteTextures(int heightID, int colorID, int textureID);
void noteNeedToLight() { _needToLight = true; }
signals:
void rendering();
@ -66,18 +64,6 @@ private:
void guideToAugmented(MetavoxelVisitor& visitor, bool render = false);
class LightLocations {
public:
int shadowDistances;
int shadowScale;
int nearLocation;
int depthScale;
int depthTexCoordOffset;
int depthTexCoordScale;
};
static void loadLightProgram(const char* name, ProgramObject& program, LightLocations& locations);
AttributePointer _pointBufferAttribute;
AttributePointer _heightfieldBufferAttribute;
AttributePointer _voxelBufferAttribute;
@ -85,14 +71,6 @@ private:
MetavoxelLOD _lod;
QReadWriteLock _lodLock;
Frustum _frustum;
bool _needToLight;
ProgramObject _directionalLight;
LightLocations _directionalLightLocations;
ProgramObject _directionalLightShadowMap;
LightLocations _directionalLightShadowMapLocations;
ProgramObject _directionalLightCascadedShadowMap;
LightLocations _directionalLightCascadedShadowMapLocations;
};
/// Describes contents of a point in a point buffer.

View file

@ -0,0 +1,163 @@
//
// DeferredLightingEffect.cpp
// interface/src/renderer
//
// Created by Andrzej Kapolka on 9/11/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <QOpenGLFramebufferObject>
#include "Application.h"
#include "DeferredLightingEffect.h"
#include "RenderUtil.h"
void DeferredLightingEffect::init() {
loadLightProgram("shaders/directional_light.frag", _directionalLight, _directionalLightLocations);
loadLightProgram("shaders/directional_light_shadow_map.frag", _directionalLightShadowMap,
_directionalLightShadowMapLocations);
loadLightProgram("shaders/directional_light_cascaded_shadow_map.frag", _directionalLightCascadedShadowMap,
_directionalLightCascadedShadowMapLocations);
}
void DeferredLightingEffect::render() {
// perform deferred lighting, rendering to free fbo
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glDisable(GL_BLEND);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();
primaryFBO->release();
QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject();
freeFBO->bind();
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, primaryFBO->texture());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryNormalTextureID());
// get the viewport side (left, right, both)
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
const int VIEWPORT_X_INDEX = 0;
const int VIEWPORT_WIDTH_INDEX = 2;
float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width();
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width();
if (Menu::getInstance()->getShadowsEnabled()) {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID());
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID());
ProgramObject* program = &_directionalLightShadowMap;
const LightLocations* locations = &_directionalLightShadowMapLocations;
if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
program = &_directionalLightCascadedShadowMap;
locations = &_directionalLightCascadedShadowMapLocations;
_directionalLightCascadedShadowMap.bind();
_directionalLightCascadedShadowMap.setUniform(locations->shadowDistances,
Application::getInstance()->getShadowDistances());
} else {
program->bind();
}
program->setUniformValue(locations->shadowScale,
1.0f / Application::getInstance()->getTextureCache()->getShadowFramebufferObject()->width());
float left, right, bottom, top, nearVal, farVal;
glm::vec4 nearClipPlane, farClipPlane;
Application::getInstance()->computeOffAxisFrustum(
left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
program->setUniformValue(locations->nearLocation, nearVal);
program->setUniformValue(locations->depthScale, (farVal - nearVal) / farVal);
float nearScale = -1.0f / nearVal;
float sScale = 1.0f / sWidth;
float depthTexCoordScaleS = (right - left) * nearScale * sScale;
program->setUniformValue(locations->depthTexCoordOffset, left * nearScale - sMin * depthTexCoordScaleS,
bottom * nearScale);
program->setUniformValue(locations->depthTexCoordScale, depthTexCoordScaleS, (top - bottom) * nearScale);
renderFullscreenQuad(sMin, sMin + sWidth);
program->release();
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1);
} else {
_directionalLight.bind();
renderFullscreenQuad(sMin, sMin + sWidth);
_directionalLight.release();
}
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
freeFBO->release();
// now transfer the lit region to the primary fbo
glEnable(GL_BLEND);
primaryFBO->bind();
glBindTexture(GL_TEXTURE_2D, freeFBO->texture());
glEnable(GL_TEXTURE_2D);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
renderFullscreenQuad(sMin, sMin + sWidth);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
glDisable(GL_ALPHA_TEST);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
void DeferredLightingEffect::loadLightProgram(const char* name, ProgramObject& program, LightLocations& locations) {
program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + name);
program.link();
program.bind();
program.setUniformValue("diffuseMap", 0);
program.setUniformValue("normalMap", 1);
program.setUniformValue("depthMap", 2);
program.setUniformValue("shadowMap", 3);
locations.shadowDistances = program.uniformLocation("shadowDistances");
locations.shadowScale = program.uniformLocation("shadowScale");
locations.nearLocation = program.uniformLocation("near");
locations.depthScale = program.uniformLocation("depthScale");
locations.depthTexCoordOffset = program.uniformLocation("depthTexCoordOffset");
locations.depthTexCoordScale = program.uniformLocation("depthTexCoordScale");
program.release();
}

View file

@ -0,0 +1,46 @@
//
// DeferredLightingEffect.h
// interface/src/renderer
//
// Created by Andrzej Kapolka on 9/11/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_DeferredLightingEffect_h
#define hifi_DeferredLightingEffect_h
#include "ProgramObject.h"
/// Handles deferred lighting for the bits that require it (voxels, metavoxels...)
class DeferredLightingEffect {
public:
void init();
void render();
private:
class LightLocations {
public:
int shadowDistances;
int shadowScale;
int nearLocation;
int depthScale;
int depthTexCoordOffset;
int depthTexCoordScale;
};
static void loadLightProgram(const char* name, ProgramObject& program, LightLocations& locations);
ProgramObject _directionalLight;
LightLocations _directionalLightLocations;
ProgramObject _directionalLightShadowMap;
LightLocations _directionalLightShadowMapLocations;
ProgramObject _directionalLightCascadedShadowMap;
LightLocations _directionalLightCascadedShadowMapLocations;
};
#endif // hifi_DeferredLightingEffect_h