diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1908684595..1aa9fe0427 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -894,6 +894,11 @@ void Application::paintGL() { { PerformanceTimer perfTimer("renderOverlay"); + + // NOTE: There is no batch associated with this renderArgs + // the ApplicationOverlay class assumes it's viewport is setup to be the device size + QSize size = qApp->getDeviceSize(); + renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height()); _applicationOverlay.renderOverlay(&renderArgs); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 2cbf718479..1fe1acb25a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -360,9 +360,6 @@ signals: /// Fired when we're rendering in-world interface elements; allows external parties to hook in. void renderingInWorldInterface(); - /// Fired when we're rendering the overlay. - void renderingOverlay(); - /// Fired when the import window is closed void importDone(); diff --git a/interface/src/audio/AudioScope.cpp b/interface/src/audio/AudioScope.cpp index 4b4e86e7f4..75a5137ca4 100644 --- a/interface/src/audio/AudioScope.cpp +++ b/interface/src/audio/AudioScope.cpp @@ -38,6 +38,7 @@ AudioScope::AudioScope() : _scopeOutputLeft(NULL), _scopeOutputRight(NULL), _scopeLastFrame(), + _audioScopeBackground(DependencyManager::get()->allocateID()), _audioScopeGrid(DependencyManager::get()->allocateID()), _inputID(DependencyManager::get()->allocateID()), _outputLeftID(DependencyManager::get()->allocateID()), @@ -126,22 +127,24 @@ void AudioScope::render(RenderArgs* renderArgs, int width, int height) { int w = (int)SCOPE_WIDTH; int h = (int)SCOPE_HEIGHT; - gpu::Batch batch; + gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); geometryCache->useSimpleDrawPipeline(batch); auto textureCache = DependencyManager::get(); batch.setResourceTexture(0, textureCache->getWhiteTexture()); + + // FIXME - do we really need to reset this here? we know that we're called inside of ApplicationOverlay::renderOverlays + // which already set up our batch for us to have these settings mat4 legacyProjection = glm::ortho(0, width, height, 0, -1000, 1000); batch.setProjectionTransform(legacyProjection); batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); - geometryCache->renderQuad(batch, x, y, w, h, backgroundColor); + batch._glLineWidth(1.0f); // default + geometryCache->renderQuad(batch, x, y, w, h, backgroundColor, _audioScopeBackground); geometryCache->renderGrid(batch, x, y, w, h, gridRows, gridCols, gridColor, _audioScopeGrid); renderLineStrip(batch, _inputID, inputColor, x, y, _samplesPerScope, _scopeInputOffset, _scopeInput); renderLineStrip(batch, _outputLeftID, outputLeftColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputLeft); renderLineStrip(batch, _outputRightD, outputRightColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputRight); - renderArgs->_context->syncCache(); - renderArgs->_context->render(batch); } void AudioScope::renderLineStrip(gpu::Batch& batch, int id, const glm::vec4& color, int x, int y, int n, int offset, const QByteArray* byteArray) { diff --git a/interface/src/audio/AudioScope.h b/interface/src/audio/AudioScope.h index 4ff4b55c29..0b716d7666 100644 --- a/interface/src/audio/AudioScope.h +++ b/interface/src/audio/AudioScope.h @@ -69,6 +69,7 @@ private: QByteArray* _scopeOutputRight; QByteArray _scopeLastFrame; + int _audioScopeBackground; int _audioScopeGrid; int _inputID; int _outputLeftID; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 4623109cdd..cd28ca0732 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -189,8 +189,8 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { return; } - GLuint texture = qApp->getApplicationOverlay().getOverlayTexture(); - if (!texture) { + gpu::FramebufferPointer overlayFramebuffer = qApp->getApplicationOverlay().getOverlayFramebuffer(); + if (!overlayFramebuffer) { return; } @@ -209,9 +209,7 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); batch.setProjectionTransform(mat4()); - batch._glBindTexture(GL_TEXTURE_2D, texture); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + batch.setResourceTexture(0, overlayFramebuffer->getRenderBuffer(0)); geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha)); // Doesn't actually render @@ -258,8 +256,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int return; } - GLuint texture = qApp->getApplicationOverlay().getOverlayTexture(); - if (!texture) { + gpu::FramebufferPointer overlayFramebuffer = qApp->getApplicationOverlay().getOverlayFramebuffer(); + if (!overlayFramebuffer) { return; } @@ -275,9 +273,12 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int geometryCache->useSimpleDrawPipeline(batch); batch._glDisable(GL_DEPTH_TEST); batch._glDisable(GL_CULL_FACE); - batch._glBindTexture(GL_TEXTURE_2D, texture); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //batch._glBindTexture(GL_TEXTURE_2D, texture); + //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + batch.setResourceTexture(0, overlayFramebuffer->getRenderBuffer(0)); + batch.setViewTransform(Transform()); batch.setProjectionTransform(qApp->getEyeProjection(eye)); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 860a108349..2717a7fa8f 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -40,12 +40,6 @@ const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; static const float ORTHO_NEAR_CLIP = -10000; static const float ORTHO_FAR_CLIP = 10000; -// TODO move somewhere useful -static void fboViewport(QOpenGLFramebufferObject* fbo) { - auto size = fbo->size(); - glViewport(0, 0, size.width(), size.height()); -} - ApplicationOverlay::ApplicationOverlay() { auto geometryCache = DependencyManager::get(); @@ -82,63 +76,84 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { AvatarInputs::getInstance()->update(); buildFramebufferObject(); + + if (!_overlayFramebuffer) { + return; // we can't do anything without our frame buffer. + } // Execute the batch into our framebuffer - _overlayFramebuffer->bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - fboViewport(_overlayFramebuffer); + gpu::Batch batch; + renderArgs->_batch = &batch; + + int width = _overlayFramebuffer->getWidth(); + int height = _overlayFramebuffer->getHeight(); + + batch.setViewportTransform(glm::ivec4(0, 0, width, height)); + batch.setFramebuffer(_overlayFramebuffer); + + glm::vec4 color { 0.0f, 0.0f, 0.0f, 0.0f }; + float depth = 1.0f; + int stencil = 0; + batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); // Now render the overlay components together into a single texture - renderOverlays(renderArgs); - renderStatsAndLogs(renderArgs); - renderDomainConnectionStatusBorder(renderArgs); - renderQmlUi(renderArgs); - _overlayFramebuffer->release(); + renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope + renderStatsAndLogs(renderArgs); // currently renders nothing + renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line + renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture + + renderArgs->_context->syncCache(); + renderArgs->_context->render(batch); + + renderArgs->_batch = nullptr; // so future users of renderArgs don't try to use our batch + CHECK_GL_ERROR(); } void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { PROFILE_RANGE(__FUNCTION__); if (_uiTexture) { - gpu::Batch batch; + gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); + geometryCache->useSimpleDrawPipeline(batch); batch.setProjectionTransform(mat4()); - batch.setModelTransform(mat4()); + batch.setModelTransform(Transform()); + batch.setViewTransform(Transform()); batch._glBindTexture(GL_TEXTURE_2D, _uiTexture); + geometryCache->renderUnitQuad(batch, glm::vec4(1)); - renderArgs->_context->syncCache(); - renderArgs->_context->render(batch); } } void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { PROFILE_RANGE(__FUNCTION__); - glm::vec2 size = qApp->getCanvasSize(); - mat4 legacyProjection = glm::ortho(0, size.x, size.y, 0, ORTHO_NEAR_CLIP, ORTHO_FAR_CLIP); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(glm::value_ptr(legacyProjection)); - glMatrixMode(GL_MODELVIEW); + gpu::Batch& batch = *renderArgs->_batch; + auto geometryCache = DependencyManager::get(); + geometryCache->useSimpleDrawPipeline(batch); + auto textureCache = DependencyManager::get(); + batch.setResourceTexture(0, textureCache->getWhiteTexture()); + int width = renderArgs->_viewport.z; + int height = renderArgs->_viewport.w; + mat4 legacyProjection = glm::ortho(0, width, height, 0, -1000, 1000); + batch.setProjectionTransform(legacyProjection); + batch.setModelTransform(Transform()); + batch.setViewTransform(Transform()); + batch._glLineWidth(1.0f); // default + + { + // Render the audio scope + //int width = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; + //int height = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; + DependencyManager::get()->render(renderArgs, width, height); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glUseProgram(0); - - // give external parties a change to hook in - emit qApp->renderingOverlay(); - qApp->getOverlays().renderHUD(renderArgs); - - DependencyManager::get()->render(renderArgs, _overlayFramebuffer->size().width(), _overlayFramebuffer->size().height()); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - - fboViewport(_overlayFramebuffer); + // Render all of the Script based "HUD" aka 2D overlays. + // note: we call them HUD, as opposed to 2D, only because there are some cases of 3D HUD overlays, like the + // cameral controls for the edit.js + qApp->getOverlays().renderHUD(renderArgs); + + } } void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { @@ -183,7 +198,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr }); auto nodeList = DependencyManager::get(); if (nodeList && !nodeList->getDomainHandler().isConnected()) { - gpu::Batch batch; + gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); geometryCache->useSimpleDrawPipeline(batch); batch.setProjectionTransform(mat4()); @@ -198,37 +213,40 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr //batch.setModelTransform(glm::scale(mat4(), vec3(scaleAmount))); geometryCache->renderVertices(batch, gpu::LINE_STRIP, _domainStatusBorder); - renderArgs->_context->syncCache(); - renderArgs->_context->render(batch); } } -GLuint ApplicationOverlay::getOverlayTexture() { - if (!_overlayFramebuffer) { - return 0; - } - return _overlayFramebuffer->texture(); -} - void ApplicationOverlay::buildFramebufferObject() { PROFILE_RANGE(__FUNCTION__); - QSize fboSize = qApp->getDeviceSize(); - if (_overlayFramebuffer && fboSize == _overlayFramebuffer->size()) { + + QSize desiredSize = qApp->getDeviceSize(); + int currentWidth = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; + int currentHeight = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; + QSize frameBufferCurrentSize(currentWidth, currentHeight); + + if (_overlayFramebuffer && desiredSize == frameBufferCurrentSize) { // Already built return; } if (_overlayFramebuffer) { - delete _overlayFramebuffer; + _overlayFramebuffer.reset(); + _overlayDepthTexture.reset(); + _overlayColorTexture.reset(); } - - _overlayFramebuffer = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth); - glBindTexture(GL_TEXTURE_2D, getOverlayTexture()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - glBindTexture(GL_TEXTURE_2D, 0); + + _overlayFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + + auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = desiredSize.width(); + auto height = desiredSize.height(); + + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); + _overlayColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + _overlayFramebuffer->setRenderBuffer(0, _overlayColorTexture); + + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); + _overlayDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); + + _overlayFramebuffer->setDepthStencilBuffer(_overlayDepthTexture, depthFormat); } diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 2f434ed7e1..0bbe4e3f77 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -25,7 +25,8 @@ public: ~ApplicationOverlay(); void renderOverlay(RenderArgs* renderArgs); - GLuint getOverlayTexture(); + + gpu::FramebufferPointer getOverlayFramebuffer() const { return _overlayFramebuffer; } private: void renderStatsAndLogs(RenderArgs* renderArgs); @@ -44,7 +45,11 @@ private: int _magnifierBorder; ivec2 _previousBorderSize{ -1 }; - QOpenGLFramebufferObject* _overlayFramebuffer{ nullptr }; + + gpu::TexturePointer _overlayDepthTexture; + gpu::TexturePointer _overlayColorTexture; + gpu::FramebufferPointer _overlayFramebuffer; + }; #endif // hifi_ApplicationOverlay_h diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index e4401b32ef..63b87a30ae 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -98,16 +98,29 @@ void Overlays::cleanupOverlaysToDelete() { void Overlays::renderHUD(RenderArgs* renderArgs) { PROFILE_RANGE(__FUNCTION__); QReadLocker lock(&_lock); - gpu::Batch batch; - renderArgs->_batch = &batch; - + gpu::Batch& batch = *renderArgs->_batch; + + auto geometryCache = DependencyManager::get(); + auto textureCache = DependencyManager::get(); + + auto size = qApp->getCanvasSize(); + int width = size.x; + int height = size.y; + mat4 legacyProjection = glm::ortho(0, width, height, 0, -1000, 1000); + foreach(Overlay::Pointer thisOverlay, _overlaysHUD) { + + // Reset all batch pipeline settings between overlay + geometryCache->useSimpleDrawPipeline(batch); + batch.setResourceTexture(0, textureCache->getWhiteTexture()); // FIXME - do we really need to do this?? + batch.setProjectionTransform(legacyProjection); + batch.setModelTransform(Transform()); + batch.setViewTransform(Transform()); + batch._glLineWidth(1.0f); // default + thisOverlay->render(renderArgs); } - - renderArgs->_context->syncCache(); - renderArgs->_context->render(batch); } unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) { diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index adbef7cb31..b14f9afc97 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -227,7 +227,7 @@ void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { int stencil = batch._params[paramOffset + 0]._float; GLuint glmask = 0; - if (masks & Framebuffer::BUFFER_DEPTH) { + if (masks & Framebuffer::BUFFER_STENCIL) { glClearStencil(stencil); glmask |= GL_STENCIL_BUFFER_BIT; } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 2bf41bc9b3..7cb882acc1 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -433,6 +433,8 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int h } // Draw vertical grid lines for (int i = cols + 1; --i >= 0; ) { + //glVertex2i(tx, y); + //glVertex2i(tx, y + height); *(vertex++) = tx; *(vertex++) = y;