From cc30c0b841dd5a6baef7fe61411870d3b509f8c8 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 19 Oct 2017 11:35:26 +0200 Subject: [PATCH] Expanded scissor rect with outline blur width --- libraries/render-utils/src/OutlineEffect.cpp | 48 +++++++++++++++++--- libraries/render-utils/src/OutlineEffect.h | 19 +++++++- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 36faee8119..918f769277 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -81,6 +81,10 @@ gpu::TexturePointer OutlineRessources::getDepthTexture() { return getDepthFramebuffer()->getDepthStencilBuffer(); } +OutlineSharedParameters::OutlineSharedParameters() { + std::fill(_blurPixelWidths.begin(), _blurPixelWidths.end(), 0); +} + PrepareDrawOutline::PrepareDrawOutline() { _ressources = std::make_shared(); } @@ -92,6 +96,13 @@ void PrepareDrawOutline::run(const render::RenderContextPointer& renderContext, outputs = _ressources; } +DrawOutlineMask::DrawOutlineMask(unsigned int outlineIndex, + render::ShapePlumberPointer shapePlumber, OutlineSharedParametersPointer parameters) : + _outlineIndex{ outlineIndex }, + _shapePlumber { shapePlumber }, + _parameters{ parameters } { +} + void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); @@ -106,9 +117,12 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con // First thing we do is determine the projected bounding rect of all the outlined items auto outlinedRect = computeOutlineRect(inShapes, args->getViewFrustum(), framebufferSize); + auto blurPixelWidth = _parameters->_blurPixelWidths[_outlineIndex]; qCDebug(renderutils) << "Outline rect is " << outlinedRect.x << ' ' << outlinedRect.y << ' ' << outlinedRect.z << ' ' << outlinedRect.w; - outputs = outlinedRect; + // Add 1 pixel of extra margin to be on the safe side + outputs = expandRect(outlinedRect, blurPixelWidth+1, framebufferSize); + outlinedRect = expandRect(outputs, blurPixelWidth+1, framebufferSize); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -202,10 +216,28 @@ glm::ivec4 DrawOutlineMask::computeOutlineRect(const render::ShapeBounds& shapes } } +glm::ivec4 DrawOutlineMask::expandRect(glm::ivec4 rect, int amount, glm::ivec2 frameSize) { + // Go bo back to min max values + rect.z += rect.x; + rect.w += rect.y; + + rect.x = std::max(0, rect.x - amount); + rect.y = std::max(0, rect.y - amount); + rect.z = std::min(frameSize.x, rect.z + amount); + rect.w = std::min(frameSize.y, rect.w + amount); + + // Back to width height + rect.z -= rect.x; + rect.w -= rect.y; + return rect; +} + gpu::PipelinePointer DrawOutline::_pipeline; gpu::PipelinePointer DrawOutline::_pipelineFilled; -DrawOutline::DrawOutline() { +DrawOutline::DrawOutline(unsigned int outlineIndex, OutlineSharedParametersPointer parameters) : + _outlineIndex{ outlineIndex }, + _parameters{ parameters } { } void DrawOutline::configure(const Config& config) { @@ -222,7 +254,7 @@ void DrawOutline::configure(const Config& config) { _size = config.width / 400.0f; configuration._size.x = (_size * _framebufferSize.y) / _framebufferSize.x; configuration._size.y = _size; - + _parameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y); _isFilled = (config.unoccludedFillOpacity > OPACITY_EPSILON || config.occludedFillOpacity > OPACITY_EPSILON); } @@ -247,18 +279,19 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I configuration._size.x = (_size * framebufferSize.y) / framebufferSize.x; configuration._size.y = _size; _framebufferSize = framebufferSize; + _parameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y); } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); batch.setFramebuffer(destinationFrameBuffer); - batch.setStateScissorRect(outlineRect); batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); batch.setPipeline(pipeline); + batch.setStateScissorRect(outlineRect); batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); @@ -410,7 +443,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende const auto deferredFrameTransform = inputs.getN(3); // Prepare the ShapePipeline - ShapePlumberPointer shapePlumber = std::make_shared(); + auto shapePlumber = std::make_shared(); { auto state = std::make_shared(); state->setDepthTest(true, true, gpu::LESS); @@ -418,6 +451,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende state->setScissorEnable(true); initMaskPipelines(*shapePlumber, state); } + auto sharedParameters = std::make_shared(); // Prepare for outline group rendering. const auto outlineRessources = task.addJob("PrepareOutline", primaryFramebuffer); @@ -440,7 +474,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende name = stream.str(); } const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedBounds, outlineRessources).asVarying(); - const auto outlinedRect = task.addJob(name, drawMaskInputs, shapePlumber); + const auto outlinedRect = task.addJob(name, drawMaskInputs, i, shapePlumber, sharedParameters); if (i == 0) { outline0Rect = outlinedRect; } @@ -452,7 +486,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende name = stream.str(); } const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlineRessources, sceneFrameBuffer, outlinedRect).asVarying(); - task.addJob(name, drawOutlineInputs); + task.addJob(name, drawOutlineInputs, i, sharedParameters); } // Debug outline diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 878bdf2c04..ab603ecab6 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -42,6 +42,16 @@ protected: using OutlineRessourcesPointer = std::shared_ptr; +class OutlineSharedParameters { +public: + + OutlineSharedParameters(); + + std::array _blurPixelWidths; +}; + +using OutlineSharedParametersPointer = std::shared_ptr; + class PrepareDrawOutline { public: using Inputs = gpu::FramebufferPointer; @@ -65,15 +75,18 @@ public: using Outputs = glm::ivec4; using JobModel = render::Job::ModelIO; - DrawOutlineMask(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + DrawOutlineMask(unsigned int outlineIndex, render::ShapePlumberPointer shapePlumber, OutlineSharedParametersPointer parameters); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); protected: + unsigned int _outlineIndex; render::ShapePlumberPointer _shapePlumber; + OutlineSharedParametersPointer _parameters; static glm::ivec4 computeOutlineRect(const render::ShapeBounds& shapes, const ViewFrustum& viewFrustum, glm::ivec2 frameSize); + static glm::ivec4 expandRect(glm::ivec4 rect, int amount, glm::ivec2 frameSize); }; class DrawOutlineConfig : public render::Job::Config { @@ -116,7 +129,7 @@ public: using Config = DrawOutlineConfig; using JobModel = render::Job::ModelI; - DrawOutline(); + DrawOutline(unsigned int outlineIndex, OutlineSharedParametersPointer parameters); void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); @@ -140,6 +153,8 @@ private: static gpu::PipelinePointer _pipeline; static gpu::PipelinePointer _pipelineFilled; + unsigned int _outlineIndex; + OutlineSharedParametersPointer _parameters; OutlineConfigurationBuffer _configuration; glm::ivec2 _framebufferSize{ 0,0 }; bool _isFilled{ false };