From 1e90aaf9c36a197c076e328f0f896203bd66b081 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 17 Jun 2015 11:35:30 -0700 Subject: [PATCH] Working on overlays still, mirror rendering and overlay order --- interface/resources/qml/Stats.qml | 1 + interface/src/Application.cpp | 9 +- interface/src/ui/ApplicationOverlay.cpp | 157 ++++++++++++++---------- interface/src/ui/ApplicationOverlay.h | 3 +- interface/src/ui/Stats.cpp | 8 +- interface/src/ui/Stats.h | 4 + 6 files changed, 112 insertions(+), 70 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 89961aeb9c..c77ab8ec27 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -230,6 +230,7 @@ Hifi.Stats { Rectangle { y: 250 + visible: root.timingExpanded width: perfText.width + 8 height: perfText.height + 8 color: root.bgColor; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8e3c4e416d..058f809249 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -874,6 +874,11 @@ void Application::paintGL() { OculusManager::beginFrameTiming(); } + { + PerformanceTimer perfTimer("renderOverlay"); + _applicationOverlay.renderOverlay(&renderArgs); + } + PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); @@ -974,10 +979,6 @@ void Application::paintGL() { glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); } - { - PerformanceTimer perfTimer("renderOverlay"); - _applicationOverlay.renderOverlay(&renderArgs); - } if (!OculusManager::isConnected() || OculusManager::allowSwap()) { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index ba0cdf3be0..d3c433339b 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -87,16 +87,16 @@ ApplicationOverlay::~ApplicationOverlay() { void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); - glm::vec2 size = qApp->getCanvasSize(); - // TODO Handle fading and deactivation/activation of UI + buildFramebufferObject(); - // TODO First render the mirror to the mirror FBO + // First render the mirror to the mirror FBO + renderRearViewToFbo(renderArgs); // Execute the batch into our framebuffer - buildFramebufferObject(); _overlayFramebuffer->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glm::vec2 size = qApp->getCanvasSize(); glViewport(0, 0, size.x, size.y); // Now render the overlay components together into a single texture @@ -104,6 +104,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { //renderAudioMeter(renderArgs); //renderCameraToggle(renderArgs); renderStatsAndLogs(renderArgs); + renderRearView(renderArgs); renderDomainConnectionStatusBorder(renderArgs); renderQmlUi(renderArgs); @@ -284,73 +285,77 @@ void ApplicationOverlay::renderAudioMeter(RenderArgs* renderArgs) { } } -void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { - // // Grab current viewport to reset it at the end - // int viewport[4]; - // glGetIntegerv(GL_VIEWPORT, viewport); - // float aspect = (float)region.width() / region.height(); - // float fov = MIRROR_FIELD_OF_VIEW; +void fboViewport(QOpenGLFramebufferObject* fbo) { + auto size = fbo->size(); + glViewport(0, 0, size.width(), size.height()); +} - // // bool eyeRelativeCamera = false; - // if (billboard) { - // fov = BILLBOARD_FIELD_OF_VIEW; // degees - // _mirrorCamera.setPosition(_myAvatar->getPosition() + - // _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale()); +void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { + // Grab current viewport to reset it at the end + auto mirrorSize = _mirrorFramebuffer->size(); + float aspect = (float)mirrorSize.width() / mirrorSize.height(); + float fov = MIRROR_FIELD_OF_VIEW; + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + // bool eyeRelativeCamera = false; + bool billboard = false; + if (billboard) { + fov = BILLBOARD_FIELD_OF_VIEW; // degees + _mirrorCamera.setPosition(myAvatar->getPosition() + + myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * myAvatar->getScale()); - // } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { - // _mirrorCamera.setPosition(_myAvatar->getChestPosition() + - // _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); + } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { + _mirrorCamera.setPosition(myAvatar->getChestPosition() + + myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * myAvatar->getScale()); - // } else { // HEAD zoom level - // // FIXME note that the positioing of the camera relative to the avatar can suffer limited - // // precision as the user's position moves further away from the origin. Thus at - // // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways - // // wildly as you rotate your avatar because the floating point values are becoming - // // larger, squeezing out the available digits of precision you have available at the - // // human scale for camera positioning. + } else { // HEAD zoom level + // FIXME note that the positioing of the camera relative to the avatar can suffer limited + // precision as the user's position moves further away from the origin. Thus at + // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways + // wildly as you rotate your avatar because the floating point values are becoming + // larger, squeezing out the available digits of precision you have available at the + // human scale for camera positioning. - // // Previously there was a hack to correct this using the mechanism of repositioning - // // the avatar at the origin of the world for the purposes of rendering the mirror, - // // but it resulted in failing to render the avatar's head model in the mirror view - // // when in first person mode. Presumably this was because of some missed culling logic - // // that was not accounted for in the hack. + // Previously there was a hack to correct this using the mechanism of repositioning + // the avatar at the origin of the world for the purposes of rendering the mirror, + // but it resulted in failing to render the avatar's head model in the mirror view + // when in first person mode. Presumably this was because of some missed culling logic + // that was not accounted for in the hack. - // // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further - // // investigated in order to adapt the technique while fixing the head rendering issue, - // // but the complexity of the hack suggests that a better approach - // _mirrorCamera.setPosition(_myAvatar->getHead()->getEyePosition() + - // _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); - // } - // _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); - // _mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); + // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further + // investigated in order to adapt the technique while fixing the head rendering issue, + // but the complexity of the hack suggests that a better approach + _mirrorCamera.setPosition(myAvatar->getHead()->getEyePosition() + + myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * myAvatar->getScale()); + } + _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); + _mirrorCamera.setRotation(myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); - // // set the bounds of rear mirror view - // if (billboard) { - // QSize size = DependencyManager::get()->getFrameBufferSize(); - // glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); - // glScissor(region.x(), size.height() - region.y() - region.height(), 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 = QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); - // int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; - // glViewport(x, size.height() - y - height, width, height); - // glScissor(x, size.height() - y - height, width, height); - // } - // bool updateViewFrustum = false; - // updateProjectionMatrix(_mirrorCamera, updateViewFrustum); - // glEnable(GL_SCISSOR_TEST); - // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // set the bounds of rear mirror view + if (billboard) { + //QSize size = DependencyManager::get()->getFrameBufferSize(); + //glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); + //glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); + } else { + auto mirrorSize = _mirrorFramebuffer->size(); + fboViewport(_mirrorFramebuffer); + } - // // render rear mirror view - // glMatrixMode(GL_MODELVIEW); - // glPushMatrix(); - // glLoadIdentity(); - // glLoadMatrixf(glm::value_ptr(glm::mat4_cast(_mirrorCamera.getOrientation()) * glm::translate(glm::mat4(), _mirrorCamera.getPosition()))); - // renderArgs->_context->syncCache(); - // displaySide(renderArgs, _mirrorCamera, true, billboard); - // glMatrixMode(GL_MODELVIEW); - // glPopMatrix(); + _mirrorFramebuffer->bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + { + auto projection = _mirrorCamera.getProjection(); + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(glm::value_ptr(projection)); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glLoadMatrixf(glm::value_ptr(glm::mat4_cast(_mirrorCamera.getOrientation()) * glm::translate(glm::mat4(), _mirrorCamera.getPosition()))); + renderArgs->_context->syncCache(); + qApp->displaySide(renderArgs, _mirrorCamera, true, billboard); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } + _mirrorFramebuffer->release(); // if (!billboard) { // _rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos())); @@ -363,6 +368,30 @@ void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { //} } +void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { + if (_mirrorFramebuffer && _mirrorFramebuffer->texture()) { + gpu::Batch batch; + auto geometryCache = DependencyManager::get(); + geometryCache->useSimpleDrawPipeline(batch); + batch._glDisable(GL_DEPTH_TEST); + batch._glDisable(GL_LIGHTING); + batch._glEnable(GL_BLEND); + batch.setProjectionTransform(mat4()); + batch.setModelTransform(mat4()); + auto textureCache = DependencyManager::get(); + batch.setUniformTexture(0, textureCache->getBlueTexture()); + geometryCache->renderUnitQuad(batch, glm::vec4(1)); + batch._glBindTexture(GL_TEXTURE_2D, _mirrorFramebuffer->texture()); + geometryCache->renderUnitQuad(batch, glm::vec4(1)); + renderArgs->_context->syncCache(); + auto overlaySize = _overlayFramebuffer->size(); + glViewport(MIRROR_VIEW_LEFT_PADDING, overlaySize.height() - MIRROR_VIEW_TOP_PADDING - MIRROR_VIEW_HEIGHT, + MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT); + renderArgs->_context->render(batch); + fboViewport(_overlayFramebuffer); + } +} + void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) { // Display stats and log text onscreen diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index efdec01fb5..ab242e592b 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -33,6 +33,7 @@ private: void renderCameraToggle(RenderArgs* renderArgs); void renderStatsAndLogs(RenderArgs* renderArgs); void renderDomainConnectionStatusBorder(RenderArgs* renderArgs); + void renderRearViewToFbo(RenderArgs* renderArgs); void renderRearView(RenderArgs* renderArgs); void renderQmlUi(RenderArgs* renderArgs); void renderOverlays(RenderArgs* renderArgs); @@ -52,7 +53,7 @@ private: float _rotateMirror{ 0.0f }; float _raiseMirror{ 0.0f }; - + Camera _mirrorCamera; ivec2 _previousBorderSize{ -1 }; QRect _mirrorViewRect; QOpenGLFramebufferObject* _overlayFramebuffer{ nullptr }; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index ca91e3a919..f541357486 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -296,6 +296,10 @@ void Stats::updateStats() { bool performanceTimerIsActive = PerformanceTimer::isActive(); bool displayPerf = _expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails); if (displayPerf && performanceTimerIsActive) { + if (!_timingExpanded) { + _timingExpanded = true; + emit timingExpandedChanged(); + } PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up // we will also include room for 1 line per timing record and a header of 4 lines @@ -336,8 +340,10 @@ void Stats::updateStats() { } _timingStats = perfLines; emit timingStatsChanged(); + } else if (_timingExpanded) { + _timingExpanded = false; + emit timingExpandedChanged(); } - } void Stats::setRenderDetails(const RenderDetails& details) { diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 01179ad353..efe340ed18 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -31,6 +31,7 @@ class Stats : public QQuickItem { Q_OBJECT HIFI_QML_DECL Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged) + Q_PROPERTY(bool timingExpanded READ isTimingExpanded NOTIFY timingExpandedChanged) STATS_PROPERTY(int, serverCount, 0) STATS_PROPERTY(int, framerate, 0) STATS_PROPERTY(int, avatarCount, 0) @@ -82,6 +83,7 @@ public: void updateStats(); bool isExpanded() { return _expanded; } + bool isTimingExpanded() { return _timingExpanded; } void setExpanded(bool expanded) { if (_expanded != expanded) { @@ -92,6 +94,7 @@ public: signals: void expandedChanged(); + void timingExpandedChanged(); void serverCountChanged(); void framerateChanged(); void avatarCountChanged(); @@ -137,6 +140,7 @@ private: int _recentMaxPackets{ 0 } ; // recent max incoming voxel packets to process bool _resetRecentMaxPacketsSoon{ true }; bool _expanded{ false }; + bool _timingExpanded{ false }; }; #endif // hifi_Stats_h