Merge pull request #879 from ey6es/master

Fix for glow/ambient occlusion with Oculus, made lookat vectors glow and enabled by default.
This commit is contained in:
Stephen Birarda 2013-08-21 16:04:30 -07:00
commit ee0d965ed4
11 changed files with 79 additions and 49 deletions

View file

@ -44,7 +44,8 @@ float texCoordToViewSpaceZ(vec2 texCoord) {
// 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);
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) {

View file

@ -35,6 +35,7 @@
#include <QMenuBar>
#include <QMouseEvent>
#include <QNetworkAccessManager>
#include <QOpenGLFramebufferObject>
#include <QWheelEvent>
#include <QSettings>
#include <QShortcut>
@ -116,7 +117,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_lookatIndicatorScale(1.0f),
_perfStatsOn(false),
_chatEntryOn(false),
_oculusTextureID(0),
_oculusProgram(0),
_oculusDistortionScale(1.25),
#ifndef _WIN32
@ -378,13 +378,18 @@ void Application::paintGL() {
if (OculusManager::isConnected()) {
displayOculus(whichCamera);
} else {
_glowEffect.prepare();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
displaySide(whichCamera);
glPopMatrix();
_glowEffect.render();
displayOverlay();
}
@ -408,13 +413,6 @@ void Application::resizeGL(int width, int height) {
resetCamerasOnResizeGL(_viewFrustumOffsetCamera, 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
loadViewFrustum(_myCamera, _viewFrustum);
@ -1923,6 +1921,8 @@ static const char* DISTORTION_FRAGMENT_SHADER =
"}";
void Application::displayOculus(Camera& whichCamera) {
_glowEffect.prepare();
// 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
// constants using the stats for the current-model hardware as contained in the SDK file
@ -1965,12 +1965,10 @@ void Application::displayOculus(Camera& whichCamera) {
// restore our normal viewport
glViewport(0, 0, _glWidget->width(), _glWidget->height());
if (_oculusTextureID == 0) {
glGenTextures(1, &_oculusTextureID);
glBindTexture(GL_TEXTURE_2D, _oculusTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _glWidget->width(), _glWidget->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
QOpenGLFramebufferObject* fbo = _glowEffect.render(true);
glBindTexture(GL_TEXTURE_2D, fbo->texture());
if (_oculusProgram == 0) {
_oculusProgram = new ProgramObject();
_oculusProgram->addShaderFromSourceCode(QGLShader::Fragment, DISTORTION_FRAGMENT_SHADER);
_oculusProgram->link();
@ -1980,18 +1978,13 @@ void Application::displayOculus(Camera& whichCamera) {
_screenCenterLocation = _oculusProgram->uniformLocation("screenCenter");
_scaleLocation = _oculusProgram->uniformLocation("scale");
_scaleInLocation = _oculusProgram->uniformLocation("scaleIn");
_hmdWarpParamLocation = _oculusProgram->uniformLocation("hmdWarpParam");
} else {
glBindTexture(GL_TEXTURE_2D, _oculusTextureID);
_hmdWarpParamLocation = _oculusProgram->uniformLocation("hmdWarpParam");
}
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, _glWidget->width(), _glWidget->height());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, _glWidget->width(), 0, _glWidget->height());
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
// for reference on setting these values, see SDK file Samples/OculusRoomTiny/RenderTiny_Device.cpp
@ -1999,7 +1992,6 @@ void Application::displayOculus(Camera& whichCamera) {
float aspectRatio = (_glWidget->width() * 0.5) / _glWidget->height();
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
_oculusProgram->bind();
_oculusProgram->setUniformValue(_textureLocation, 0);
_oculusProgram->setUniformValue(_lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
@ -2035,7 +2027,6 @@ void Application::displayOculus(Camera& whichCamera) {
glEnd();
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
_oculusProgram->release();
@ -2096,9 +2087,6 @@ void Application::displaySide(Camera& whichCamera) {
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
setupWorldLight(whichCamera);
// prepare the glow effect
_glowEffect.prepare();
if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
if (!_stars.getFileLoaded()) {
_stars.readInput(STAR_FILE, STAR_CACHE_FILE, 0);
@ -2256,7 +2244,7 @@ void Application::displaySide(Camera& whichCamera) {
_myAvatar.renderScreenTint(SCREEN_TINT_AFTER_AVATARS, whichCamera);
// 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();
}
@ -2283,9 +2271,6 @@ void Application::displaySide(Camera& whichCamera) {
}
renderFollowIndicator();
// render the glow effect
_glowEffect.render();
}
void Application::displayOverlay() {

View file

@ -302,7 +302,6 @@ private:
ChatEntry _chatEntry; // chat entry field
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
float _oculusDistortionScale; // Controls the Oculus field of view
int _textureLocation;

View file

@ -165,7 +165,7 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::AmbientOcclusion);
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::FrameTimer);
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtVectors);
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtVectors, 0, true);
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::LookAtIndicator, 0, true);
addCheckableActionToQMenuAndActionHash(renderMenu, MenuOption::FirstPerson, Qt::Key_P, true);

View file

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

View file

@ -742,6 +742,8 @@ void Head::renderEyeBalls() {
void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) {
Application::getInstance()->getGlowEffect()->begin();
glLineWidth(2.0);
glBegin(GL_LINES);
glColor4f(0.2f, 0.2f, 0.2f, 1.f);
@ -753,6 +755,8 @@ void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosi
glColor4f(1.0f, 1.0f, 1.0f, 0.f);
glVertex3f(lookatPosition.x, lookatPosition.y, lookatPosition.z);
glEnd();
Application::getInstance()->getGlowEffect()->end();
}
void Head::updateHairPhysics(float deltaTime) {

View file

@ -111,11 +111,17 @@ void AmbientOcclusionEffect::render() {
_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);
QSize widgetSize = Application::getInstance()->getGLWidget()->size();
_occlusionProgram->setUniformValue(_noiseScaleLocation, widgetSize.width() / (float)ROTATION_WIDTH,
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();
@ -133,9 +139,9 @@ void AmbientOcclusionEffect::render() {
glBindTexture(GL_TEXTURE_2D, freeFBO->texture());
_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();

View file

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

View file

@ -40,7 +40,9 @@ public:
void end();
/// 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:

View file

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

View file

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