mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 11:45:36 +02:00
Merge pull request #865 from ey6es/ssao
Basic screen space ambient occlusion effect. Defaults to off, because at the moment it slows things down substantially.
This commit is contained in:
commit
d0ab8317c4
14 changed files with 382 additions and 17 deletions
66
interface/resources/shaders/ambient_occlusion.frag
Normal file
66
interface/resources/shaders/ambient_occlusion.frag
Normal file
|
@ -0,0 +1,66 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// ambient_occlusion.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 7/5/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
// the depth texture
|
||||
uniform sampler2D depthTexture;
|
||||
|
||||
// the random rotation texture
|
||||
uniform sampler2D rotationTexture;
|
||||
|
||||
// the sample kernel containing the unit offset vectors
|
||||
const int SAMPLE_KERNEL_SIZE = 16;
|
||||
uniform vec3 sampleKernel[SAMPLE_KERNEL_SIZE];
|
||||
|
||||
// the distance to the near clip plane
|
||||
uniform float near;
|
||||
|
||||
// the distance to the far clip plane
|
||||
uniform float far;
|
||||
|
||||
// the left and bottom edges of the view window
|
||||
uniform vec2 leftBottom;
|
||||
|
||||
// the right and top edges of the view window
|
||||
uniform vec2 rightTop;
|
||||
|
||||
// the radius of the effect
|
||||
uniform float radius;
|
||||
|
||||
// the scale for the noise texture
|
||||
uniform vec2 noiseScale;
|
||||
|
||||
// given a texture coordinate, returns the 3D view space z coordinate
|
||||
float texCoordToViewSpaceZ(vec2 texCoord) {
|
||||
return (far * near) / (texture2D(depthTexture, texCoord).r * (far - near) - far);
|
||||
}
|
||||
|
||||
// given a texture coordinate, returns the 3D view space coordinate
|
||||
vec3 texCoordToViewSpace(vec2 texCoord) {
|
||||
float z = texCoordToViewSpaceZ(texCoord);
|
||||
return vec3(((texCoord * 2.0 - vec2(1.0, 1.0)) * (rightTop - leftBottom) + rightTop + leftBottom) * z / (-2.0 * near), z);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
vec3 rotationX = texture2D(rotationTexture, gl_TexCoord[0].st * noiseScale).rgb;
|
||||
vec3 rotationY = normalize(cross(rotationX, vec3(0.0, 0.0, 1.0)));
|
||||
mat3 rotation = mat3(rotationX, rotationY, cross(rotationX, rotationY));
|
||||
|
||||
vec3 center = texCoordToViewSpace(gl_TexCoord[0].st);
|
||||
|
||||
float occlusion = 4.0;
|
||||
for (int i = 0; i < SAMPLE_KERNEL_SIZE; i++) {
|
||||
vec3 offset = center + rotation * (radius * sampleKernel[i]);
|
||||
vec4 projected = gl_ProjectionMatrix * vec4(offset, 1.0);
|
||||
float depth = texCoordToViewSpaceZ(projected.xy * 0.5 / projected.w + vec2(0.5, 0.5));
|
||||
occlusion += 1.0 - step(offset.z, depth); // * step(abs(center.z - depth), radius);
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(occlusion, occlusion, occlusion, 0.0) / 16.0;
|
||||
}
|
14
interface/resources/shaders/ambient_occlusion.vert
Normal file
14
interface/resources/shaders/ambient_occlusion.vert
Normal file
|
@ -0,0 +1,14 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// ambient_occlusion.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 8/16/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
void main(void) {
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = gl_Vertex;
|
||||
}
|
25
interface/resources/shaders/occlusion_blur.frag
Normal file
25
interface/resources/shaders/occlusion_blur.frag
Normal file
|
@ -0,0 +1,25 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// occlusion_blur.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 8/16/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
// the original texture
|
||||
uniform sampler2D originalTexture;
|
||||
|
||||
void main(void) {
|
||||
float ds = dFdx(gl_TexCoord[0].s);
|
||||
float dt = dFdy(gl_TexCoord[0].t);
|
||||
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
sum += texture2D(originalTexture, gl_TexCoord[0].st +
|
||||
vec2(ds, dt) * vec2(-2.0 + float(i), -2.0 + float(j)));
|
||||
}
|
||||
}
|
||||
gl_FragColor = sum / 16.0;
|
||||
}
|
|
@ -1449,6 +1449,7 @@ void Application::init() {
|
|||
_environment.init();
|
||||
|
||||
_glowEffect.init();
|
||||
_ambientOcclusionEffect.init();
|
||||
|
||||
_handControl.setScreenDimensions(_glWidget->width(), _glWidget->height());
|
||||
|
||||
|
@ -2375,6 +2376,11 @@ void Application::displaySide(Camera& whichCamera) {
|
|||
renderWorldBox();
|
||||
}
|
||||
|
||||
// render the ambient occlusion effect if enabled
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) {
|
||||
_ambientOcclusionEffect.render();
|
||||
}
|
||||
|
||||
// brad's frustum for debugging
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum)) {
|
||||
renderViewFrustum(_viewFrustum);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "Environment.h"
|
||||
#include "GLCanvas.h"
|
||||
#include "PacketHeaders.h"
|
||||
#include "PieMenu.h"
|
||||
#include "SerialInterface.h"
|
||||
#include "Stars.h"
|
||||
#include "Swatch.h"
|
||||
|
@ -42,9 +43,9 @@
|
|||
#include "VoxelPacketProcessor.h"
|
||||
#include "VoxelSystem.h"
|
||||
#include "Webcam.h"
|
||||
#include "PieMenu.h"
|
||||
#include "avatar/Avatar.h"
|
||||
#include "avatar/HandControl.h"
|
||||
#include "renderer/AmbientOcclusionEffect.h"
|
||||
#include "renderer/GeometryCache.h"
|
||||
#include "renderer/GlowEffect.h"
|
||||
#include "renderer/TextureCache.h"
|
||||
|
@ -314,6 +315,7 @@ private:
|
|||
TextureCache _textureCache;
|
||||
|
||||
GlowEffect _glowEffect;
|
||||
AmbientOcclusionEffect _ambientOcclusionEffect;
|
||||
|
||||
#ifndef _WIN32
|
||||
Audio _audio;
|
||||
|
|
|
@ -163,6 +163,7 @@ Menu::Menu() :
|
|||
appInstance->getGlowEffect(),
|
||||
SLOT(cycleRenderMode()));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::AmbientOcclusion);
|
||||
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::FrameTimer);
|
||||
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtVectors);
|
||||
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtIndicator, 0, true);
|
||||
|
|
|
@ -108,6 +108,7 @@ private:
|
|||
|
||||
namespace MenuOption {
|
||||
|
||||
const QString AmbientOcclusion = "Ambient Occlusion";
|
||||
const QString Avatars = "Avatars";
|
||||
const QString AvatarAsBalls = "Avatar as Balls";
|
||||
const QString Atmosphere = "Atmosphere";
|
||||
|
|
145
interface/src/renderer/AmbientOcclusionEffect.cpp
Normal file
145
interface/src/renderer/AmbientOcclusionEffect.cpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
//
|
||||
// AmbientOcclusionEffect.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 7/14/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QOpenGLFramebufferObject>
|
||||
|
||||
#include <glm/gtc/random.hpp>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "AmbientOcclusionEffect.h"
|
||||
#include "Application.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "ProgramObject.h"
|
||||
#include "RenderUtil.h"
|
||||
|
||||
const int ROTATION_WIDTH = 4;
|
||||
const int ROTATION_HEIGHT = 4;
|
||||
|
||||
void AmbientOcclusionEffect::init() {
|
||||
switchToResourcesParentIfRequired();
|
||||
|
||||
_occlusionProgram = new ProgramObject();
|
||||
_occlusionProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/ambient_occlusion.vert");
|
||||
_occlusionProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/ambient_occlusion.frag");
|
||||
_occlusionProgram->link();
|
||||
|
||||
_blurProgram = new ProgramObject();
|
||||
_blurProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/ambient_occlusion.vert");
|
||||
_blurProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/occlusion_blur.frag");
|
||||
_blurProgram->link();
|
||||
|
||||
_blurProgram->bind();
|
||||
_blurProgram->setUniformValue("originalTexture", 0);
|
||||
_blurProgram->release();
|
||||
|
||||
// create the sample kernel: an array of spherically distributed offset vectors
|
||||
const int SAMPLE_KERNEL_SIZE = 16;
|
||||
QVector3D sampleKernel[SAMPLE_KERNEL_SIZE];
|
||||
for (int i = 0; i < SAMPLE_KERNEL_SIZE; i++) {
|
||||
// square the length in order to increase density towards the center
|
||||
glm::vec3 vector = glm::sphericalRand(1.0f);
|
||||
float scale = randFloat();
|
||||
const float MIN_VECTOR_LENGTH = 0.01f;
|
||||
const float MAX_VECTOR_LENGTH = 1.0f;
|
||||
vector *= glm::mix(MIN_VECTOR_LENGTH, MAX_VECTOR_LENGTH, scale * scale);
|
||||
sampleKernel[i] = QVector3D(vector.x, vector.y, vector.z);
|
||||
}
|
||||
|
||||
_occlusionProgram->bind();
|
||||
_occlusionProgram->setUniformValue("depthTexture", 0);
|
||||
_occlusionProgram->setUniformValue("rotationTexture", 1);
|
||||
_occlusionProgram->setUniformValueArray("sampleKernel", sampleKernel, SAMPLE_KERNEL_SIZE);
|
||||
_occlusionProgram->setUniformValue("radius", 0.1f);
|
||||
_occlusionProgram->release();
|
||||
|
||||
_nearLocation = _occlusionProgram->uniformLocation("near");
|
||||
_farLocation = _occlusionProgram->uniformLocation("far");
|
||||
_leftBottomLocation = _occlusionProgram->uniformLocation("leftBottom");
|
||||
_rightTopLocation = _occlusionProgram->uniformLocation("rightTop");
|
||||
_noiseScaleLocation = _occlusionProgram->uniformLocation("noiseScale");
|
||||
|
||||
// generate the random rotation texture
|
||||
glGenTextures(1, &_rotationTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _rotationTextureID);
|
||||
const int ELEMENTS_PER_PIXEL = 3;
|
||||
unsigned char rotationData[ROTATION_WIDTH * ROTATION_HEIGHT * ELEMENTS_PER_PIXEL];
|
||||
unsigned char* rotation = rotationData;
|
||||
for (int i = 0; i < ROTATION_WIDTH * ROTATION_HEIGHT; i++) {
|
||||
glm::vec3 randvec = glm::sphericalRand(1.0f);
|
||||
*rotation++ = ((randvec.x + 1.0f) / 2.0f) * 255.0f;
|
||||
*rotation++ = ((randvec.y + 1.0f) / 2.0f) * 255.0f;
|
||||
*rotation++ = ((randvec.z + 1.0f) / 2.0f) * 255.0f;
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ROTATION_WIDTH, ROTATION_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, rotationData);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffect::render() {
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID());
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, _rotationTextureID);
|
||||
|
||||
// render with the occlusion shader to the secondary buffer
|
||||
QOpenGLFramebufferObject* secondaryFBO = Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject();
|
||||
secondaryFBO->bind();
|
||||
|
||||
float left, right, bottom, top, nearVal, farVal;
|
||||
glm::vec4 nearClipPlane, farClipPlane;
|
||||
Application::getInstance()->getViewFrustum()->computeOffAxisFrustum(
|
||||
left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||
|
||||
_occlusionProgram->bind();
|
||||
_occlusionProgram->setUniformValue(_nearLocation, nearVal);
|
||||
_occlusionProgram->setUniformValue(_farLocation, farVal);
|
||||
_occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom);
|
||||
_occlusionProgram->setUniformValue(_rightTopLocation, right, top);
|
||||
QSize size = Application::getInstance()->getGLWidget()->size();
|
||||
_occlusionProgram->setUniformValue(_noiseScaleLocation, size.width() / (float)ROTATION_WIDTH,
|
||||
size.height() / (float)ROTATION_HEIGHT);
|
||||
|
||||
renderFullscreenQuad();
|
||||
|
||||
_occlusionProgram->release();
|
||||
|
||||
secondaryFBO->release();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// now render secondary to primary with 4x4 blur
|
||||
Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture());
|
||||
|
||||
_blurProgram->bind();
|
||||
|
||||
renderFullscreenQuad();
|
||||
|
||||
_blurProgram->release();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
//glEnable(GL_BLEND);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
39
interface/src/renderer/AmbientOcclusionEffect.h
Normal file
39
interface/src/renderer/AmbientOcclusionEffect.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// AmbientOcclusionEffect.h
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 7/14/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__AmbientOcclusionEffect__
|
||||
#define __interface__AmbientOcclusionEffect__
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
class ProgramObject;
|
||||
|
||||
/// A screen space ambient occlusion effect. See John Chapman's tutorial at
|
||||
/// http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html for reference.
|
||||
class AmbientOcclusionEffect {
|
||||
public:
|
||||
|
||||
void init();
|
||||
|
||||
void render();
|
||||
|
||||
private:
|
||||
|
||||
ProgramObject* _occlusionProgram;
|
||||
int _nearLocation;
|
||||
int _farLocation;
|
||||
int _leftBottomLocation;
|
||||
int _rightTopLocation;
|
||||
int _noiseScaleLocation;
|
||||
|
||||
ProgramObject* _blurProgram;
|
||||
|
||||
GLuint _rotationTextureID;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__AmbientOcclusionEffect__) */
|
|
@ -5,7 +5,7 @@
|
|||
// Created by Andrzej Kapolka on 8/7/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QOpenGLFramebufferObject>
|
||||
|
@ -13,6 +13,7 @@
|
|||
#include "Application.h"
|
||||
#include "GlowEffect.h"
|
||||
#include "ProgramObject.h"
|
||||
#include "RenderUtil.h"
|
||||
|
||||
GlowEffect::GlowEffect() : _renderMode(BLUR_ADD_MODE) {
|
||||
}
|
||||
|
@ -68,19 +69,6 @@ void GlowEffect::end() {
|
|||
glBlendColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
static void renderFullscreenQuad() {
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0f, 0.0f);
|
||||
glVertex2f(-1.0f, -1.0f);
|
||||
glTexCoord2f(1.0f, 0.0f);
|
||||
glVertex2f(1.0f, -1.0f);
|
||||
glTexCoord2f(1.0f, 1.0f);
|
||||
glVertex2f(1.0f, 1.0f);
|
||||
glTexCoord2f(0.0f, 1.0f);
|
||||
glVertex2f(-1.0f, 1.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void GlowEffect::render() {
|
||||
QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();
|
||||
primaryFBO->release();
|
||||
|
@ -95,6 +83,7 @@ void GlowEffect::render() {
|
|||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
if (_isEmpty) {
|
||||
// copy the primary to the screen
|
||||
|
@ -210,6 +199,7 @@ void GlowEffect::render() {
|
|||
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
|
|
22
interface/src/renderer/RenderUtil.cpp
Normal file
22
interface/src/renderer/RenderUtil.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// RenderUtil.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 8/15/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include "RenderUtil.h"
|
||||
|
||||
void renderFullscreenQuad() {
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0f, 0.0f);
|
||||
glVertex2f(-1.0f, -1.0f);
|
||||
glTexCoord2f(1.0f, 0.0f);
|
||||
glVertex2f(1.0f, -1.0f);
|
||||
glTexCoord2f(1.0f, 1.0f);
|
||||
glVertex2f(1.0f, 1.0f);
|
||||
glTexCoord2f(0.0f, 1.0f);
|
||||
glVertex2f(-1.0f, 1.0f);
|
||||
glEnd();
|
||||
}
|
15
interface/src/renderer/RenderUtil.h
Normal file
15
interface/src/renderer/RenderUtil.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// RenderUtil.h
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 8/15/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__RenderUtil__
|
||||
#define __interface__RenderUtil__
|
||||
|
||||
/// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (0, 0) to (1, 1).
|
||||
void renderFullscreenQuad();
|
||||
|
||||
#endif /* defined(__interface__RenderUtil__) */
|
|
@ -5,6 +5,9 @@
|
|||
// Created by Andrzej Kapolka on 8/6/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QGLWidget>
|
||||
#include <QOpenGLFramebufferObject>
|
||||
|
||||
|
@ -23,6 +26,7 @@ TextureCache::~TextureCache() {
|
|||
}
|
||||
if (_primaryFramebufferObject != NULL) {
|
||||
delete _primaryFramebufferObject;
|
||||
glDeleteTextures(1, &_primaryDepthTextureID);
|
||||
}
|
||||
if (_secondaryFramebufferObject != NULL) {
|
||||
delete _secondaryFramebufferObject;
|
||||
|
@ -60,13 +64,31 @@ GLuint TextureCache::getPermutationNormalTextureID() {
|
|||
|
||||
QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() {
|
||||
if (_primaryFramebufferObject == NULL) {
|
||||
_primaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size(),
|
||||
QOpenGLFramebufferObject::Depth);
|
||||
QSize size = Application::getInstance()->getGLWidget()->size();
|
||||
_primaryFramebufferObject = new QOpenGLFramebufferObject(size);
|
||||
Application::getInstance()->getGLWidget()->installEventFilter(this);
|
||||
|
||||
glGenTextures(1, &_primaryDepthTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _primaryDepthTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width(), size.height(),
|
||||
0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
_primaryFramebufferObject->bind();
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _primaryDepthTextureID, 0);
|
||||
_primaryFramebufferObject->release();
|
||||
}
|
||||
return _primaryFramebufferObject;
|
||||
}
|
||||
|
||||
GLuint TextureCache::getPrimaryDepthTextureID() {
|
||||
// ensure that the primary framebuffer object is initialized before returning the depth texture id
|
||||
getPrimaryFramebufferObject();
|
||||
return _primaryDepthTextureID;
|
||||
}
|
||||
|
||||
QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() {
|
||||
if (_secondaryFramebufferObject == NULL) {
|
||||
_secondaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size());
|
||||
|
@ -89,6 +111,7 @@ bool TextureCache::eventFilter(QObject* watched, QEvent* event) {
|
|||
if (_primaryFramebufferObject != NULL && _primaryFramebufferObject->size() != size) {
|
||||
delete _primaryFramebufferObject;
|
||||
_primaryFramebufferObject = NULL;
|
||||
glDeleteTextures(1, &_primaryDepthTextureID);
|
||||
}
|
||||
if (_secondaryFramebufferObject != NULL && _secondaryFramebufferObject->size() != size) {
|
||||
delete _secondaryFramebufferObject;
|
||||
|
|
|
@ -15,16 +15,31 @@
|
|||
|
||||
class QOpenGLFramebufferObject;
|
||||
|
||||
/// Stored cached textures, including render-to-texture targets.
|
||||
class TextureCache : public QObject {
|
||||
public:
|
||||
|
||||
TextureCache();
|
||||
~TextureCache();
|
||||
|
||||
/// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture
|
||||
/// has two lines: the first, a set of random numbers in [0, 255] to be used as permutation offsets, and
|
||||
/// the second, a set of random unit vectors to be used as noise gradients.
|
||||
GLuint getPermutationNormalTextureID();
|
||||
|
||||
/// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is
|
||||
/// used for scene rendering.
|
||||
QOpenGLFramebufferObject* getPrimaryFramebufferObject();
|
||||
|
||||
/// Returns the ID of the primary framebuffer object's depth texture. This contains the Z buffer used in rendering.
|
||||
GLuint getPrimaryDepthTextureID();
|
||||
|
||||
/// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full
|
||||
/// screen effects.
|
||||
QOpenGLFramebufferObject* getSecondaryFramebufferObject();
|
||||
|
||||
/// Returns a pointer to the tertiary framebuffer object, used as an additional render target when performing full
|
||||
/// screen effects.
|
||||
QOpenGLFramebufferObject* getTertiaryFramebufferObject();
|
||||
|
||||
virtual bool eventFilter(QObject* watched, QEvent* event);
|
||||
|
@ -34,6 +49,7 @@ private:
|
|||
GLuint _permutationNormalTextureID;
|
||||
|
||||
QOpenGLFramebufferObject* _primaryFramebufferObject;
|
||||
GLuint _primaryDepthTextureID;
|
||||
QOpenGLFramebufferObject* _secondaryFramebufferObject;
|
||||
QOpenGLFramebufferObject* _tertiaryFramebufferObject;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue