diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9960e64bb4..d8ec35c584 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -812,8 +812,7 @@ void Application::initializeUi() { if (devicePixelRatio != oldDevicePixelRatio) { oldDevicePixelRatio = devicePixelRatio; qDebug() << "Device pixel ratio changed, triggering GL resize"; - resizeGL(_glWidget->width(), - _glWidget->height()); + resizeGL(); } }); } @@ -830,15 +829,7 @@ void Application::paintGL() { PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); - - // Set the desired FBO texture size. If it hasn't changed, this does nothing. - // Otherwise, it must rebuild the FBOs - if (OculusManager::isConnected()) { - DependencyManager::get()->setFrameBufferSize(OculusManager::getRenderTargetSize()); - } else { - QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); - DependencyManager::get()->setFrameBufferSize(fbSize); - } + resizeGL(); glEnable(GL_LINE_SMOOTH); @@ -915,7 +906,14 @@ void Application::paintGL() { renderRearViewMirror(_mirrorViewRect); } - DependencyManager::get()->render(); + auto finalFbo = DependencyManager::get()->render(); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); + glBlitFramebuffer(0, 0, _renderResolution.x, _renderResolution.y, + 0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + { PerformanceTimer perfTimer("renderOverlay"); @@ -960,33 +958,47 @@ void Application::showEditEntitiesHelp() { InfoView::show(INFO_EDIT_ENTITIES_PATH); } -void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) { +void Application::resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size) { if (OculusManager::isConnected()) { - OculusManager::configureCamera(camera, width, height); + OculusManager::configureCamera(camera, size.x, size.y); } else if (TV3DManager::isConnected()) { - TV3DManager::configureCamera(camera, width, height); + TV3DManager::configureCamera(camera, size.x, size.y); } else { - camera.setAspectRatio((float)width / height); + camera.setAspectRatio((float)size.x / size.y); camera.setFieldOfView(_fieldOfView.get()); } } -void Application::resizeGL(int width, int height) { - DependencyManager::get()->setFrameBufferSize(QSize(width, height)); - resetCamerasOnResizeGL(_myCamera, width, height); +void Application::resizeGL() { + // Set the desired FBO texture size. If it hasn't changed, this does nothing. + // Otherwise, it must rebuild the FBOs + QSize renderSize; + if (OculusManager::isConnected()) { + renderSize = OculusManager::getRenderTargetSize(); + } else { + renderSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); + } + if (_renderResolution == toGlm(renderSize)) { + return; + } - glViewport(0, 0, width, height); // shouldn't this account for the menu??? + _renderResolution = toGlm(renderSize); + DependencyManager::get()->setFrameBufferSize(renderSize); + resetCamerasOnResizeGL(_myCamera, _renderResolution); + + glViewport(0, 0, _renderResolution.x, _renderResolution.y); // shouldn't this account for the menu??? updateProjectionMatrix(); glLoadIdentity(); auto offscreenUi = DependencyManager::get(); offscreenUi->resize(_glWidget->size()); + _glWidget->makeCurrent(); // update Stats width // let's set horizontal offset to give stats some margin to mirror int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; - Stats::getInstance()->resetWidth(width, horizontalOffset); + Stats::getInstance()->resetWidth(_renderResolution.x, horizontalOffset); } void Application::updateProjectionMatrix() { @@ -1824,7 +1836,7 @@ void Application::setFullscreen(bool fullscreen) { } void Application::setEnable3DTVMode(bool enable3DTVMode) { - resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); + resizeGL(); } void Application::setEnableVRMode(bool enableVRMode) { @@ -1849,7 +1861,7 @@ void Application::setEnableVRMode(bool enableVRMode) { _myCamera.setHmdRotation(glm::quat()); } - resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); + resizeGL(); updateCursorVisibility(); } @@ -3227,12 +3239,12 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs _stars.render(theCamera.getFieldOfView(), theCamera.getAspectRatio(), theCamera.getNearClip(), alpha); } - // draw the sky dome - if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { - PerformanceTimer perfTimer("atmosphere"); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... atmosphere..."); - _environment.renderAtmospheres(theCamera); + // draw the sky dome + if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { + PerformanceTimer perfTimer("atmosphere"); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "Application::displaySide() ... atmosphere..."); + _environment.renderAtmospheres(theCamera); } } @@ -4635,7 +4647,3 @@ PickRay Application::computePickRay() const { bool Application::hasFocus() const { return _glWidget->hasFocus(); } - -void Application::resizeGL() { - this->resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); -} diff --git a/interface/src/Application.h b/interface/src/Application.h index 10df094c2e..5a3756e768 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -163,7 +163,7 @@ public: void initializeGL(); void initializeUi(); void paintGL(); - void resizeGL(int width, int height); + void resizeGL(); void resizeEvent(QResizeEvent * size); @@ -194,7 +194,6 @@ public: bool hasFocus() const; PickRay computePickRay() const; PickRay computeViewPickRay(float xRatio, float yRatio) const; - void resizeGL(); bool isThrottleRendering() const; @@ -463,7 +462,7 @@ private slots: void setCursorVisible(bool visible); private: - void resetCamerasOnResizeGL(Camera& camera, int width, int height); + void resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size); void updateProjectionMatrix(); void updateProjectionMatrix(Camera& camera, bool updateViewFrustum = true); @@ -662,6 +661,7 @@ private: QHash _acceptedExtensions; QList _domainConnectionRefusals; + glm::uvec2 _renderResolution; }; #endif // hifi_Application_h diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 2cbec1b258..995e1908a9 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -64,7 +64,7 @@ void GLCanvas::paintGL() { } void GLCanvas::resizeGL(int width, int height) { - Application::getInstance()->resizeGL(width, height); + Application::getInstance()->resizeGL(); } void GLCanvas::activeChanged(Qt::ApplicationState state) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b15607df8f..d4ff3dead2 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -181,7 +181,7 @@ namespace MenuOption { const QString EditEntitiesHelp = "Edit Entities Help..."; const QString Enable3DTVMode = "Enable 3DTV Mode"; const QString EnableCharacterController = "Enable avatar collisions"; - const QString EnableGlowEffect = "Enable Glow Effect (Warning: Poor Oculus Performance)"; + const QString EnableGlowEffect = "Enable Glow Effect"; const QString EnableVRMode = "Enable VR Mode"; const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation"; const QString ExpandMyAvatarTiming = "Expand /myAvatar"; diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 065b7499d3..f4693d3c08 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -627,7 +627,7 @@ void OculusManager::display(QGLWidget * glCanvas, const glm::quat &bodyOrientati if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { //Full texture viewport for glow effect glViewport(0, 0, _renderTargetSize.w, _renderTargetSize.h); - finalFbo = DependencyManager::get()->render(true); + finalFbo = DependencyManager::get()->render(); } else { finalFbo = DependencyManager::get()->getPrimaryFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, 0); diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index 9d5dd2faae..5d60bf7e19 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -14,7 +14,7 @@ #include #include - +#include "gpu/GLBackend.h" #include "Application.h" #include "TV3DManager.h" @@ -163,10 +163,18 @@ void TV3DManager::display(Camera& whichCamera) { glPopMatrix(); glDisable(GL_SCISSOR_TEST); + auto finalFbo = DependencyManager::get()->render(); + auto fboSize = finalFbo->getSize(); + // Get the ACTUAL device size for the BLIT + deviceSize = qApp->getDeviceSize(); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); + glBlitFramebuffer(0, 0, fboSize.x, fboSize.y, + 0, 0, deviceSize.width(), deviceSize.height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + // reset the viewport to how we started glViewport(0, 0, deviceSize.width(), deviceSize.height()); - - DependencyManager::get()->render(); } void TV3DManager::overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 5c878b484c..1bfdf88032 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -190,8 +190,8 @@ void ApplicationOverlay::renderOverlay() { Overlays& overlays = qApp->getOverlays(); _textureFov = glm::radians(_hmdUIAngularSize); - glm::vec2 deviceSize = qApp->getCanvasSize(); - _textureAspectRatio = (float)deviceSize.x / (float)deviceSize.y; + glm::vec2 size = qApp->getCanvasSize(); + _textureAspectRatio = aspect(size); //Handle fading and deactivation/activation of UI @@ -204,12 +204,13 @@ void ApplicationOverlay::renderOverlay() { _overlays.buildFramebufferObject(); _overlays.bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, size.x, size.y); glPushMatrix(); { const float NEAR_CLIP = -10000; const float FAR_CLIP = 10000; glLoadIdentity(); - glOrtho(0, deviceSize.x, deviceSize.y, 0, NEAR_CLIP, FAR_CLIP); + glOrtho(0, size.x, size.y, 0, NEAR_CLIP, FAR_CLIP); glMatrixMode(GL_MODELVIEW); @@ -269,6 +270,7 @@ void ApplicationOverlay::displayOverlayTexture() { if (_alpha < 1.0) { glEnable(GL_BLEND); } + glViewport(0, 0, qApp->getDeviceSize().width(), qApp->getDeviceSize().height()); static const glm::vec2 topLeft(-1, 1); static const glm::vec2 bottomRight(1, -1); @@ -1129,8 +1131,9 @@ void ApplicationOverlay::TexturedHemisphere::cleanupVBO() { } void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { - auto deviceSize = qApp->getDeviceSize(); - if (_framebufferObject != NULL && deviceSize == _framebufferObject->size()) { + auto canvasSize = qApp->getCanvasSize(); + QSize fboSize = QSize(canvasSize.x, canvasSize.y); + if (_framebufferObject != NULL && fboSize == _framebufferObject->size()) { // Already build return; } @@ -1139,7 +1142,7 @@ void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { delete _framebufferObject; } - _framebufferObject = new QOpenGLFramebufferObject(deviceSize, QOpenGLFramebufferObject::Depth); + _framebufferObject = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth); glBindTexture(GL_TEXTURE_2D, getTexture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); diff --git a/libraries/render-utils/src/FboCache.cpp b/libraries/render-utils/src/FboCache.cpp index de2b483573..b6cca8116b 100644 --- a/libraries/render-utils/src/FboCache.cpp +++ b/libraries/render-utils/src/FboCache.cpp @@ -95,4 +95,7 @@ void FboCache::setSize(const QSize& newSize) { }); } +const QSize& FboCache::getSize() { + return _size; +} diff --git a/libraries/render-utils/src/FboCache.h b/libraries/render-utils/src/FboCache.h index 30278470fd..78c3194eb5 100644 --- a/libraries/render-utils/src/FboCache.h +++ b/libraries/render-utils/src/FboCache.h @@ -37,6 +37,8 @@ public: // internal locks and pointers but execute no OpenGL opreations. void lockTexture(int texture); void releaseTexture(int texture); + + const QSize& getSize(); protected: QMap> _fboMap; diff --git a/libraries/render-utils/src/GlowEffect.cpp b/libraries/render-utils/src/GlowEffect.cpp index 3040088ce5..bb18729f12 100644 --- a/libraries/render-utils/src/GlowEffect.cpp +++ b/libraries/render-utils/src/GlowEffect.cpp @@ -129,7 +129,7 @@ static void maybeRelease(const gpu::FramebufferPointer& fbo) { } } -gpu::FramebufferPointer GlowEffect::render(bool toTexture) { +gpu::FramebufferPointer GlowEffect::render() { PerformanceTimer perfTimer("glowEffect"); auto textureCache = DependencyManager::get(); @@ -151,26 +151,24 @@ gpu::FramebufferPointer GlowEffect::render(bool toTexture) { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - gpu::FramebufferPointer destFBO = toTexture ? - textureCache->getSecondaryFramebuffer() : nullptr; + gpu::FramebufferPointer destFBO = textureCache->getSecondaryFramebuffer(); if (!_enabled || _isEmpty) { // copy the primary to the screen - if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, primaryFBO); + if (QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO)); - glBlitFramebuffer(0, 0, framebufferSize.width(), framebufferSize.height(), 0, 0, framebufferSize.width(), framebufferSize.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, primaryFBO); + glBlitFramebuffer(0, 0, framebufferSize.width(), framebufferSize.height(), + 0, 0, framebufferSize.width(), framebufferSize.height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); } else { - maybeBind(destFBO); - if (!destFBO) { - //destFBO->getSize(); - glViewport(0, 0, framebufferSize.width(), framebufferSize.height()); - } + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO)); + glViewport(0, 0, framebufferSize.width(), framebufferSize.height()); glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); renderFullscreenQuad(); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); - maybeRelease(destFBO); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } } else { // diffuse into the secondary/tertiary (alternating between frames) @@ -199,22 +197,18 @@ gpu::FramebufferPointer GlowEffect::render(bool toTexture) { _diffuseProgram->release(); } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + destFBO = oldDiffusedFBO; + glBindFramebuffer(GL_FRAMEBUFFER, 0); // add diffused texture to the primary glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(newDiffusedFBO->getRenderBuffer(0))); - if (toTexture) { - destFBO = oldDiffusedFBO; - } - maybeBind(destFBO); - if (!destFBO) { - glViewport(0, 0, framebufferSize.width(), framebufferSize.height()); - } + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO)); + glViewport(0, 0, framebufferSize.width(), framebufferSize.height()); _addSeparateProgram->bind(); renderFullscreenQuad(); _addSeparateProgram->release(); - maybeRelease(destFBO); + glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); diff --git a/libraries/render-utils/src/GlowEffect.h b/libraries/render-utils/src/GlowEffect.h index 1cee7b2e9d..73c512ecf5 100644 --- a/libraries/render-utils/src/GlowEffect.h +++ b/libraries/render-utils/src/GlowEffect.h @@ -52,7 +52,7 @@ public: /// Renders the glow effect. To be called after rendering the scene. /// \param toTexture whether to render to a texture, rather than to the frame buffer /// \return the framebuffer object to which we rendered, or NULL if to the frame buffer - gpu::FramebufferPointer render(bool toTexture = false); + gpu::FramebufferPointer render(); public slots: void toggleGlowEffect(bool enabled); diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index a06f6f26cf..9b7cca70ee 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -117,6 +117,11 @@ QMatrix4x4 fromGlm(const glm::mat4 & m); QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size); +template +float aspect(const T& t) { + return (float)t.x / (float)t.y; +} + #define YAW(euler) euler.y #define PITCH(euler) euler.x #define ROLL(euler) euler.z diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 9b32aca96f..7d13a00324 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -117,8 +117,13 @@ void OffscreenUi::addImportPath(const QString& path) { void OffscreenUi::resize(const QSize& newSize) { makeCurrent(); - // Clear out any fbos with the old size qreal pixelRatio = _renderControl->_renderWindow ? _renderControl->_renderWindow->devicePixelRatio() : 1.0; + QSize newOffscreenSize = newSize * pixelRatio; + if (newOffscreenSize == _fboCache.getSize()) { + return; + } + + // Clear out any fbos with the old size qDebug() << "Offscreen UI resizing to " << newSize.width() << "x" << newSize.height() << " with pixel ratio " << pixelRatio; _fboCache.setSize(newSize * pixelRatio);