Fixed glow/ambient occlusion with Oculus.

This commit is contained in:
Andrzej Kapolka 2013-08-21 15:44:57 -07:00
parent f39050ae28
commit d63bb3afaa
9 changed files with 74 additions and 48 deletions

View file

@ -44,7 +44,8 @@ float texCoordToViewSpaceZ(vec2 texCoord) {
// given a texture coordinate, returns the 3D view space coordinate // given a texture coordinate, returns the 3D view space coordinate
vec3 texCoordToViewSpace(vec2 texCoord) { vec3 texCoordToViewSpace(vec2 texCoord) {
float z = texCoordToViewSpaceZ(texCoord); float z = texCoordToViewSpaceZ(texCoord);
return vec3(((texCoord * 2.0 - vec2(1.0, 1.0)) * (rightTop - leftBottom) + rightTop + leftBottom) * z / (-2.0 * near), z); return vec3(((texCoord * 2.0 - vec2(1.0 - gl_ProjectionMatrix[2][0], 1.0)) *
(rightTop - leftBottom) + rightTop + leftBottom) * z / (-2.0 * near), z);
} }
void main(void) { void main(void) {

View file

@ -35,6 +35,7 @@
#include <QMenuBar> #include <QMenuBar>
#include <QMouseEvent> #include <QMouseEvent>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QOpenGLFramebufferObject>
#include <QWheelEvent> #include <QWheelEvent>
#include <QSettings> #include <QSettings>
#include <QShortcut> #include <QShortcut>
@ -112,7 +113,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_lookatIndicatorScale(1.0f), _lookatIndicatorScale(1.0f),
_perfStatsOn(false), _perfStatsOn(false),
_chatEntryOn(false), _chatEntryOn(false),
_oculusTextureID(0),
_oculusProgram(0), _oculusProgram(0),
_oculusDistortionScale(1.25), _oculusDistortionScale(1.25),
#ifndef _WIN32 #ifndef _WIN32
@ -370,13 +370,18 @@ void Application::paintGL() {
if (OculusManager::isConnected()) { if (OculusManager::isConnected()) {
displayOculus(whichCamera); displayOculus(whichCamera);
} else { } else {
_glowEffect.prepare();
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPushMatrix(); glPushMatrix();
glLoadIdentity(); glLoadIdentity();
displaySide(whichCamera); displaySide(whichCamera);
glPopMatrix(); glPopMatrix();
_glowEffect.render();
displayOverlay(); displayOverlay();
} }
@ -400,13 +405,6 @@ void Application::resizeGL(int width, int height) {
resetCamerasOnResizeGL(_viewFrustumOffsetCamera, width, height); resetCamerasOnResizeGL(_viewFrustumOffsetCamera, width, height);
resetCamerasOnResizeGL(_myCamera, width, height); resetCamerasOnResizeGL(_myCamera, width, height);
// resize the render texture
if (OculusManager::isConnected() && _oculusTextureID != 0) {
glBindTexture(GL_TEXTURE_2D, _oculusTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
// Tell our viewFrustum about this change, using the application camera // Tell our viewFrustum about this change, using the application camera
loadViewFrustum(_myCamera, _viewFrustum); loadViewFrustum(_myCamera, _viewFrustum);
@ -2056,6 +2054,8 @@ static const char* DISTORTION_FRAGMENT_SHADER =
"}"; "}";
void Application::displayOculus(Camera& whichCamera) { void Application::displayOculus(Camera& whichCamera) {
_glowEffect.prepare();
// magic numbers ahoy! in order to avoid pulling in the Oculus utility library that calculates // magic numbers ahoy! in order to avoid pulling in the Oculus utility library that calculates
// the rendering parameters from the hardware stats, i just folded their calculations into // the rendering parameters from the hardware stats, i just folded their calculations into
// constants using the stats for the current-model hardware as contained in the SDK file // constants using the stats for the current-model hardware as contained in the SDK file
@ -2098,12 +2098,10 @@ void Application::displayOculus(Camera& whichCamera) {
// restore our normal viewport // restore our normal viewport
glViewport(0, 0, _glWidget->width(), _glWidget->height()); glViewport(0, 0, _glWidget->width(), _glWidget->height());
if (_oculusTextureID == 0) { QOpenGLFramebufferObject* fbo = _glowEffect.render(true);
glGenTextures(1, &_oculusTextureID); glBindTexture(GL_TEXTURE_2D, fbo->texture());
glBindTexture(GL_TEXTURE_2D, _oculusTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _glWidget->width(), _glWidget->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); if (_oculusProgram == 0) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
_oculusProgram = new ProgramObject(); _oculusProgram = new ProgramObject();
_oculusProgram->addShaderFromSourceCode(QGLShader::Fragment, DISTORTION_FRAGMENT_SHADER); _oculusProgram->addShaderFromSourceCode(QGLShader::Fragment, DISTORTION_FRAGMENT_SHADER);
_oculusProgram->link(); _oculusProgram->link();
@ -2113,18 +2111,13 @@ void Application::displayOculus(Camera& whichCamera) {
_screenCenterLocation = _oculusProgram->uniformLocation("screenCenter"); _screenCenterLocation = _oculusProgram->uniformLocation("screenCenter");
_scaleLocation = _oculusProgram->uniformLocation("scale"); _scaleLocation = _oculusProgram->uniformLocation("scale");
_scaleInLocation = _oculusProgram->uniformLocation("scaleIn"); _scaleInLocation = _oculusProgram->uniformLocation("scaleIn");
_hmdWarpParamLocation = _oculusProgram->uniformLocation("hmdWarpParam"); _hmdWarpParamLocation = _oculusProgram->uniformLocation("hmdWarpParam");
} else {
glBindTexture(GL_TEXTURE_2D, _oculusTextureID);
} }
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, _glWidget->width(), _glWidget->height());
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
gluOrtho2D(0, _glWidget->width(), 0, _glWidget->height()); gluOrtho2D(0, _glWidget->width(), 0, _glWidget->height());
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
// for reference on setting these values, see SDK file Samples/OculusRoomTiny/RenderTiny_Device.cpp // for reference on setting these values, see SDK file Samples/OculusRoomTiny/RenderTiny_Device.cpp
@ -2132,7 +2125,6 @@ void Application::displayOculus(Camera& whichCamera) {
float aspectRatio = (_glWidget->width() * 0.5) / _glWidget->height(); float aspectRatio = (_glWidget->width() * 0.5) / _glWidget->height();
glDisable(GL_BLEND); glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
_oculusProgram->bind(); _oculusProgram->bind();
_oculusProgram->setUniformValue(_textureLocation, 0); _oculusProgram->setUniformValue(_textureLocation, 0);
_oculusProgram->setUniformValue(_lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29 _oculusProgram->setUniformValue(_lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
@ -2168,7 +2160,6 @@ void Application::displayOculus(Camera& whichCamera) {
glEnd(); glEnd();
glEnable(GL_BLEND); glEnable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
_oculusProgram->release(); _oculusProgram->release();
@ -2229,9 +2220,6 @@ void Application::displaySide(Camera& whichCamera) {
// Setup 3D lights (after the camera transform, so that they are positioned in world space) // Setup 3D lights (after the camera transform, so that they are positioned in world space)
setupWorldLight(whichCamera); setupWorldLight(whichCamera);
// prepare the glow effect
_glowEffect.prepare();
if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) { if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
if (!_stars.getFileLoaded()) { if (!_stars.getFileLoaded()) {
_stars.readInput(STAR_FILE, STAR_CACHE_FILE, 0); _stars.readInput(STAR_FILE, STAR_CACHE_FILE, 0);
@ -2372,7 +2360,7 @@ void Application::displaySide(Camera& whichCamera) {
_myAvatar.renderScreenTint(SCREEN_TINT_AFTER_AVATARS, whichCamera); _myAvatar.renderScreenTint(SCREEN_TINT_AFTER_AVATARS, whichCamera);
// Render the world box // Render the world box
if (!Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { if (!Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
renderWorldBox(); renderWorldBox();
} }
@ -2399,9 +2387,6 @@ void Application::displaySide(Camera& whichCamera) {
} }
renderFollowIndicator(); renderFollowIndicator();
// render the glow effect
_glowEffect.render();
} }
void Application::displayOverlay() { void Application::displayOverlay() {

View file

@ -301,7 +301,6 @@ private:
ChatEntry _chatEntry; // chat entry field ChatEntry _chatEntry; // chat entry field
bool _chatEntryOn; // Whether to show the chat entry bool _chatEntryOn; // Whether to show the chat entry
GLuint _oculusTextureID; // The texture to which we render for Oculus distortion
ProgramObject* _oculusProgram; // The GLSL program containing the distortion shader ProgramObject* _oculusProgram; // The GLSL program containing the distortion shader
float _oculusDistortionScale; // Controls the Oculus field of view float _oculusDistortionScale; // Controls the Oculus field of view
int _textureLocation; int _textureLocation;

View file

@ -46,6 +46,7 @@ void OculusManager::updateYawOffset() {
} }
void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) { void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {
yaw = pitch = roll = 0.0f;
#ifdef __APPLE__ #ifdef __APPLE__
_sensorFusion.GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll); _sensorFusion.GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);

View file

@ -111,11 +111,17 @@ void AmbientOcclusionEffect::render() {
_occlusionProgram->setUniformValue(_farLocation, farVal); _occlusionProgram->setUniformValue(_farLocation, farVal);
_occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom); _occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom);
_occlusionProgram->setUniformValue(_rightTopLocation, right, top); _occlusionProgram->setUniformValue(_rightTopLocation, right, top);
QSize size = Application::getInstance()->getGLWidget()->size(); QSize widgetSize = Application::getInstance()->getGLWidget()->size();
_occlusionProgram->setUniformValue(_noiseScaleLocation, size.width() / (float)ROTATION_WIDTH, _occlusionProgram->setUniformValue(_noiseScaleLocation, widgetSize.width() / (float)ROTATION_WIDTH,
size.height() / (float)ROTATION_HEIGHT); widgetSize.height() / (float)ROTATION_HEIGHT);
renderFullscreenQuad(); 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)widgetSize.width();
float sMax = (viewport[VIEWPORT_X_INDEX] + viewport[VIEWPORT_WIDTH_INDEX]) / (float)widgetSize.width();
renderFullscreenQuad(sMin, sMax);
_occlusionProgram->release(); _occlusionProgram->release();
@ -133,9 +139,9 @@ void AmbientOcclusionEffect::render() {
glBindTexture(GL_TEXTURE_2D, freeFBO->texture()); glBindTexture(GL_TEXTURE_2D, freeFBO->texture());
_blurProgram->bind(); _blurProgram->bind();
_blurProgram->setUniformValue(_blurScaleLocation, 1.0f / size.width(), 1.0f / size.height()); _blurProgram->setUniformValue(_blurScaleLocation, 1.0f / widgetSize.width(), 1.0f / widgetSize.height());
renderFullscreenQuad(); renderFullscreenQuad(sMin, sMax);
_blurProgram->release(); _blurProgram->release();

View file

@ -78,7 +78,19 @@ void GlowEffect::end() {
glBlendColor(0.0f, 0.0f, 0.0f, 0.0f); glBlendColor(0.0f, 0.0f, 0.0f, 0.0f);
} }
void GlowEffect::render() { static void maybeBind(QOpenGLFramebufferObject* fbo) {
if (fbo != NULL) {
fbo->bind();
}
}
static void maybeRelease(QOpenGLFramebufferObject* fbo) {
if (fbo != NULL) {
fbo->release();
}
}
QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) {
QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();
primaryFBO->release(); primaryFBO->release();
glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture());
@ -94,23 +106,29 @@ void GlowEffect::render() {
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
QOpenGLFramebufferObject* destFBO = toTexture ?
Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject() : NULL;
if (_isEmpty) { if (_isEmpty) {
// copy the primary to the screen // copy the primary to the screen
if (QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { if (QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
QOpenGLFramebufferObject::blitFramebuffer(NULL, primaryFBO); QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO);
} else { } else {
maybeBind(destFBO);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
glColor3f(1.0f, 1.0f, 1.0f); glColor3f(1.0f, 1.0f, 1.0f);
renderFullscreenQuad(); renderFullscreenQuad();
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
maybeRelease(destFBO);
} }
} else if (_renderMode == ADD_MODE) { } else if (_renderMode == ADD_MODE) {
maybeBind(destFBO);
_addProgram->bind(); _addProgram->bind();
renderFullscreenQuad(); renderFullscreenQuad();
_addProgram->release(); _addProgram->release();
maybeRelease(destFBO);
} else if (_renderMode == DIFFUSE_ADD_MODE) { } else if (_renderMode == DIFFUSE_ADD_MODE) {
// diffuse into the secondary/tertiary (alternating between frames) // diffuse into the secondary/tertiary (alternating between frames)
@ -139,9 +157,14 @@ void GlowEffect::render() {
// add diffused texture to the primary // add diffused texture to the primary
glBindTexture(GL_TEXTURE_2D, newDiffusedFBO->texture()); glBindTexture(GL_TEXTURE_2D, newDiffusedFBO->texture());
if (toTexture) {
destFBO = oldDiffusedFBO;
}
maybeBind(destFBO);
_addSeparateProgram->bind(); _addSeparateProgram->bind();
renderFullscreenQuad(); renderFullscreenQuad();
_addSeparateProgram->release(); _addSeparateProgram->release();
maybeRelease(destFBO);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
@ -163,9 +186,14 @@ void GlowEffect::render() {
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture()); glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture());
if (toTexture) {
destFBO = Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject();
}
maybeBind(destFBO);
_verticalBlurAddProgram->bind(); _verticalBlurAddProgram->bind();
renderFullscreenQuad(); renderFullscreenQuad();
_verticalBlurAddProgram->release(); _verticalBlurAddProgram->release();
maybeRelease(destFBO);
} else { // _renderMode == BLUR_PERSIST_ADD_MODE } else { // _renderMode == BLUR_PERSIST_ADD_MODE
// render the secondary to the tertiary with horizontal blur and persistence // render the secondary to the tertiary with horizontal blur and persistence
@ -196,9 +224,11 @@ void GlowEffect::render() {
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, tertiaryFBO->texture()); glBindTexture(GL_TEXTURE_2D, tertiaryFBO->texture());
maybeBind(destFBO);
_addSeparateProgram->bind(); _addSeparateProgram->bind();
renderFullscreenQuad(); renderFullscreenQuad();
_addSeparateProgram->release(); _addSeparateProgram->release();
maybeRelease(destFBO);
} }
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
@ -214,6 +244,8 @@ void GlowEffect::render() {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
return destFBO;
} }
void GlowEffect::cycleRenderMode() { void GlowEffect::cycleRenderMode() {

View file

@ -40,7 +40,9 @@ public:
void end(); void end();
/// Renders the glow effect. To be called after rendering the scene. /// Renders the glow effect. To be called after rendering the scene.
void render(); /// \param toTexture whether to render to a texture, rather than to the frame buffer
/// \return the framebuffer object to which we rendered, or NULL if to the frame buffer
QOpenGLFramebufferObject* render(bool toTexture = false);
public slots: public slots:

View file

@ -8,15 +8,15 @@
#include "InterfaceConfig.h" #include "InterfaceConfig.h"
#include "RenderUtil.h" #include "RenderUtil.h"
void renderFullscreenQuad() { void renderFullscreenQuad(float sMin, float sMax) {
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glTexCoord2f(sMin, 0.0f);
glVertex2f(-1.0f, -1.0f); glVertex2f(-1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glTexCoord2f(sMax, 0.0f);
glVertex2f(1.0f, -1.0f); glVertex2f(1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glTexCoord2f(sMax, 1.0f);
glVertex2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glTexCoord2f(sMin, 1.0f);
glVertex2f(-1.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
glEnd(); glEnd();
} }

View file

@ -9,7 +9,7 @@
#ifndef __interface__RenderUtil__ #ifndef __interface__RenderUtil__
#define __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). /// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (sMin, 0) to (sMax, 1).
void renderFullscreenQuad(); void renderFullscreenQuad(float sMin = 0.0f, float sMax = 1.0f);
#endif /* defined(__interface__RenderUtil__) */ #endif /* defined(__interface__RenderUtil__) */