From 321447ca6a13292e42f228bf54131f4862f3a28c Mon Sep 17 00:00:00 2001 From: Studio Date: Sun, 12 Jul 2015 14:44:38 -0400 Subject: [PATCH 01/35] Change default value of output buffer size frames to 20 as a default and added functionality to increase to 40. --- libraries/audio-client/src/AudioClient.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index aeea7c07c1..3a85adbc97 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -55,9 +55,9 @@ static const int NUM_AUDIO_CHANNELS = 2; -static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; +static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; -static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; +static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 40; #if defined(Q_OS_ANDROID) || defined(Q_OS_WIN) static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = false; #else From b93ae7b5273dcf305fc9ebdc5e57b7b3261641e2 Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Wed, 15 Jul 2015 19:25:18 -0400 Subject: [PATCH 02/35] Move reload content item to developer menu. --- interface/src/Menu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8b14830c2d..6fe3a4dff9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -255,8 +255,6 @@ Menu::Menu() { avatar, SLOT(updateMotionBehavior())); MenuWrapper* viewMenu = addMenu("View"); - - addActionToQMenuAndActionHash(viewMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Fullscreen, @@ -329,6 +327,8 @@ Menu::Menu() { MenuWrapper* developerMenu = addMenu("Developer"); + addActionToQMenuAndActionHash(developerMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); + MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render"); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, 0, // QML Qt::SHIFT | Qt::Key_A, From 671263909a6db098f1f28c49d828682e7b9acbfb Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Wed, 15 Jul 2015 19:47:37 -0400 Subject: [PATCH 03/35] Moved reload content item to nested Network menu item. --- interface/src/Menu.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6fe3a4dff9..7315c02825 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -327,8 +327,6 @@ Menu::Menu() { MenuWrapper* developerMenu = addMenu("Developer"); - addActionToQMenuAndActionHash(developerMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); - MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render"); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, 0, // QML Qt::SHIFT | Qt::Key_A, @@ -491,6 +489,7 @@ Menu::Menu() { #endif MenuWrapper* networkMenu = developerMenu->addMenu("Network"); + addActionToQMenuAndActionHash(networkMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableNackPackets, 0, false); addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableActivityLogger, From 5d7485850049d43f5a426c13e0c3699680ed46d0 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 21 Jul 2015 17:01:54 +0200 Subject: [PATCH 04/35] edit.js - entityList - delete key deletes entities, hold shift to select a group of entities, moved appending single entity to selection to ctrl key --- examples/html/entityList.html | 37 ++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/examples/html/entityList.html b/examples/html/entityList.html index 9506c78994..62bbbd08a6 100644 --- a/examples/html/entityList.html +++ b/examples/html/entityList.html @@ -35,8 +35,32 @@ function onRowClicked(e) { var id = this.dataset.entityId; var selection = [this.dataset.entityId]; - if (e.shiftKey) { + if (e.ctrlKey) { selection = selection.concat(selectedEntities); + } else if (e.shiftKey && selectedEntities.length > 0) { + var previousItemFound = -1; + var clickedItemFound = -1; + for (var i in entityList.visibleItems) { + if (clickedItemFound === -1 && this.dataset.entityId == entityList.visibleItems[i].values().id) { + clickedItemFound = i; + } else if(previousItemFound === -1 && selectedEntities[0] == entityList.visibleItems[i].values().id) { + previousItemFound = i; + } + } + if (previousItemFound !== -1 && clickedItemFound !== -1) { + var betweenItems = []; + var toItem = Math.max(previousItemFound, clickedItemFound); + // skip first and last item in this loop, we add them to selection after the loop + for (var i = (Math.min(previousItemFound, clickedItemFound) + 1); i < toItem; i++) { + entityList.visibleItems[i].elm.className = 'selected'; + betweenItems.push(entityList.visibleItems[i].values().id); + } + if (previousItemFound > clickedItemFound) { + // always make sure that we add the items in the right order + betweenItems.reverse(); + } + selection = selection.concat(betweenItems, selectedEntities); + } } selectedEntities = selection; @@ -151,6 +175,17 @@ refreshEntities(); } + document.addEventListener("keydown", function (e) { + if (e.target.nodeName === "INPUT") { + return; + } + var keyCode = e.keyCode; + if (keyCode === 46) { + EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' })); + refreshEntities(); + } + }, false); + if (window.EventBridge !== undefined) { EventBridge.scriptEventReceived.connect(function(data) { data = JSON.parse(data); From 9ac4e2f6877f9bd56112b40d1fc39064427c43a8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 21 Jul 2015 18:22:27 -0700 Subject: [PATCH 05/35] Render spheres over avatar eyes if they're looking at me --- interface/src/avatar/Avatar.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 3a55e73fa6..f9a1185e24 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -448,36 +448,35 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo } } - // Stack indicator spheres - float indicatorOffset = 0.0f; - if (!_displayName.isEmpty() && _displayNameAlpha != 0.0f) { - const float DISPLAY_NAME_INDICATOR_OFFSET = 0.22f; - indicatorOffset = DISPLAY_NAME_INDICATOR_OFFSET; - } - const float INDICATOR_RADIUS = 0.03f; - const float INDICATOR_INDICATOR_OFFSET = 3.0f * INDICATOR_RADIUS; - // If this is the avatar being looked at, render a little ball above their head if (_isLookAtTarget && Menu::getInstance()->isOptionChecked(MenuOption::RenderFocusIndicator)) { + const float INDICATOR_OFFSET = 0.22f; + const float INDICATOR_RADIUS = 0.03f; const glm::vec4 LOOK_AT_INDICATOR_COLOR = { 0.8f, 0.0f, 0.0f, 0.75f }; - glm::vec3 position = glm::vec3(_position.x, getDisplayNamePosition().y + indicatorOffset, _position.z); + glm::vec3 position = glm::vec3(_position.x, getDisplayNamePosition().y + INDICATOR_OFFSET, _position.z); Transform transform; transform.setTranslation(position); batch.setModelTransform(transform); DependencyManager::get()->renderSolidSphere(batch, INDICATOR_RADIUS, 15, 15, LOOK_AT_INDICATOR_COLOR); - indicatorOffset += INDICATOR_INDICATOR_OFFSET; } - // If the avatar is looking at me, render an indication that they area + // If the avatar is looking at me, indicate that they are if (getHead()->getIsLookingAtMe() && Menu::getInstance()->isOptionChecked(MenuOption::ShowWhosLookingAtMe)) { - const glm::vec4 LOOKING_AT_ME_COLOR = { 0.8f, 0.65f, 0.0f, 0.1f }; - glm::vec3 position = glm::vec3(_position.x, getDisplayNamePosition().y + indicatorOffset, _position.z); + const glm::vec3 LOOKING_AT_ME_COLOR = { 1.0f, 1.0f, 1.0f }; + float alpha = 1.0f; + float radius = 0.035f; Transform transform; + glm::vec3 position = getHead()->getLeftEyePosition(); transform.setTranslation(position); batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, INDICATOR_RADIUS, - 15, 15, LOOKING_AT_ME_COLOR); + DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + position = getHead()->getRightEyePosition(); + transform.setTranslation(position); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); } // quick check before falling into the code below: From bed266dfe993469cb6252fccf90a6e48e00767a8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 21 Jul 2015 18:23:50 -0700 Subject: [PATCH 06/35] Fade looking-at-me eye spheres over half a second --- interface/src/avatar/Avatar.cpp | 31 ++++++++++++++++++------------- interface/src/avatar/Head.cpp | 4 ++++ interface/src/avatar/Head.h | 2 ++ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f9a1185e24..884540bf7c 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -464,19 +464,24 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo // If the avatar is looking at me, indicate that they are if (getHead()->getIsLookingAtMe() && Menu::getInstance()->isOptionChecked(MenuOption::ShowWhosLookingAtMe)) { const glm::vec3 LOOKING_AT_ME_COLOR = { 1.0f, 1.0f, 1.0f }; - float alpha = 1.0f; - float radius = 0.035f; - Transform transform; - glm::vec3 position = getHead()->getLeftEyePosition(); - transform.setTranslation(position); - batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); - position = getHead()->getRightEyePosition(); - transform.setTranslation(position); - batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + const float LOOKING_AT_ME_DURATION = 0.5f; // seconds + quint64 now = usecTimestampNow(); + float alpha = 1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) + / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND); + if (alpha > 0.0f) { + float radius = 0.035f; + Transform transform; + glm::vec3 position = getHead()->getLeftEyePosition(); + transform.setTranslation(position); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + position = getHead()->getRightEyePosition(); + transform.setTranslation(position); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + } } // quick check before falling into the code below: diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 43e68557ce..94a163e508 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -55,6 +55,7 @@ Head::Head(Avatar* owningAvatar) : _deltaLeanForward(0.0f), _isCameraMoving(false), _isLookingAtMe(false), + _isLookingAtMeStarted(0), _faceModel(this), _leftEyeLookAtID(DependencyManager::get()->allocateID()), _rightEyeLookAtID(DependencyManager::get()->allocateID()) @@ -323,6 +324,9 @@ glm::vec3 Head::getCorrectedLookAtPosition() { } void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { + if (!_isLookingAtMe) { + _isLookingAtMeStarted = usecTimestampNow(); + } _isLookingAtMe = true; _correctedLookAtPosition = correctedLookAtPosition; } diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index d7a8462693..58f6f14b0a 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -53,6 +53,7 @@ public: glm::vec3 getCorrectedLookAtPosition(); void clearCorrectedLookAtPosition() { _isLookingAtMe = false; } bool getIsLookingAtMe() { return _isLookingAtMe; } + quint64 getIsLookingAtMeStarted() { return _isLookingAtMeStarted; } float getScale() const { return _scale; } glm::vec3 getPosition() const { return _position; } @@ -139,6 +140,7 @@ private: bool _isCameraMoving; bool _isLookingAtMe; + quint64 _isLookingAtMeStarted; FaceModel _faceModel; glm::vec3 _correctedLookAtPosition; From 55683e0cd589d353b7367a0aaaace23203d42229 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 21 Jul 2015 18:24:47 -0700 Subject: [PATCH 07/35] Size looking-at-me eye spheres per avatar model dimensions --- interface/src/avatar/Avatar.cpp | 14 +++++++++----- libraries/fbx/src/FBXReader.cpp | 9 ++++++++- libraries/fbx/src/FBXReader.h | 5 ++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 884540bf7c..ba0e0126ba 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -469,18 +469,22 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo float alpha = 1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND); if (alpha > 0.0f) { - float radius = 0.035f; + const float RADIUS_INCREMENT = 0.005f; Transform transform; + glm::vec3 position = getHead()->getLeftEyePosition(); transform.setTranslation(position); batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + DependencyManager::get()->renderSolidSphere(batch, + getHead()->getFaceModel().getGeometry()->getFBXGeometry().leftEyeSize * _scale / 2.0f + RADIUS_INCREMENT, + 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + position = getHead()->getRightEyePosition(); transform.setTranslation(position); batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, radius, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + DependencyManager::get()->renderSolidSphere(batch, + getHead()->getFaceModel().getGeometry()->getFBXGeometry().rightEyeSize * _scale / 2.0f + RADIUS_INCREMENT, + 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); } } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 4d7bff4df0..466b3de3ee 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -2616,10 +2616,17 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, buildModelMesh(extracted); # endif + if (extracted.mesh.isEye) { + if (maxJointIndex == geometry.leftEyeJointIndex) { + geometry.leftEyeSize = extracted.mesh.meshExtents.largestDimension() * offsetScale; + } else { + geometry.rightEyeSize = extracted.mesh.meshExtents.largestDimension() * offsetScale; + } + } + geometry.meshes.append(extracted.mesh); int meshIndex = geometry.meshes.size() - 1; meshIDsToMeshIndices.insert(it.key(), meshIndex); - } // now that all joints have been scanned, compute a collision shape for each joint diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 200cd4a121..3b3d90eb05 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -232,7 +232,10 @@ public: int rightHandJointIndex = -1; int leftToeJointIndex = -1; int rightToeJointIndex = -1; - + + float leftEyeSize = 0.0f; // Maximum mesh extents dimension + float rightEyeSize = 0.0f; + QVector humanIKJointIndices; glm::vec3 palmDirection; From 87dbbdb2e8a4c740f9c37b76cdd6fcba2c4983c5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 21 Jul 2015 18:25:35 -0700 Subject: [PATCH 08/35] Set an initial alpha in anticipation of sphere alpha working --- interface/src/avatar/Avatar.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ba0e0126ba..6aa70196bd 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -464,10 +464,12 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo // If the avatar is looking at me, indicate that they are if (getHead()->getIsLookingAtMe() && Menu::getInstance()->isOptionChecked(MenuOption::ShowWhosLookingAtMe)) { const glm::vec3 LOOKING_AT_ME_COLOR = { 1.0f, 1.0f, 1.0f }; + const float LOOKING_AT_ME_ALPHA_START = 0.8f; const float LOOKING_AT_ME_DURATION = 0.5f; // seconds quint64 now = usecTimestampNow(); - float alpha = 1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) - / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND); + float alpha = LOOKING_AT_ME_ALPHA_START + * (1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) + / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND)); if (alpha > 0.0f) { const float RADIUS_INCREMENT = 0.005f; Transform transform; From e44cba500dc90ec00af72269be3a6df90dc06502 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 22 Jul 2015 09:52:49 -0700 Subject: [PATCH 09/35] Guard against head model not being available yet --- interface/src/avatar/Avatar.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 6aa70196bd..e30c2ac24d 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -471,22 +471,26 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo * (1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND)); if (alpha > 0.0f) { - const float RADIUS_INCREMENT = 0.005f; - Transform transform; + QSharedPointer geometry = getHead()->getFaceModel().getGeometry(); + if (geometry) { + const float RADIUS_INCREMENT = 0.005f; + Transform transform; - glm::vec3 position = getHead()->getLeftEyePosition(); - transform.setTranslation(position); - batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, - getHead()->getFaceModel().getGeometry()->getFBXGeometry().leftEyeSize * _scale / 2.0f + RADIUS_INCREMENT, - 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + glm::vec3 position = getHead()->getLeftEyePosition(); + transform.setTranslation(position); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphere(batch, + geometry->getFBXGeometry().leftEyeSize * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); - position = getHead()->getRightEyePosition(); - transform.setTranslation(position); - batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, - getHead()->getFaceModel().getGeometry()->getFBXGeometry().rightEyeSize * _scale / 2.0f + RADIUS_INCREMENT, - 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + position = getHead()->getRightEyePosition(); + transform.setTranslation(position); + batch.setModelTransform(transform); + DependencyManager::get()->renderSolidSphere(batch, + geometry->getFBXGeometry().rightEyeSize * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, + glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + + } } } From 9d33cfa9650eabbe07e54bcf027a8145ac083f7b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 22 Jul 2015 09:53:37 -0700 Subject: [PATCH 10/35] Allow for look-at positions being not quite up to date as avatars move So that looking-at-me indicators don't flicker on when they shouldn't. --- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/Head.cpp | 17 +++++++++++++---- interface/src/avatar/Head.h | 9 +++++---- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e30c2ac24d..1fee720ad4 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -462,13 +462,13 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo } // If the avatar is looking at me, indicate that they are - if (getHead()->getIsLookingAtMe() && Menu::getInstance()->isOptionChecked(MenuOption::ShowWhosLookingAtMe)) { + if (getHead()->isLookingAtMe() && Menu::getInstance()->isOptionChecked(MenuOption::ShowWhosLookingAtMe)) { const glm::vec3 LOOKING_AT_ME_COLOR = { 1.0f, 1.0f, 1.0f }; const float LOOKING_AT_ME_ALPHA_START = 0.8f; const float LOOKING_AT_ME_DURATION = 0.5f; // seconds quint64 now = usecTimestampNow(); float alpha = LOOKING_AT_ME_ALPHA_START - * (1.0f - ((float)(usecTimestampNow() - getHead()->getIsLookingAtMeStarted())) + * (1.0f - ((float)(usecTimestampNow() - getHead()->getLookingAtMeStarted())) / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND)); if (alpha > 0.0f) { QSharedPointer geometry = getHead()->getFaceModel().getGeometry(); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 94a163e508..d4ef793ab3 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -55,7 +55,8 @@ Head::Head(Avatar* owningAvatar) : _deltaLeanForward(0.0f), _isCameraMoving(false), _isLookingAtMe(false), - _isLookingAtMeStarted(0), + _lookingAtMeStarted(0), + _wasLastLookingAtMe(0), _faceModel(this), _leftEyeLookAtID(DependencyManager::get()->allocateID()), _rightEyeLookAtID(DependencyManager::get()->allocateID()) @@ -316,7 +317,7 @@ glm::quat Head::getFinalOrientationInLocalFrame() const { } glm::vec3 Head::getCorrectedLookAtPosition() { - if (_isLookingAtMe) { + if (isLookingAtMe()) { return _correctedLookAtPosition; } else { return getLookAtPosition(); @@ -324,13 +325,21 @@ glm::vec3 Head::getCorrectedLookAtPosition() { } void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { - if (!_isLookingAtMe) { - _isLookingAtMeStarted = usecTimestampNow(); + if (!isLookingAtMe()) { + _lookingAtMeStarted = usecTimestampNow(); } _isLookingAtMe = true; + _wasLastLookingAtMe = usecTimestampNow(); _correctedLookAtPosition = correctedLookAtPosition; } +bool Head::isLookingAtMe() { + // Allow for outages such as may be encountered during avatar movement + quint64 now = usecTimestampNow(); + const quint64 LOOKING_AT_ME_GAP_ALLOWED = 1000000; // microseconds + return _isLookingAtMe || (now - _wasLastLookingAtMe) < LOOKING_AT_ME_GAP_ALLOWED; +} + glm::quat Head::getCameraOrientation() const { // NOTE: Head::getCameraOrientation() is not used for orienting the camera "view" while in Oculus mode, so // you may wonder why this code is here. This method will be called while in Oculus mode to determine how diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 58f6f14b0a..a8161d1c7b 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -52,9 +52,9 @@ public: void setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition); glm::vec3 getCorrectedLookAtPosition(); void clearCorrectedLookAtPosition() { _isLookingAtMe = false; } - bool getIsLookingAtMe() { return _isLookingAtMe; } - quint64 getIsLookingAtMeStarted() { return _isLookingAtMeStarted; } - + bool isLookingAtMe(); + quint64 getLookingAtMeStarted() { return _lookingAtMeStarted; } + float getScale() const { return _scale; } glm::vec3 getPosition() const { return _position; } const glm::vec3& getEyePosition() const { return _eyePosition; } @@ -140,7 +140,8 @@ private: bool _isCameraMoving; bool _isLookingAtMe; - quint64 _isLookingAtMeStarted; + quint64 _lookingAtMeStarted; + quint64 _wasLastLookingAtMe; FaceModel _faceModel; glm::vec3 _correctedLookAtPosition; From 3350d638dd5cd2b8fc5983bafab2aca92746a8cc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 23 Jul 2015 09:29:27 -0700 Subject: [PATCH 11/35] always use the _viewFrustum for caluclating the pick ray, not the _displayViewFrustum which can be the mirror --- interface/src/Application.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8f825a2768..3130e172af 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2963,11 +2963,7 @@ PickRay Application::computePickRay(float x, float y) const { if (isHMDMode()) { getApplicationCompositor().computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction); } else { - if (QThread::currentThread() == activeRenderingThread) { - getDisplayViewFrustum()->computePickRay(x, y, result.origin, result.direction); - } else { - getViewFrustum()->computePickRay(x, y, result.origin, result.direction); - } + getViewFrustum()->computePickRay(x, y, result.origin, result.direction); } return result; } From f4ec09a48b935ebbef05c66d90d5c57276dd781a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 23 Jul 2015 10:42:22 -0700 Subject: [PATCH 12/35] move renderLaserPointers() into a draw item --- interface/src/Application.cpp | 4 ---- interface/src/avatar/MyAvatar.cpp | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8f825a2768..2ea923db2d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3295,10 +3295,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se sceneInterface->setEngineFeedOverlay3DItems(engineRC->_numFeedOverlay3DItems); sceneInterface->setEngineDrawnOverlay3DItems(engineRC->_numDrawnOverlay3DItems); } - //Render the sixense lasers - if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { - _myAvatar->renderLaserPointers(*renderArgs->_batch); - } if (!selfAvatarOnly) { // give external parties a change to hook in diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ac0cb3feda..2a5e92014c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -345,6 +345,11 @@ void MyAvatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { renderArgs && renderArgs->_batch) { _skeletonModel.renderIKConstraints(*renderArgs->_batch); } + + //Render the sixense lasers + if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { + renderLaserPointers(*renderArgs->_batch); + } } const glm::vec3 HAND_TO_PALM_OFFSET(0.0f, 0.12f, 0.08f); From 7c4f6b665bcd614cc6739fd1e28531621385cec4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 23 Jul 2015 11:04:58 -0700 Subject: [PATCH 13/35] Use a default eye diameter for models without eyes, e.g., the masks --- interface/src/avatar/Avatar.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index bf41449f13..9f457e558d 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -468,22 +468,29 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { if (alpha > 0.0f) { QSharedPointer geometry = getHead()->getFaceModel().getGeometry(); if (geometry) { + const float DEFAULT_EYE_DIAMETER = 0.048f; // Typical human eye const float RADIUS_INCREMENT = 0.005f; Transform transform; glm::vec3 position = getHead()->getLeftEyePosition(); transform.setTranslation(position); batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, - geometry->getFBXGeometry().leftEyeSize * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + float eyeDiameter = geometry->getFBXGeometry().leftEyeSize; + if (eyeDiameter == 0.0f) { + eyeDiameter = DEFAULT_EYE_DIAMETER; + } + DependencyManager::get()->renderSolidSphere(batch, + eyeDiameter * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); position = getHead()->getRightEyePosition(); transform.setTranslation(position); batch.setModelTransform(transform); - DependencyManager::get()->renderSolidSphere(batch, - geometry->getFBXGeometry().rightEyeSize * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, - glm::vec4(LOOKING_AT_ME_COLOR, alpha)); + eyeDiameter = geometry->getFBXGeometry().rightEyeSize; + if (eyeDiameter == 0.0f) { + eyeDiameter = DEFAULT_EYE_DIAMETER; + } + DependencyManager::get()->renderSolidSphere(batch, + eyeDiameter * _scale / 2.0f + RADIUS_INCREMENT, 15, 15, glm::vec4(LOOKING_AT_ME_COLOR, alpha)); } } From 720f6ec529d7b9f023569599651cfd2d30742b36 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 23 Jul 2015 11:17:22 -0700 Subject: [PATCH 14/35] completely remove six sense lasers --- interface/src/Menu.cpp | 1 - interface/src/Menu.h | 1 - interface/src/avatar/MyAvatar.cpp | 5 ----- interface/src/devices/SixenseManager.cpp | 3 +-- interface/src/ui/ApplicationCompositor.cpp | 24 ++++++++-------------- 5 files changed, 10 insertions(+), 24 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 25f993d77e..ddc76663f4 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -478,7 +478,6 @@ Menu::Menu() { qApp, SLOT(setLowVelocityFilter(bool))); addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseMouseInput, 0, true); - addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseLasers, 0, false); MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion"); addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b6c2e47329..bf0f89abb5 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -272,7 +272,6 @@ namespace MenuOption { const QString SimpleShadows = "Simple"; const QString SixenseEnabled = "Enable Hydra Support"; const QString SixenseMouseInput = "Enable Sixense Mouse Input"; - const QString SixenseLasers = "Enable Sixense UI Lasers"; const QString ShiftHipsForIdleAnimations = "Shift hips for idle animations"; const QString Stars = "Stars"; const QString Stats = "Stats"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2a5e92014c..ac0cb3feda 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -345,11 +345,6 @@ void MyAvatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { renderArgs && renderArgs->_batch) { _skeletonModel.renderIKConstraints(*renderArgs->_batch); } - - //Render the sixense lasers - if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { - renderLaserPointers(*renderArgs->_batch); - } } const glm::vec3 HAND_TO_PALM_OFFSET(0.0f, 0.12f, 0.08f); diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 5ead0c4409..45fb2fa1ed 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -520,8 +520,7 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { triggerButton = Qt::LeftButton; } - if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers) - || Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { pos = qApp->getApplicationCompositor().getPalmClickLocation(palm); } else { // Get directon relative to avatar orientation diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index afdeb7b94e..de65817620 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -491,24 +491,18 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) { auto canvasSize = qApp->getCanvasSize(); int mouseX, mouseY; - if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { - QPoint res = getPalmClickLocation(palmData); - mouseX = res.x(); - mouseY = res.y(); - } else { - // Get directon relative to avatar orientation - glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection(); + // Get directon relative to avatar orientation + glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection(); - // Get the angles, scaled between (-0.5,0.5) - float xAngle = (atan2(direction.z, direction.x) + PI_OVER_TWO); - float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)PI_OVER_TWO)); + // Get the angles, scaled between (-0.5,0.5) + float xAngle = (atan2(direction.z, direction.x) + PI_OVER_TWO); + float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)PI_OVER_TWO)); - // Get the pixel range over which the xAngle and yAngle are scaled - float cursorRange = canvasSize.x * SixenseManager::getInstance().getCursorPixelRangeMult(); + // Get the pixel range over which the xAngle and yAngle are scaled + float cursorRange = canvasSize.x * SixenseManager::getInstance().getCursorPixelRangeMult(); - mouseX = (canvasSize.x / 2.0f + cursorRange * xAngle); - mouseY = (canvasSize.y / 2.0f + cursorRange * yAngle); - } + mouseX = (canvasSize.x / 2.0f + cursorRange * xAngle); + mouseY = (canvasSize.y / 2.0f + cursorRange * yAngle); //If the cursor is out of the screen then don't render it if (mouseX < 0 || mouseX >= (int)canvasSize.x || mouseY < 0 || mouseY >= (int)canvasSize.y) { From a561874ce3c918b87f0fda8cc69054e4f9ccba74 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 23 Jul 2015 14:56:14 -0700 Subject: [PATCH 15/35] Render the rear view mirror in a separate target and then display it during overlay pass --- interface/src/Application.cpp | 93 +++++++++++++++---- interface/src/Application.h | 2 + interface/src/avatar/MyAvatar.cpp | 1 + interface/src/ui/ApplicationOverlay.cpp | 30 ++++++ libraries/gpu/src/gpu/GLBackendOutput.cpp | 6 ++ .../src/DeferredLightingEffect.cpp | 10 +- .../render-utils/src/FramebufferCache.cpp | 9 +- libraries/render-utils/src/FramebufferCache.h | 7 ++ libraries/render-utils/src/GeometryCache.cpp | 14 ++- libraries/render-utils/src/GeometryCache.h | 3 +- 10 files changed, 147 insertions(+), 28 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7de69ef602..eebdf61c5b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -875,6 +875,33 @@ void Application::paintGL() { PerformanceWarning warn(showWarnings, "Application::paintGL()"); resizeGL(); + // Before anything else, let's sync up the gpuContext with the true glcontext used in case anything happened + renderArgs._context->syncCache(); + + if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); + { + gpu::Batch batch; + batch.setFramebuffer(nullptr); + batch.setFramebuffer(primaryFbo); + renderArgs._context->render(batch); + } + renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; + renderRearViewMirror(&renderArgs, _mirrorViewRect); + renderArgs._renderMode = RenderArgs::NORMAL_RENDER_MODE; + + { + auto mirrorViewport = glm::ivec4(0, 0, _mirrorViewRect.width(), _mirrorViewRect.height()); + float ratio = 1.0f / ((float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale()); + + auto mirrorViewportDest = glm::ivec4(0, 0, ratio * mirrorViewport.z, ratio * mirrorViewport.w); + + auto selfieFbo = DependencyManager::get()->getSelfieFramebuffer(); + gpu::Batch batch; + batch.blit(primaryFbo, mirrorViewport, selfieFbo, mirrorViewportDest); + renderArgs._context->render(batch); + } + } { PerformanceTimer perfTimer("renderOverlay"); @@ -936,7 +963,7 @@ void Application::paintGL() { } // Sync up the View Furstum with the camera - loadViewFrustum(_myCamera, _viewFrustum); + // loadViewFrustum(_myCamera, _viewFrustum); renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; @@ -974,19 +1001,17 @@ void Application::paintGL() { displaySide(&renderArgs, _myCamera); - if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; - renderRearViewMirror(&renderArgs, _mirrorViewRect); - renderArgs._renderMode = RenderArgs::NORMAL_RENDER_MODE; - } - { auto geometryCache = DependencyManager::get(); auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); gpu::Batch batch; batch.blit(primaryFbo, glm::ivec4(0, 0, _renderResolution.x, _renderResolution.y), nullptr, glm::ivec4(0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height())); + + batch.setFramebuffer(nullptr); + renderArgs._context->render(batch); + } _compositor.displayOverlayTexture(&renderArgs); @@ -2958,7 +2983,7 @@ PickRay Application::computePickRay(float x, float y) const { } QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { - auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); +/* auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer)); // clear the alpha channel so the background is transparent @@ -2966,17 +2991,41 @@ QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + */ - const int BILLBOARD_SIZE = 64; - // TODO: Pass a RenderArgs to renderAvatarBillboard - renderRearViewMirror(renderArgs, QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, + // const int BILLBOARD_SIZE = 64; + const int BILLBOARD_SIZE = 256; + _glWidget->makeCurrent(); + + auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); + + { + gpu::Batch batch; + batch.setFramebuffer(nullptr); + batch.setFramebuffer(primaryFbo); + renderArgs->_context->render(batch); + } + renderArgs->_renderMode = RenderArgs::MIRROR_RENDER_MODE; + renderRearViewMirror(renderArgs, QRect(0, /*_glWidget->getDeviceHeight() - BILLBOARD_SIZE*/ 0, BILLBOARD_SIZE, BILLBOARD_SIZE), - true); - QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); - glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + false); + renderArgs->_renderMode = RenderArgs::NORMAL_RENDER_MODE; + auto selfieFbo = DependencyManager::get()->getSelfieFramebuffer(); + { + auto mirrorViewport = glm::ivec4(0, 0,BILLBOARD_SIZE, BILLBOARD_SIZE); + gpu::Batch batch; + // batch.blit(primaryFbo, mirrorViewport, selfieFbo, mirrorViewport); + batch.setFramebuffer(nullptr); + renderArgs->_context->render(batch); + } + + + QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFbo)); + glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); glBindFramebuffer(GL_FRAMEBUFFER, 0); + return image; } @@ -3390,13 +3439,18 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi gpu::Vec4i viewport; if (billboard) { QSize size = DependencyManager::get()->getFrameBufferSize(); - viewport = gpu::Vec4i(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); + // viewport = gpu::Vec4i(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); + viewport = gpu::Vec4i(0, 0, region.width(), region.height()); } else { // if not rendering the billboard, the region is in device independent coordinates; must convert to device QSize size = DependencyManager::get()->getFrameBufferSize(); float ratio = (float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); - int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; - viewport = gpu::Vec4i(x, size.height() - y - height, width, height); + int x = region.x() * ratio; + int y = region.y() * ratio; + int width = region.width() * ratio; + int height = region.height() * ratio; + // viewport = gpu::Vec4i(x, size.height() - y - height, width, height); + viewport = gpu::Vec4i(0, 0, width, height); } renderArgs->_viewport = viewport; @@ -3414,8 +3468,7 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi renderArgs->_context->render(batch); } - bool updateViewFrustum = false; - loadViewFrustum(_mirrorCamera, _viewFrustum); + // loadViewFrustum(_mirrorCamera, _viewFrustum); // render rear mirror view displaySide(renderArgs, _mirrorCamera, true, billboard); diff --git a/interface/src/Application.h b/interface/src/Application.h index 3a07fb656d..b335b8a333 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -328,6 +328,8 @@ public: gpu::ContextPointer getGPUContext() const { return _gpuContext; } + const QRect& getMirrorViewRect() const { return _mirrorViewRect; } + signals: /// Fired when we're simulating; allows external parties to hook in. diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4147d24b15..f92c3c6700 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1539,6 +1539,7 @@ void MyAvatar::maybeUpdateBillboard() { QBuffer buffer(&_billboard); buffer.open(QIODevice::WriteOnly); image.save(&buffer, "PNG"); + image.save("billboard.png", "PNG"); _billboardValid = true; sendBillboardPacket(); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index a7f03db24f..d1154bda03 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture, and the text overlays from scripts renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope renderStatsAndLogs(renderArgs); // currently renders nothing + renderRearView(renderArgs); // renders the mirror view selfie renderArgs->_context->syncCache(); renderArgs->_context->render(batch); @@ -167,6 +169,34 @@ void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { } void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + gpu::Batch& batch = *renderArgs->_batch; + + auto geometryCache = DependencyManager::get(); + + auto framebuffer = DependencyManager::get(); + auto selfieTexture = framebuffer->getSelfieFramebuffer()->getRenderBuffer(0); + + int width = renderArgs->_viewport.z; + int height = renderArgs->_viewport.w; + mat4 legacyProjection = glm::ortho(0, width, height, 0, ORTHO_NEAR_CLIP, ORTHO_FAR_CLIP); + batch.setProjectionTransform(legacyProjection); + batch.setModelTransform(Transform()); + batch.setViewTransform(Transform()); + + auto viewport = qApp->getMirrorViewRect(); + glm::vec2 bottomLeft(viewport.left(), viewport.bottom()); + glm::vec2 topRight(viewport.right(), viewport.top()); + glm::vec2 texCoordMinCorner(0.0f, 0.0f); + glm::vec2 texCoordMaxCorner(viewport.width() / float(selfieTexture->getWidth()), viewport.height() / float(selfieTexture->getHeight())); + + geometryCache->useSimpleDrawPipeline(batch, false); + batch.setResourceTexture(0, renderArgs->_whiteTexture); + geometryCache->renderQuad(batch, bottomLeft, topRight, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); + geometryCache->useSimpleDrawPipeline(batch, true); + batch.setResourceTexture(0, selfieTexture); + geometryCache->renderQuad(batch, bottomLeft, topRight, texCoordMinCorner, texCoordMaxCorner, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); + } } void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) { diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 8876db95ac..621f04b71b 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -184,4 +184,10 @@ void GLBackend::do_blit(Batch& batch, uint32 paramOffset) { glBlitFramebuffer(srcvp.x, srcvp.y, srcvp.z, srcvp.w, dstvp.x, dstvp.y, dstvp.z, dstvp.w, GL_COLOR_BUFFER_BIT, GL_LINEAR); + + (void) CHECK_GL_ERROR(); + + if (_output._framebuffer) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(_output._framebuffer)); + } } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index e6f2b520c7..5680165969 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -217,11 +217,12 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu void DeferredLightingEffect::prepare(RenderArgs* args) { gpu::Batch batch; - + + batch.setStateScissorRect(args->_viewport); // clear the normal and specular buffers - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR1, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR1, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); const float MAX_SPECULAR_EXPONENT = 128.0f; - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR2, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT)); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR2, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT), true); args->_context->syncCache(); args->_context->render(batch); @@ -242,8 +243,9 @@ void DeferredLightingEffect::render(RenderArgs* args) { batch.setFramebuffer(_copyFBO); batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); - batch.clearColorFramebuffer(_copyFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); + batch.clearColorFramebuffer(_copyFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture()); diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index c7cb6451f7..0bcb54fe2c 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -39,6 +39,7 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) { _primaryColorTexture.reset(); _primaryNormalTexture.reset(); _primarySpecularTexture.reset(); + _selfieFramebuffer.reset(); _cachedFramebuffers.clear(); } } @@ -112,7 +113,6 @@ gpu::FramebufferPointer FramebufferCache::getFramebuffer() { return result; } - void FramebufferCache::releaseFramebuffer(const gpu::FramebufferPointer& framebuffer) { if (QSize(framebuffer->getSize().x, framebuffer->getSize().y) == _frameBufferSize) { _cachedFramebuffers.push_back(framebuffer); @@ -126,3 +126,10 @@ gpu::FramebufferPointer FramebufferCache::getShadowFramebuffer() { } return _shadowFramebuffer; } + +gpu::FramebufferPointer FramebufferCache::getSelfieFramebuffer() { + if (!_selfieFramebuffer) { + _selfieFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height())); + } + return _selfieFramebuffer; +} diff --git a/libraries/render-utils/src/FramebufferCache.h b/libraries/render-utils/src/FramebufferCache.h index ca01a470d9..d65c467be1 100644 --- a/libraries/render-utils/src/FramebufferCache.h +++ b/libraries/render-utils/src/FramebufferCache.h @@ -39,8 +39,12 @@ public: /// Returns the framebuffer object used to render shadow maps; gpu::FramebufferPointer getShadowFramebuffer(); + /// Returns the framebuffer object used to render selfie maps; + gpu::FramebufferPointer getSelfieFramebuffer(); + /// Returns a free framebuffer with a single color attachment for temp or intra-frame operations gpu::FramebufferPointer getFramebuffer(); + // TODO add sync functionality to the release, so we don't reuse a framebuffer being read from /// Releases a free framebuffer back for reuse void releaseFramebuffer(const gpu::FramebufferPointer& framebuffer); @@ -58,6 +62,9 @@ private: gpu::TexturePointer _primarySpecularTexture; gpu::FramebufferPointer _shadowFramebuffer; + + gpu::FramebufferPointer _selfieFramebuffer; + QSize _frameBufferSize{ 100, 100 }; }; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 6c03d57de3..d9b40a70f9 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1749,7 +1749,7 @@ QSharedPointer GeometryCache::createResource(const QUrl& url, const QS return geometry.staticCast(); } -void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch) { +void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) { if (!_standardDrawPipeline) { auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert))); auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(standardDrawTexture_frag))); @@ -1762,8 +1762,18 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch) { state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); _standardDrawPipeline.reset(gpu::Pipeline::create(program, state)); + + auto stateNoBlend = std::make_shared(); + stateNoBlend->setColorWriteMask(true, true, true, false); + stateNoBlend->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + + _standardDrawPipelineNoBlend.reset(gpu::Pipeline::create(program, stateNoBlend)); + } + if (noBlend) { + batch.setPipeline(_standardDrawPipelineNoBlend); + } else { + batch.setPipeline(_standardDrawPipeline); } - batch.setPipeline(_standardDrawPipeline); } const float NetworkGeometry::NO_HYSTERESIS = -1.0f; diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 147b4f8093..dbf9c4a95d 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -248,7 +248,7 @@ public: QSharedPointer getGeometry(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false); /// Set a batch to the simple pipeline, returning the previous pipeline - void useSimpleDrawPipeline(gpu::Batch& batch); + void useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend = false); protected: @@ -263,6 +263,7 @@ private: typedef QPair VerticesIndices; gpu::PipelinePointer _standardDrawPipeline; + gpu::PipelinePointer _standardDrawPipelineNoBlend; QHash _cubeVerticies; QHash _cubeColors; gpu::BufferPointer _wireCubeIndexBuffer; From be9d99264feec6b26df35820a86773af18e7133f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 23 Jul 2015 16:15:10 -0700 Subject: [PATCH 16/35] Introducing the download Framebuffer call on the context to capture a snapshot --- interface/src/Application.cpp | 26 ++++------------------- libraries/gpu/src/gpu/Batch.h | 1 - libraries/gpu/src/gpu/Context.cpp | 6 +++++- libraries/gpu/src/gpu/Context.h | 6 ++++++ libraries/gpu/src/gpu/Framebuffer.h | 2 -- libraries/gpu/src/gpu/GLBackend.h | 4 ++++ libraries/gpu/src/gpu/GLBackendOutput.cpp | 12 +++++++++++ 7 files changed, 31 insertions(+), 26 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e7479b94d8..ced6d2b301 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2998,18 +2998,8 @@ PickRay Application::computePickRay(float x, float y) const { } QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { -/* auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); - glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer)); - // clear the alpha channel so the background is transparent - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); - */ - - // const int BILLBOARD_SIZE = 64; - const int BILLBOARD_SIZE = 256; + const int BILLBOARD_SIZE = 64; _glWidget->makeCurrent(); auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); @@ -3020,26 +3010,18 @@ QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { batch.setFramebuffer(primaryFbo); renderArgs->_context->render(batch); } - renderArgs->_renderMode = RenderArgs::MIRROR_RENDER_MODE; - renderRearViewMirror(renderArgs, QRect(0, /*_glWidget->getDeviceHeight() - BILLBOARD_SIZE*/ 0, - BILLBOARD_SIZE, BILLBOARD_SIZE), - false); - renderArgs->_renderMode = RenderArgs::NORMAL_RENDER_MODE; + renderArgs->_renderMode = RenderArgs::NORMAL_RENDER_MODE; + renderRearViewMirror(renderArgs, QRect(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), true); - auto selfieFbo = DependencyManager::get()->getSelfieFramebuffer(); { auto mirrorViewport = glm::ivec4(0, 0,BILLBOARD_SIZE, BILLBOARD_SIZE); gpu::Batch batch; - // batch.blit(primaryFbo, mirrorViewport, selfieFbo, mirrorViewport); batch.setFramebuffer(nullptr); renderArgs->_context->render(batch); } - QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); - glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFbo)); - glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + renderArgs->_context->downloadFramebuffer(primaryFbo, glm::ivec4(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), image); return image; } diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 2f1d2e8ece..acc1f6fdac 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -108,7 +108,6 @@ public: void blit(const FramebufferPointer& src, const Vec4i& srcViewport, const FramebufferPointer& dst, const Vec4i& dstViewport); - // Query Section void beginQuery(const QueryPointer& query); void endQuery(const QueryPointer& query); diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 51335f78df..604f39f46f 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -40,4 +40,8 @@ void Context::render(Batch& batch) { void Context::syncCache() { PROFILE_RANGE(__FUNCTION__); _backend->syncCache(); -} \ No newline at end of file +} + +void Context::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) { + _backend->downloadFramebuffer(srcFramebuffer, region, destImage); +} diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 484c772c71..0c4ead6eae 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -28,6 +28,8 @@ public: virtual~ Backend() {}; virtual void render(Batch& batch) = 0; virtual void syncCache() = 0; + virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0; + class TransformObject { public: @@ -121,6 +123,10 @@ public: void syncCache(); + // Downloading the Framebuffer is a synchronous action that is not efficient. + // It s here for convenience to easily capture a snapshot + void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage); + protected: Context(const Context& context); diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index 5a1504d25c..c1b5358d3c 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -14,8 +14,6 @@ #include "Texture.h" #include -class QImage; - namespace gpu { typedef Element Format; diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 0e6f181028..c924395334 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -38,6 +38,10 @@ public: // Let's try to avoid to do that as much as possible! virtual void syncCache(); + // This is the ugly "download the pixels to sysmem for taking a snapshot" + // Just avoid using it, it's ugly and will break performances + virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage); + static bool checkGLError(const char* name = nullptr); // Only checks in debug builds diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 621f04b71b..ec1b9de341 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -11,6 +11,8 @@ #include "GPULogging.h" #include "GLBackendShared.h" +#include "qimage.h" + using namespace gpu; GLBackend::GLFramebuffer::GLFramebuffer() {} @@ -191,3 +193,13 @@ void GLBackend::do_blit(Batch& batch, uint32 paramOffset) { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(_output._framebuffer)); } } + + +void GLBackend::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) { + + glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(srcFramebuffer)); + glReadPixels(region.x, region.y, region.z, region.w, GL_BGRA, GL_UNSIGNED_BYTE, destImage.bits()); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + (void) CHECK_GL_ERROR(); +} \ No newline at end of file From d56b5f39fb3a3d9bb95bbbdd86bcb7a2e0aa221b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 23 Jul 2015 16:31:11 -0700 Subject: [PATCH 17/35] strenghening the checks in GLBackend::downloadFramebuffer before actually calling the true glReadPixels --- interface/src/Application.cpp | 2 -- libraries/gpu/src/gpu/GLBackendOutput.cpp | 22 ++++++++++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ced6d2b301..f073e5cb26 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3436,7 +3436,6 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi gpu::Vec4i viewport; if (billboard) { QSize size = DependencyManager::get()->getFrameBufferSize(); - // viewport = gpu::Vec4i(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); viewport = gpu::Vec4i(0, 0, region.width(), region.height()); } else { // if not rendering the billboard, the region is in device independent coordinates; must convert to device @@ -3446,7 +3445,6 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi int y = region.y() * ratio; int width = region.width() * ratio; int height = region.height() * ratio; - // viewport = gpu::Vec4i(x, size.height() - y - height, width, height); viewport = gpu::Vec4i(0, 0, width, height); } renderArgs->_viewport = viewport; diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index ec1b9de341..44dee90fa7 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -196,9 +196,27 @@ void GLBackend::do_blit(Batch& batch, uint32 paramOffset) { void GLBackend::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) { - + auto readFBO = gpu::GLBackend::getFramebufferID(srcFramebuffer); + if (srcFramebuffer && readFBO) { + if ((srcFramebuffer->getWidth() < (region.x + region.z)) || (srcFramebuffer->getHeight() < (region.y + region.w))) { + qCDebug(gpulogging) << "GLBackend::downloadFramebuffer : srcFramebuffer is too small to provide the region queried"; + return; + } + } + + if ((destImage.width() < region.z) || (destImage.height() < region.w)) { + qCDebug(gpulogging) << "GLBackend::downloadFramebuffer : destImage is too small to receive the region of the framebuffer"; + return; + } + + GLenum format = GL_BGRA; + if (destImage.format() != QImage::Format_ARGB32) { + qCDebug(gpulogging) << "GLBackend::downloadFramebuffer : destImage format must be FORMAT_ARGB32 to receive the region of the framebuffer"; + return; + } + glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(srcFramebuffer)); - glReadPixels(region.x, region.y, region.z, region.w, GL_BGRA, GL_UNSIGNED_BYTE, destImage.bits()); + glReadPixels(region.x, region.y, region.z, region.w, format, GL_UNSIGNED_BYTE, destImage.bits()); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); (void) CHECK_GL_ERROR(); From a424ff98ca06157d94ffa04c9be9221bf1f54d08 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 23 Jul 2015 16:55:18 -0700 Subject: [PATCH 18/35] Fixing issues with the review process --- interface/src/Application.cpp | 7 ++----- interface/src/avatar/MyAvatar.cpp | 2 ++ libraries/gpu/src/gpu/Context.h | 2 ++ libraries/gpu/src/gpu/GLBackendOutput.cpp | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f073e5cb26..efe208a1b8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -962,10 +962,6 @@ void Application::paintGL() { _myCamera.update(1.0f / _fps); } - // Sync up the View Furstum with the camera - // loadViewFrustum(_myCamera, _viewFrustum); - - renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; if (OculusManager::isConnected()) { @@ -3010,7 +3006,8 @@ QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { batch.setFramebuffer(primaryFbo); renderArgs->_context->render(batch); } - renderArgs->_renderMode = RenderArgs::NORMAL_RENDER_MODE; + renderArgs->_renderMode = RenderArgs::DEFAULT_RENDER_MODE; + renderRearViewMirror(renderArgs, QRect(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), true); { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9752536f60..c6c6919325 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1551,7 +1551,9 @@ void MyAvatar::maybeUpdateBillboard() { QBuffer buffer(&_billboard); buffer.open(QIODevice::WriteOnly); image.save(&buffer, "PNG"); +#ifdef DEBUG image.save("billboard.png", "PNG"); +#endif _billboardValid = true; sendBillboardPacket(); diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 0c4ead6eae..ab7a1d1c11 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -20,6 +20,8 @@ #include "Pipeline.h" #include "Framebuffer.h" +class QImage; + namespace gpu { class Backend { diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 44dee90fa7..7245272131 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -8,10 +8,11 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "GPULogging.h" #include "GLBackendShared.h" -#include "qimage.h" using namespace gpu; From ded95a3dde482f21d48577d370559561b3f91fbf Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 23 Jul 2015 16:58:21 -0700 Subject: [PATCH 19/35] removing dead code --- libraries/gpu/src/gpu/Framebuffer.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index c1b5358d3c..6f2b762bb0 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -132,8 +132,6 @@ public: static const uint32 MAX_NUM_RENDER_BUFFERS = 8; static uint32 getMaxNumRenderBuffers() { return MAX_NUM_RENDER_BUFFERS; } - void getImage(QImage* result) const; - protected: SwapchainPointer _swapchain; From 2fc158246dd8504bc524182f708286d2a2529993 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 23 Jul 2015 17:30:50 -0700 Subject: [PATCH 20/35] decouple FPS from rotation rate during mouse drag --- interface/src/Application.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8f825a2768..34791b29f1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2495,10 +2495,18 @@ void Application::update(float deltaTime) { _myAvatar->setDriveKeys(DOWN, _userInputMapper.getActionState(UserInputMapper::VERTICAL_DOWN)); _myAvatar->setDriveKeys(LEFT, _userInputMapper.getActionState(UserInputMapper::LATERAL_LEFT)); _myAvatar->setDriveKeys(RIGHT, _userInputMapper.getActionState(UserInputMapper::LATERAL_RIGHT)); - _myAvatar->setDriveKeys(ROT_UP, _userInputMapper.getActionState(UserInputMapper::PITCH_UP)); - _myAvatar->setDriveKeys(ROT_DOWN, _userInputMapper.getActionState(UserInputMapper::PITCH_DOWN)); - _myAvatar->setDriveKeys(ROT_LEFT, _userInputMapper.getActionState(UserInputMapper::YAW_LEFT)); - _myAvatar->setDriveKeys(ROT_RIGHT, _userInputMapper.getActionState(UserInputMapper::YAW_RIGHT)); + if (deltaTime > FLT_EPSILON) { + // For rotations what we really want are meausures of "angles per second" (in order to prevent + // fps-dependent spin rates) so we need to scale the units of the controller contribution. + // (TODO?: maybe we should similarly scale ALL action state info, or change the expected behavior + // controllers to provide a delta_per_second value rather than a raw delta.) + const float EXPECTED_FRAME_RATE = 60.0f; + float timeFactor = EXPECTED_FRAME_RATE * deltaTime; + _myAvatar->setDriveKeys(ROT_UP, _userInputMapper.getActionState(UserInputMapper::PITCH_UP) / timeFactor); + _myAvatar->setDriveKeys(ROT_DOWN, _userInputMapper.getActionState(UserInputMapper::PITCH_DOWN) / timeFactor); + _myAvatar->setDriveKeys(ROT_LEFT, _userInputMapper.getActionState(UserInputMapper::YAW_LEFT) / timeFactor); + _myAvatar->setDriveKeys(ROT_RIGHT, _userInputMapper.getActionState(UserInputMapper::YAW_RIGHT) / timeFactor); + } } _myAvatar->setDriveKeys(BOOM_IN, _userInputMapper.getActionState(UserInputMapper::BOOM_IN)); _myAvatar->setDriveKeys(BOOM_OUT, _userInputMapper.getActionState(UserInputMapper::BOOM_OUT)); From cdcab299b65c9ca400881e1e25c13be104279b5f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 23 Jul 2015 17:58:39 -0700 Subject: [PATCH 21/35] bring back delayed queue of Application events --- interface/src/Application.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8e8b4544b7..b237d003e0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1798,13 +1798,6 @@ void Application::idle() { } double timeSinceLastUpdate = (double)_lastTimeUpdated.nsecsElapsed() / 1000000.0; if (timeSinceLastUpdate > targetFramePeriod) { - - { - static const int IDLE_EVENT_PROCESS_MAX_TIME_MS = 2; - PerformanceTimer perfTimer("processEvents"); - processEvents(QEventLoop::AllEvents, IDLE_EVENT_PROCESS_MAX_TIME_MS); - } - _lastTimeUpdated.start(); { PerformanceTimer perfTimer("update"); @@ -1836,12 +1829,8 @@ void Application::idle() { // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in // perpetuity and not expect events to get backed up. - static const int IDLE_TIMER_DELAY_MS = 0; - int desiredInterval = _glWidget->isThrottleRendering() ? THROTTLED_IDLE_TIMER_DELAY : IDLE_TIMER_DELAY_MS; - - if (idleTimer->interval() != desiredInterval) { - idleTimer->start(desiredInterval); - } + static const int IDLE_TIMER_DELAY_MS = 2; + idleTimer->start(_glWidget->isThrottleRendering() ? THROTTLED_IDLE_TIMER_DELAY : IDLE_TIMER_DELAY_MS); } // check for any requested background downloads. From 8421aafe33efc21215c2cc67bbe82f192365a43f Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 23 Jul 2015 18:17:10 -0700 Subject: [PATCH 22/35] try to fix the scaling issues on mac --- interface/src/Application.cpp | 7 +++---- interface/src/ui/ApplicationOverlay.cpp | 13 +++++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index efe208a1b8..2e1a708fa2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -891,10 +891,9 @@ void Application::paintGL() { renderArgs._renderMode = RenderArgs::NORMAL_RENDER_MODE; { - auto mirrorViewport = glm::ivec4(0, 0, _mirrorViewRect.width(), _mirrorViewRect.height()); - float ratio = 1.0f / ((float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale()); - - auto mirrorViewportDest = glm::ivec4(0, 0, ratio * mirrorViewport.z, ratio * mirrorViewport.w); + float ratio = ((float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale()); + auto mirrorViewport = glm::ivec4(0, 0, _mirrorViewRect.width() * ratio, _mirrorViewRect.height() * ratio); + auto mirrorViewportDest = mirrorViewport; auto selfieFbo = DependencyManager::get()->getSelfieFramebuffer(); gpu::Batch batch; diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index d1154bda03..643663e658 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -183,12 +183,17 @@ void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { batch.setProjectionTransform(legacyProjection); batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); - + + float screenRatio = ((float)qApp->getDevicePixelRatio()); + float renderRatio = ((float)screenRatio * qApp->getRenderResolutionScale()); + auto viewport = qApp->getMirrorViewRect(); - glm::vec2 bottomLeft(viewport.left(), viewport.bottom()); - glm::vec2 topRight(viewport.right(), viewport.top()); + glm::vec2 bottomLeft(viewport.left(), viewport.top() + viewport.height()); + glm::vec2 topRight(viewport.left() + viewport.width(), viewport.top()); + bottomLeft *= screenRatio; + topRight *= screenRatio; glm::vec2 texCoordMinCorner(0.0f, 0.0f); - glm::vec2 texCoordMaxCorner(viewport.width() / float(selfieTexture->getWidth()), viewport.height() / float(selfieTexture->getHeight())); + glm::vec2 texCoordMaxCorner(viewport.width() * renderRatio / float(selfieTexture->getWidth()), viewport.height() * renderRatio / float(selfieTexture->getHeight())); geometryCache->useSimpleDrawPipeline(batch, false); batch.setResourceTexture(0, renderArgs->_whiteTexture); From c1e1caa7092c30d8bc9398990621e13d6296c064 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 23 Jul 2015 21:59:19 -0700 Subject: [PATCH 23/35] Add ability to update title of WebWindow after it's created --- interface/src/scripting/WebWindowClass.cpp | 4 ++++ interface/src/scripting/WebWindowClass.h | 1 + 2 files changed, 5 insertions(+) diff --git a/interface/src/scripting/WebWindowClass.cpp b/interface/src/scripting/WebWindowClass.cpp index 67e5e86280..3bd7e390ec 100644 --- a/interface/src/scripting/WebWindowClass.cpp +++ b/interface/src/scripting/WebWindowClass.cpp @@ -142,3 +142,7 @@ QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine* return engine->newQObject(retVal); } + +void WebWindowClass::setTitle(const QString& title) { + _windowWidget->setWindowTitle(title); +} diff --git a/interface/src/scripting/WebWindowClass.h b/interface/src/scripting/WebWindowClass.h index f5a292874c..c44898fa97 100644 --- a/interface/src/scripting/WebWindowClass.h +++ b/interface/src/scripting/WebWindowClass.h @@ -48,6 +48,7 @@ public slots: void raise(); ScriptEventBridge* getEventBridge() const { return _eventBridge; } void addEventBridgeToWindowObject(); + void setTitle(const QString& title); signals: void closed(); From 66cd17ec6663e0800e20753e8a552ee0a7e1d94f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 23 Jul 2015 23:09:40 -0700 Subject: [PATCH 24/35] REmove the crappy solution for drawing transparent texture into overlay by a proper shader --- interface/src/ui/ApplicationOverlay.cpp | 8 +++---- libraries/gpu/src/gpu/DrawTextureOpaque.slf | 22 ++++++++++++++++++++ libraries/gpu/src/gpu/StandardShaderLib.cpp | 11 ++++++++++ libraries/gpu/src/gpu/StandardShaderLib.h | 2 ++ libraries/model/src/model/Skybox.cpp | 2 +- libraries/render-utils/src/GeometryCache.cpp | 14 +++++++++---- 6 files changed, 50 insertions(+), 9 deletions(-) create mode 100755 libraries/gpu/src/gpu/DrawTextureOpaque.slf diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 643663e658..8ec2183681 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -92,12 +92,12 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); // Now render the overlay components together into a single texture + renderRearView(renderArgs); // renders the mirror view selfie renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line renderAudioScope(renderArgs); // audio scope in the very back renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture, and the text overlays from scripts renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope renderStatsAndLogs(renderArgs); // currently renders nothing - renderRearView(renderArgs); // renders the mirror view selfie renderArgs->_context->syncCache(); renderArgs->_context->render(batch); @@ -195,12 +195,12 @@ void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { glm::vec2 texCoordMinCorner(0.0f, 0.0f); glm::vec2 texCoordMaxCorner(viewport.width() * renderRatio / float(selfieTexture->getWidth()), viewport.height() * renderRatio / float(selfieTexture->getHeight())); - geometryCache->useSimpleDrawPipeline(batch, false); - batch.setResourceTexture(0, renderArgs->_whiteTexture); - geometryCache->renderQuad(batch, bottomLeft, topRight, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); geometryCache->useSimpleDrawPipeline(batch, true); batch.setResourceTexture(0, selfieTexture); geometryCache->renderQuad(batch, bottomLeft, topRight, texCoordMinCorner, texCoordMaxCorner, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); + + batch.setResourceTexture(0, renderArgs->_whiteTexture); + geometryCache->useSimpleDrawPipeline(batch, false); } } diff --git a/libraries/gpu/src/gpu/DrawTextureOpaque.slf b/libraries/gpu/src/gpu/DrawTextureOpaque.slf new file mode 100755 index 0000000000..1ce3a34c02 --- /dev/null +++ b/libraries/gpu/src/gpu/DrawTextureOpaque.slf @@ -0,0 +1,22 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// Draw texture 0 fetched at texcoord.xy +// Alpha is 1 +// +// Created by Sam Gateau on 6/22/2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +uniform sampler2D colorMap; + +varying vec2 varTexcoord; + +void main(void) { + gl_FragColor = vec4(texture2D(colorMap, varTexcoord).xyz, 1.0); +} diff --git a/libraries/gpu/src/gpu/StandardShaderLib.cpp b/libraries/gpu/src/gpu/StandardShaderLib.cpp index 1c1cca458a..3f27a7fc35 100755 --- a/libraries/gpu/src/gpu/StandardShaderLib.cpp +++ b/libraries/gpu/src/gpu/StandardShaderLib.cpp @@ -16,6 +16,7 @@ #include "DrawTexcoordRectTransformUnitQuad_vert.h" #include "DrawViewportQuadTransformTexcoord_vert.h" #include "DrawTexture_frag.h" +#include "DrawTextureOpaque_frag.h" #include "DrawColoredTexture_frag.h" using namespace gpu; @@ -24,6 +25,7 @@ ShaderPointer StandardShaderLib::_drawTransformUnitQuadVS; ShaderPointer StandardShaderLib::_drawTexcoordRectTransformUnitQuadVS; ShaderPointer StandardShaderLib::_drawViewportQuadTransformTexcoordVS; ShaderPointer StandardShaderLib::_drawTexturePS; +ShaderPointer StandardShaderLib::_drawTextureOpaquePS; ShaderPointer StandardShaderLib::_drawColoredTexturePS; StandardShaderLib::ProgramMap StandardShaderLib::_programs; @@ -82,6 +84,15 @@ ShaderPointer StandardShaderLib::getDrawTexturePS() { return _drawTexturePS; } +ShaderPointer StandardShaderLib::getDrawTextureOpaquePS() { + if (!_drawTextureOpaquePS) { + _drawTextureOpaquePS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(DrawTextureOpaque_frag))); + } + return _drawTextureOpaquePS; +} + + + ShaderPointer StandardShaderLib::getDrawColoredTexturePS() { if (!_drawColoredTexturePS) { _drawColoredTexturePS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(DrawColoredTexture_frag))); diff --git a/libraries/gpu/src/gpu/StandardShaderLib.h b/libraries/gpu/src/gpu/StandardShaderLib.h index d5a3685feb..2d9c168473 100755 --- a/libraries/gpu/src/gpu/StandardShaderLib.h +++ b/libraries/gpu/src/gpu/StandardShaderLib.h @@ -35,6 +35,7 @@ public: static ShaderPointer getDrawViewportQuadTransformTexcoordVS(); static ShaderPointer getDrawTexturePS(); + static ShaderPointer getDrawTextureOpaquePS(); static ShaderPointer getDrawColoredTexturePS(); // The shader program combining the shaders available above, so they are unique @@ -47,6 +48,7 @@ protected: static ShaderPointer _drawTexcoordRectTransformUnitQuadVS; static ShaderPointer _drawViewportQuadTransformTexcoordVS; static ShaderPointer _drawTexturePS; + static ShaderPointer _drawTextureOpaquePS; static ShaderPointer _drawColoredTexturePS; typedef std::map, ShaderPointer> ProgramMap; diff --git a/libraries/model/src/model/Skybox.cpp b/libraries/model/src/model/Skybox.cpp index 1464afa45d..314492881f 100755 --- a/libraries/model/src/model/Skybox.cpp +++ b/libraries/model/src/model/Skybox.cpp @@ -110,7 +110,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky } else { // skybox has no cubemap, just clear the color buffer auto color = skybox.getColor(); - batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(color, 0.0f), 0.0f, 0); + batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(color, 0.0f), 0.0f, 0, true); } } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 45106cf1b6..595e901919 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -29,6 +29,8 @@ #include "standardTransformPNTC_vert.h" #include "standardDrawTexture_frag.h" +#include "gpu/StandardShaderLib.h" + //#define WANT_DEBUG const int GeometryCache::UNKNOWN_ID = -1; @@ -1660,16 +1662,20 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) { auto state = std::make_shared(); + // enable decal blend state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); _standardDrawPipeline.reset(gpu::Pipeline::create(program, state)); - auto stateNoBlend = std::make_shared(); - stateNoBlend->setColorWriteMask(true, true, true, false); - stateNoBlend->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); - _standardDrawPipelineNoBlend.reset(gpu::Pipeline::create(program, stateNoBlend)); + auto stateNoBlend = std::make_shared(); + // stateNoBlend->setColorWriteMask(true, true, true, false); + // stateNoBlend->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + + auto programNoBlend = gpu::ShaderPointer(gpu::Shader::createProgram(vs, gpu::StandardShaderLib::getDrawTextureOpaquePS())); + gpu::Shader::makeProgram((*programNoBlend)); + _standardDrawPipelineNoBlend.reset(gpu::Pipeline::create(programNoBlend, stateNoBlend)); } if (noBlend) { batch.setPipeline(_standardDrawPipelineNoBlend); From cb375e8ecee5ce439e2714eb3635bfa44050c1c4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 24 Jul 2015 02:15:50 -0700 Subject: [PATCH 25/35] FIund a nasty bug with the scissor which was the reason for many issues, tried to integrate the framebuffer setup and clear as part of the enginepipeline so calling display side is simpler --- interface/src/Application.cpp | 75 ++++--------------- libraries/gpu/src/gpu/Batch.cpp | 5 +- libraries/gpu/src/gpu/GLBackendState.cpp | 7 +- .../src/DeferredLightingEffect.cpp | 14 ++-- .../render-utils/src/FramebufferCache.cpp | 27 +++++-- libraries/render-utils/src/FramebufferCache.h | 4 +- .../render-utils/src/RenderDeferredTask.cpp | 48 ++++++------ .../render-utils/src/RenderDeferredTask.h | 7 ++ 8 files changed, 79 insertions(+), 108 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2e1a708fa2..8c5769c26c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -879,16 +879,11 @@ void Application::paintGL() { renderArgs._context->syncCache(); if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); - { - gpu::Batch batch; - batch.setFramebuffer(nullptr); - batch.setFramebuffer(primaryFbo); - renderArgs._context->render(batch); - } + auto primaryFbo = DependencyManager::get()->getPrimaryFramebufferDepthColor(); + renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; renderRearViewMirror(&renderArgs, _mirrorViewRect); - renderArgs._renderMode = RenderArgs::NORMAL_RENDER_MODE; + renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; { float ratio = ((float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale()); @@ -918,6 +913,9 @@ void Application::paintGL() { Application::getInstance()->cameraMenuChanged(); } + // The render mode is default or mirror if the camera is in mirror mode, assigned further below + renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; + if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { // Always use the default eye position, not the actual head eye position. // Using the latter will cause the camera to wobble with idle animations, @@ -954,6 +952,7 @@ void Application::paintGL() { glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) + (_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); + renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; } // Update camera position @@ -961,8 +960,6 @@ void Application::paintGL() { _myCamera.update(1.0f / _fps); } - renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; - if (OculusManager::isConnected()) { //When in mirror mode, use camera rotation. Otherwise, use body rotation if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { @@ -974,31 +971,16 @@ void Application::paintGL() { TV3DManager::display(&renderArgs, _myCamera); } else { PROFILE_RANGE(__FUNCTION__ "/mainRender"); + // Viewport is assigned to the size of the framebuffer + QSize size = DependencyManager::get()->getFrameBufferSize(); + renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height()); - { - gpu::Batch batch; - auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); - batch.setFramebuffer(primaryFbo); - // clear the normal and specular buffers - batch.clearFramebuffer( - gpu::Framebuffer::BUFFER_COLOR0 | - gpu::Framebuffer::BUFFER_COLOR1 | - gpu::Framebuffer::BUFFER_COLOR2 | - gpu::Framebuffer::BUFFER_DEPTH, - vec4(vec3(0), 1), 1.0, 0.0); - - // Viewport is assigned to the size of the framebuffer - QSize size = DependencyManager::get()->getFrameBufferSize(); - renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height()); - batch.setViewportTransform(renderArgs._viewport); - renderArgs._context->render(batch); - } displaySide(&renderArgs, _myCamera); { auto geometryCache = DependencyManager::get(); - auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); + auto primaryFbo = DependencyManager::get()->getPrimaryFramebufferDepthColor(); gpu::Batch batch; batch.blit(primaryFbo, glm::ivec4(0, 0, _renderResolution.x, _renderResolution.y), nullptr, glm::ivec4(0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height())); @@ -1006,7 +988,6 @@ void Application::paintGL() { batch.setFramebuffer(nullptr); renderArgs._context->render(batch); - } _compositor.displayOverlayTexture(&renderArgs); @@ -2995,27 +2976,14 @@ PickRay Application::computePickRay(float x, float y) const { QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { const int BILLBOARD_SIZE = 64; + + // Need to make sure the gl context is current here _glWidget->makeCurrent(); - auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); - - { - gpu::Batch batch; - batch.setFramebuffer(nullptr); - batch.setFramebuffer(primaryFbo); - renderArgs->_context->render(batch); - } renderArgs->_renderMode = RenderArgs::DEFAULT_RENDER_MODE; - renderRearViewMirror(renderArgs, QRect(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), true); - { - auto mirrorViewport = glm::ivec4(0, 0,BILLBOARD_SIZE, BILLBOARD_SIZE); - gpu::Batch batch; - batch.setFramebuffer(nullptr); - renderArgs->_context->render(batch); - } - + auto primaryFbo = DependencyManager::get()->getPrimaryFramebufferDepthColor(); QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); renderArgs->_context->downloadFramebuffer(primaryFbo, glm::ivec4(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE), image); @@ -3445,25 +3413,10 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi } renderArgs->_viewport = viewport; - { - gpu::Batch batch; - batch.setViewportTransform(viewport); - batch.setStateScissorRect(viewport); - batch.clearFramebuffer( - gpu::Framebuffer::BUFFER_COLOR0 | - gpu::Framebuffer::BUFFER_COLOR1 | - gpu::Framebuffer::BUFFER_COLOR2 | - gpu::Framebuffer::BUFFER_DEPTH, - vec4(vec3(0), 1), 1.0, 0.0, true); - // Viewport is assigned to the size of the framebuffer - renderArgs->_context->render(batch); - } - // render rear mirror view displaySide(renderArgs, _mirrorCamera, true, billboard); renderArgs->_viewport = originalViewport; - } void Application::resetSensors() { diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 01c3c4ade7..567ce66cd8 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -220,10 +220,7 @@ void Batch::setStateBlendFactor(const Vec4& factor) { void Batch::setStateScissorRect(const Vec4i& rect) { ADD_COMMAND(setStateScissorRect); - _params.push_back(rect.x); - _params.push_back(rect.y); - _params.push_back(rect.z); - _params.push_back(rect.w); + _params.push_back(cacheData(sizeof(Vec4i), &rect)); } void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) { diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index f4f27a5ee9..18fc9ddd3c 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -757,11 +757,8 @@ void GLBackend::do_setStateBlendFactor(Batch& batch, uint32 paramOffset) { } void GLBackend::do_setStateScissorRect(Batch& batch, uint32 paramOffset) { - - Vec4 rect(batch._params[paramOffset + 0]._float, - batch._params[paramOffset + 1]._float, - batch._params[paramOffset + 2]._float, - batch._params[paramOffset + 3]._float); + Vec4i rect; + memcpy(&rect, batch.editData(batch._params[paramOffset]._uint), sizeof(Vec4i)); glScissor(rect.x, rect.y, rect.z, rect.w); (void) CHECK_GL_ERROR(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index b527390589..c14bbfcb1d 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -222,12 +222,15 @@ void DeferredLightingEffect::prepare(RenderArgs* args) { gpu::Batch batch; batch.setStateScissorRect(args->_viewport); + + auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); + + batch.setFramebuffer(primaryFbo); // clear the normal and specular buffers batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR1, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f), true); const float MAX_SPECULAR_EXPONENT = 128.0f; batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR2, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f / MAX_SPECULAR_EXPONENT), true); - args->_context->syncCache(); args->_context->render(batch); } @@ -535,7 +538,6 @@ void DeferredLightingEffect::render(RenderArgs* args) { batch.setResourceTexture(2, nullptr); batch.setResourceTexture(3, nullptr); - args->_context->syncCache(); args->_context->render(batch); // End of the Lighting pass @@ -548,7 +550,8 @@ void DeferredLightingEffect::copyBack(RenderArgs* args) { QSize framebufferSize = framebufferCache->getFrameBufferSize(); // TODO why doesn't this blit work? It only seems to affect a small area below the rear view mirror. - auto destFbo = framebufferCache->getPrimaryFramebuffer(); + // auto destFbo = framebufferCache->getPrimaryFramebuffer(); + auto destFbo = framebufferCache->getPrimaryFramebufferDepthColor(); // gpu::Vec4i vp = args->_viewport; // batch.blit(_copyFBO, vp, framebufferCache->getPrimaryFramebuffer(), vp); batch.setFramebuffer(destFbo); @@ -567,11 +570,6 @@ void DeferredLightingEffect::copyBack(RenderArgs* args) { batch.setModelTransform(model); } - GLenum buffers[3]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - batch._glDrawBuffers(bufferCount, buffers); - batch.setResourceTexture(0, _copyFBO->getRenderBuffer(0)); batch.draw(gpu::TRIANGLE_STRIP, 4); diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index 0bcb54fe2c..b4865ef58c 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -34,7 +34,8 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) { //If the size changed, we need to delete our FBOs if (_frameBufferSize != frameBufferSize) { _frameBufferSize = frameBufferSize; - _primaryFramebuffer.reset(); + _primaryFramebufferFull.reset(); + _primaryFramebufferDepthColor.reset(); _primaryDepthTexture.reset(); _primaryColorTexture.reset(); _primaryNormalTexture.reset(); @@ -45,7 +46,8 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) { } void FramebufferCache::createPrimaryFramebuffer() { - _primaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + _primaryFramebufferFull = gpu::FramebufferPointer(gpu::Framebuffer::create()); + _primaryFramebufferDepthColor = gpu::FramebufferPointer(gpu::Framebuffer::create()); auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); auto width = _frameBufferSize.width(); @@ -56,24 +58,33 @@ void FramebufferCache::createPrimaryFramebuffer() { _primaryNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); _primarySpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); - _primaryFramebuffer->setRenderBuffer(0, _primaryColorTexture); - _primaryFramebuffer->setRenderBuffer(1, _primaryNormalTexture); - _primaryFramebuffer->setRenderBuffer(2, _primarySpecularTexture); + _primaryFramebufferFull->setRenderBuffer(0, _primaryColorTexture); + _primaryFramebufferFull->setRenderBuffer(1, _primaryNormalTexture); + _primaryFramebufferFull->setRenderBuffer(2, _primarySpecularTexture); + _primaryFramebufferDepthColor->setRenderBuffer(0, _primaryColorTexture); auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); _primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); - _primaryFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); + _primaryFramebufferFull->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); + + _primaryFramebufferDepthColor->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); } gpu::FramebufferPointer FramebufferCache::getPrimaryFramebuffer() { - if (!_primaryFramebuffer) { + if (!_primaryFramebufferFull) { createPrimaryFramebuffer(); } - return _primaryFramebuffer; + return _primaryFramebufferFull; } +gpu::FramebufferPointer FramebufferCache::getPrimaryFramebufferDepthColor() { + if (!_primaryFramebufferDepthColor) { + createPrimaryFramebuffer(); + } + return _primaryFramebufferDepthColor; +} gpu::TexturePointer FramebufferCache::getPrimaryDepthTexture() { diff --git a/libraries/render-utils/src/FramebufferCache.h b/libraries/render-utils/src/FramebufferCache.h index d65c467be1..c2274a77e8 100644 --- a/libraries/render-utils/src/FramebufferCache.h +++ b/libraries/render-utils/src/FramebufferCache.h @@ -30,6 +30,7 @@ public: /// Returns a pointer to the primary framebuffer object. This render target includes a depth component, and is /// used for scene rendering. gpu::FramebufferPointer getPrimaryFramebuffer(); + gpu::FramebufferPointer getPrimaryFramebufferDepthColor(); gpu::TexturePointer getPrimaryDepthTexture(); gpu::TexturePointer getPrimaryColorTexture(); @@ -55,7 +56,8 @@ private: void createPrimaryFramebuffer(); - gpu::FramebufferPointer _primaryFramebuffer; + gpu::FramebufferPointer _primaryFramebufferFull; + gpu::FramebufferPointer _primaryFramebufferDepthColor; gpu::TexturePointer _primaryDepthTexture; gpu::TexturePointer _primaryColorTexture; gpu::TexturePointer _primaryNormalTexture; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 6a627bb6ab..0c8d19250b 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -17,6 +17,7 @@ #include #include +#include "FramebufferCache.h" #include "DeferredLightingEffect.h" #include "TextureCache.h" @@ -27,6 +28,26 @@ using namespace render; +void SetupDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + RenderArgs* args = renderContext->args; + + auto primaryFbo = DependencyManager::get()->getPrimaryFramebufferDepthColor(); + + gpu::Batch batch; + batch.setFramebuffer(nullptr); + batch.setFramebuffer(primaryFbo); + + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + batch.clearFramebuffer( + gpu::Framebuffer::BUFFER_COLOR0 | + gpu::Framebuffer::BUFFER_DEPTH, + vec4(vec3(0), 1), 1.0, 0.0, true); + + args->_context->render(batch); +} + void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { DependencyManager::get()->prepare(renderContext->args); } @@ -41,6 +62,7 @@ void ResolveDeferred::run(const SceneContextPointer& sceneContext, const RenderC } RenderDeferredTask::RenderDeferredTask() : Task() { + _jobs.push_back(Job(new SetupDeferred::JobModel("SetupFramebuffer"))); _jobs.push_back(Job(new DrawBackground::JobModel("DrawBackground"))); _jobs.push_back(Job(new PrepareDeferred::JobModel("PrepareDeferred"))); @@ -56,7 +78,6 @@ RenderDeferredTask::RenderDeferredTask() : Task() { auto& renderedOpaques = _jobs.back().getOutput(); _jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", _jobs.back().getOutput()))); _jobs.push_back(Job(new DrawLight::JobModel("DrawLight"))); - _jobs.push_back(Job(new ResetGLState::JobModel())); _jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred"))); _jobs.push_back(Job(new ResolveDeferred::JobModel("ResolveDeferred"))); _jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent", @@ -133,21 +154,12 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend batch.setViewTransform(viewMat); { - GLenum buffers[3]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; - batch._glDrawBuffers(bufferCount, buffers); const float OPAQUE_ALPHA_THRESHOLD = 0.5f; args->_alphaThreshold = OPAQUE_ALPHA_THRESHOLD; } renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnOpaqueItems); - // Before rendering the batch make sure we re in sync with gl state - args->_context->syncCache(); - renderContext->args->_context->syncCache(); args->_context->render((*args->_batch)); args->_batch = nullptr; } @@ -171,21 +183,15 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const } batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; { - GLenum buffers[3]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - batch._glDrawBuffers(bufferCount, buffers); + const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD; } renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnTransparentItems); - - // Before rendering the batch make sure we re in sync with gl state - args->_context->syncCache(); + args->_context->render((*args->_batch)); args->_batch = nullptr; } @@ -239,17 +245,17 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon } batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); if (!inItems.empty()) { - batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0); + batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0, true); renderItems(sceneContext, renderContext, inItems, renderContext->_maxDrawnOverlay3DItems); } - // Before rendering the batch make sure we re in sync with gl state - args->_context->syncCache(); args->_context->render((*args->_batch)); args->_batch = nullptr; args->_whiteTexture.reset(); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 4040606c62..1fec1c936f 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -16,6 +16,13 @@ #include "gpu/Pipeline.h" +class SetupDeferred { +public: + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + + typedef render::Job::Model JobModel; +}; + class PrepareDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); From 52ac5b3ef63331d193f6abe4c8bab39a1410b3d4 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 24 Jul 2015 03:38:21 -0700 Subject: [PATCH 26/35] On mac cannot get ther erendering to properly display the overlay if the rear view mirror is active on resize --- interface/src/Application.cpp | 19 ++++++++------- interface/src/Application.h | 1 + interface/src/ui/ApplicationOverlay.cpp | 2 +- libraries/gpu/src/gpu/GLBackend.cpp | 1 + libraries/gpu/src/gpu/GLBackend.h | 7 ++++-- libraries/gpu/src/gpu/GLBackendOutput.cpp | 23 ++++++++++++++++++- .../render-utils/src/FramebufferCache.cpp | 6 ++++- libraries/render-utils/src/GeometryCache.cpp | 6 ++--- 8 files changed, 48 insertions(+), 17 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8c5769c26c..cb1291337d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -877,22 +877,25 @@ void Application::paintGL() { // Before anything else, let's sync up the gpuContext with the true glcontext used in case anything happened renderArgs._context->syncCache(); - - if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + + if ((_numFramesSinceLastResize > 1) && Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { auto primaryFbo = DependencyManager::get()->getPrimaryFramebufferDepthColor(); - + renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; renderRearViewMirror(&renderArgs, _mirrorViewRect); renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; - + { float ratio = ((float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale()); auto mirrorViewport = glm::ivec4(0, 0, _mirrorViewRect.width() * ratio, _mirrorViewRect.height() * ratio); auto mirrorViewportDest = mirrorViewport; - + auto selfieFbo = DependencyManager::get()->getSelfieFramebuffer(); gpu::Batch batch; + batch.setFramebuffer(selfieFbo); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); batch.blit(primaryFbo, mirrorViewport, selfieFbo, mirrorViewportDest); + batch.setFramebuffer(nullptr); renderArgs._context->render(batch); } } @@ -992,8 +995,7 @@ void Application::paintGL() { _compositor.displayOverlayTexture(&renderArgs); } - - + if (!OculusManager::isConnected() || OculusManager::allowSwap()) { PROFILE_RANGE(__FUNCTION__ "/bufferSwap"); _glWidget->swapBuffers(); @@ -1003,6 +1005,7 @@ void Application::paintGL() { OculusManager::endFrameTiming(); } _frameCount++; + _numFramesSinceLastResize++; Stats::getInstance()->setRenderDetails(renderArgs._details); } @@ -1056,6 +1059,7 @@ void Application::resizeGL() { } if (_renderResolution != toGlm(renderSize)) { + _numFramesSinceLastResize = 0; _renderResolution = toGlm(renderSize); DependencyManager::get()->setFrameBufferSize(renderSize); @@ -1069,7 +1073,6 @@ void Application::resizeGL() { auto canvasSize = _glWidget->size(); offscreenUi->resize(canvasSize); _glWidget->makeCurrent(); - } bool Application::importSVOFromURL(const QString& urlString) { diff --git a/interface/src/Application.h b/interface/src/Application.h index b335b8a333..d1886862d2 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -642,6 +642,7 @@ private: Overlays _overlays; ApplicationOverlay _applicationOverlay; ApplicationCompositor _compositor; + int _numFramesSinceLastResize = 0; }; #endif // hifi_Application_h diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 8ec2183681..bc10b555e4 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -92,9 +92,9 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); // Now render the overlay components together into a single texture - renderRearView(renderArgs); // renders the mirror view selfie renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line renderAudioScope(renderArgs); // audio scope in the very back + renderRearView(renderArgs); // renders the mirror view selfie renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture, and the text overlays from scripts renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope renderStatsAndLogs(renderArgs); // currently renders nothing diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 7fd0f9be76..d704a4d17f 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -192,6 +192,7 @@ void GLBackend::syncCache() { syncTransformStateCache(); syncPipelineStateCache(); syncInputStateCache(); + syncOutputStateCache(); glEnable(GL_LINE_SMOOTH); } diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index c924395334..894e2c4548 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -387,11 +387,14 @@ protected: void do_setFramebuffer(Batch& batch, uint32 paramOffset); void do_blit(Batch& batch, uint32 paramOffset); - + // Synchronize the state cache of this Backend with the actual real state of the GL Context + void syncOutputStateCache(); + struct OutputStageState { FramebufferPointer _framebuffer = nullptr; - + GLuint _drawFBO = 0; + OutputStageState() {} } _output; diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 7245272131..1b22649ad6 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -37,6 +37,9 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe // need to have a gpu object? if (!object) { + GLint currentFBO; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤tFBO); + GLuint fbo; glGenFramebuffers(1, &fbo); (void) CHECK_GL_ERROR(); @@ -87,6 +90,8 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer); (void) CHECK_GL_ERROR(); } + + // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); #endif @@ -142,6 +147,9 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe object->_fbo = fbo; object->_colorBuffers = colorBuffers; Backend::setGPUObject(framebuffer, object); + + // restore the current framebuffer + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, currentFBO); } return object; @@ -161,11 +169,24 @@ GLuint GLBackend::getFramebufferID(const FramebufferPointer& framebuffer) { } } +void GLBackend::syncOutputStateCache() { + GLint currentFBO; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤tFBO); + + _output._drawFBO = currentFBO; + _output._framebuffer.reset(); +} + + void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint); if (_output._framebuffer != framebuffer) { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(framebuffer)); + auto newFBO = getFramebufferID(framebuffer); + if (_output._drawFBO != newFBO) { + _output._drawFBO = newFBO; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, newFBO); + } _output._framebuffer = framebuffer; } } diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index b4865ef58c..601d99108d 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -70,6 +70,10 @@ void FramebufferCache::createPrimaryFramebuffer() { _primaryFramebufferFull->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); _primaryFramebufferDepthColor->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); + + _selfieFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + auto tex = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width * 0.5, height * 0.5, defaultSampler)); + _selfieFramebuffer->setRenderBuffer(0, tex); } gpu::FramebufferPointer FramebufferCache::getPrimaryFramebuffer() { @@ -140,7 +144,7 @@ gpu::FramebufferPointer FramebufferCache::getShadowFramebuffer() { gpu::FramebufferPointer FramebufferCache::getSelfieFramebuffer() { if (!_selfieFramebuffer) { - _selfieFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, _frameBufferSize.width(), _frameBufferSize.height())); + createPrimaryFramebuffer(); } return _selfieFramebuffer; } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 595e901919..8550f8d8b6 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1670,10 +1670,8 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) { auto stateNoBlend = std::make_shared(); - // stateNoBlend->setColorWriteMask(true, true, true, false); - // stateNoBlend->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); - - auto programNoBlend = gpu::ShaderPointer(gpu::Shader::createProgram(vs, gpu::StandardShaderLib::getDrawTextureOpaquePS())); + auto noBlendPS = gpu::StandardShaderLib::getDrawTextureOpaquePS(); + auto programNoBlend = gpu::ShaderPointer(gpu::Shader::createProgram(vs, noBlendPS)); gpu::Shader::makeProgram((*programNoBlend)); _standardDrawPipelineNoBlend.reset(gpu::Pipeline::create(programNoBlend, stateNoBlend)); } From 28e6a4ac6331f9810c300eb032b0ae44c4eb6d89 Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Fri, 24 Jul 2015 09:36:35 -0400 Subject: [PATCH 27/35] Updating master as old job related to AudioClient.h was incorretly included with current job. --- libraries/audio-client/src/AudioClient.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 3a85adbc97..aeea7c07c1 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -55,9 +55,9 @@ static const int NUM_AUDIO_CHANNELS = 2; -static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; +static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; -static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 40; +static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; #if defined(Q_OS_ANDROID) || defined(Q_OS_WIN) static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = false; #else From 6ba135de0937641f55a4743a15b7f98f972604f8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 24 Jul 2015 07:16:40 -0700 Subject: [PATCH 28/35] when creating a walking surface collision hull from a flat mesh, ignore triangles with a normal that's not mostly up or down --- tools/vhacd-util/src/VHACDUtil.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/vhacd-util/src/VHACDUtil.cpp b/tools/vhacd-util/src/VHACDUtil.cpp index f1ff0e9e4f..4860785091 100644 --- a/tools/vhacd-util/src/VHACDUtil.cpp +++ b/tools/vhacd-util/src/VHACDUtil.cpp @@ -118,6 +118,13 @@ void vhacd::VHACDUtil::fattenMeshes(const FBXMesh& mesh, FBXMesh& result, glm::vec3 p2 = result.vertices[index2]; glm::vec3 av = (p0 + p1 + p2) / 3.0f; // center of the triangular face + glm::vec3 normal = glm::normalize(glm::cross(p1 - p0, p2 - p0)); + float threshold = 1.0f / sqrtf(3.0f); + if (normal.y > -threshold && normal.y < threshold) { + // this triangle is more a wall than a floor, skip it. + continue; + } + float dropAmount = 0; dropAmount = glm::max(glm::length(p1 - p0), dropAmount); dropAmount = glm::max(glm::length(p2 - p1), dropAmount); From e6f2504514313538689b721d7fa2b3e86c0df688 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 24 Jul 2015 09:26:32 -0700 Subject: [PATCH 29/35] FIx the problem of clear when the color mask is not WRITE_ALL --- interface/src/Application.cpp | 2 +- libraries/gpu/src/gpu/GLBackend.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cb1291337d..f6433cfb45 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -878,7 +878,7 @@ void Application::paintGL() { // Before anything else, let's sync up the gpuContext with the true glcontext used in case anything happened renderArgs._context->syncCache(); - if ((_numFramesSinceLastResize > 1) && Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { auto primaryFbo = DependencyManager::get()->getPrimaryFramebufferDepthColor(); renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index d704a4d17f..ae50b96bc5 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -282,6 +282,9 @@ void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { glClearColor(color.x, color.y, color.z, color.w); glmask |= GL_COLOR_BUFFER_BIT; } + + // Force the color mask cache to WRITE_ALL if not the case + do_setStateColorWriteMask(State::ColorMask::WRITE_ALL); } // Apply scissor if needed and if not already on From 71557a1846b63652a564ef3e7b7e741cd507ba5e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 24 Jul 2015 09:36:27 -0700 Subject: [PATCH 30/35] only output no listener for type message one time --- libraries/networking/src/PacketReceiver.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/networking/src/PacketReceiver.cpp b/libraries/networking/src/PacketReceiver.cpp index f59be35dc5..5fc327673d 100644 --- a/libraries/networking/src/PacketReceiver.cpp +++ b/libraries/networking/src/PacketReceiver.cpp @@ -280,7 +280,7 @@ void PacketReceiver::processDatagrams() { auto it = _packetListenerMap.find(packet->getType()); - if (it != _packetListenerMap.end()) { + if (it != _packetListenerMap.end() && it->second.isValid()) { auto listener = it.value(); @@ -367,10 +367,12 @@ void PacketReceiver::processDatagrams() { } } else { - qWarning() << "No listener found for packet type " << nameForPacketType(packet->getType()); - - // insert a dummy listener so we don't print this again - _packetListenerMap.insert(packet->getType(), { nullptr, QMetaMethod() }); + if (it == _packetListenerMap.end()) { + qWarning() << "No listener found for packet type " << nameForPacketType(packet->getType()); + + // insert a dummy listener so we don't print this again + _packetListenerMap.insert(packet->getType(), { nullptr, QMetaMethod() }); + } } _packetListenerLock.unlock(); From 3893add1487143b6d79f1012f612a250242f29a1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 24 Jul 2015 10:43:24 -0700 Subject: [PATCH 31/35] Fix setting WebWindow's width and height Width and height parameters now set the WebWindow's width and height instead of its minimum size, when not part of a tool window. --- interface/src/scripting/WebWindowClass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/WebWindowClass.cpp b/interface/src/scripting/WebWindowClass.cpp index 3bd7e390ec..f187de95d2 100644 --- a/interface/src/scripting/WebWindowClass.cpp +++ b/interface/src/scripting/WebWindowClass.cpp @@ -57,7 +57,7 @@ WebWindowClass::WebWindowClass(const QString& title, const QString& url, int wid } else { auto dialogWidget = new QDialog(Application::getInstance()->getWindow(), Qt::Window); dialogWidget->setWindowTitle(title); - dialogWidget->setMinimumSize(width, height); + dialogWidget->resize(width, height); connect(dialogWidget, &QDialog::finished, this, &WebWindowClass::hasClosed); auto layout = new QVBoxLayout(dialogWidget); From 67c9a33cc0a0b57d79d957adb176c56976dbe68e Mon Sep 17 00:00:00 2001 From: "Kevin M. Thomas" Date: Fri, 24 Jul 2015 15:16:02 -0400 Subject: [PATCH 32/35] Update Menu.cpp --- interface/src/Menu.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d5f4d78f5b..91ae6a4d02 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -487,14 +487,10 @@ Menu::Menu() { #endif MenuWrapper* networkMenu = developerMenu->addMenu("Network"); -<<<<<<< HEAD addActionToQMenuAndActionHash(networkMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); - addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableNackPackets, 0, false); -======= addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableNackPackets, 0, false, qApp->getEntityEditPacketSender(), SLOT(toggleNackPackets())); ->>>>>>> f3dc159e336b7b580bbd39b367802b0099e66ccb addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableActivityLogger, 0, From 776d4747b2fc17fce67a8a8ef34c6e77f0adfb63 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 24 Jul 2015 14:47:44 -0700 Subject: [PATCH 33/35] Cleaning up the FBO cache and the output stage in general --- libraries/gpu/src/gpu/Batch.cpp | 59 ++++++++------- libraries/gpu/src/gpu/Batch.h | 25 +++---- libraries/gpu/src/gpu/GLBackend.cpp | 67 +---------------- libraries/gpu/src/gpu/GLBackend.h | 3 +- libraries/gpu/src/gpu/GLBackendOutput.cpp | 91 +++++++++++++++++++++-- 5 files changed, 127 insertions(+), 118 deletions(-) diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 567ce66cd8..4ac33d8f14 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -106,36 +106,6 @@ void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, ui _params.push_back(nbInstances); } -void Batch::clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor) { - ADD_COMMAND(clearFramebuffer); - - _params.push_back(enableScissor); - _params.push_back(stencil); - _params.push_back(depth); - _params.push_back(color.w); - _params.push_back(color.z); - _params.push_back(color.y); - _params.push_back(color.x); - _params.push_back(targets); -} - -void Batch::clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor) { - clearFramebuffer(targets & Framebuffer::BUFFER_COLORS, color, 1.0f, 0, enableScissor); -} - -void Batch::clearDepthFramebuffer(float depth, bool enableScissor) { - clearFramebuffer(Framebuffer::BUFFER_DEPTH, Vec4(0.0f), depth, 0, enableScissor); -} - -void Batch::clearStencilFramebuffer(int stencil, bool enableScissor) { - clearFramebuffer(Framebuffer::BUFFER_STENCIL, Vec4(0.0f), 1.0f, stencil, enableScissor); -} - -void Batch::clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor) { - clearFramebuffer(Framebuffer::BUFFER_DEPTHSTENCIL, Vec4(0.0f), depth, stencil, enableScissor); -} - - void Batch::setInputFormat(const Stream::FormatPointer& format) { ADD_COMMAND(setInputFormat); @@ -255,6 +225,35 @@ void Batch::setFramebuffer(const FramebufferPointer& framebuffer) { } +void Batch::clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor) { + ADD_COMMAND(clearFramebuffer); + + _params.push_back(enableScissor); + _params.push_back(stencil); + _params.push_back(depth); + _params.push_back(color.w); + _params.push_back(color.z); + _params.push_back(color.y); + _params.push_back(color.x); + _params.push_back(targets); +} + +void Batch::clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor) { + clearFramebuffer(targets & Framebuffer::BUFFER_COLORS, color, 1.0f, 0, enableScissor); +} + +void Batch::clearDepthFramebuffer(float depth, bool enableScissor) { + clearFramebuffer(Framebuffer::BUFFER_DEPTH, Vec4(0.0f), depth, 0, enableScissor); +} + +void Batch::clearStencilFramebuffer(int stencil, bool enableScissor) { + clearFramebuffer(Framebuffer::BUFFER_STENCIL, Vec4(0.0f), 1.0f, stencil, enableScissor); +} + +void Batch::clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor) { + clearFramebuffer(Framebuffer::BUFFER_DEPTHSTENCIL, Vec4(0.0f), depth, stencil, enableScissor); +} + void Batch::blit(const FramebufferPointer& src, const Vec4i& srcViewport, const FramebufferPointer& dst, const Vec4i& dstViewport) { ADD_COMMAND(blit); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index acc1f6fdac..58fe03c9cf 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -54,15 +54,6 @@ public: void drawInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbVertices, uint32 startVertex = 0, uint32 startInstance = 0); void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbIndices, uint32 startIndex = 0, uint32 startInstance = 0); - // Clear framebuffer layers - // Targets can be any of the render buffers contained in the Framebuffer - // Optionally the scissor test can be enabled locally for this command and to restrict the clearing command to the pixels contained in the scissor rectangle - void clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor = false); - void clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, mask out targets to make sure it touches only color targets - void clearDepthFramebuffer(float depth, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only depth target - void clearStencilFramebuffer(int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only stencil target - void clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches depth and stencil target - // Input Stage // InputFormat // InputBuffers @@ -105,8 +96,17 @@ public: // Framebuffer Stage void setFramebuffer(const FramebufferPointer& framebuffer); - void blit(const FramebufferPointer& src, const Vec4i& srcViewport, - const FramebufferPointer& dst, const Vec4i& dstViewport); + + // Clear framebuffer layers + // Targets can be any of the render buffers contained in the currnetly bound Framebuffer + // Optionally the scissor test can be enabled locally for this command and to restrict the clearing command to the pixels contained in the scissor rectangle + void clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor = false); + void clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, mask out targets to make sure it touches only color targets + void clearDepthFramebuffer(float depth, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only depth target + void clearStencilFramebuffer(int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only stencil target + void clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches depth and stencil target + + void blit(const FramebufferPointer& src, const Vec4i& srcViewport, const FramebufferPointer& dst, const Vec4i& dstViewport); // Query Section void beginQuery(const QueryPointer& query); @@ -162,8 +162,6 @@ public: COMMAND_drawInstanced, COMMAND_drawIndexedInstanced, - COMMAND_clearFramebuffer, - COMMAND_setInputFormat, COMMAND_setInputBuffer, COMMAND_setIndexBuffer, @@ -181,6 +179,7 @@ public: COMMAND_setResourceTexture, COMMAND_setFramebuffer, + COMMAND_clearFramebuffer, COMMAND_blit, COMMAND_beginQuery, diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index ae50b96bc5..6b1d552be9 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -21,7 +21,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_drawIndexed), (&::gpu::GLBackend::do_drawInstanced), (&::gpu::GLBackend::do_drawIndexedInstanced), - (&::gpu::GLBackend::do_clearFramebuffer), (&::gpu::GLBackend::do_setInputFormat), (&::gpu::GLBackend::do_setInputBuffer), @@ -40,6 +39,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setResourceTexture), (&::gpu::GLBackend::do_setFramebuffer), + (&::gpu::GLBackend::do_clearFramebuffer), (&::gpu::GLBackend::do_blit), (&::gpu::GLBackend::do_beginQuery), @@ -246,71 +246,6 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); } -void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { - - uint32 masks = batch._params[paramOffset + 7]._uint; - Vec4 color; - color.x = batch._params[paramOffset + 6]._float; - color.y = batch._params[paramOffset + 5]._float; - color.z = batch._params[paramOffset + 4]._float; - color.w = batch._params[paramOffset + 3]._float; - float depth = batch._params[paramOffset + 2]._float; - int stencil = batch._params[paramOffset + 1]._int; - int useScissor = batch._params[paramOffset + 0]._int; - - GLuint glmask = 0; - if (masks & Framebuffer::BUFFER_STENCIL) { - glClearStencil(stencil); - glmask |= GL_STENCIL_BUFFER_BIT; - } - - if (masks & Framebuffer::BUFFER_DEPTH) { - glClearDepth(depth); - glmask |= GL_DEPTH_BUFFER_BIT; - } - - std::vector drawBuffers; - if (masks & Framebuffer::BUFFER_COLORS) { - for (unsigned int i = 0; i < Framebuffer::MAX_NUM_RENDER_BUFFERS; i++) { - if (masks & (1 << i)) { - drawBuffers.push_back(GL_COLOR_ATTACHMENT0 + i); - } - } - - if (!drawBuffers.empty()) { - glDrawBuffers(drawBuffers.size(), drawBuffers.data()); - glClearColor(color.x, color.y, color.z, color.w); - glmask |= GL_COLOR_BUFFER_BIT; - } - - // Force the color mask cache to WRITE_ALL if not the case - do_setStateColorWriteMask(State::ColorMask::WRITE_ALL); - } - - // Apply scissor if needed and if not already on - bool doEnableScissor = (useScissor && (!_pipeline._stateCache.scissorEnable)); - if (doEnableScissor) { - glEnable(GL_SCISSOR_TEST); - } - - glClear(glmask); - - // Restore scissor if needed - if (doEnableScissor) { - glDisable(GL_SCISSOR_TEST); - } - - // Restore the color draw buffers only if a frmaebuffer is bound - if (_output._framebuffer && !drawBuffers.empty()) { - auto glFramebuffer = syncGPUObject(*_output._framebuffer); - if (glFramebuffer) { - glDrawBuffers(glFramebuffer->_colorBuffers.size(), glFramebuffer->_colorBuffers.data()); - } - } - - (void) CHECK_GL_ERROR(); -} - // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 894e2c4548..9d8c9ef805 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -241,8 +241,6 @@ protected: void do_drawInstanced(Batch& batch, uint32 paramOffset); void do_drawIndexedInstanced(Batch& batch, uint32 paramOffset); - void do_clearFramebuffer(Batch& batch, uint32 paramOffset); - // Input Stage void do_setInputFormat(Batch& batch, uint32 paramOffset); void do_setInputBuffer(Batch& batch, uint32 paramOffset); @@ -385,6 +383,7 @@ protected: // Output stage void do_setFramebuffer(Batch& batch, uint32 paramOffset); + void do_clearFramebuffer(Batch& batch, uint32 paramOffset); void do_blit(Batch& batch, uint32 paramOffset); // Synchronize the state cache of this Backend with the actual real state of the GL Context diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 1b22649ad6..b37def48e7 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -180,7 +180,6 @@ void GLBackend::syncOutputStateCache() { void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint); - if (_output._framebuffer != framebuffer) { auto newFBO = getFramebufferID(framebuffer); if (_output._drawFBO != newFBO) { @@ -191,6 +190,72 @@ void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { } } +void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { + + uint32 masks = batch._params[paramOffset + 7]._uint; + Vec4 color; + color.x = batch._params[paramOffset + 6]._float; + color.y = batch._params[paramOffset + 5]._float; + color.z = batch._params[paramOffset + 4]._float; + color.w = batch._params[paramOffset + 3]._float; + float depth = batch._params[paramOffset + 2]._float; + int stencil = batch._params[paramOffset + 1]._int; + int useScissor = batch._params[paramOffset + 0]._int; + + GLuint glmask = 0; + if (masks & Framebuffer::BUFFER_STENCIL) { + glClearStencil(stencil); + glmask |= GL_STENCIL_BUFFER_BIT; + } + + if (masks & Framebuffer::BUFFER_DEPTH) { + glClearDepth(depth); + glmask |= GL_DEPTH_BUFFER_BIT; + } + + std::vector drawBuffers; + if (masks & Framebuffer::BUFFER_COLORS) { + for (unsigned int i = 0; i < Framebuffer::MAX_NUM_RENDER_BUFFERS; i++) { + if (masks & (1 << i)) { + drawBuffers.push_back(GL_COLOR_ATTACHMENT0 + i); + } + } + + if (!drawBuffers.empty()) { + glDrawBuffers(drawBuffers.size(), drawBuffers.data()); + glClearColor(color.x, color.y, color.z, color.w); + glmask |= GL_COLOR_BUFFER_BIT; + } + + // Force the color mask cache to WRITE_ALL if not the case + do_setStateColorWriteMask(State::ColorMask::WRITE_ALL); + } + + // Apply scissor if needed and if not already on + bool doEnableScissor = (useScissor && (!_pipeline._stateCache.scissorEnable)); + if (doEnableScissor) { + glEnable(GL_SCISSOR_TEST); + } + + // Clear! + glClear(glmask); + + // Restore scissor if needed + if (doEnableScissor) { + glDisable(GL_SCISSOR_TEST); + } + + // Restore the color draw buffers only if a frmaebuffer is bound + if (_output._framebuffer && !drawBuffers.empty()) { + auto glFramebuffer = syncGPUObject(*_output._framebuffer); + if (glFramebuffer) { + glDrawBuffers(glFramebuffer->_colorBuffers.size(), glFramebuffer->_colorBuffers.data()); + } + } + + (void) CHECK_GL_ERROR(); +} + void GLBackend::do_blit(Batch& batch, uint32 paramOffset) { auto srcframebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint); Vec4i srcvp; @@ -203,19 +268,31 @@ void GLBackend::do_blit(Batch& batch, uint32 paramOffset) { for (size_t i = 0; i < 4; ++i) { dstvp[i] = batch._params[paramOffset + 6 + i]._int; } - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(dstframebuffer)); + + // Assign dest framebuffer if not bound already + auto newDrawFBO = getFramebufferID(dstframebuffer); + if (_output._drawFBO != newDrawFBO) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, newDrawFBO); + } + + // always bind the read fbo glBindFramebuffer(GL_READ_FRAMEBUFFER, getFramebufferID(srcframebuffer)); + + // Blit! glBlitFramebuffer(srcvp.x, srcvp.y, srcvp.z, srcvp.w, dstvp.x, dstvp.y, dstvp.z, dstvp.w, GL_COLOR_BUFFER_BIT, GL_LINEAR); - - (void) CHECK_GL_ERROR(); - if (_output._framebuffer) { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFramebufferID(_output._framebuffer)); + // Always clean the read fbo to 0 + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + // Restore draw fbo if changed + if (_output._drawFBO != newDrawFBO) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _output._drawFBO); } -} + (void) CHECK_GL_ERROR(); +} void GLBackend::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) { auto readFBO = gpu::GLBackend::getFramebufferID(srcFramebuffer); From 7be33dcb5845908254950206ce6cff794ff1edde Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Sat, 25 Jul 2015 11:40:58 -0400 Subject: [PATCH 34/35] Limit the amount of time consumed by rendering QML --- .../render-utils/src/OffscreenQmlSurface.cpp | 21 +++++++++++++------ .../render-utils/src/OffscreenQmlSurface.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/OffscreenQmlSurface.cpp b/libraries/render-utils/src/OffscreenQmlSurface.cpp index 3ebc7704a8..056f9dbc6d 100644 --- a/libraries/render-utils/src/OffscreenQmlSurface.cpp +++ b/libraries/render-utils/src/OffscreenQmlSurface.cpp @@ -19,6 +19,7 @@ #include "FboCache.h" #include +#include class QMyQuickRenderControl : public QQuickRenderControl { protected: @@ -44,7 +45,10 @@ Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus") // Time between receiving a request to render the offscreen UI actually triggering // the render. Could possibly be increased depending on the framerate we expect to // achieve. -static const int SMALL_INTERVAL = 5; +static const int MAX_QML_FRAMERATE = 10; +static const int MIN_RENDER_INTERVAL_US = USECS_PER_SECOND / MAX_QML_FRAMERATE; +static const int MIN_TIMER_MS = 5; + OffscreenQmlSurface::OffscreenQmlSurface() : _renderControl(new QMyQuickRenderControl), _fboCache(new FboCache) { @@ -90,7 +94,6 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { // When Quick says there is a need to render, we will not render immediately. Instead, // a timer with a small interval is used to get better performance. _updateTimer.setSingleShot(true); - _updateTimer.setInterval(SMALL_INTERVAL); connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick); // Now hook up the signals. For simplicy we don't differentiate between @@ -170,13 +173,18 @@ QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function MIN_RENDER_INTERVAL_US) { + _updateTimer.setInterval(MIN_TIMER_MS); + } else { + _updateTimer.setInterval((MIN_RENDER_INTERVAL_US - lastInterval) / USECS_PER_MSEC); + } _updateTimer.start(); } } @@ -243,6 +251,7 @@ void OffscreenQmlSurface::updateQuick() { if (_paused) { return; } + if (!makeCurrent()) { return; } @@ -270,11 +279,11 @@ void OffscreenQmlSurface::updateQuick() { // Need a debug context with sync logging to figure out why. // for now just clear the errors glGetError(); -// Q_ASSERT(!glGetError()); _quickWindow->resetOpenGLState(); QOpenGLFramebufferObject::bindDefault(); + _lastRenderTime = usecTimestampNow(); // Force completion of all the operations before we emit the texture as being ready for use glFinish(); diff --git a/libraries/render-utils/src/OffscreenQmlSurface.h b/libraries/render-utils/src/OffscreenQmlSurface.h index b892806c44..1fbf69ef4d 100644 --- a/libraries/render-utils/src/OffscreenQmlSurface.h +++ b/libraries/render-utils/src/OffscreenQmlSurface.h @@ -86,6 +86,7 @@ private: QQuickItem* _rootItem{ nullptr }; QTimer _updateTimer; FboCache* _fboCache; + quint64 _lastRenderTime{ 0 }; bool _polish{ true }; bool _paused{ true }; MouseTranslator _mouseTranslator{ [](const QPointF& p) { return p; } }; From 24fff719c57d2a6daf565b9a5410b29fb8c431f1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 25 Jul 2015 21:11:23 -0700 Subject: [PATCH 35/35] quiet compiler --- interface/src/Application.cpp | 4 ---- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/MyAvatar.cpp | 1 - interface/src/devices/DdeFaceTracker.h | 5 ++--- interface/src/ui/ApplicationCompositor.cpp | 2 +- interface/src/ui/AudioStatsDialog.cpp | 6 ++++-- interface/src/ui/overlays/Cube3DOverlay.cpp | 1 - 7 files changed, 9 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c2be31cfb3..fa2a82ecb4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3389,14 +3389,10 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi // set the bounds of rear mirror view gpu::Vec4i viewport; if (billboard) { - QSize size = DependencyManager::get()->getFrameBufferSize(); viewport = gpu::Vec4i(0, 0, region.width(), region.height()); } else { // if not rendering the billboard, the region is in device independent coordinates; must convert to device - QSize size = DependencyManager::get()->getFrameBufferSize(); float ratio = (float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); - int x = region.x() * ratio; - int y = region.y() * ratio; int width = region.width() * ratio; int height = region.height() * ratio; viewport = gpu::Vec4i(0, 0, width, height); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 9f457e558d..095a225952 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -462,8 +462,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { const float LOOKING_AT_ME_ALPHA_START = 0.8f; const float LOOKING_AT_ME_DURATION = 0.5f; // seconds quint64 now = usecTimestampNow(); - float alpha = LOOKING_AT_ME_ALPHA_START - * (1.0f - ((float)(usecTimestampNow() - getHead()->getLookingAtMeStarted())) + float alpha = LOOKING_AT_ME_ALPHA_START + * (1.0f - ((float)(now - getHead()->getLookingAtMeStarted())) / (LOOKING_AT_ME_DURATION * (float)USECS_PER_SECOND)); if (alpha > 0.0f) { QSharedPointer geometry = getHead()->getFaceModel().getGeometry(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c6c6919325..f332173568 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1290,7 +1290,6 @@ bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { void MyAvatar::updateOrientation(float deltaTime) { // Smoothly rotate body with arrow keys - float driveLeft = _driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT]; float targetSpeed = (_driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT]) * YAW_SPEED; if (targetSpeed != 0.0f) { const float ROTATION_RAMP_TIMESCALE = 0.1f; diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 5536fa14bd..9673f541d2 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -91,13 +91,12 @@ private: int _leftBlinkIndex; int _rightBlinkIndex; - int _leftEyeOpenIndex; - int _rightEyeOpenIndex; - int _leftEyeDownIndex; int _rightEyeDownIndex; int _leftEyeInIndex; int _rightEyeInIndex; + int _leftEyeOpenIndex; + int _rightEyeOpenIndex; int _browDownLeftIndex; int _browDownRightIndex; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 54fb4fbd1f..9bda88b3bf 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -495,7 +495,7 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) { glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection(); // Get the angles, scaled between (-0.5,0.5) - float xAngle = (atan2(direction.z, direction.x) + PI_OVER_TWO); + float xAngle = (atan2f(direction.z, direction.x) + PI_OVER_TWO); float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)PI_OVER_TWO)); // Get the pixel range over which the xAngle and yAngle are scaled diff --git a/interface/src/ui/AudioStatsDialog.cpp b/interface/src/ui/AudioStatsDialog.cpp index 116cc60b5e..e57182e251 100644 --- a/interface/src/ui/AudioStatsDialog.cpp +++ b/interface/src/ui/AudioStatsDialog.cpp @@ -125,8 +125,10 @@ void AudioStatsDialog::renderStats() { audioInputBufferLatency = (double)_stats->getAudioInputMsecsReadStats().getWindowAverage(); inputRingBufferLatency = (double)_stats->getInputRungBufferMsecsAvailableStats().getWindowAverage(); networkRoundtripLatency = (double) audioMixerNodePointer->getPingMs(); - mixerRingBufferLatency = (double)_stats->getMixerAvatarStreamStats()._framesAvailableAverage * AudioConstants::NETWORK_FRAME_MSECS; - outputRingBufferLatency = (double)downstreamAudioStreamStats._framesAvailableAverage * AudioConstants::NETWORK_FRAME_MSECS; + mixerRingBufferLatency = (double)_stats->getMixerAvatarStreamStats()._framesAvailableAverage * + (double)AudioConstants::NETWORK_FRAME_MSECS; + outputRingBufferLatency = (double)downstreamAudioStreamStats._framesAvailableAverage * + (double)AudioConstants::NETWORK_FRAME_MSECS; audioOutputBufferLatency = (double)_stats->getAudioOutputMsecsUnplayedStats().getWindowAverage(); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 961d7f765b..200a1a328f 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -36,7 +36,6 @@ void Cube3DOverlay::render(RenderArgs* args) { // TODO: handle registration point?? glm::vec3 position = getPosition(); - glm::vec3 center = getCenter(); glm::vec3 dimensions = getDimensions(); glm::quat rotation = getRotation();