From 5cc5d9bba8eae08f5ea98c418663f73d7ee48265 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 20 Nov 2013 16:23:54 -0800 Subject: [PATCH 01/10] Progress towards shadow maps. --- interface/src/Application.cpp | 181 ++++++++++++++++++------ interface/src/Application.h | 6 +- interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + interface/src/avatar/MyAvatar.cpp | 4 +- interface/src/avatar/MyAvatar.h | 2 +- interface/src/renderer/Model.cpp | 2 +- interface/src/renderer/TextureCache.cpp | 30 +++- interface/src/renderer/TextureCache.h | 9 ++ 9 files changed, 188 insertions(+), 48 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 628a91c69b..60d35f522e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -424,12 +424,15 @@ void Application::paintGL() { whichCamera = _viewFrustumOffsetCamera; } + if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { + updateShadowMap(); + } + if (OculusManager::isConnected()) { displayOculus(whichCamera); } else { _glowEffect.prepare(); - glMatrixMode(GL_MODELVIEW); glPushMatrix(); @@ -2754,6 +2757,76 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { viewFrustum.calculate(); } +glm::vec3 Application::getSunDirection() { + return glm::normalize(_environment.getClosestData(_myCamera.getPosition()).getSunLocation() - _myCamera.getPosition()); +} + +void Application::updateShadowMap() { + QOpenGLFramebufferObject* fbo = _textureCache.getShadowFramebufferObject(); + fbo->bind(); + glEnable(GL_DEPTH_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glViewport(0, 0, fbo->width(), fbo->height()); + + glm::vec3 lightDirection = -getSunDirection(); + glm::quat rotation = glm::inverse(rotationBetween(IDENTITY_FRONT, lightDirection)); + glm::vec3 translation = glm::vec3(); + float nearScale = 0.0f; + float farScale = 0.000001f; + /* glm::vec3 points[] = { + rotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale) + translation), + rotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale) + translation), + rotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale) + translation), + rotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale) + translation), + rotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale) + translation), + rotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale) + translation), + rotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale) + translation), + rotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) + translation) }; */ + glm::vec3 points[] = { + rotation * (_myAvatar.getPosition() + glm::vec3(-1, 0, 0) + translation), + rotation * (_myAvatar.getPosition() + glm::vec3(1, 0, 0) + translation), + rotation * (_myAvatar.getPosition() + glm::vec3(0, -1, 0) + translation), + rotation * (_myAvatar.getPosition() + glm::vec3(0, 1, 0) + translation), + rotation * (_myAvatar.getPosition() + glm::vec3(0, 0, -1) + translation), + rotation * (_myAvatar.getPosition() + glm::vec3(0, 0, 1) + translation) }; + glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX), maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX); + for (int i = 0; i < sizeof(points) / sizeof(points[0]); i++) { + minima = glm::min(minima, points[i]); + maxima = glm::max(maxima, points[i]); + } + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z); + + // store view matrix without translation, which we'll use for precision-sensitive objects + glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&_untranslatedViewMatrix); + _viewMatrixTranslation = translation; + + glTranslatef(translation.x, translation.y, translation.z); + + renderAvatars(_myCamera); + + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + + fbo->release(); + + glViewport(0, 0, _glWidget->width(), _glWidget->height()); +} + // this shader is an adaptation (HLSL -> GLSL, removed conditional) of the one in the Oculus sample // code (Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp), which is under the Apache license // (http://www.apache.org/licenses/LICENSE-2.0) @@ -2896,15 +2969,14 @@ void Application::displayOculus(Camera& whichCamera) { const GLfloat WHITE_SPECULAR_COLOR[] = { 1.0f, 1.0f, 1.0f, 1.0f }; const GLfloat NO_SPECULAR_COLOR[] = { 0.0f, 0.0f, 0.0f, 1.0f }; -void Application::setupWorldLight(Camera& whichCamera) { +void Application::setupWorldLight() { // Setup 3D lights (after the camera transform, so that they are positioned in world space) glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glm::vec3 relativeSunLoc = glm::normalize(_environment.getClosestData(whichCamera.getPosition()).getSunLocation() - - whichCamera.getPosition()); - GLfloat light_position0[] = { relativeSunLoc.x, relativeSunLoc.y, relativeSunLoc.z, 0.0 }; + glm::vec3 sunDirection = getSunDirection(); + GLfloat light_position0[] = { sunDirection.x, sunDirection.y, sunDirection.z, 0.0 }; glLightfv(GL_LIGHT0, GL_POSITION, light_position0); GLfloat ambient_color[] = { 0.7, 0.7, 0.8 }; glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color); @@ -2962,7 +3034,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { glTranslatef(_viewMatrixTranslation.x, _viewMatrixTranslation.y, _viewMatrixTranslation.z); // Setup 3D lights (after the camera transform, so that they are positioned in world space) - setupWorldLight(whichCamera); + setupWorldLight(); if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), @@ -3099,44 +3171,11 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { } } - _myAvatar.renderScreenTint(SCREEN_TINT_BEFORE_AVATARS, whichCamera); + _myAvatar.renderScreenTint(SCREEN_TINT_BEFORE_AVATARS); - if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... Avatars..."); + renderAvatars(whichCamera, selfAvatarOnly); - - if (!selfAvatarOnly) { - // Render avatars of other nodes - NodeList* nodeList = NodeList::getInstance(); - - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - node->lock(); - - if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { - Avatar *avatar = (Avatar *)node->getLinkedData(); - if (!avatar->isInitialized()) { - avatar->init(); - } - avatar->render(false, Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); - avatar->setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); - } - - node->unlock(); - } - } - - // Render my own Avatar - _myAvatar.render(whichCamera.getMode() == CAMERA_MODE_MIRROR, - Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); - _myAvatar.setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); - - if (Menu::getInstance()->isOptionChecked(MenuOption::LookAtIndicator) && _lookatTargetAvatar) { - renderLookatIndicator(_lookatOtherPosition, whichCamera); - } - } - - _myAvatar.renderScreenTint(SCREEN_TINT_AFTER_AVATARS, whichCamera); + _myAvatar.renderScreenTint(SCREEN_TINT_AFTER_AVATARS); if (!selfAvatarOnly) { // Render the world box @@ -3336,6 +3375,29 @@ void Application::displayOverlay() { // render the webcam input frame _webcam.renderPreview(_glWidget->width(), _glWidget->height()); + if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { + glBindTexture(GL_TEXTURE_2D, _textureCache.getShadowDepthTextureID()); + glEnable(GL_TEXTURE_2D); + glColor3f(1.0f, 1.0f, 1.0f); + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); + glVertex2f(500, 500); + + glTexCoord2f(1.0f, 0.0f); + glVertex2f(1000, 500); + + glTexCoord2f(1.0f, 1.0f); + glVertex2f(1000, 0); + + glTexCoord2f(0.0f, 1.0f); + glVertex2f(500, 0); + glEnd(); + + glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + } + _palette.render(_glWidget->width(), _glWidget->height()); QAction* paintColorAction = NULL; @@ -3758,7 +3820,42 @@ void Application::renderCoverageMapsRecursively(CoverageMap* map) { } } +void Application::renderAvatars(Camera& whichCamera, bool selfAvatarOnly) { + if (!Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { + return; + } + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "Application::displaySide() ... Avatars..."); + if (!selfAvatarOnly) { + // Render avatars of other nodes + NodeList* nodeList = NodeList::getInstance(); + + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + node->lock(); + + if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { + Avatar *avatar = (Avatar *)node->getLinkedData(); + if (!avatar->isInitialized()) { + avatar->init(); + } + avatar->render(false, Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); + avatar->setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); + } + + node->unlock(); + } + } + + // Render my own Avatar + _myAvatar.render(whichCamera.getMode() == CAMERA_MODE_MIRROR, + Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); + _myAvatar.setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); + + if (Menu::getInstance()->isOptionChecked(MenuOption::LookAtIndicator) && _lookatTargetAvatar) { + renderLookatIndicator(_lookatOtherPosition, whichCamera); + } +} // renderViewFrustum() // diff --git a/interface/src/Application.h b/interface/src/Application.h index 78530ecea2..b94ccd1e72 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -150,7 +150,7 @@ public: static void controlledBroadcastToNodes(unsigned char* broadcastData, size_t dataBytes, const char* nodeTypes, int numNodeTypes); - void setupWorldLight(Camera& whichCamera); + void setupWorldLight(); /// Loads a view matrix that incorporates the specified model translation without the precision issues that can /// result from matrix multiplication at high translation magnitudes. @@ -263,10 +263,14 @@ private: void queryVoxels(); void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum); + glm::vec3 getSunDirection(); + + void updateShadowMap(); void displayOculus(Camera& whichCamera); void displaySide(Camera& whichCamera, bool selfAvatarOnly = false); void displayOverlay(); void displayStats(); + void renderAvatars(Camera& whichCamera, bool selfAvatarOnly = false); void renderViewFrustum(ViewFrustum& viewFrustum); void checkBandwidthMeterClick(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 69ea9d010e..f663f22f0a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -267,6 +267,7 @@ Menu::Menu() : SLOT(cycleRenderMode())); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ParticleCloud, 0, false); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Shadows, 0, false); QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxel Options"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index dd1789689b..711b8938d2 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -225,6 +225,7 @@ namespace MenuOption { const QString RunTimingTests = "Run Timing Tests"; const QString SendVoxelColors = "Colored Voxels"; const QString SettingsImport = "Import Settings"; + const QString Shadows = "Shadows"; const QString SettingsExport = "Export Settings"; const QString ShowAllLocalVoxels = "Show All Local Voxels"; const QString ShowTrueColors = "Show TRUE Colors"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3ce54d7032..2b23bc9bcf 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -522,7 +522,7 @@ void MyAvatar::render(bool lookingInMirror, bool renderAvatarBalls) { } } -void MyAvatar::renderScreenTint(ScreenTintLayer layer, Camera& whichCamera) { +void MyAvatar::renderScreenTint(ScreenTintLayer layer) { if (layer == SCREEN_TINT_BEFORE_AVATARS) { if (_hand.isRaveGloveActive()) { @@ -532,7 +532,7 @@ void MyAvatar::renderScreenTint(ScreenTintLayer layer, Camera& whichCamera) { else if (layer == SCREEN_TINT_BEFORE_AVATARS) { if (_hand.isRaveGloveActive()) { // Restore the world lighting - Application::getInstance()->setupWorldLight(whichCamera); + Application::getInstance()->setupWorldLight(); } } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 790510536f..99557ab162 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -21,7 +21,7 @@ public: void simulate(float deltaTime, Transmitter* transmitter); void updateFromGyrosAndOrWebcam(float pitchFromTouch, bool turnWithHead); void render(bool lookingInMirror, bool renderAvatarBalls); - void renderScreenTint(ScreenTintLayer layer, Camera& whichCamera); + void renderScreenTint(ScreenTintLayer layer); // setters void setMousePressed(bool mousePressed) { _mousePressed = mousePressed; } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index ac6f2c4c47..3698f0682f 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -447,7 +447,7 @@ bool Model::render(float alpha) { glBindTexture(GL_TEXTURE_2D, 0); // restore all the default material settings - Application::getInstance()->setupWorldLight(*Application::getInstance()->getCamera()); + Application::getInstance()->setupWorldLight(); return true; } diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index c99f82fdb4..94857b2c1e 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -23,7 +23,8 @@ TextureCache::TextureCache() : _blueTextureID(0), _primaryFramebufferObject(NULL), _secondaryFramebufferObject(NULL), - _tertiaryFramebufferObject(NULL) + _tertiaryFramebufferObject(NULL), + _shadowFramebufferObject(NULL) { } @@ -179,6 +180,33 @@ QOpenGLFramebufferObject* TextureCache::getTertiaryFramebufferObject() { return _tertiaryFramebufferObject; } +QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() { + if (_shadowFramebufferObject == NULL) { + const int SHADOW_MAP_SIZE = 1024; + _shadowFramebufferObject = new QOpenGLFramebufferObject(SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, + QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D, GL_RGB); + + glGenTextures(1, &_shadowDepthTextureID); + glBindTexture(GL_TEXTURE_2D, _shadowDepthTextureID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, + 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); + + _shadowFramebufferObject->bind(); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _shadowDepthTextureID, 0); + _shadowFramebufferObject->release(); + } + return _shadowFramebufferObject; +} + +GLuint TextureCache::getShadowDepthTextureID() { + // ensure that the shadow framebuffer object is initialized before returning the depth texture id + getShadowFramebufferObject(); + return _shadowDepthTextureID; +} + bool TextureCache::eventFilter(QObject* watched, QEvent* event) { if (event->type() == QEvent::Resize) { QSize size = static_cast(event)->size(); diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index cab9446782..40f2bc5ac3 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -64,6 +64,12 @@ public: /// screen effects. QOpenGLFramebufferObject* getTertiaryFramebufferObject(); + /// Returns a pointer to the framebuffer object used to render shadow maps. + QOpenGLFramebufferObject* getShadowFramebufferObject(); + + /// Returns the ID of the shadow framebuffer object's depth texture. + GLuint getShadowDepthTextureID(); + virtual bool eventFilter(QObject* watched, QEvent* event); private: @@ -83,6 +89,9 @@ private: QOpenGLFramebufferObject* _primaryFramebufferObject; QOpenGLFramebufferObject* _secondaryFramebufferObject; QOpenGLFramebufferObject* _tertiaryFramebufferObject; + + QOpenGLFramebufferObject* _shadowFramebufferObject; + GLuint _shadowDepthTextureID; }; /// A simple object wrapper for an OpenGL texture. From 4bcc6fdc0dbbf65e90f25f15c6a2d76c96456954 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 20 Nov 2013 18:27:59 -0800 Subject: [PATCH 02/10] More progress on shadows. --- interface/src/Application.cpp | 5 +++++ interface/src/Application.h | 4 ++++ interface/src/VoxelSystem.cpp | 27 +++++++++++++++++++++---- interface/src/renderer/TextureCache.cpp | 4 ++++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 60d35f522e..a16cc2b9e4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2796,6 +2796,11 @@ void Application::updateShadowMap() { maxima = glm::max(maxima, points[i]); } + // save the combined matrix for rendering + _shadowMatrix = glm::transpose(glm::translate(0.5f, 0.5f, 0.5f) * glm::scale(0.5f, 0.5f, 0.5f) * + glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) * + glm::mat4_cast(rotation) * glm::translate(translation)); + glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); diff --git a/interface/src/Application.h b/interface/src/Application.h index b94ccd1e72..33858e8556 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -156,6 +156,8 @@ public: /// result from matrix multiplication at high translation magnitudes. void loadTranslatedViewMatrix(const glm::vec3& translation); + const glm::mat4& getShadowMatrix() const { return _shadowMatrix; } + /// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account. void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near, float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; @@ -350,6 +352,8 @@ private: glm::mat4 _untranslatedViewMatrix; glm::vec3 _viewMatrixTranslation; + glm::mat4 _shadowMatrix; + Environment _environment; int _headMouseX, _headMouseY; diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 62419565c6..c4e700ad82 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -1386,20 +1386,39 @@ void VoxelSystem::render(bool texture) { } void VoxelSystem::applyScaleAndBindProgram(bool texture) { - glPushMatrix(); - glScalef(_treeScale, _treeScale, _treeScale); - if (texture) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { + glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_2D); + + glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[0]); + glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[1]); + glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[2]); + + } else if (texture) { _perlinModulateProgram.bind(); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID()); } + + glPushMatrix(); + glScalef(_treeScale, _treeScale, _treeScale); } void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { // scale back down to 1 so heads aren't massive glPopMatrix(); - if (texture) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_2D); + + } else if (texture) { _perlinModulateProgram.release(); glBindTexture(GL_TEXTURE_2D, 0); } diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index 94857b2c1e..bffc342f09 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -192,6 +192,10 @@ QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() { 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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + const float DISTANT_BORDER[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, DISTANT_BORDER); glBindTexture(GL_TEXTURE_2D, 0); _shadowFramebufferObject->bind(); From 758246309a972fd22be08303628d06423f260a05 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 20 Nov 2013 20:06:22 -0800 Subject: [PATCH 03/10] Use compare mode. --- interface/src/Application.cpp | 4 ++-- interface/src/renderer/TextureCache.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a16cc2b9e4..abce4f3986 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2773,7 +2773,7 @@ void Application::updateShadowMap() { glm::quat rotation = glm::inverse(rotationBetween(IDENTITY_FRONT, lightDirection)); glm::vec3 translation = glm::vec3(); float nearScale = 0.0f; - float farScale = 0.000001f; + float farScale = 0.00000244f; /* glm::vec3 points[] = { rotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale) + translation), rotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale) + translation), @@ -3380,7 +3380,7 @@ void Application::displayOverlay() { // render the webcam input frame _webcam.renderPreview(_glWidget->width(), _glWidget->height()); - if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows) && false) { glBindTexture(GL_TEXTURE_2D, _textureCache.getShadowDepthTextureID()); glEnable(GL_TEXTURE_2D); glColor3f(1.0f, 1.0f, 1.0f); diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index bffc342f09..9461ebae77 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -195,7 +195,8 @@ QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); const float DISTANT_BORDER[] = { 1.0f, 1.0f, 1.0f, 1.0f }; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, DISTANT_BORDER); + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, DISTANT_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); glBindTexture(GL_TEXTURE_2D, 0); _shadowFramebufferObject->bind(); From dcc926a0db52f122b076f2e816551de975e4c444 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 20 Nov 2013 20:36:54 -0800 Subject: [PATCH 04/10] Working on the "real" shadow volume. --- interface/src/Application.cpp | 15 ++++++++------- interface/src/renderer/TextureCache.cpp | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index abce4f3986..33c280f60a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2772,9 +2772,10 @@ void Application::updateShadowMap() { glm::vec3 lightDirection = -getSunDirection(); glm::quat rotation = glm::inverse(rotationBetween(IDENTITY_FRONT, lightDirection)); glm::vec3 translation = glm::vec3(); - float nearScale = 0.0f; - float farScale = 0.00000244f; - /* glm::vec3 points[] = { + float nearScale = 0.0f; // (1.0f - _viewFrustum.getNearClip()) / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); + float farScale = (2.0f - _viewFrustum.getNearClip()) / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); + loadViewFrustum(_myCamera, _viewFrustum); + glm::vec3 points[] = { rotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale) + translation), rotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale) + translation), rotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale) + translation), @@ -2782,14 +2783,14 @@ void Application::updateShadowMap() { rotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale) + translation), rotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale) + translation), rotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale) + translation), - rotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) + translation) }; */ - glm::vec3 points[] = { + rotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) + translation) }; + /* glm::vec3 points[] = { rotation * (_myAvatar.getPosition() + glm::vec3(-1, 0, 0) + translation), rotation * (_myAvatar.getPosition() + glm::vec3(1, 0, 0) + translation), rotation * (_myAvatar.getPosition() + glm::vec3(0, -1, 0) + translation), rotation * (_myAvatar.getPosition() + glm::vec3(0, 1, 0) + translation), rotation * (_myAvatar.getPosition() + glm::vec3(0, 0, -1) + translation), - rotation * (_myAvatar.getPosition() + glm::vec3(0, 0, 1) + translation) }; + rotation * (_myAvatar.getPosition() + glm::vec3(0, 0, 1) + translation) }; */ glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX), maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX); for (int i = 0; i < sizeof(points) / sizeof(points[0]); i++) { minima = glm::min(minima, points[i]); @@ -3381,7 +3382,7 @@ void Application::displayOverlay() { _webcam.renderPreview(_glWidget->width(), _glWidget->height()); if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows) && false) { - glBindTexture(GL_TEXTURE_2D, _textureCache.getShadowDepthTextureID()); + glBindTexture(GL_TEXTURE_2D, _textureCache.getShadowFramebufferObject()->texture()); glEnable(GL_TEXTURE_2D); glColor3f(1.0f, 1.0f, 1.0f); diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index 9461ebae77..4e346b6dff 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -182,7 +182,7 @@ QOpenGLFramebufferObject* TextureCache::getTertiaryFramebufferObject() { QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() { if (_shadowFramebufferObject == NULL) { - const int SHADOW_MAP_SIZE = 1024; + const int SHADOW_MAP_SIZE = 2048; _shadowFramebufferObject = new QOpenGLFramebufferObject(SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D, GL_RGB); From f0e5872b89fe90a4b8b069496192df074890e008 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 21 Nov 2013 12:29:22 -0800 Subject: [PATCH 05/10] Lighten the shadows, remove some debug code. --- interface/resources/shaders/shadow_map.frag | 16 +++++++++++ interface/src/Application.cpp | 32 +-------------------- interface/src/VoxelSystem.cpp | 10 +++++++ interface/src/VoxelSystem.h | 1 + 4 files changed, 28 insertions(+), 31 deletions(-) create mode 100644 interface/resources/shaders/shadow_map.frag diff --git a/interface/resources/shaders/shadow_map.frag b/interface/resources/shaders/shadow_map.frag new file mode 100644 index 0000000000..4bd8b8b768 --- /dev/null +++ b/interface/resources/shaders/shadow_map.frag @@ -0,0 +1,16 @@ +#version 120 + +// +// shadow_map.frag +// fragment shader +// +// Created by Andrzej Kapolka on 11/21/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +uniform sampler2DShadow shadowMap; + +void main(void) { + gl_FragColor = gl_Color * mix(vec4(0.8, 0.8, 0.8, 1.0), vec4(1.0, 1.0, 1.0, 1.0), + shadow2D(shadowMap, gl_TexCoord[0].stp)); +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d5f68aa558..a6a5a9e20f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2782,7 +2782,7 @@ void Application::updateShadowMap() { glm::vec3 lightDirection = -getSunDirection(); glm::quat rotation = glm::inverse(rotationBetween(IDENTITY_FRONT, lightDirection)); glm::vec3 translation = glm::vec3(); - float nearScale = 0.0f; // (1.0f - _viewFrustum.getNearClip()) / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); + float nearScale = 0.0f; float farScale = (2.0f - _viewFrustum.getNearClip()) / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); loadViewFrustum(_myCamera, _viewFrustum); glm::vec3 points[] = { @@ -2794,13 +2794,6 @@ void Application::updateShadowMap() { rotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale) + translation), rotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale) + translation), rotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) + translation) }; - /* glm::vec3 points[] = { - rotation * (_myAvatar.getPosition() + glm::vec3(-1, 0, 0) + translation), - rotation * (_myAvatar.getPosition() + glm::vec3(1, 0, 0) + translation), - rotation * (_myAvatar.getPosition() + glm::vec3(0, -1, 0) + translation), - rotation * (_myAvatar.getPosition() + glm::vec3(0, 1, 0) + translation), - rotation * (_myAvatar.getPosition() + glm::vec3(0, 0, -1) + translation), - rotation * (_myAvatar.getPosition() + glm::vec3(0, 0, 1) + translation) }; */ glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX), maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX); for (int i = 0; i < sizeof(points) / sizeof(points[0]); i++) { minima = glm::min(minima, points[i]); @@ -3391,29 +3384,6 @@ void Application::displayOverlay() { // render the webcam input frame _webcam.renderPreview(_glWidget->width(), _glWidget->height()); - if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows) && false) { - glBindTexture(GL_TEXTURE_2D, _textureCache.getShadowFramebufferObject()->texture()); - glEnable(GL_TEXTURE_2D); - glColor3f(1.0f, 1.0f, 1.0f); - - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 0.0f); - glVertex2f(500, 500); - - glTexCoord2f(1.0f, 0.0f); - glVertex2f(1000, 500); - - glTexCoord2f(1.0f, 1.0f); - glVertex2f(1000, 0); - - glTexCoord2f(0.0f, 1.0f); - glVertex2f(500, 0); - glEnd(); - - glDisable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - } - _palette.render(_glWidget->width(), _glWidget->height()); QAction* paintColorAction = NULL; diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index c4e700ad82..2b4ca7839a 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -519,6 +519,13 @@ void VoxelSystem::initVoxelMemory() { _perlinModulateProgram.bind(); _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); _perlinModulateProgram.release(); + + _shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/shadow_map.frag"); + _shadowMapProgram.link(); + + _shadowMapProgram.bind(); + _shadowMapProgram.setUniformValue("shadowMap", 0); + _shadowMapProgram.release(); } } @@ -1080,6 +1087,7 @@ glm::vec3 VoxelSystem::computeVoxelVertex(const glm::vec3& startVertex, float vo } ProgramObject VoxelSystem::_perlinModulateProgram; +ProgramObject VoxelSystem::_shadowMapProgram; void VoxelSystem::init() { if (_initialized) { @@ -1388,6 +1396,7 @@ void VoxelSystem::render(bool texture) { void VoxelSystem::applyScaleAndBindProgram(bool texture) { if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { + _shadowMapProgram.bind(); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); @@ -1412,6 +1421,7 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { glPopMatrix(); if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { + _shadowMapProgram.release(); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 0fdbb5b884..d9c672fdf3 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -282,6 +282,7 @@ private: bool _voxelsDirty; static ProgramObject _perlinModulateProgram; + static ProgramObject _shadowMapProgram; int _hookID; std::vector _freeIndexes; From 898135fbf257b17b4fe4fc22005a0fdf2325a190 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 21 Nov 2013 13:36:16 -0800 Subject: [PATCH 06/10] Linear filtering for more smoothness. --- interface/src/renderer/TextureCache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index 4e346b6dff..778fb8fb12 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -190,8 +190,8 @@ QOpenGLFramebufferObject* TextureCache::getShadowFramebufferObject() { glBindTexture(GL_TEXTURE_2D, _shadowDepthTextureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); const float DISTANT_BORDER[] = { 1.0f, 1.0f, 1.0f, 1.0f }; From 3137e9a3e6e32d6182b727a4ee94cc40c0d13ca0 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 21 Nov 2013 13:57:55 -0800 Subject: [PATCH 07/10] Don't leave out the head when we draw our shadow. --- interface/src/Application.cpp | 13 ++++++------- interface/src/Application.h | 4 ++-- interface/src/avatar/Avatar.cpp | 16 ++++++++-------- interface/src/avatar/Avatar.h | 6 +++--- interface/src/avatar/Hand.cpp | 4 +--- interface/src/avatar/Hand.h | 3 +-- interface/src/avatar/MyAvatar.cpp | 18 +++++++++--------- interface/src/avatar/MyAvatar.h | 6 +++--- 8 files changed, 33 insertions(+), 37 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a6a5a9e20f..b0d4611ac1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1876,7 +1876,7 @@ bool Application::isLookingAtMyAvatar(Avatar* avatar) { return false; } -void Application::renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera) { +void Application::renderLookatIndicator(glm::vec3 pointOfInterest) { const float DISTANCE_FROM_HEAD_SPHERE = 0.1f * _lookatIndicatorScale; const float INDICATOR_RADIUS = 0.1f * _lookatIndicatorScale; @@ -2822,7 +2822,7 @@ void Application::updateShadowMap() { glTranslatef(translation.x, translation.y, translation.z); - renderAvatars(_myCamera); + renderAvatars(true); glPopMatrix(); @@ -3182,7 +3182,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { _myAvatar.renderScreenTint(SCREEN_TINT_BEFORE_AVATARS); - renderAvatars(whichCamera, selfAvatarOnly); + renderAvatars(whichCamera.getMode() == CAMERA_MODE_MIRROR, selfAvatarOnly); _myAvatar.renderScreenTint(SCREEN_TINT_AFTER_AVATARS); @@ -3806,7 +3806,7 @@ void Application::renderCoverageMapsRecursively(CoverageMap* map) { } } -void Application::renderAvatars(Camera& whichCamera, bool selfAvatarOnly) { +void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { if (!Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { return; } @@ -3834,12 +3834,11 @@ void Application::renderAvatars(Camera& whichCamera, bool selfAvatarOnly) { } // Render my own Avatar - _myAvatar.render(whichCamera.getMode() == CAMERA_MODE_MIRROR, - Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); + _myAvatar.render(forceRenderHead, Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); _myAvatar.setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); if (Menu::getInstance()->isOptionChecked(MenuOption::LookAtIndicator) && _lookatTargetAvatar) { - renderLookatIndicator(_lookatOtherPosition, whichCamera); + renderLookatIndicator(_lookatOtherPosition); } } diff --git a/interface/src/Application.h b/interface/src/Application.h index c91d17ecff..981938f221 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -262,7 +262,7 @@ private: glm::vec3& eyePosition, QUuid &nodeUUID); bool isLookingAtMyAvatar(Avatar* avatar); - void renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera); + void renderLookatIndicator(glm::vec3 pointOfInterest); void renderFollowIndicator(); void updateAvatar(float deltaTime); void updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm::vec3 mouseRayDirection); @@ -276,7 +276,7 @@ private: void displaySide(Camera& whichCamera, bool selfAvatarOnly = false); void displayOverlay(); void displayStats(); - void renderAvatars(Camera& whichCamera, bool selfAvatarOnly = false); + void renderAvatars(bool forceRenderHead, bool selfAvatarOnly = false); void renderViewFrustum(ViewFrustum& viewFrustum); void checkBandwidthMeterClick(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 829c4f4464..44e1f0aad1 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -439,7 +439,7 @@ static TextRenderer* textRenderer() { return renderer; } -void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) { +void Avatar::render(bool forceRenderHead, bool renderAvatarBalls) { if (Application::getInstance()->getAvatar()->getHand().isRaveGloveActive()) { _hand.setRaveLights(RAVE_LIGHTS_AVATAR); @@ -455,7 +455,7 @@ void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) { Glower glower(_moving && glm::length(toTarget) > GLOW_DISTANCE ? 1.0f : 0.0f); // render body - renderBody(lookingInMirror, renderAvatarBalls); + renderBody(forceRenderHead, renderAvatarBalls); // render sphere when far away const float MAX_ANGLE = 10.f; @@ -709,15 +709,15 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { return glm::angleAxis(angle * proportion, axis); } -float Avatar::getBallRenderAlpha(int ball, bool lookingInMirror) const { +float Avatar::getBallRenderAlpha(int ball, bool forceRenderHead) const { return 1.0f; } -void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { +void Avatar::renderBody(bool forceRenderHead, bool renderAvatarBalls) { if (_head.getVideoFace().isFullFrame()) { // Render the full-frame video - float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, lookingInMirror); + float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, forceRenderHead); if (alpha > 0.0f) { _head.getVideoFace().render(1.0f); } @@ -726,7 +726,7 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { glm::vec3 skinColor, darkSkinColor; getSkinColors(skinColor, darkSkinColor); for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - float alpha = getBallRenderAlpha(b, lookingInMirror); + float alpha = getBallRenderAlpha(b, forceRenderHead); // When we have leap hands, hide part of the arms. if (_hand.getNumPalms() > 0) { @@ -779,7 +779,7 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { } } else { // Render the body's voxels and head - float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, lookingInMirror); + float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, forceRenderHead); if (alpha > 0.0f) { if (!_skeletonModel.render(alpha)) { _voxels.render(false); @@ -787,7 +787,7 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { _head.render(alpha, false); } } - _hand.render(lookingInMirror); + _hand.render(); } void Avatar::getSkinColors(glm::vec3& lighter, glm::vec3& darker) { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index aad3e4ce72..d633871891 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -141,7 +141,7 @@ public: void init(); void simulate(float deltaTime, Transmitter* transmitter); void follow(Avatar* leadingAvatar); - void render(bool lookingInMirror, bool renderAvatarBalls); + void render(bool forceRenderHead, bool renderAvatarBalls); //setters void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors); } @@ -255,8 +255,8 @@ private: // private methods... glm::vec3 calculateAverageEyePosition() { return _head.calculateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat) - float getBallRenderAlpha(int ball, bool lookingInMirror) const; - void renderBody(bool lookingInMirror, bool renderAvatarBalls); + float getBallRenderAlpha(int ball, bool forceRenderHead) const; + void renderBody(bool forceRenderHead, bool renderAvatarBalls); void initializeBodyBalls(); void resetBodyBalls(); void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement); diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index ae22752acb..43fc8cc0de 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -24,7 +24,6 @@ Hand::Hand(Avatar* owningAvatar) : _raveGloveInitialized(false), _owningAvatar(owningAvatar), _renderAlpha(1.0), - _lookingInMirror(false), _ballColor(0.0, 0.0, 0.4) { // initialize all finger particle emitters with an invalid id as default @@ -133,10 +132,9 @@ void Hand::setRaveGloveEffectsMode(QKeyEvent* event) { }; } -void Hand::render(bool lookingInMirror) { +void Hand::render() { _renderAlpha = 1.0; - _lookingInMirror = lookingInMirror; if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayLeapHands)) { if (!isRaveGloveActive()) { diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 145ec67c15..36573cfc86 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -50,7 +50,7 @@ public: void init(); void reset(); void simulate(float deltaTime, bool isMine); - void render(bool lookingInMirror); + void render(); void renderRaveGloveStage(); void setRaveLights(RaveLightsSetting setting); @@ -75,7 +75,6 @@ private: Avatar* _owningAvatar; float _renderAlpha; - bool _lookingInMirror; glm::vec3 _ballColor; std::vector _leapFingerTipBalls; std::vector _leapFingerRootBalls; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index d229e784e8..87f5165f1a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -485,7 +485,7 @@ static TextRenderer* textRenderer() { return renderer; } -void MyAvatar::render(bool lookingInMirror, bool renderAvatarBalls) { +void MyAvatar::render(bool forceRenderHead, bool renderAvatarBalls) { if (Application::getInstance()->getAvatar()->getHand().isRaveGloveActive()) { _hand.setRaveLights(RAVE_LIGHTS_AVATAR); @@ -495,7 +495,7 @@ void MyAvatar::render(bool lookingInMirror, bool renderAvatarBalls) { renderDiskShadow(_position, glm::vec3(0.0f, 1.0f, 0.0f), _scale * 0.1f, 0.2f); // render body - renderBody(lookingInMirror, renderAvatarBalls); + renderBody(forceRenderHead, renderAvatarBalls); // if this is my avatar, then render my interactions with the other avatar _avatarTouch.render(Application::getInstance()->getCamera()->getPosition()); @@ -623,19 +623,19 @@ glm::vec3 MyAvatar::getEyeLevelPosition() const { glm::vec3(0.0f, _pelvisToHeadLength + _scale * BODY_BALL_RADIUS_HEAD_BASE * EYE_UP_OFFSET, 0.0f); } -float MyAvatar::getBallRenderAlpha(int ball, bool lookingInMirror) const { +float MyAvatar::getBallRenderAlpha(int ball, bool forceRenderHead) const { const float RENDER_OPAQUE_OUTSIDE = _scale * 0.25f; // render opaque if greater than this distance const float DO_NOT_RENDER_INSIDE = _scale * 0.25f; // do not render if less than this distance float distanceToCamera = glm::length(Application::getInstance()->getCamera()->getPosition() - _bodyBall[ball].position); - return (lookingInMirror) ? 1.0f : glm::clamp( + return (forceRenderHead) ? 1.0f : glm::clamp( (distanceToCamera - DO_NOT_RENDER_INSIDE) / (RENDER_OPAQUE_OUTSIDE - DO_NOT_RENDER_INSIDE), 0.f, 1.f); } -void MyAvatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { +void MyAvatar::renderBody(bool forceRenderHead, bool renderAvatarBalls) { if (_head.getVideoFace().isFullFrame()) { // Render the full-frame video - float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, lookingInMirror); + float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, forceRenderHead); if (alpha > 0.0f) { _head.getVideoFace().render(1.0f); } @@ -644,7 +644,7 @@ void MyAvatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { glm::vec3 skinColor, darkSkinColor; getSkinColors(skinColor, darkSkinColor); for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - float alpha = getBallRenderAlpha(b, lookingInMirror); + float alpha = getBallRenderAlpha(b, forceRenderHead); // When we have leap hands, hide part of the arms. if (_hand.getNumPalms() > 0) { @@ -710,12 +710,12 @@ void MyAvatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { if (!_skeletonModel.render(1.0f)) { _voxels.render(false); } - float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, lookingInMirror); + float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, forceRenderHead); if (alpha > 0.0f) { _head.render(alpha, true); } } - _hand.render(lookingInMirror); + _hand.render(); } void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 3747bb307e..b5f735a93e 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -20,7 +20,7 @@ public: void reset(); void simulate(float deltaTime, Transmitter* transmitter); void updateFromGyrosAndOrWebcam(float pitchFromTouch, bool turnWithHead); - void render(bool lookingInMirror, bool renderAvatarBalls); + void render(bool forceRenderHead, bool renderAvatarBalls); void renderScreenTint(ScreenTintLayer layer); // setters @@ -84,8 +84,8 @@ private: int _moveTargetStepCounter; // private methods - float getBallRenderAlpha(int ball, bool lookingInMirror) const; - void renderBody(bool lookingInMirror, bool renderAvatarBalls); + float getBallRenderAlpha(int ball, bool forceRenderHead) const; + void renderBody(bool forceRenderHead, bool renderAvatarBalls); void updateThrust(float deltaTime, Transmitter * transmitter); void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement); void updateAvatarCollisions(float deltaTime); From 053d6b1e7187d60da17a3ccff6da337b3b7c1bd9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 21 Nov 2013 14:01:12 -0800 Subject: [PATCH 08/10] Fix for Leap drive enabled without Leap. --- interface/src/devices/LeapManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/LeapManager.cpp b/interface/src/devices/LeapManager.cpp index b0f6f6077f..b4e745420d 100644 --- a/interface/src/devices/LeapManager.cpp +++ b/interface/src/devices/LeapManager.cpp @@ -271,7 +271,7 @@ void LeapManager::nextFrame() { hand.updateFingerTrails(); // if Leap drive is enabled, drive avatar based on Leap input - if (!Menu::getInstance()->isOptionChecked(MenuOption::LeapDrive)) { + if (!(Menu::getInstance()->isOptionChecked(MenuOption::LeapDrive) && gotRealData)) { return; } glm::vec3 relativePosition; From 88a84c733e3df7ba16e85432b77a2f558746ec79 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 21 Nov 2013 14:14:09 -0800 Subject: [PATCH 09/10] Stretch out shadow volume to encompass all avatars. --- interface/src/Application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b0d4611ac1..085725ba07 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2800,6 +2800,10 @@ void Application::updateShadowMap() { maxima = glm::max(maxima, points[i]); } + // stretch out our extents in z so that we get all of the avatars + minima.z -= _viewFrustum.getFarClip() * 0.5f; + maxima.z += _viewFrustum.getFarClip() * 0.5f; + // save the combined matrix for rendering _shadowMatrix = glm::transpose(glm::translate(0.5f, 0.5f, 0.5f) * glm::scale(0.5f, 0.5f, 0.5f) * glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) * From b04a249079bef59e0fd0e729f4fb8cdfcadc21fe Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 21 Nov 2013 14:24:30 -0800 Subject: [PATCH 10/10] Make this a constant. --- interface/src/Application.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 085725ba07..becaf2cc5b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2783,7 +2783,8 @@ void Application::updateShadowMap() { glm::quat rotation = glm::inverse(rotationBetween(IDENTITY_FRONT, lightDirection)); glm::vec3 translation = glm::vec3(); float nearScale = 0.0f; - float farScale = (2.0f - _viewFrustum.getNearClip()) / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); + const float MAX_SHADOW_DISTANCE = 2.0f; + float farScale = (MAX_SHADOW_DISTANCE - _viewFrustum.getNearClip()) / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); loadViewFrustum(_myCamera, _viewFrustum); glm::vec3 points[] = { rotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale) + translation),