From add675e16c7814c95e14a68611b5eb856211b7a7 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 8 Aug 2017 12:04:44 +0200 Subject: [PATCH 01/33] Create PickItemsJob than can be used to select a render item in front of the camera --- libraries/render-utils/src/PickItemsJob.cpp | 51 ++++++++++++++++++++ libraries/render-utils/src/PickItemsJob.h | 53 +++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 libraries/render-utils/src/PickItemsJob.cpp create mode 100644 libraries/render-utils/src/PickItemsJob.h diff --git a/libraries/render-utils/src/PickItemsJob.cpp b/libraries/render-utils/src/PickItemsJob.cpp new file mode 100644 index 0000000000..4665a45989 --- /dev/null +++ b/libraries/render-utils/src/PickItemsJob.cpp @@ -0,0 +1,51 @@ +// +// PickItemsJob.cpp +// render-utils/src/ +// +// Created by Olivier Prat on 08/08/17. +// Copyright 2017 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 +// +#include "PickItemsJob.h" + +void PickItemsJob::configure(const Config& config) { + _isEnabled = config.isEnabled; +} + +void PickItemsJob::run(const render::RenderContextPointer& renderContext, const PickItemsJob::Input& input, PickItemsJob::Output& output) { + output.clear(); + + if (_isEnabled) { + float minIsectDistance = std::numeric_limits::max(); + auto& itemBounds = input; + auto itemID = findNearestItem(renderContext, itemBounds, minIsectDistance); + + if (render::Item::isValidID(itemID)) { + output.emplace_back(itemID); + } + } +} + +render::ItemID PickItemsJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const { + const glm::vec3 rayOrigin = renderContext->args->getViewFrustum().getPosition(); + const glm::vec3 rayDirection = renderContext->args->getViewFrustum().getDirection(); + BoxFace face; + glm::vec3 normal; + float isectDistance; + render::ItemID nearestItem = render::Item::INVALID_ITEM_ID; + const float minDistance = 1.f; + const float maxDistance = 50.f; + + for (const auto& itemBound : inputs) { + if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { + auto& item = renderContext->_scene->getItem(itemBound.id); + if (item.getKey().isWorldSpace() && isectDistance>minDistance && isectDistance < minIsectDistance && isectDistance + +class PickItemsConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(bool isEnabled MEMBER isEnabled NOTIFY dirty) + +public: + + bool isEnabled{ false }; + +signals: + + void dirty(); +}; + +class PickItemsJob { + +public: + + using Config = PickItemsConfig; + using Input = render::ItemBounds; + using Output = render::ItemBounds; + using JobModel = render::Job::ModelIO; + + PickItemsJob() {} + + void configure(const Config& config); + void run(const render::RenderContextPointer& renderContext, const PickItemsJob::Input& input, PickItemsJob::Output& output); + +private: + + bool _isEnabled{ false }; + + render::ItemID findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const; +}; + +#endif // hifi_render_utils_PickItemsJob_h + + From 7de6079df89feec5020b7273905fa455de7bb541 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 8 Aug 2017 15:28:36 +0200 Subject: [PATCH 02/33] Added PrepareOutline job to save outlined zbuffer --- libraries/gpu/src/gpu/Format.cpp | 2 + libraries/gpu/src/gpu/Format.h | 2 + .../render-utils/src/RenderDeferredTask.cpp | 12 +++ libraries/render-utils/src/RenderOutline.cpp | 76 +++++++++++++++++++ libraries/render-utils/src/RenderOutline.h | 53 +++++++++++++ .../src/surfaceGeometry_copyDepth.slf | 20 +++++ 6 files changed, 165 insertions(+) create mode 100644 libraries/render-utils/src/RenderOutline.cpp create mode 100644 libraries/render-utils/src/RenderOutline.h create mode 100644 libraries/render-utils/src/surfaceGeometry_copyDepth.slf diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index b15f8d929f..4079606286 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -30,6 +30,8 @@ const Element Element::VEC2NU8_XY{ VEC2, NUINT8, XY }; const Element Element::COLOR_R11G11B10{ SCALAR, FLOAT, R11G11B10 }; const Element Element::VEC4F_COLOR_RGBA{ VEC4, FLOAT, RGBA }; +const Element Element::COLOR_RED_FLOAT{ SCALAR, FLOAT, RED }; +const Element Element::COLOR_RED_HALF{ SCALAR, HALF, RED }; const Element Element::VEC2F_UV{ VEC2, FLOAT, UV }; const Element Element::VEC2F_XY{ VEC2, FLOAT, XY }; const Element Element::VEC3F_XYZ{ VEC3, FLOAT, XYZ }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index c4d88236da..19965077b5 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -314,6 +314,8 @@ public: static const Element COLOR_COMPRESSED_SRGBA_HIGH; static const Element VEC2NU8_XY; static const Element VEC4F_COLOR_RGBA; + static const Element COLOR_RED_FLOAT; + static const Element COLOR_RED_HALF; static const Element VEC2F_UV; static const Element VEC2F_XY; static const Element VEC3F_XYZ; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 20c999019b..01c111151f 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -39,6 +39,8 @@ #include "AntialiasingEffect.h" #include "ToneMappingEffect.h" #include "SubsurfaceScattering.h" +#include "PickItemsJob.h" +#include "RenderOutline.h" #include @@ -85,6 +87,16 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // draw a stencil mask in hidden regions of the framebuffer. task.addJob("PrepareStencil", primaryFramebuffer); + // Select items that need to be outlined + const auto outlinedOpaques = task.addJob("PickOutlined", opaques); + + // Render opaque outline objects first in DeferredBuffer + const auto opaqueOutlineInputs = DrawStateSortDeferred::Inputs(outlinedOpaques, lightingModel).hasVarying(); + task.addJob("DrawOpaqueOutlined", opaqueOutlineInputs, shapePlumber); + + // Retrieve z value of the outlined objects + const auto outlinedZBuffer = task.addJob("PrepareOutline", deferredFramebuffer); + // Render opaque objects in DeferredBuffer const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying(); task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber); diff --git a/libraries/render-utils/src/RenderOutline.cpp b/libraries/render-utils/src/RenderOutline.cpp new file mode 100644 index 0000000000..6ecf86143f --- /dev/null +++ b/libraries/render-utils/src/RenderOutline.cpp @@ -0,0 +1,76 @@ +// +// RenderOutline.cpp +// render-utils/src/ +// +// Created by Olivier Prat on 08/08/17. +// Copyright 2017 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 +// +#include "RenderOutline.h" + +#include "gpu/Context.h" +#include "gpu/StandardShaderLib.h" + +#include "surfaceGeometry_copyDepth_frag.h" + +void PrepareOutline::run(const render::RenderContextPointer& renderContext, const PrepareOutline::Input& deferredFramebuffer, PrepareOutline::Output& output) { + glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w); + auto args = renderContext->args; + + // Resizing framebuffers instead of re-building them seems to cause issues with threaded + // rendering + if (_outlineFramebuffer && _outlineFramebuffer->getSize() != frameSize) { + _outlineFramebuffer.reset(); + } + + if (!_outlineFramebuffer) { + _outlineFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("deferredOutline")); + auto colorFormat = gpu::Element::COLOR_RED_HALF; + + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + auto primaryColorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); + + _outlineFramebuffer->setRenderBuffer(0, primaryColorTexture); + } + + if (!_copyDepthPipeline) { + auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + auto ps = gpu::Shader::createPixel(std::string(surfaceGeometry_copyDepth_frag)); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), 0)); + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setColorWriteMask(true, false, false, false); + + // Good to go add the brand new pipeline + _copyDepthPipeline = gpu::Pipeline::create(program, state); + } + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + auto depthBuffer = deferredFramebuffer->getPrimaryDepthTexture(); + + // Copy depth to texture as we will overwrite + batch.enableStereo(false); + + batch.setViewportTransform(args->_viewport); + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(frameSize, args->_viewport)); + + batch.setFramebuffer(_outlineFramebuffer); + batch.setPipeline(_copyDepthPipeline); + batch.setResourceTexture(0, depthBuffer); + batch.draw(gpu::TRIANGLE_STRIP, 4); + + // Restore previous frame buffer + batch.setFramebuffer(deferredFramebuffer->getDeferredFramebuffer()); + }); + + output = _outlineFramebuffer->getRenderBuffer(0); +} diff --git a/libraries/render-utils/src/RenderOutline.h b/libraries/render-utils/src/RenderOutline.h new file mode 100644 index 0000000000..a97f2033ef --- /dev/null +++ b/libraries/render-utils/src/RenderOutline.h @@ -0,0 +1,53 @@ +// +// RenderOutline.h +// render-utils/src/ +// +// Created by Olivier Prat on 08/08/17. +// Copyright 2017 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 +// + +#ifndef hifi_render_utils_RenderOutline_h +#define hifi_render_utils_RenderOutline_h + +#include +#include "DeferredFramebuffer.h" + +/* +class PickItemsConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(bool isEnabled MEMBER isEnabled NOTIFY dirty) + +public: + + bool isEnabled{ false }; + +signals: + + void dirty(); +}; +*/ +class PrepareOutline { + +public: + + using Input = DeferredFramebufferPointer; + // Output will contain outlined objects only z-depth texture + using Output = gpu::TexturePointer; + using JobModel = render::Job::ModelIO; + + PrepareOutline() {} + + void run(const render::RenderContextPointer& renderContext, const PrepareOutline::Input& input, PrepareOutline::Output& output); + +private: + + gpu::FramebufferPointer _outlineFramebuffer; + gpu::PipelinePointer _copyDepthPipeline; +}; + +#endif // hifi_render_utils_RenderOutline_h + + diff --git a/libraries/render-utils/src/surfaceGeometry_copyDepth.slf b/libraries/render-utils/src/surfaceGeometry_copyDepth.slf new file mode 100644 index 0000000000..9db8cdbb01 --- /dev/null +++ b/libraries/render-utils/src/surfaceGeometry_copyDepth.slf @@ -0,0 +1,20 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// Created by Olivier Prat on 08/08/17. +// Copyright 2017 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 depthMap; + +out vec4 outFragColor; + +void main(void) { + float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x; + outFragColor = vec4(Zdb, 0.0, 0.0, 1.0); +} + From 27227d6bd2c493df4f5d2fa6a89633fd13f0e399 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 8 Aug 2017 17:45:17 +0200 Subject: [PATCH 03/33] Simplified pick item jobs by using inherited enabled flag in render::Job::Config --- libraries/render-utils/src/PickItemsJob.cpp | 18 +++++++++--------- libraries/render-utils/src/PickItemsJob.h | 10 ++-------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/libraries/render-utils/src/PickItemsJob.cpp b/libraries/render-utils/src/PickItemsJob.cpp index 4665a45989..866510a115 100644 --- a/libraries/render-utils/src/PickItemsJob.cpp +++ b/libraries/render-utils/src/PickItemsJob.cpp @@ -10,22 +10,22 @@ // #include "PickItemsJob.h" +PickItemsJob::PickItemsJob() { +} + void PickItemsJob::configure(const Config& config) { - _isEnabled = config.isEnabled; } void PickItemsJob::run(const render::RenderContextPointer& renderContext, const PickItemsJob::Input& input, PickItemsJob::Output& output) { output.clear(); - if (_isEnabled) { - float minIsectDistance = std::numeric_limits::max(); - auto& itemBounds = input; - auto itemID = findNearestItem(renderContext, itemBounds, minIsectDistance); + float minIsectDistance = std::numeric_limits::max(); + auto& itemBounds = input; + auto itemID = findNearestItem(renderContext, itemBounds, minIsectDistance); - if (render::Item::isValidID(itemID)) { - output.emplace_back(itemID); - } - } + if (render::Item::isValidID(itemID)) { + output.emplace_back(itemID); + } } render::ItemID PickItemsJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const { diff --git a/libraries/render-utils/src/PickItemsJob.h b/libraries/render-utils/src/PickItemsJob.h index c6fea52207..b88c881b16 100644 --- a/libraries/render-utils/src/PickItemsJob.h +++ b/libraries/render-utils/src/PickItemsJob.h @@ -15,16 +15,10 @@ #include class PickItemsConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(bool isEnabled MEMBER isEnabled NOTIFY dirty) public: - bool isEnabled{ false }; - -signals: - - void dirty(); + PickItemsConfig() : render::Job::Config(false) {} }; class PickItemsJob { @@ -36,7 +30,7 @@ public: using Output = render::ItemBounds; using JobModel = render::Job::ModelIO; - PickItemsJob() {} + PickItemsJob(); void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, const PickItemsJob::Input& input, PickItemsJob::Output& output); From 44ee7c4bf14e7380f163eb2f33f32b6bd2a66ab5 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 8 Aug 2017 18:41:57 +0200 Subject: [PATCH 04/33] Renamed to OutlineEffect and working on debugging tool. Problems with outline framebuffer not complete --- libraries/render-utils/src/OutlineEffect.cpp | 207 ++++++++++++++++++ libraries/render-utils/src/OutlineEffect.h | 112 ++++++++++ .../render-utils/src/RenderDeferredTask.cpp | 8 +- libraries/render-utils/src/RenderOutline.cpp | 76 ------- libraries/render-utils/src/RenderOutline.h | 53 ----- .../utilities/render/debugOutline.js | 20 ++ .../developer/utilities/render/outline.qml | 37 ++++ 7 files changed, 382 insertions(+), 131 deletions(-) create mode 100644 libraries/render-utils/src/OutlineEffect.cpp create mode 100644 libraries/render-utils/src/OutlineEffect.h delete mode 100644 libraries/render-utils/src/RenderOutline.cpp delete mode 100644 libraries/render-utils/src/RenderOutline.h create mode 100644 scripts/developer/utilities/render/debugOutline.js create mode 100644 scripts/developer/utilities/render/outline.qml diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp new file mode 100644 index 0000000000..45bf9c7d81 --- /dev/null +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -0,0 +1,207 @@ +// +// OutlineEffect.cpp +// render-utils/src/ +// +// Created by Olivier Prat on 08/08/17. +// Copyright 2017 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 +// +#include "OutlineEffect.h" + +#include "GeometryCache.h" + +#include "gpu/Context.h" +#include "gpu/StandardShaderLib.h" + +#include "surfaceGeometry_copyDepth_frag.h" +#include "debug_deferred_buffer_vert.h" +#include "debug_deferred_buffer_frag.h" + +OutlineFramebuffer::OutlineFramebuffer() { +} + +void OutlineFramebuffer::update(const gpu::TexturePointer& linearDepthBuffer) { + //If the depth buffer or size changed, we need to delete our FBOs + bool reset = false; + + if (_depthTexture) { + auto newFrameSize = glm::ivec2(linearDepthBuffer->getDimensions()); + if (_frameSize != newFrameSize) { + _frameSize = newFrameSize; + reset = true; + } + } + + if (reset) { + clear(); + } +} + +void OutlineFramebuffer::clear() { + _depthFramebuffer.reset(); + _depthTexture.reset(); +} + +void OutlineFramebuffer::allocate() { + + auto width = _frameSize.x; + auto height = _frameSize.y; + auto colorFormat = gpu::Element::VEC4F_COLOR_RGBA; // TODO : find a more compact format + + _depthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth", colorFormat, width, height)); + _depthTexture = _depthFramebuffer->getRenderBuffer(0); +} + +gpu::FramebufferPointer OutlineFramebuffer::getDepthFramebuffer() { + if (!_depthFramebuffer) { + allocate(); + } + return _depthFramebuffer; +} + +gpu::TexturePointer OutlineFramebuffer::getDepthTexture() { + if (!_depthTexture) { + allocate(); + } + return _depthTexture; +} + +void PrepareOutline::run(const render::RenderContextPointer& renderContext, const PrepareOutline::Input& input, PrepareOutline::Output& output) { + auto outlinedItems = input.get1(); + + if (!outlinedItems.empty()) { + glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w); + auto args = renderContext->args; + auto deferredFrameBuffer = input.get0(); + + if (!_outlineFramebuffer) { + _outlineFramebuffer = std::make_shared(); + } + _outlineFramebuffer->update(deferredFrameBuffer->getPrimaryDepthTexture()); + + if (!_copyDepthPipeline) { + auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + auto ps = gpu::Shader::createPixel(std::string(surfaceGeometry_copyDepth_frag)); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), 0)); + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setColorWriteMask(true, false, false, false); + + // Good to go add the brand new pipeline + _copyDepthPipeline = gpu::Pipeline::create(program, state); + } + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + auto depthBuffer = deferredFrameBuffer->getPrimaryDepthTexture(); + + // Copy depth to texture as we will overwrite + batch.enableStereo(false); + + batch.setViewportTransform(args->_viewport); + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(frameSize, args->_viewport)); + + batch.setFramebuffer(_outlineFramebuffer->getDepthFramebuffer()); + batch.setPipeline(_copyDepthPipeline); + batch.setResourceTexture(0, depthBuffer); + batch.draw(gpu::TRIANGLE_STRIP, 4); + + // Restore previous frame buffer + batch.setFramebuffer(deferredFrameBuffer->getDeferredFramebuffer()); + }); + + output = _outlineFramebuffer; + } else { + output = nullptr; + } +} + +DebugOutline::DebugOutline() { + _geometryId = DependencyManager::get()->allocateID(); +} + +DebugOutline::~DebugOutline() { + auto geometryCache = DependencyManager::get(); + if (geometryCache) { + geometryCache->releaseID(_geometryId); + } +} + +void DebugOutline::configure(const Config& config) { + _isDisplayDepthEnabled = config.viewOutlinedDepth; +} + +void DebugOutline::run(const render::RenderContextPointer& renderContext, const Input& input) { + if (_isDisplayDepthEnabled && input) { + assert(renderContext->args); + assert(renderContext->args->hasViewFrustum()); + RenderArgs* args = renderContext->args; + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setViewportTransform(args->_viewport); + + const auto geometryBuffer = DependencyManager::get(); + + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat, true); + batch.setModelTransform(Transform()); + + batch.setPipeline(getDebugPipeline()); + batch.setResourceTexture(0, input->getDepthTexture()); + const glm::vec4 color(1.0f, 0.5f, 0.2f, 1.0f); + const glm::vec2 bottomLeft(-1.0f, -1.0f); + const glm::vec2 topRight(1.0f, 1.0f); + geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryId); + + batch.setResourceTexture(0, nullptr); + }); + } +} + +const gpu::PipelinePointer& DebugOutline::getDebugPipeline() { + if (!_debugPipeline) { + static const std::string VERTEX_SHADER{ debug_deferred_buffer_vert }; + static const std::string FRAGMENT_SHADER{ debug_deferred_buffer_frag }; + static const std::string SOURCE_PLACEHOLDER{ "//SOURCE_PLACEHOLDER" }; + static const auto SOURCE_PLACEHOLDER_INDEX = FRAGMENT_SHADER.find(SOURCE_PLACEHOLDER); + Q_ASSERT_X(SOURCE_PLACEHOLDER_INDEX != std::string::npos, Q_FUNC_INFO, + "Could not find source placeholder"); + static const std::string DEFAULT_DEPTH_SHADER{ + "vec4 getFragmentColor() {" + " float depth = texture(depthMap, uv).x;" + " return vec4(vec3(depth), 1.0);" + " }" + }; + + auto bakedFragmentShader = FRAGMENT_SHADER; + bakedFragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(), DEFAULT_DEPTH_SHADER); + + static const auto vs = gpu::Shader::createVertex(VERTEX_SHADER); + const auto ps = gpu::Shader::createPixel(bakedFragmentShader); + const auto program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding("depthMap", 0)); + gpu::Shader::makeProgram(*program, slotBindings); + + auto state = std::make_shared(); + state->setDepthTest(gpu::State::DepthTest(false)); + state->setColorWriteMask(true, false, false, false); + _debugPipeline = gpu::Pipeline::create(program, state); + } + + return _debugPipeline; +} diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h new file mode 100644 index 0000000000..bb4343b06a --- /dev/null +++ b/libraries/render-utils/src/OutlineEffect.h @@ -0,0 +1,112 @@ +// +// OutlineEffect.h +// render-utils/src/ +// +// Created by Olivier Prat on 08/08/17. +// Copyright 2017 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 +// + +#ifndef hifi_render_utils_OutlineEffect_h +#define hifi_render_utils_OutlineEffect_h + +#include +#include "DeferredFramebuffer.h" + +/* +class PickItemsConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(bool isEnabled MEMBER isEnabled NOTIFY dirty) + +public: + + bool isEnabled{ false }; + +signals: + + void dirty(); +}; +*/ + +class OutlineFramebuffer { +public: + OutlineFramebuffer(); + + gpu::FramebufferPointer getDepthFramebuffer(); + gpu::TexturePointer getDepthTexture(); + + // Update the source framebuffer size which will drive the allocation of all the other resources. + void update(const gpu::TexturePointer& linearDepthBuffer); + const glm::ivec2& getSourceFrameSize() const { return _frameSize; } + +protected: + + void clear(); + void allocate(); + + gpu::FramebufferPointer _depthFramebuffer; + gpu::TexturePointer _depthTexture; + + glm::ivec2 _frameSize; +}; + +using OutlineFramebufferPointer = std::shared_ptr; + +class PrepareOutline { + +public: + + using Input = render::VaryingSet2; + // Output will contain outlined objects only z-depth texture + using Output = OutlineFramebufferPointer; + using JobModel = render::Job::ModelIO; + + PrepareOutline() {} + + void run(const render::RenderContextPointer& renderContext, const PrepareOutline::Input& input, PrepareOutline::Output& output); + +private: + + OutlineFramebufferPointer _outlineFramebuffer; + gpu::PipelinePointer _copyDepthPipeline; +}; + +class DebugOutlineConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(bool viewOutlinedDepth MEMBER viewOutlinedDepth NOTIFY dirty) + +public: + + bool viewOutlinedDepth{ false }; + +signals: + void dirty(); +}; + + +class DebugOutline { +public: + using Input = OutlineFramebufferPointer; + using Config = DebugOutlineConfig; + using JobModel = render::Job::ModelI; + + DebugOutline(); + ~DebugOutline(); + + void configure(const Config& config); + void run(const render::RenderContextPointer& renderContext, const Input& inputs); + +private: + + const gpu::PipelinePointer& getDebugPipeline(); + + gpu::PipelinePointer _debugPipeline; + int _geometryId{ 0 }; + bool _isDisplayDepthEnabled{ false }; +}; + +#endif // hifi_render_utils_OutlineEffect_h + + diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 01c111151f..8740b767f6 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -40,7 +40,7 @@ #include "ToneMappingEffect.h" #include "SubsurfaceScattering.h" #include "PickItemsJob.h" -#include "RenderOutline.h" +#include "OutlineEffect.h" #include @@ -95,7 +95,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawOpaqueOutlined", opaqueOutlineInputs, shapePlumber); // Retrieve z value of the outlined objects - const auto outlinedZBuffer = task.addJob("PrepareOutline", deferredFramebuffer); + const auto outlinePrepareInputs = PrepareOutline::Input(deferredFramebuffer, outlinedOpaques).hasVarying(); + const auto outlinedFrameBuffer = task.addJob("PrepareOutline", outlinePrepareInputs); // Render opaque objects in DeferredBuffer const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying(); @@ -199,6 +200,9 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto debugAmbientOcclusionInputs = DebugAmbientOcclusion::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget, ambientOcclusionUniforms).hasVarying(); task.addJob("DebugAmbientOcclusion", debugAmbientOcclusionInputs); + // Debug outline + task.addJob("DebugOutline", outlinedFrameBuffer); + // Scene Octree Debugging job { task.addJob("DrawSceneOctree", spatialSelection); diff --git a/libraries/render-utils/src/RenderOutline.cpp b/libraries/render-utils/src/RenderOutline.cpp deleted file mode 100644 index 6ecf86143f..0000000000 --- a/libraries/render-utils/src/RenderOutline.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// RenderOutline.cpp -// render-utils/src/ -// -// Created by Olivier Prat on 08/08/17. -// Copyright 2017 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 -// -#include "RenderOutline.h" - -#include "gpu/Context.h" -#include "gpu/StandardShaderLib.h" - -#include "surfaceGeometry_copyDepth_frag.h" - -void PrepareOutline::run(const render::RenderContextPointer& renderContext, const PrepareOutline::Input& deferredFramebuffer, PrepareOutline::Output& output) { - glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w); - auto args = renderContext->args; - - // Resizing framebuffers instead of re-building them seems to cause issues with threaded - // rendering - if (_outlineFramebuffer && _outlineFramebuffer->getSize() != frameSize) { - _outlineFramebuffer.reset(); - } - - if (!_outlineFramebuffer) { - _outlineFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("deferredOutline")); - auto colorFormat = gpu::Element::COLOR_RED_HALF; - - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); - auto primaryColorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); - - _outlineFramebuffer->setRenderBuffer(0, primaryColorTexture); - } - - if (!_copyDepthPipeline) { - auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); - auto ps = gpu::Shader::createPixel(std::string(surfaceGeometry_copyDepth_frag)); - gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); - - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), 0)); - gpu::Shader::makeProgram(*program, slotBindings); - - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - - state->setColorWriteMask(true, false, false, false); - - // Good to go add the brand new pipeline - _copyDepthPipeline = gpu::Pipeline::create(program, state); - } - - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - auto depthBuffer = deferredFramebuffer->getPrimaryDepthTexture(); - - // Copy depth to texture as we will overwrite - batch.enableStereo(false); - - batch.setViewportTransform(args->_viewport); - batch.setProjectionTransform(glm::mat4()); - batch.resetViewTransform(); - batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(frameSize, args->_viewport)); - - batch.setFramebuffer(_outlineFramebuffer); - batch.setPipeline(_copyDepthPipeline); - batch.setResourceTexture(0, depthBuffer); - batch.draw(gpu::TRIANGLE_STRIP, 4); - - // Restore previous frame buffer - batch.setFramebuffer(deferredFramebuffer->getDeferredFramebuffer()); - }); - - output = _outlineFramebuffer->getRenderBuffer(0); -} diff --git a/libraries/render-utils/src/RenderOutline.h b/libraries/render-utils/src/RenderOutline.h deleted file mode 100644 index a97f2033ef..0000000000 --- a/libraries/render-utils/src/RenderOutline.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// RenderOutline.h -// render-utils/src/ -// -// Created by Olivier Prat on 08/08/17. -// Copyright 2017 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 -// - -#ifndef hifi_render_utils_RenderOutline_h -#define hifi_render_utils_RenderOutline_h - -#include -#include "DeferredFramebuffer.h" - -/* -class PickItemsConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(bool isEnabled MEMBER isEnabled NOTIFY dirty) - -public: - - bool isEnabled{ false }; - -signals: - - void dirty(); -}; -*/ -class PrepareOutline { - -public: - - using Input = DeferredFramebufferPointer; - // Output will contain outlined objects only z-depth texture - using Output = gpu::TexturePointer; - using JobModel = render::Job::ModelIO; - - PrepareOutline() {} - - void run(const render::RenderContextPointer& renderContext, const PrepareOutline::Input& input, PrepareOutline::Output& output); - -private: - - gpu::FramebufferPointer _outlineFramebuffer; - gpu::PipelinePointer _copyDepthPipeline; -}; - -#endif // hifi_render_utils_RenderOutline_h - - diff --git a/scripts/developer/utilities/render/debugOutline.js b/scripts/developer/utilities/render/debugOutline.js new file mode 100644 index 0000000000..6a456054e1 --- /dev/null +++ b/scripts/developer/utilities/render/debugOutline.js @@ -0,0 +1,20 @@ +// +// debugOutline.js +// developer/utilities/render +// +// Olivier Prat, created on 08/08/2017. +// Copyright 2017 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 +// + +// Set up the qml ui +var qml = Script.resolvePath('outline.qml'); +var window = new OverlayWindow({ + title: 'Outline', + source: qml, + width: 250, + height: 80, +}); +window.closed.connect(function() { Script.stop(); }); \ No newline at end of file diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml new file mode 100644 index 0000000000..11a9ecf432 --- /dev/null +++ b/scripts/developer/utilities/render/outline.qml @@ -0,0 +1,37 @@ +// +// outline.qml +// developer/utilities/render +// +// Olivier Prat, created on 08/08/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Item { + id: root + property var pickConfig: Render.getConfig("RenderMainView.PickOutlined") + property var debugConfig: Render.getConfig("RenderMainView.DebugOutline") + + Column { + spacing: 8 + + CheckBox { + text: "Edit Outline" + checked: root.pickConfig["enabled"] + onCheckedChanged: { + root.pickConfig["enabled"] = checked; + } + } + CheckBox { + text: "View Outlined Depth" + checked: root.debugConfig["viewOutlinedDepth"] + onCheckedChanged: { + root.debugConfig["viewOutlinedDepth"] = checked; + } + } + } +} From 0fb4e42e1fc9c64ff58a762e3d5d0ff8a90071cf Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 9 Aug 2017 11:52:31 +0200 Subject: [PATCH 05/33] Improved PickItemJob with item key filter --- libraries/render-utils/src/PickItemsJob.cpp | 19 +++++++++++-------- libraries/render-utils/src/PickItemsJob.h | 8 +++++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/libraries/render-utils/src/PickItemsJob.cpp b/libraries/render-utils/src/PickItemsJob.cpp index 866510a115..3cfbd0f956 100644 --- a/libraries/render-utils/src/PickItemsJob.cpp +++ b/libraries/render-utils/src/PickItemsJob.cpp @@ -10,7 +10,7 @@ // #include "PickItemsJob.h" -PickItemsJob::PickItemsJob() { +PickItemsJob::PickItemsJob(render::ItemKey::Flags validKeys, render::ItemKey::Flags excludeKeys) : _validKeys{ validKeys }, _excludeKeys{ excludeKeys } { } void PickItemsJob::configure(const Config& config) { @@ -21,28 +21,31 @@ void PickItemsJob::run(const render::RenderContextPointer& renderContext, const float minIsectDistance = std::numeric_limits::max(); auto& itemBounds = input; - auto itemID = findNearestItem(renderContext, itemBounds, minIsectDistance); + auto item = findNearestItem(renderContext, itemBounds, minIsectDistance); - if (render::Item::isValidID(itemID)) { - output.emplace_back(itemID); + if (render::Item::isValidID(item.id)) { + output.push_back(item); } } -render::ItemID PickItemsJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const { +render::ItemBound PickItemsJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const { const glm::vec3 rayOrigin = renderContext->args->getViewFrustum().getPosition(); const glm::vec3 rayDirection = renderContext->args->getViewFrustum().getDirection(); BoxFace face; glm::vec3 normal; float isectDistance; - render::ItemID nearestItem = render::Item::INVALID_ITEM_ID; + render::ItemBound nearestItem( render::Item::INVALID_ITEM_ID ); const float minDistance = 1.f; const float maxDistance = 50.f; + render::ItemKey itemKey; for (const auto& itemBound : inputs) { if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { auto& item = renderContext->_scene->getItem(itemBound.id); - if (item.getKey().isWorldSpace() && isectDistance>minDistance && isectDistance < minIsectDistance && isectDistanceminDistance && isectDistance < minIsectDistance && isectDistance +#include class PickItemsConfig : public render::Job::Config { @@ -30,16 +31,17 @@ public: using Output = render::ItemBounds; using JobModel = render::Job::ModelIO; - PickItemsJob(); + PickItemsJob(render::ItemKey::Flags validKeys = render::ItemKey::Builder().withTypeMeta().withTypeShape().build()._flags, render::ItemKey::Flags excludeKeys = 0); void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, const PickItemsJob::Input& input, PickItemsJob::Output& output); private: - bool _isEnabled{ false }; + render::ItemKey::Flags _validKeys; + render::ItemKey::Flags _excludeKeys; - render::ItemID findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const; + render::ItemBound findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const; }; #endif // hifi_render_utils_PickItemsJob_h From cfa23b1758b5e40db34e90f3af6960776a4b008b Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 9 Aug 2017 12:32:32 +0200 Subject: [PATCH 06/33] Writing out depth buffer of outlined objects to texture working --- libraries/render-utils/src/OutlineEffect.cpp | 15 ++++++--------- libraries/render-utils/src/RenderDeferredTask.cpp | 4 +++- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 45bf9c7d81..758783760d 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -48,10 +48,11 @@ void OutlineFramebuffer::allocate() { auto width = _frameSize.x; auto height = _frameSize.y; - auto colorFormat = gpu::Element::VEC4F_COLOR_RGBA; // TODO : find a more compact format + auto format = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED); - _depthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth", colorFormat, width, height)); - _depthTexture = _depthFramebuffer->getRenderBuffer(0); + _depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(format, width, height)); + _depthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); + _depthFramebuffer->setRenderBuffer(0, _depthTexture); } gpu::FramebufferPointer OutlineFramebuffer::getDepthFramebuffer() { @@ -72,9 +73,9 @@ void PrepareOutline::run(const render::RenderContextPointer& renderContext, cons auto outlinedItems = input.get1(); if (!outlinedItems.empty()) { - glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w); auto args = renderContext->args; auto deferredFrameBuffer = input.get0(); + auto frameSize = deferredFrameBuffer->getFrameSize(); if (!_outlineFramebuffer) { _outlineFramebuffer = std::make_shared(); @@ -99,9 +100,6 @@ void PrepareOutline::run(const render::RenderContextPointer& renderContext, cons } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - auto depthBuffer = deferredFrameBuffer->getPrimaryDepthTexture(); - - // Copy depth to texture as we will overwrite batch.enableStereo(false); batch.setViewportTransform(args->_viewport); @@ -111,7 +109,7 @@ void PrepareOutline::run(const render::RenderContextPointer& renderContext, cons batch.setFramebuffer(_outlineFramebuffer->getDepthFramebuffer()); batch.setPipeline(_copyDepthPipeline); - batch.setResourceTexture(0, depthBuffer); + batch.setResourceTexture(0, deferredFrameBuffer->getPrimaryDepthTexture()); batch.draw(gpu::TRIANGLE_STRIP, 4); // Restore previous frame buffer @@ -199,7 +197,6 @@ const gpu::PipelinePointer& DebugOutline::getDebugPipeline() { auto state = std::make_shared(); state->setDepthTest(gpu::State::DepthTest(false)); - state->setColorWriteMask(true, false, false, false); _debugPipeline = gpu::Pipeline::create(program, state); } diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 8740b767f6..ba045dfff9 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -88,7 +88,9 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("PrepareStencil", primaryFramebuffer); // Select items that need to be outlined - const auto outlinedOpaques = task.addJob("PickOutlined", opaques); + const auto outlinedOpaques = task.addJob("PickOutlined", opaques, + // Pick only shapes so exclude meta + render::ItemKey::Builder().withTypeShape().build()._flags, render::ItemKey::Builder().withTypeMeta().build()._flags); // Render opaque outline objects first in DeferredBuffer const auto opaqueOutlineInputs = DrawStateSortDeferred::Inputs(outlinedOpaques, lightingModel).hasVarying(); From f36500a74c281a864b55c506349b0fab659c382c Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 9 Aug 2017 14:52:52 +0200 Subject: [PATCH 07/33] Working outline debugging view --- libraries/render-utils/src/OutlineEffect.cpp | 16 ++++++++++------ libraries/render-utils/src/OutlineEffect.h | 12 ++++++------ .../render-utils/src/RenderDeferredTask.cpp | 2 +- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 758783760d..84315c6004 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -69,7 +69,7 @@ gpu::TexturePointer OutlineFramebuffer::getDepthTexture() { return _depthTexture; } -void PrepareOutline::run(const render::RenderContextPointer& renderContext, const PrepareOutline::Input& input, PrepareOutline::Output& output) { +void PrepareOutline::run(const render::RenderContextPointer& renderContext, const PrepareOutline::Inputs& input, PrepareOutline::Output& output) { auto outlinedItems = input.get1(); if (!outlinedItems.empty()) { @@ -137,8 +137,10 @@ void DebugOutline::configure(const Config& config) { _isDisplayDepthEnabled = config.viewOutlinedDepth; } -void DebugOutline::run(const render::RenderContextPointer& renderContext, const Input& input) { - if (_isDisplayDepthEnabled && input) { +void DebugOutline::run(const render::RenderContextPointer& renderContext, const Inputs& input) { + const auto outlineFramebuffer = input; + + if (_isDisplayDepthEnabled && outlineFramebuffer) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; @@ -158,7 +160,8 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const batch.setModelTransform(Transform()); batch.setPipeline(getDebugPipeline()); - batch.setResourceTexture(0, input->getDepthTexture()); + batch.setResourceTexture(0, outlineFramebuffer->getDepthTexture()); + const glm::vec4 color(1.0f, 0.5f, 0.2f, 1.0f); const glm::vec2 bottomLeft(-1.0f, -1.0f); const glm::vec2 topRight(1.0f, 1.0f); @@ -179,8 +182,9 @@ const gpu::PipelinePointer& DebugOutline::getDebugPipeline() { "Could not find source placeholder"); static const std::string DEFAULT_DEPTH_SHADER{ "vec4 getFragmentColor() {" - " float depth = texture(depthMap, uv).x;" - " return vec4(vec3(depth), 1.0);" + " float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;" + " Zdb = 1.0-(1.0-Zdb)*100;" + " return vec4(Zdb, Zdb, Zdb, 1.0);" " }" }; diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index bb4343b06a..2b5faf4378 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -58,14 +58,14 @@ class PrepareOutline { public: - using Input = render::VaryingSet2; + using Inputs = render::VaryingSet2; // Output will contain outlined objects only z-depth texture using Output = OutlineFramebufferPointer; - using JobModel = render::Job::ModelIO; + using JobModel = render::Job::ModelIO; PrepareOutline() {} - void run(const render::RenderContextPointer& renderContext, const PrepareOutline::Input& input, PrepareOutline::Output& output); + void run(const render::RenderContextPointer& renderContext, const PrepareOutline::Inputs& input, PrepareOutline::Output& output); private: @@ -88,15 +88,15 @@ signals: class DebugOutline { public: - using Input = OutlineFramebufferPointer; + using Inputs = OutlineFramebufferPointer; using Config = DebugOutlineConfig; - using JobModel = render::Job::ModelI; + using JobModel = render::Job::ModelI; DebugOutline(); ~DebugOutline(); void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext, const Input& inputs); + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); private: diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ba045dfff9..b48934f664 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -97,7 +97,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawOpaqueOutlined", opaqueOutlineInputs, shapePlumber); // Retrieve z value of the outlined objects - const auto outlinePrepareInputs = PrepareOutline::Input(deferredFramebuffer, outlinedOpaques).hasVarying(); + const auto outlinePrepareInputs = PrepareOutline::Inputs(deferredFramebuffer, outlinedOpaques).hasVarying(); const auto outlinedFrameBuffer = task.addJob("PrepareOutline", outlinePrepareInputs); // Render opaque objects in DeferredBuffer From 01a028cbb63081a7a2fee960773b1868e47095cb Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 9 Aug 2017 18:03:52 +0200 Subject: [PATCH 08/33] First alpha working version of outline --- libraries/render-utils/src/Outline.slf | 63 ++++++++++++++++++ libraries/render-utils/src/OutlineEffect.cpp | 66 +++++++++++++++++++ libraries/render-utils/src/OutlineEffect.h | 55 +++++++++++++++- libraries/render-utils/src/Outline_shared.slh | 17 +++++ libraries/render-utils/src/PickItemsJob.cpp | 14 ++-- libraries/render-utils/src/PickItemsJob.h | 8 ++- .../render-utils/src/RenderDeferredTask.cpp | 4 ++ .../utilities/render/debugOutline.js | 2 +- .../developer/utilities/render/outline.qml | 42 +++++++++++- 9 files changed, 260 insertions(+), 11 deletions(-) create mode 100644 libraries/render-utils/src/Outline.slf create mode 100644 libraries/render-utils/src/Outline_shared.slh diff --git a/libraries/render-utils/src/Outline.slf b/libraries/render-utils/src/Outline.slf new file mode 100644 index 0000000000..f3f01ff72b --- /dev/null +++ b/libraries/render-utils/src/Outline.slf @@ -0,0 +1,63 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// +// Add outline effect based on two zbuffers : one containing the total scene z and another +// with the z of only the objects to be outlined +// +// Created by Olivier Prat on 08/09/2017 +// Copyright 2017 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 +// + +<@include Outline_shared.slh@> + +uniform outlineParamsBuffer { + OutlineParameters params; +}; + +uniform sampler2D sceneDepthMap; +uniform sampler2D outlinedDepthMap; + +in vec2 varTexCoord0; +out vec4 outFragColor; + +const int BLUR_KERNEL_SIZE = 9; +const float FAR_DISTANCE = 1.0; + +void main(void) { + float outlinedDepth = texture(outlinedDepthMap, varTexCoord0).x; + if (outlinedDepth < FAR_DISTANCE) { + // We're not on the far plane so we are on the outlined object, thus no outline to do! + discard; + } + + //float sceneDepth = texture(sceneDepthMap, varTexCoord0).x; + float outlineIntensity = 0.0; + { + const float deltaUv = params._size / BLUR_KERNEL_SIZE; + vec2 uv; + vec2 startUv = varTexCoord0 - vec2(params._size, params._size) / 2.0; + int x; + int y; + + for (y=0 ; y_context, [&](gpu::Batch& batch) { batch.enableStereo(false); @@ -122,6 +125,69 @@ void PrepareOutline::run(const render::RenderContextPointer& renderContext, cons } } +DrawOutline::DrawOutline() { +} + +void DrawOutline::configure(const Config& config) { + _color = config.color; + _size = config.width; +} + +void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { + auto mainFrameBuffer = inputs.get0(); + + if (mainFrameBuffer) { + auto sceneDepthBuffer = mainFrameBuffer->getPrimaryDepthTexture(); + auto outlinedDepthBuffer = inputs.get1(); + auto pipeline = getPipeline(); + + if (outlinedDepthBuffer) { + auto framebufferSize = glm::ivec2(sceneDepthBuffer->getDimensions()); + auto args = renderContext->args; + { + auto& configuration = _configuration.edit(); + configuration._color = _color; + configuration._size = _size / 1024.f; + } + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + + batch.setViewportTransform(args->_viewport); + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); + batch.setPipeline(pipeline); + + batch.setUniformBuffer(0, _configuration); + batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer); + batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthBuffer->getDepthTexture()); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); + } + } +} + +const gpu::PipelinePointer& DrawOutline::getPipeline() { + if (!_pipeline) { + auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + auto ps = gpu::Shader::createPixel(std::string(Outline_frag)); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding("outlineParamsBuffer", 0)); + slotBindings.insert(gpu::Shader::Binding("sceneDepthMap", SCENE_DEPTH_SLOT)); + slotBindings.insert(gpu::Shader::Binding("outlinedDepthMap", OUTLINED_DEPTH_SLOT)); + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(false); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + _pipeline = gpu::Pipeline::create(program, state); + } + return _pipeline; +} + DebugOutline::DebugOutline() { _geometryId = DependencyManager::get()->allocateID(); } diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 2b5faf4378..0561510d2b 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -73,6 +73,60 @@ private: gpu::PipelinePointer _copyDepthPipeline; }; +class DrawOutlineConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(float width MEMBER width NOTIFY dirty) + Q_PROPERTY(float colorR READ getColorR WRITE setColorR NOTIFY dirty) + Q_PROPERTY(float colorG READ getColorG WRITE setColorG NOTIFY dirty) + Q_PROPERTY(float colorB READ getColorB WRITE setColorB NOTIFY dirty) +public: + + void setColorR(float value) { color.r = value; } + float getColorR() const { return color.r; } + + void setColorG(float value) { color.g = value; } + float getColorG() const { return color.g; } + + void setColorB(float value) { color.b = value; } + float getColorB() const { return color.b; } + + float width{ 5.f }; + glm::vec3 color{ 1.f, 0.7f, 0.2f }; + +signals: + void dirty(); +}; + +class DrawOutline { +public: + using Inputs = render::VaryingSet2; + using Config = DrawOutlineConfig; + using JobModel = render::Job::ModelI; + + DrawOutline(); + + void configure(const Config& config); + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); + +private: + + enum { + SCENE_DEPTH_SLOT = 0, + OUTLINED_DEPTH_SLOT + }; + +#include "Outline_shared.slh" + + using OutlineConfigurationBuffer = gpu::StructBuffer; + + const gpu::PipelinePointer& getPipeline(); + + gpu::PipelinePointer _pipeline; + OutlineConfigurationBuffer _configuration; + glm::vec3 _color; + float _size; +}; + class DebugOutlineConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(bool viewOutlinedDepth MEMBER viewOutlinedDepth NOTIFY dirty) @@ -85,7 +139,6 @@ signals: void dirty(); }; - class DebugOutline { public: using Inputs = OutlineFramebufferPointer; diff --git a/libraries/render-utils/src/Outline_shared.slh b/libraries/render-utils/src/Outline_shared.slh new file mode 100644 index 0000000000..fd1d9aac49 --- /dev/null +++ b/libraries/render-utils/src/Outline_shared.slh @@ -0,0 +1,17 @@ +// glsl / C++ compatible source as interface for Outline +#ifdef __cplusplus +# define VEC3 glm::vec3 +#else +# define VEC3 vec3 +#endif + +struct OutlineParameters +{ + VEC3 _color; + float _size; +}; + +// <@if 1@> +// Trigger Scribe include +// <@endif@> +// diff --git a/libraries/render-utils/src/PickItemsJob.cpp b/libraries/render-utils/src/PickItemsJob.cpp index 3cfbd0f956..5d67f26157 100644 --- a/libraries/render-utils/src/PickItemsJob.cpp +++ b/libraries/render-utils/src/PickItemsJob.cpp @@ -14,17 +14,19 @@ PickItemsJob::PickItemsJob(render::ItemKey::Flags validKeys, render::ItemKey::Fl } void PickItemsJob::configure(const Config& config) { + _isEnabled = config.pick; } void PickItemsJob::run(const render::RenderContextPointer& renderContext, const PickItemsJob::Input& input, PickItemsJob::Output& output) { output.clear(); + if (_isEnabled) { + float minIsectDistance = std::numeric_limits::max(); + auto& itemBounds = input; + auto item = findNearestItem(renderContext, itemBounds, minIsectDistance); - float minIsectDistance = std::numeric_limits::max(); - auto& itemBounds = input; - auto item = findNearestItem(renderContext, itemBounds, minIsectDistance); - - if (render::Item::isValidID(item.id)) { - output.push_back(item); + if (render::Item::isValidID(item.id)) { + output.push_back(item); + } } } diff --git a/libraries/render-utils/src/PickItemsJob.h b/libraries/render-utils/src/PickItemsJob.h index 3e220a4e7f..221ef13b13 100644 --- a/libraries/render-utils/src/PickItemsJob.h +++ b/libraries/render-utils/src/PickItemsJob.h @@ -16,10 +16,15 @@ #include class PickItemsConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(bool pick MEMBER pick NOTIFY dirty) public: - PickItemsConfig() : render::Job::Config(false) {} + bool pick{ false }; + +signals: + void dirty(); }; class PickItemsJob { @@ -40,6 +45,7 @@ private: render::ItemKey::Flags _validKeys; render::ItemKey::Flags _excludeKeys; + bool _isEnabled{ false }; render::ItemBound findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const; }; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index b48934f664..945e1c0fe3 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -169,6 +169,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto toneMappingInputs = render::Varying(ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer)); task.addJob("ToneMapping", toneMappingInputs); + // Draw outline + const auto outlineInputs = DrawOutline::Inputs(deferredFramebuffer, outlinedFrameBuffer).hasVarying(); + task.addJob("DrawOutline", outlineInputs); + { // DEbug the bounds of the rendered items, still look at the zbuffer task.addJob("DrawMetaBounds", metas); task.addJob("DrawOpaqueBounds", opaques); diff --git a/scripts/developer/utilities/render/debugOutline.js b/scripts/developer/utilities/render/debugOutline.js index 6a456054e1..05b7ffbbc9 100644 --- a/scripts/developer/utilities/render/debugOutline.js +++ b/scripts/developer/utilities/render/debugOutline.js @@ -15,6 +15,6 @@ var window = new OverlayWindow({ title: 'Outline', source: qml, width: 250, - height: 80, + height: 250, }); window.closed.connect(function() { Script.stop(); }); \ No newline at end of file diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index 11a9ecf432..4ba7dad157 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -10,20 +10,22 @@ // import QtQuick 2.5 import QtQuick.Controls 1.4 +import "configSlider" Item { id: root property var pickConfig: Render.getConfig("RenderMainView.PickOutlined") property var debugConfig: Render.getConfig("RenderMainView.DebugOutline") + property var drawConfig: Render.getConfig("RenderMainView.DrawOutline") Column { spacing: 8 CheckBox { text: "Edit Outline" - checked: root.pickConfig["enabled"] + checked: root.pickConfig["pick"] onCheckedChanged: { - root.pickConfig["enabled"] = checked; + root.pickConfig["pick"] = checked; } } CheckBox { @@ -33,5 +35,41 @@ Item { root.debugConfig["viewOutlinedDepth"] = checked; } } + ConfigSlider { + label: "Width" + integral: false + config: root.drawConfig + property: "width" + max: 15.0 + min: 0.0 + width: 230 + } + ConfigSlider { + label: "Color R" + integral: false + config: root.drawConfig + property: "colorR" + max: 1.0 + min: 0.0 + width: 230 + } + ConfigSlider { + label: "Color G" + integral: false + config: root.drawConfig + property: "colorG" + max: 1.0 + min: 0.0 + width: 230 + } + ConfigSlider { + label: "Color B" + integral: false + config: root.drawConfig + property: "colorB" + max: 1.0 + min: 0.0 + width: 230 + } } } From 57dfe10baf6d4be910de76806c9e4a4559bf849f Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 9 Aug 2017 18:15:05 +0200 Subject: [PATCH 09/33] Fixed blur problems on screen edges --- libraries/render-utils/src/Outline.slf | 17 ++++++++++++----- libraries/render-utils/src/OutlineEffect.h | 6 +++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/libraries/render-utils/src/Outline.slf b/libraries/render-utils/src/Outline.slf index f3f01ff72b..d55938e9d7 100644 --- a/libraries/render-utils/src/Outline.slf +++ b/libraries/render-utils/src/Outline.slf @@ -35,6 +35,7 @@ void main(void) { //float sceneDepth = texture(sceneDepthMap, varTexCoord0).x; float outlineIntensity = 0.0; + float weight = 0.0; { const float deltaUv = params._size / BLUR_KERNEL_SIZE; vec2 uv; @@ -46,14 +47,20 @@ void main(void) { uv = startUv; startUv.y += deltaUv; - for (x=0 ; x=0.0 && uv.y<=1.0) { + for (x=0 ; x=0.0 && uv.x<=1.0) + { + outlinedDepth = texture(outlinedDepthMap, uv).x; + outlineIntensity += (outlinedDepth < FAR_DISTANCE) ? 1.0 : 0.0; + weight += 1.f; + } + uv.x += deltaUv; + } } } - outlineIntensity /= BLUR_KERNEL_SIZE*BLUR_KERNEL_SIZE; + outlineIntensity /= weight; } if (outlineIntensity < 1e-3) { diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 0561510d2b..3e58d78acc 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -81,13 +81,13 @@ class DrawOutlineConfig : public render::Job::Config { Q_PROPERTY(float colorB READ getColorB WRITE setColorB NOTIFY dirty) public: - void setColorR(float value) { color.r = value; } + void setColorR(float value) { color.r = value; emit dirty(); } float getColorR() const { return color.r; } - void setColorG(float value) { color.g = value; } + void setColorG(float value) { color.g = value; emit dirty(); } float getColorG() const { return color.g; } - void setColorB(float value) { color.b = value; } + void setColorB(float value) { color.b = value; emit dirty(); } float getColorB() const { return color.b; } float width{ 5.f }; From 0f2c41b0095d96e26226b34ba8182020281e79d7 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 9 Aug 2017 18:27:39 +0200 Subject: [PATCH 10/33] Added outline intensity --- libraries/render-utils/src/Outline.slf | 1 + libraries/render-utils/src/OutlineEffect.cpp | 6 ++++-- libraries/render-utils/src/OutlineEffect.h | 5 ++++- libraries/render-utils/src/Outline_shared.slh | 1 + scripts/developer/utilities/render/outline.qml | 9 +++++++++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/Outline.slf b/libraries/render-utils/src/Outline.slf index d55938e9d7..1aec1efd5a 100644 --- a/libraries/render-utils/src/Outline.slf +++ b/libraries/render-utils/src/Outline.slf @@ -66,5 +66,6 @@ void main(void) { if (outlineIntensity < 1e-3) { discard; } + outlineIntensity = min(1.0, outlineIntensity * params._intensity); outFragColor = vec4(params._color.rgb, outlineIntensity); } diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index b63f30f51c..c91f10001d 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -130,7 +130,8 @@ DrawOutline::DrawOutline() { void DrawOutline::configure(const Config& config) { _color = config.color; - _size = config.width; + _size = config.width / 1024.f; + _intensity = config.intensity * 10.f; } void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { @@ -147,7 +148,8 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I { auto& configuration = _configuration.edit(); configuration._color = _color; - configuration._size = _size / 1024.f; + configuration._size = _size; + configuration._intensity = _intensity; } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 3e58d78acc..fc8a715a53 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -76,6 +76,7 @@ private: class DrawOutlineConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(float width MEMBER width NOTIFY dirty) + Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty) Q_PROPERTY(float colorR READ getColorR WRITE setColorR NOTIFY dirty) Q_PROPERTY(float colorG READ getColorG WRITE setColorG NOTIFY dirty) Q_PROPERTY(float colorB READ getColorB WRITE setColorB NOTIFY dirty) @@ -90,8 +91,9 @@ public: void setColorB(float value) { color.b = value; emit dirty(); } float getColorB() const { return color.b; } - float width{ 5.f }; glm::vec3 color{ 1.f, 0.7f, 0.2f }; + float width{ 5.f }; + float intensity{ 1.f }; signals: void dirty(); @@ -125,6 +127,7 @@ private: OutlineConfigurationBuffer _configuration; glm::vec3 _color; float _size; + float _intensity; }; class DebugOutlineConfig : public render::Job::Config { diff --git a/libraries/render-utils/src/Outline_shared.slh b/libraries/render-utils/src/Outline_shared.slh index fd1d9aac49..602e15f8e7 100644 --- a/libraries/render-utils/src/Outline_shared.slh +++ b/libraries/render-utils/src/Outline_shared.slh @@ -9,6 +9,7 @@ struct OutlineParameters { VEC3 _color; float _size; + float _intensity; }; // <@if 1@> diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index 4ba7dad157..7ed3b6a2bb 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -44,6 +44,15 @@ Item { min: 0.0 width: 230 } + ConfigSlider { + label: "Intensity" + integral: false + config: root.drawConfig + property: "intensity" + max: 1.0 + min: 0.0 + width: 230 + } ConfigSlider { label: "Color R" integral: false From 392a99f038cf7367dba134d086d72d6c92b2201a Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 9 Aug 2017 19:18:16 +0200 Subject: [PATCH 11/33] Added some fill parameters. Still need to fix issues with blur changing with screen aspect ratio --- libraries/render-utils/src/Outline.slf | 38 ++++--- libraries/render-utils/src/OutlineEffect.cpp | 8 +- libraries/render-utils/src/OutlineEffect.h | 10 ++ libraries/render-utils/src/Outline_shared.slh | 3 + .../utilities/render/debugOutline.js | 4 +- .../developer/utilities/render/outline.qml | 101 +++++++++++++----- 6 files changed, 119 insertions(+), 45 deletions(-) diff --git a/libraries/render-utils/src/Outline.slf b/libraries/render-utils/src/Outline.slf index 1aec1efd5a..acb79184fe 100644 --- a/libraries/render-utils/src/Outline.slf +++ b/libraries/render-utils/src/Outline.slf @@ -28,15 +28,25 @@ const float FAR_DISTANCE = 1.0; void main(void) { float outlinedDepth = texture(outlinedDepthMap, varTexCoord0).x; + float intensity = 0.0; + if (outlinedDepth < FAR_DISTANCE) { // We're not on the far plane so we are on the outlined object, thus no outline to do! - discard; - } - //float sceneDepth = texture(sceneDepthMap, varTexCoord0).x; - float outlineIntensity = 0.0; - float weight = 0.0; - { + // But maybe we need to fill the interior + if (params._fillOpacityUnoccluded>1e-3 && params._fillOpacityUnoccluded>1e-3) { + // Are we occluded? + float sceneDepth = texture(sceneDepthMap, varTexCoord0).x; + if (sceneDepth < outlinedDepth) { + intensity = params._fillOpacityOccluded; + } else { + intensity = params._fillOpacityUnoccluded; + } + } else { + discard; + } + } else { + float weight = 0.0; const float deltaUv = params._size / BLUR_KERNEL_SIZE; vec2 uv; vec2 startUv = varTexCoord0 - vec2(params._size, params._size) / 2.0; @@ -52,7 +62,7 @@ void main(void) { if (uv.x>=0.0 && uv.x<=1.0) { outlinedDepth = texture(outlinedDepthMap, uv).x; - outlineIntensity += (outlinedDepth < FAR_DISTANCE) ? 1.0 : 0.0; + intensity += (outlinedDepth < FAR_DISTANCE) ? 1.0 : 0.0; weight += 1.f; } uv.x += deltaUv; @@ -60,12 +70,14 @@ void main(void) { } } - outlineIntensity /= weight; + intensity /= weight; + + if (intensity < 1e-3) { + discard; + } + + intensity = min(1.0, intensity / params._threshold) * params._intensity; } - if (outlineIntensity < 1e-3) { - discard; - } - outlineIntensity = min(1.0, outlineIntensity * params._intensity); - outFragColor = vec4(params._color.rgb, outlineIntensity); + outFragColor = vec4(params._color.rgb, intensity); } diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index c91f10001d..1012067851 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -131,7 +131,10 @@ DrawOutline::DrawOutline() { void DrawOutline::configure(const Config& config) { _color = config.color; _size = config.width / 1024.f; - _intensity = config.intensity * 10.f; + _fillOpacityUnoccluded = config.fillOpacityUnoccluded; + _fillOpacityOccluded = config.fillOpacityOccluded; + _threshold = config.glow ? 1.f : 0.f; + _intensity = config.intensity * (config.glow ? 2.f : 1.f); } void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { @@ -150,6 +153,9 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I configuration._color = _color; configuration._size = _size; configuration._intensity = _intensity; + configuration._fillOpacityUnoccluded = _fillOpacityUnoccluded; + configuration._fillOpacityOccluded = _fillOpacityOccluded; + configuration._threshold = _threshold; } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index fc8a715a53..d0c586dafc 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -75,11 +75,15 @@ private: class DrawOutlineConfig : public render::Job::Config { Q_OBJECT + Q_PROPERTY(bool glow MEMBER glow NOTIFY dirty) Q_PROPERTY(float width MEMBER width NOTIFY dirty) Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty) Q_PROPERTY(float colorR READ getColorR WRITE setColorR NOTIFY dirty) Q_PROPERTY(float colorG READ getColorG WRITE setColorG NOTIFY dirty) Q_PROPERTY(float colorB READ getColorB WRITE setColorB NOTIFY dirty) + Q_PROPERTY(float fillOpacityUnoccluded MEMBER fillOpacityUnoccluded NOTIFY dirty) + Q_PROPERTY(float fillOpacityOccluded MEMBER fillOpacityOccluded NOTIFY dirty) + public: void setColorR(float value) { color.r = value; emit dirty(); } @@ -94,6 +98,9 @@ public: glm::vec3 color{ 1.f, 0.7f, 0.2f }; float width{ 5.f }; float intensity{ 1.f }; + float fillOpacityUnoccluded{ 0.35f }; + float fillOpacityOccluded{ 0.1f }; + bool glow{ false }; signals: void dirty(); @@ -128,6 +135,9 @@ private: glm::vec3 _color; float _size; float _intensity; + float _fillOpacityUnoccluded; + float _fillOpacityOccluded; + float _threshold; }; class DebugOutlineConfig : public render::Job::Config { diff --git a/libraries/render-utils/src/Outline_shared.slh b/libraries/render-utils/src/Outline_shared.slh index 602e15f8e7..27c9882815 100644 --- a/libraries/render-utils/src/Outline_shared.slh +++ b/libraries/render-utils/src/Outline_shared.slh @@ -10,6 +10,9 @@ struct OutlineParameters VEC3 _color; float _size; float _intensity; + float _fillOpacityUnoccluded; + float _fillOpacityOccluded; + float _threshold; }; // <@if 1@> diff --git a/scripts/developer/utilities/render/debugOutline.js b/scripts/developer/utilities/render/debugOutline.js index 05b7ffbbc9..e333ab5869 100644 --- a/scripts/developer/utilities/render/debugOutline.js +++ b/scripts/developer/utilities/render/debugOutline.js @@ -14,7 +14,7 @@ var qml = Script.resolvePath('outline.qml'); var window = new OverlayWindow({ title: 'Outline', source: qml, - width: 250, - height: 250, + width: 285, + height: 370, }); window.closed.connect(function() { Script.stop(); }); \ No newline at end of file diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index 7ed3b6a2bb..321dd9271b 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -35,6 +35,13 @@ Item { root.debugConfig["viewOutlinedDepth"] = checked; } } + CheckBox { + text: "Glow" + checked: root.drawConfig["glow"] + onCheckedChanged: { + root.drawConfig["glow"] = checked; + } + } ConfigSlider { label: "Width" integral: false @@ -42,7 +49,7 @@ Item { property: "width" max: 15.0 min: 0.0 - width: 230 + width: 280 } ConfigSlider { label: "Intensity" @@ -51,34 +58,70 @@ Item { property: "intensity" max: 1.0 min: 0.0 - width: 230 - } - ConfigSlider { - label: "Color R" - integral: false - config: root.drawConfig - property: "colorR" - max: 1.0 - min: 0.0 - width: 230 - } - ConfigSlider { - label: "Color G" - integral: false - config: root.drawConfig - property: "colorG" - max: 1.0 - min: 0.0 - width: 230 - } - ConfigSlider { - label: "Color B" - integral: false - config: root.drawConfig - property: "colorB" - max: 1.0 - min: 0.0 - width: 230 + width: 280 } + + GroupBox { + title: "Color" + width: 280 + Column { + spacing: 8 + + ConfigSlider { + label: "Red" + integral: false + config: root.drawConfig + property: "colorR" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Green" + integral: false + config: root.drawConfig + property: "colorG" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Blue" + integral: false + config: root.drawConfig + property: "colorB" + max: 1.0 + min: 0.0 + width: 270 + } + } + } + + GroupBox { + title: "Fill Opacity" + width: 280 + Column { + spacing: 8 + + ConfigSlider { + label: "Unoccluded" + integral: false + config: root.drawConfig + property: "fillOpacityUnoccluded" + max: 1.0 + min: 0.0 + width: 270 + } + ConfigSlider { + label: "Occluded" + integral: false + config: root.drawConfig + property: "fillOpacityOccluded" + max: 1.0 + min: 0.0 + width: 270 + } + } + } } } From 189cc8efd0044045802046201436f9fdc93dea83 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 10 Aug 2017 10:12:10 +0200 Subject: [PATCH 12/33] Outline width is now screen aspect ratio independent --- libraries/render-utils/src/Outline.slf | 15 +++++++-------- libraries/render-utils/src/OutlineEffect.cpp | 3 ++- libraries/render-utils/src/OutlineEffect.h | 15 --------------- libraries/render-utils/src/Outline_shared.slh | 9 ++++++++- 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/libraries/render-utils/src/Outline.slf b/libraries/render-utils/src/Outline.slf index acb79184fe..7c3277d2f2 100644 --- a/libraries/render-utils/src/Outline.slf +++ b/libraries/render-utils/src/Outline.slf @@ -23,7 +23,7 @@ uniform sampler2D outlinedDepthMap; in vec2 varTexCoord0; out vec4 outFragColor; -const int BLUR_KERNEL_SIZE = 9; +const int BLUR_KERNEL_SIZE = 7; const float FAR_DISTANCE = 1.0; void main(void) { @@ -47,15 +47,15 @@ void main(void) { } } else { float weight = 0.0; - const float deltaUv = params._size / BLUR_KERNEL_SIZE; + const vec2 deltaUv = params._size / BLUR_KERNEL_SIZE; + vec2 lineStartUv = varTexCoord0 - params._size / 2.0; vec2 uv; - vec2 startUv = varTexCoord0 - vec2(params._size, params._size) / 2.0; int x; int y; for (y=0 ; y=0.0 && uv.y<=1.0) { for (x=0 ; x #include "DeferredFramebuffer.h" -/* -class PickItemsConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(bool isEnabled MEMBER isEnabled NOTIFY dirty) - -public: - - bool isEnabled{ false }; - -signals: - - void dirty(); -}; -*/ - class OutlineFramebuffer { public: OutlineFramebuffer(); diff --git a/libraries/render-utils/src/Outline_shared.slh b/libraries/render-utils/src/Outline_shared.slh index 27c9882815..4eaa995907 100644 --- a/libraries/render-utils/src/Outline_shared.slh +++ b/libraries/render-utils/src/Outline_shared.slh @@ -1,18 +1,25 @@ // glsl / C++ compatible source as interface for Outline #ifdef __cplusplus +# define VEC2 glm::vec2 # define VEC3 glm::vec3 #else +# define VEC2 vec2 # define VEC3 vec3 #endif struct OutlineParameters { VEC3 _color; - float _size; float _intensity; + + VEC2 _size; float _fillOpacityUnoccluded; float _fillOpacityOccluded; + float _threshold; + float padding1; + float padding2; + float padding3; }; // <@if 1@> From b410f97aef84e6a41fe4bf23e97ee68bb6119e63 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 10 Aug 2017 10:54:28 +0200 Subject: [PATCH 13/33] Adjusted kernel size to real pixel blur width --- libraries/render-utils/src/Outline.slf | 19 ++++++++++--------- libraries/render-utils/src/OutlineEffect.cpp | 8 +++++--- libraries/render-utils/src/Outline_shared.slh | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/libraries/render-utils/src/Outline.slf b/libraries/render-utils/src/Outline.slf index 7c3277d2f2..9117d0c340 100644 --- a/libraries/render-utils/src/Outline.slf +++ b/libraries/render-utils/src/Outline.slf @@ -23,21 +23,22 @@ uniform sampler2D outlinedDepthMap; in vec2 varTexCoord0; out vec4 outFragColor; -const int BLUR_KERNEL_SIZE = 7; const float FAR_DISTANCE = 1.0; +const float DEPTH_BIAS = 0.0; +const float OPACITY_EPSILON = 5e-3; void main(void) { float outlinedDepth = texture(outlinedDepthMap, varTexCoord0).x; float intensity = 0.0; - if (outlinedDepth < FAR_DISTANCE) { + if (outlinedDepth < (FAR_DISTANCE-DEPTH_BIAS)) { // We're not on the far plane so we are on the outlined object, thus no outline to do! // But maybe we need to fill the interior - if (params._fillOpacityUnoccluded>1e-3 && params._fillOpacityUnoccluded>1e-3) { + if (params._fillOpacityUnoccluded>OPACITY_EPSILON && params._fillOpacityUnoccluded>OPACITY_EPSILON) { // Are we occluded? float sceneDepth = texture(sceneDepthMap, varTexCoord0).x; - if (sceneDepth < outlinedDepth) { + if (sceneDepth < (outlinedDepth-DEPTH_BIAS)) { intensity = params._fillOpacityOccluded; } else { intensity = params._fillOpacityUnoccluded; @@ -47,22 +48,22 @@ void main(void) { } } else { float weight = 0.0; - const vec2 deltaUv = params._size / BLUR_KERNEL_SIZE; + const vec2 deltaUv = params._size / params._blurKernelSize; vec2 lineStartUv = varTexCoord0 - params._size / 2.0; vec2 uv; int x; int y; - for (y=0 ; y=0.0 && uv.y<=1.0) { - for (x=0 ; x=0.0 && uv.x<=1.0) { outlinedDepth = texture(outlinedDepthMap, uv).x; - intensity += (outlinedDepth < FAR_DISTANCE) ? 1.0 : 0.0; + intensity += (outlinedDepth < (FAR_DISTANCE-DEPTH_BIAS)) ? 1.0 : 0.0; weight += 1.f; } uv.x += deltaUv.x; @@ -71,7 +72,7 @@ void main(void) { } intensity /= weight; - if (intensity < 5e-3) { + if (intensity < OPACITY_EPSILON) { discard; } diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 1da83f4fe9..78952d353b 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -133,7 +133,7 @@ void DrawOutline::configure(const Config& config) { _size = config.width / 1024.f; _fillOpacityUnoccluded = config.fillOpacityUnoccluded; _fillOpacityOccluded = config.fillOpacityOccluded; - _threshold = config.glow ? 1.f : 0.f; + _threshold = config.glow ? 1.f : 1e-3f; _intensity = config.intensity * (config.glow ? 2.f : 1.f); } @@ -151,12 +151,14 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I { auto& configuration = _configuration.edit(); configuration._color = _color; - configuration._size.x = _size * framebufferSize.y / framebufferSize.x; - configuration._size.y = _size; configuration._intensity = _intensity; configuration._fillOpacityUnoccluded = _fillOpacityUnoccluded; configuration._fillOpacityOccluded = _fillOpacityOccluded; configuration._threshold = _threshold; + // Size is normalized for 1 pixel at 1024 pix resolution so we multiply by the real resolution to have the final pixel size estimate + configuration._blurKernelSize = std::min(10, std::max(2, (int)floorf(_size*framebufferSize.y + 0.5f))); + configuration._size.x = _size * framebufferSize.y / framebufferSize.x; + configuration._size.y = _size; } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { diff --git a/libraries/render-utils/src/Outline_shared.slh b/libraries/render-utils/src/Outline_shared.slh index 4eaa995907..902bbd20ad 100644 --- a/libraries/render-utils/src/Outline_shared.slh +++ b/libraries/render-utils/src/Outline_shared.slh @@ -17,7 +17,7 @@ struct OutlineParameters float _fillOpacityOccluded; float _threshold; - float padding1; + int _blurKernelSize; float padding2; float padding3; }; From f88141aa31319a2d567276df15d52ecff9b5bd58 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 10 Aug 2017 11:37:07 +0200 Subject: [PATCH 14/33] Removed unused color formats in render::Format --- libraries/gpu/src/gpu/Format.cpp | 2 -- libraries/gpu/src/gpu/Format.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index 4079606286..b15f8d929f 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -30,8 +30,6 @@ const Element Element::VEC2NU8_XY{ VEC2, NUINT8, XY }; const Element Element::COLOR_R11G11B10{ SCALAR, FLOAT, R11G11B10 }; const Element Element::VEC4F_COLOR_RGBA{ VEC4, FLOAT, RGBA }; -const Element Element::COLOR_RED_FLOAT{ SCALAR, FLOAT, RED }; -const Element Element::COLOR_RED_HALF{ SCALAR, HALF, RED }; const Element Element::VEC2F_UV{ VEC2, FLOAT, UV }; const Element Element::VEC2F_XY{ VEC2, FLOAT, XY }; const Element Element::VEC3F_XYZ{ VEC3, FLOAT, XYZ }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 19965077b5..c4d88236da 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -314,8 +314,6 @@ public: static const Element COLOR_COMPRESSED_SRGBA_HIGH; static const Element VEC2NU8_XY; static const Element VEC4F_COLOR_RGBA; - static const Element COLOR_RED_FLOAT; - static const Element COLOR_RED_HALF; static const Element VEC2F_UV; static const Element VEC2F_XY; static const Element VEC3F_XYZ; From d61652f958496157b9721b095b5299dea6608700 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 11 Aug 2017 10:11:19 +0200 Subject: [PATCH 15/33] Fixed compilation errors due to merge with master --- libraries/render-utils/src/PickItemsJob.cpp | 2 +- libraries/render-utils/src/RenderDeferredTask.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/PickItemsJob.cpp b/libraries/render-utils/src/PickItemsJob.cpp index 5d67f26157..48ba605d7b 100644 --- a/libraries/render-utils/src/PickItemsJob.cpp +++ b/libraries/render-utils/src/PickItemsJob.cpp @@ -37,7 +37,7 @@ render::ItemBound PickItemsJob::findNearestItem(const render::RenderContextPoint glm::vec3 normal; float isectDistance; render::ItemBound nearestItem( render::Item::INVALID_ITEM_ID ); - const float minDistance = 1.f; + const float minDistance = 0.2f; const float maxDistance = 50.f; render::ItemKey itemKey; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 76572eac76..3ff68b8c64 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -105,11 +105,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren render::ItemKey::Builder().withTypeShape().build()._flags, render::ItemKey::Builder().withTypeMeta().build()._flags); // Render opaque outline objects first in DeferredBuffer - const auto opaqueOutlineInputs = DrawStateSortDeferred::Inputs(outlinedOpaques, lightingModel).hasVarying(); + const auto opaqueOutlineInputs = DrawStateSortDeferred::Inputs(outlinedOpaques, lightingModel).asVarying(); task.addJob("DrawOpaqueOutlined", opaqueOutlineInputs, shapePlumber); // Retrieve z value of the outlined objects - const auto outlinePrepareInputs = PrepareOutline::Inputs(deferredFramebuffer, outlinedOpaques).hasVarying(); + const auto outlinePrepareInputs = PrepareOutline::Inputs(deferredFramebuffer, outlinedOpaques).asVarying(); const auto outlinedFrameBuffer = task.addJob("PrepareOutline", outlinePrepareInputs); // Render opaque objects in DeferredBuffer @@ -182,7 +182,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("ToneMapping", toneMappingInputs); // Draw outline - const auto outlineInputs = DrawOutline::Inputs(deferredFramebuffer, outlinedFrameBuffer).hasVarying(); + const auto outlineInputs = DrawOutline::Inputs(deferredFramebuffer, outlinedFrameBuffer).asVarying(); task.addJob("DrawOutline", outlineInputs); { // DEbug the bounds of the rendered items, still look at the zbuffer From d86c3c4f2af1924ac5af29538d7249341747aa06 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 11 Aug 2017 11:33:46 +0200 Subject: [PATCH 16/33] Outline is now drawn with framebuffer with no depth buffer attached to prevent concurrent depth clear on NVidia GPU cards --- libraries/render-utils/src/Outline.slf | 19 ++++++++---- libraries/render-utils/src/OutlineEffect.cpp | 29 ++++++++++++++----- libraries/render-utils/src/OutlineEffect.h | 15 ++++++---- .../render-utils/src/RenderDeferredTask.cpp | 4 +-- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/libraries/render-utils/src/Outline.slf b/libraries/render-utils/src/Outline.slf index 9117d0c340..c467e2db9a 100644 --- a/libraries/render-utils/src/Outline.slf +++ b/libraries/render-utils/src/Outline.slf @@ -10,6 +10,8 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include DeferredTransform.slh@> +<$declareDeferredFrameTransform()$> <@include Outline_shared.slh@> @@ -23,22 +25,27 @@ uniform sampler2D outlinedDepthMap; in vec2 varTexCoord0; out vec4 outFragColor; -const float FAR_DISTANCE = 1.0; -const float DEPTH_BIAS = 0.0; +const float FAR_Z = 1.0; +const float LINEAR_DEPTH_BIAS = 5e-3; const float OPACITY_EPSILON = 5e-3; void main(void) { float outlinedDepth = texture(outlinedDepthMap, varTexCoord0).x; float intensity = 0.0; - if (outlinedDepth < (FAR_DISTANCE-DEPTH_BIAS)) { + if (outlinedDepth < FAR_Z) { // We're not on the far plane so we are on the outlined object, thus no outline to do! // But maybe we need to fill the interior + // TODO: this should be done as another shader with switch done on CPU if (params._fillOpacityUnoccluded>OPACITY_EPSILON && params._fillOpacityUnoccluded>OPACITY_EPSILON) { - // Are we occluded? float sceneDepth = texture(sceneDepthMap, varTexCoord0).x; - if (sceneDepth < (outlinedDepth-DEPTH_BIAS)) { + // Transform to linear depth for better precision + outlinedDepth = -evalZeyeFromZdb(outlinedDepth); + sceneDepth = -evalZeyeFromZdb(sceneDepth); + + // Are we occluded? + if (sceneDepth < (outlinedDepth-LINEAR_DEPTH_BIAS)) { intensity = params._fillOpacityOccluded; } else { intensity = params._fillOpacityUnoccluded; @@ -63,7 +70,7 @@ void main(void) { if (uv.x>=0.0 && uv.x<=1.0) { outlinedDepth = texture(outlinedDepthMap, uv).x; - intensity += (outlinedDepth < (FAR_DISTANCE-DEPTH_BIAS)) ? 1.0 : 0.0; + intensity += (outlinedDepth < FAR_Z) ? 1.0 : 0.0; weight += 1.f; } uv.x += deltaUv.x; diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 78952d353b..b65422222e 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -70,12 +70,12 @@ gpu::TexturePointer OutlineFramebuffer::getDepthTexture() { return _depthTexture; } -void PrepareOutline::run(const render::RenderContextPointer& renderContext, const PrepareOutline::Inputs& input, PrepareOutline::Output& output) { - auto outlinedItems = input.get1(); +void PrepareOutline::run(const render::RenderContextPointer& renderContext, const PrepareOutline::Inputs& inputs, PrepareOutline::Output& output) { + auto outlinedItems = inputs.get0(); if (!outlinedItems.empty()) { auto args = renderContext->args; - auto deferredFrameBuffer = input.get0(); + auto deferredFrameBuffer = inputs.get1(); auto frameSize = deferredFrameBuffer->getFrameSize(); if (!_outlineFramebuffer) { @@ -138,13 +138,20 @@ void DrawOutline::configure(const Config& config) { } void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { - auto mainFrameBuffer = inputs.get0(); + auto mainFrameBuffer = inputs.get1(); if (mainFrameBuffer) { auto sceneDepthBuffer = mainFrameBuffer->getPrimaryDepthTexture(); - auto outlinedDepthBuffer = inputs.get1(); + const auto frameTransform = inputs.get0(); + auto outlinedDepthBuffer = inputs.get2(); + auto destinationFrameBuffer = inputs.get3(); auto pipeline = getPipeline(); + if (!_primaryWithoutDepthBuffer) { + _primaryWithoutDepthBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth")); + _primaryWithoutDepthBuffer->setRenderBuffer(0, destinationFrameBuffer->getRenderBuffer(0)); + } + if (outlinedDepthBuffer) { auto framebufferSize = glm::ivec2(sceneDepthBuffer->getDimensions()); auto args = renderContext->args; @@ -163,6 +170,7 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); + batch.setFramebuffer(_primaryWithoutDepthBuffer); batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); @@ -170,10 +178,14 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); batch.setPipeline(pipeline); - batch.setUniformBuffer(0, _configuration); + batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); + batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer); batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthBuffer->getDepthTexture()); batch.draw(gpu::TRIANGLE_STRIP, 4); + + // Restore previous frame buffer + batch.setFramebuffer(destinationFrameBuffer); }); } } @@ -186,13 +198,14 @@ const gpu::PipelinePointer& DrawOutline::getPipeline() { gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding("outlineParamsBuffer", 0)); + slotBindings.insert(gpu::Shader::Binding("outlineParamsBuffer", OUTLINE_PARAMS_SLOT)); + slotBindings.insert(gpu::Shader::Binding("deferredFrameTransformBuffer", FRAME_TRANSFORM_SLOT)); slotBindings.insert(gpu::Shader::Binding("sceneDepthMap", SCENE_DEPTH_SLOT)); slotBindings.insert(gpu::Shader::Binding("outlinedDepthMap", OUTLINED_DEPTH_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(false); + state->setDepthTest(gpu::State::DepthTest(false, false)); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); _pipeline = gpu::Pipeline::create(program, state); } diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index b5b44bbeb8..09b1c36883 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -14,6 +14,7 @@ #include #include "DeferredFramebuffer.h" +#include "DeferredFrameTransform.h" class OutlineFramebuffer { public: @@ -43,9 +44,9 @@ class PrepareOutline { public: - using Inputs = render::VaryingSet2; - // Output will contain outlined objects only z-depth texture - using Output = OutlineFramebufferPointer; + using Inputs = render::VaryingSet2; + // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer + using Output = OutlineFramebufferPointer; using JobModel = render::Job::ModelIO; PrepareOutline() {} @@ -93,7 +94,7 @@ signals: class DrawOutline { public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet4; using Config = DrawOutlineConfig; using JobModel = render::Job::ModelI; @@ -106,7 +107,10 @@ private: enum { SCENE_DEPTH_SLOT = 0, - OUTLINED_DEPTH_SLOT + OUTLINED_DEPTH_SLOT, + + OUTLINE_PARAMS_SLOT = 0, + FRAME_TRANSFORM_SLOT }; #include "Outline_shared.slh" @@ -115,6 +119,7 @@ private: const gpu::PipelinePointer& getPipeline(); + gpu::FramebufferPointer _primaryWithoutDepthBuffer; gpu::PipelinePointer _pipeline; OutlineConfigurationBuffer _configuration; glm::vec3 _color; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 3ff68b8c64..5d16a0727d 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -109,7 +109,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawOpaqueOutlined", opaqueOutlineInputs, shapePlumber); // Retrieve z value of the outlined objects - const auto outlinePrepareInputs = PrepareOutline::Inputs(deferredFramebuffer, outlinedOpaques).asVarying(); + const auto outlinePrepareInputs = PrepareOutline::Inputs(outlinedOpaques, deferredFramebuffer).asVarying(); const auto outlinedFrameBuffer = task.addJob("PrepareOutline", outlinePrepareInputs); // Render opaque objects in DeferredBuffer @@ -182,7 +182,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("ToneMapping", toneMappingInputs); // Draw outline - const auto outlineInputs = DrawOutline::Inputs(deferredFramebuffer, outlinedFrameBuffer).asVarying(); + const auto outlineInputs = DrawOutline::Inputs(deferredFrameTransform, deferredFramebuffer, outlinedFrameBuffer, primaryFramebuffer).asVarying(); task.addJob("DrawOutline", outlineInputs); { // DEbug the bounds of the rendered items, still look at the zbuffer From 68753211dc541ed4b7b9a9ca728bdb9f881da207 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 17 Aug 2017 15:25:41 +0200 Subject: [PATCH 17/33] Fixed bug on Mac where the outline effect would stop working once the window was resized --- libraries/render-utils/src/Outline.slf | 2 +- libraries/render-utils/src/OutlineEffect.cpp | 29 +++++++++----------- libraries/render-utils/src/OutlineEffect.h | 1 + 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/libraries/render-utils/src/Outline.slf b/libraries/render-utils/src/Outline.slf index c467e2db9a..1d3d21a3c7 100644 --- a/libraries/render-utils/src/Outline.slf +++ b/libraries/render-utils/src/Outline.slf @@ -55,7 +55,7 @@ void main(void) { } } else { float weight = 0.0; - const vec2 deltaUv = params._size / params._blurKernelSize; + vec2 deltaUv = params._size / params._blurKernelSize; vec2 lineStartUv = varTexCoord0 - params._size / 2.0; vec2 uv; int x; diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index b65422222e..b0a57a0e03 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -24,20 +24,15 @@ OutlineFramebuffer::OutlineFramebuffer() { } void OutlineFramebuffer::update(const gpu::TexturePointer& linearDepthBuffer) { - //If the depth buffer or size changed, we need to delete our FBOs - bool reset = false; - + // If the depth buffer or size changed, we need to delete our FBOs and recreate them at the + // new correct dimensions. if (_depthTexture) { auto newFrameSize = glm::ivec2(linearDepthBuffer->getDimensions()); if (_frameSize != newFrameSize) { _frameSize = newFrameSize; - reset = true; + clear(); } } - - if (reset) { - clear(); - } } void OutlineFramebuffer::clear() { @@ -46,11 +41,11 @@ void OutlineFramebuffer::clear() { } void OutlineFramebuffer::allocate() { - + auto width = _frameSize.x; auto height = _frameSize.y; - auto format = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED); - + auto format = gpu::Element(gpu::SCALAR, gpu::HALF, gpu::RED); + _depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(format, width, height)); _depthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); _depthFramebuffer->setRenderBuffer(0, _depthTexture); @@ -146,14 +141,16 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I auto outlinedDepthBuffer = inputs.get2(); auto destinationFrameBuffer = inputs.get3(); auto pipeline = getPipeline(); + auto framebufferSize = glm::ivec2(sceneDepthBuffer->getDimensions()); - if (!_primaryWithoutDepthBuffer) { + if (!_primaryWithoutDepthBuffer || framebufferSize!=_frameBufferSize) { + // Failing to recreate this frame buffer when the screen has been resized creates a bug on Mac _primaryWithoutDepthBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth")); _primaryWithoutDepthBuffer->setRenderBuffer(0, destinationFrameBuffer->getRenderBuffer(0)); + _frameBufferSize = framebufferSize; } if (outlinedDepthBuffer) { - auto framebufferSize = glm::ivec2(sceneDepthBuffer->getDimensions()); auto args = renderContext->args; { auto& configuration = _configuration.edit(); @@ -163,8 +160,8 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I configuration._fillOpacityOccluded = _fillOpacityOccluded; configuration._threshold = _threshold; // Size is normalized for 1 pixel at 1024 pix resolution so we multiply by the real resolution to have the final pixel size estimate - configuration._blurKernelSize = std::min(10, std::max(2, (int)floorf(_size*framebufferSize.y + 0.5f))); - configuration._size.x = _size * framebufferSize.y / framebufferSize.x; + configuration._blurKernelSize = std::min(10, std::max(2, (int)floorf(_size*_frameBufferSize.y + 0.5f))); + configuration._size.x = _size * _frameBufferSize.y / _frameBufferSize.x; configuration._size.y = _size; } @@ -175,7 +172,7 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); - batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_frameBufferSize, args->_viewport)); batch.setPipeline(pipeline); batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 09b1c36883..c67964a121 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -120,6 +120,7 @@ private: const gpu::PipelinePointer& getPipeline(); gpu::FramebufferPointer _primaryWithoutDepthBuffer; + glm::ivec2 _frameBufferSize {0, 0}; gpu::PipelinePointer _pipeline; OutlineConfigurationBuffer _configuration; glm::vec3 _color; From 2d598f34280c1bf0f2fe073077210123b192becd Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 17 Aug 2017 15:44:02 +0200 Subject: [PATCH 18/33] Improved outline visual width normalization that makes it independant from resolution. It is now a ratio of the screen height --- libraries/render-utils/src/OutlineEffect.cpp | 7 ++++--- libraries/render-utils/src/OutlineEffect.h | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index b0a57a0e03..c4ede4dcf6 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -125,7 +125,9 @@ DrawOutline::DrawOutline() { void DrawOutline::configure(const Config& config) { _color = config.color; - _size = config.width / 1024.f; + _blurKernelSize = std::min(10, std::max(2, (int)floorf(config.width*2 + 0.5f))); + // Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400. + _size = config.width / 400.f; _fillOpacityUnoccluded = config.fillOpacityUnoccluded; _fillOpacityOccluded = config.fillOpacityOccluded; _threshold = config.glow ? 1.f : 1e-3f; @@ -159,8 +161,7 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I configuration._fillOpacityUnoccluded = _fillOpacityUnoccluded; configuration._fillOpacityOccluded = _fillOpacityOccluded; configuration._threshold = _threshold; - // Size is normalized for 1 pixel at 1024 pix resolution so we multiply by the real resolution to have the final pixel size estimate - configuration._blurKernelSize = std::min(10, std::max(2, (int)floorf(_size*_frameBufferSize.y + 0.5f))); + configuration._blurKernelSize = _blurKernelSize; configuration._size.x = _size * _frameBufferSize.y / _frameBufferSize.x; configuration._size.y = _size; } diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index c67964a121..11bb39b954 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -82,7 +82,7 @@ public: float getColorB() const { return color.b; } glm::vec3 color{ 1.f, 0.7f, 0.2f }; - float width{ 5.f }; + float width{ 3.f }; float intensity{ 1.f }; float fillOpacityUnoccluded{ 0.35f }; float fillOpacityOccluded{ 0.1f }; @@ -125,6 +125,7 @@ private: OutlineConfigurationBuffer _configuration; glm::vec3 _color; float _size; + int _blurKernelSize; float _intensity; float _fillOpacityUnoccluded; float _fillOpacityOccluded; From 7910b0d8ffc0293ba462c6c586ab90a5c6a5af5c Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 17 Aug 2017 15:55:59 +0200 Subject: [PATCH 19/33] Switched back to full float for outline depth buffer because of precision issues --- libraries/render-utils/src/OutlineEffect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index c4ede4dcf6..4733120fd3 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -44,7 +44,7 @@ void OutlineFramebuffer::allocate() { auto width = _frameSize.x; auto height = _frameSize.y; - auto format = gpu::Element(gpu::SCALAR, gpu::HALF, gpu::RED); + auto format = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED); _depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(format, width, height)); _depthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); From 700d4a4b43ef79e31c1bea0ed5893f9162a1f2fe Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 6 Sep 2017 15:47:10 +0200 Subject: [PATCH 20/33] First working version of outline working with selection interface. --- libraries/render-utils/src/OutlineEffect.cpp | 7 ++++--- libraries/render-utils/src/OutlineEffect.h | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 17 ++++++++++------- libraries/render/src/render/FilterTask.cpp | 12 ++++++++++-- libraries/render/src/render/FilterTask.h | 4 ++-- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 4733120fd3..158cb3871a 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -66,11 +66,12 @@ gpu::TexturePointer OutlineFramebuffer::getDepthTexture() { } void PrepareOutline::run(const render::RenderContextPointer& renderContext, const PrepareOutline::Inputs& inputs, PrepareOutline::Output& output) { - auto outlinedItems = inputs.get0(); + auto outlinedOpaqueItems = inputs.get0(); + auto outlinedTransparentItems = inputs.get1(); - if (!outlinedItems.empty()) { + if (!outlinedOpaqueItems.empty() || !outlinedTransparentItems.empty()) { auto args = renderContext->args; - auto deferredFrameBuffer = inputs.get1(); + auto deferredFrameBuffer = inputs.get2(); auto frameSize = deferredFrameBuffer->getFrameSize(); if (!_outlineFramebuffer) { diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 11bb39b954..fb625fbabc 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -44,7 +44,7 @@ class PrepareOutline { public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet3; // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer using Output = OutlineFramebufferPointer; using JobModel = render::Job::ModelIO; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index f53cfa443b..f240f0728e 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -40,7 +40,6 @@ #include "AntialiasingEffect.h" #include "ToneMappingEffect.h" #include "SubsurfaceScattering.h" -#include "PickItemsJob.h" #include "OutlineEffect.h" #include @@ -96,16 +95,20 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("PrepareStencil", primaryFramebuffer); // Select items that need to be outlined - const auto outlinedOpaques = task.addJob("PickOutlined", opaques, - // Pick only shapes so exclude meta - render::ItemKey::Builder().withTypeShape().build()._flags, render::ItemKey::Builder().withTypeMeta().build()._flags); + const auto outlineSelectionName = "contextOverlayHighlightList"; + const auto outlinedOpaquesSelection = task.addJob("SelectOutlinedOpaques", opaques, outlineSelectionName); + const auto outlinedTransparentSelection = task.addJob("SelectOutlinedTransparents", transparents, outlineSelectionName); + const auto outlinedOpaqueItems = task.addJob("OutlinedOpaqueMetaToSubItems", outlinedOpaquesSelection); + const auto outlinedTransparentItems = task.addJob("OutlinedTransparentMetaToSubItems", outlinedTransparentSelection); // Render opaque outline objects first in DeferredBuffer - const auto opaqueOutlineInputs = DrawStateSortDeferred::Inputs(outlinedOpaques, lightingModel).asVarying(); - task.addJob("DrawOpaqueOutlined", opaqueOutlineInputs, shapePlumber); + const auto outlineOpaqueInputs = DrawStateSortDeferred::Inputs(outlinedOpaqueItems, lightingModel).asVarying(); + const auto outlineTransparentInputs = DrawStateSortDeferred::Inputs(outlinedTransparentItems, lightingModel).asVarying(); + task.addJob("DrawOpaqueOutlined", outlineOpaqueInputs, shapePlumber); + task.addJob("DrawTransparentOutlined", outlineTransparentInputs, shapePlumber); // Retrieve z value of the outlined objects - const auto outlinePrepareInputs = PrepareOutline::Inputs(outlinedOpaques, deferredFramebuffer).asVarying(); + const auto outlinePrepareInputs = PrepareOutline::Inputs(outlinedOpaqueItems, outlinedTransparentItems, deferredFramebuffer).asVarying(); const auto outlinedFrameBuffer = task.addJob("PrepareOutline", outlinePrepareInputs); // Render opaque objects in DeferredBuffer diff --git a/libraries/render/src/render/FilterTask.cpp b/libraries/render/src/render/FilterTask.cpp index 19953f3399..b4da280697 100644 --- a/libraries/render/src/render/FilterTask.cpp +++ b/libraries/render/src/render/FilterTask.cpp @@ -98,8 +98,9 @@ void SelectSortItems::run(const RenderContextPointer& renderContext, const ItemB } } -void MetaToSubItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemIDs& outItems) { +void MetaToSubItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { auto& scene = renderContext->_scene; + ItemIDs outItemIds; // Now we have a selection of items to render outItems.clear(); @@ -107,7 +108,14 @@ void MetaToSubItems::run(const RenderContextPointer& renderContext, const ItemBo for (auto idBound : inItems) { auto& item = scene->getItem(idBound.id); - item.fetchMetaSubItems(outItems); + item.fetchMetaSubItems(outItemIds); + } + + // Transform Item IDs to ItemBounds + for (auto id : outItemIds) { + auto& item = scene->getItem(id); + + outItems.emplace_back(ItemBound{ id, item.getBound() }); } } diff --git a/libraries/render/src/render/FilterTask.h b/libraries/render/src/render/FilterTask.h index 1c4611ee9f..b9b02017da 100644 --- a/libraries/render/src/render/FilterTask.h +++ b/libraries/render/src/render/FilterTask.h @@ -135,11 +135,11 @@ namespace render { // From meta-Items, generate the sub-items class MetaToSubItems { public: - using JobModel = Job::ModelIO; + using JobModel = Job::ModelIO; MetaToSubItems() {} - void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemIDs& outItems); + void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems); }; } From 75e06b691fba8bd399c6b810241570c57ecd957b Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 6 Sep 2017 15:59:04 +0200 Subject: [PATCH 21/33] Simplified version that works directly with metas --- libraries/render-utils/src/OutlineEffect.cpp | 7 +++---- libraries/render-utils/src/OutlineEffect.h | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 19 +++++++------------ 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 158cb3871a..4733120fd3 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -66,12 +66,11 @@ gpu::TexturePointer OutlineFramebuffer::getDepthTexture() { } void PrepareOutline::run(const render::RenderContextPointer& renderContext, const PrepareOutline::Inputs& inputs, PrepareOutline::Output& output) { - auto outlinedOpaqueItems = inputs.get0(); - auto outlinedTransparentItems = inputs.get1(); + auto outlinedItems = inputs.get0(); - if (!outlinedOpaqueItems.empty() || !outlinedTransparentItems.empty()) { + if (!outlinedItems.empty()) { auto args = renderContext->args; - auto deferredFrameBuffer = inputs.get2(); + auto deferredFrameBuffer = inputs.get1(); auto frameSize = deferredFrameBuffer->getFrameSize(); if (!_outlineFramebuffer) { diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index fb625fbabc..11bb39b954 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -44,7 +44,7 @@ class PrepareOutline { public: - using Inputs = render::VaryingSet3; + using Inputs = render::VaryingSet2; // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer using Output = OutlineFramebufferPointer; using JobModel = render::Job::ModelIO; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index f240f0728e..3d39e2ff5e 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -96,19 +96,15 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Select items that need to be outlined const auto outlineSelectionName = "contextOverlayHighlightList"; - const auto outlinedOpaquesSelection = task.addJob("SelectOutlinedOpaques", opaques, outlineSelectionName); - const auto outlinedTransparentSelection = task.addJob("SelectOutlinedTransparents", transparents, outlineSelectionName); - const auto outlinedOpaqueItems = task.addJob("OutlinedOpaqueMetaToSubItems", outlinedOpaquesSelection); - const auto outlinedTransparentItems = task.addJob("OutlinedTransparentMetaToSubItems", outlinedTransparentSelection); + const auto selectedMetas = task.addJob("PassTestSelection", metas, "contextOverlayHighlightList"); + const auto outlinedItems = task.addJob("OutlinedMetaToSubItems", selectedMetas); // Render opaque outline objects first in DeferredBuffer - const auto outlineOpaqueInputs = DrawStateSortDeferred::Inputs(outlinedOpaqueItems, lightingModel).asVarying(); - const auto outlineTransparentInputs = DrawStateSortDeferred::Inputs(outlinedTransparentItems, lightingModel).asVarying(); - task.addJob("DrawOpaqueOutlined", outlineOpaqueInputs, shapePlumber); - task.addJob("DrawTransparentOutlined", outlineTransparentInputs, shapePlumber); + const auto outlineInputs = DrawStateSortDeferred::Inputs(outlinedItems, lightingModel).asVarying(); + task.addJob("DrawOutlinedDepth", outlineInputs, shapePlumber); // Retrieve z value of the outlined objects - const auto outlinePrepareInputs = PrepareOutline::Inputs(outlinedOpaqueItems, outlinedTransparentItems, deferredFramebuffer).asVarying(); + const auto outlinePrepareInputs = PrepareOutline::Inputs(outlinedItems, deferredFramebuffer).asVarying(); const auto outlinedFrameBuffer = task.addJob("PrepareOutline", outlinePrepareInputs); // Render opaque objects in DeferredBuffer @@ -181,8 +177,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("ToneMapping", toneMappingInputs); // Draw outline - const auto outlineInputs = DrawOutline::Inputs(deferredFrameTransform, deferredFramebuffer, outlinedFrameBuffer, primaryFramebuffer).asVarying(); - task.addJob("DrawOutline", outlineInputs); + const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, deferredFramebuffer, outlinedFrameBuffer, primaryFramebuffer).asVarying(); + task.addJob("DrawOutline", drawOutlineInputs); { // DEbug the bounds of the rendered items, still look at the zbuffer task.addJob("DrawMetaBounds", metas); @@ -237,7 +233,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawZoneStack", deferredFrameTransform); // Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true - const auto selectedMetas = task.addJob("PassTestSelection", metas, "contextOverlayHighlightList"); task.addJob("DrawSelectionBounds", selectedMetas); } From d6ea01c4f3a16ace6ada6de4a9b4d30098d3e964 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 6 Sep 2017 17:34:29 +0200 Subject: [PATCH 22/33] Created outline task but still need to create specific render job with z-pass shaders --- libraries/render-utils/src/OutlineEffect.cpp | 39 +++++++++++++++++++ libraries/render-utils/src/OutlineEffect.h | 15 +++++++ .../render-utils/src/RenderDeferredTask.cpp | 20 ++-------- libraries/render/src/task/Varying.h | 18 +++++++++ 4 files changed, 75 insertions(+), 17 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 4733120fd3..a99ced93f0 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -12,6 +12,10 @@ #include "GeometryCache.h" +#include + +#include "RenderDeferredTask.h" + #include "gpu/Context.h" #include "gpu/StandardShaderLib.h" @@ -294,3 +298,38 @@ const gpu::PipelinePointer& DebugOutline::getDebugPipeline() { return _debugPipeline; } + +DrawOutlineTask::DrawOutlineTask() { + +} + +void DrawOutlineTask::configure(const Config& config) { + +} + +void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { + const auto input = inputs.get(); + const auto selectedMetas = inputs.getN(0); + const auto shapePlumber = input.get1(); + const auto lightingModel = inputs.getN(2); + const auto deferredFramebuffer = inputs.getN(3); + const auto primaryFramebuffer = inputs.getN(4); + const auto deferredFrameTransform = inputs.getN(5); + + const auto& outlinedItems = task.addJob("OutlinedMetaToSubItems", selectedMetas); + + // Render opaque outline objects first in DeferredBuffer + const auto outlineInputs = DrawStateSortDeferred::Inputs(outlinedItems, lightingModel).asVarying(); + task.addJob("DrawOutlinedDepth", outlineInputs, shapePlumber); + + // Retrieve z value of the outlined objects + const auto outlinePrepareInputs = PrepareOutline::Inputs(outlinedItems, deferredFramebuffer).asVarying(); + const auto outlinedFrameBuffer = task.addJob("CopyOutlineDepth", outlinePrepareInputs); + + // Draw outline + const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, deferredFramebuffer, outlinedFrameBuffer, primaryFramebuffer).asVarying(); + task.addJob("DrawOutlineEffect", drawOutlineInputs); + + // Debug outline + task.addJob("DebugOutline", outlinedFrameBuffer); +} diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 11bb39b954..ccc1e03fdd 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -165,6 +165,21 @@ private: bool _isDisplayDepthEnabled{ false }; }; +#include "LightingModel.h" + +class DrawOutlineTask { +public: + using Inputs = render::VaryingSet6; + using Config = render::Task::Config; + using JobModel = render::Task::ModelI; + + DrawOutlineTask(); + + void configure(const Config& config); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); + +}; + #endif // hifi_render_utils_OutlineEffect_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 3d39e2ff5e..5ea506e18f 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -95,17 +95,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("PrepareStencil", primaryFramebuffer); // Select items that need to be outlined - const auto outlineSelectionName = "contextOverlayHighlightList"; const auto selectedMetas = task.addJob("PassTestSelection", metas, "contextOverlayHighlightList"); - const auto outlinedItems = task.addJob("OutlinedMetaToSubItems", selectedMetas); - - // Render opaque outline objects first in DeferredBuffer - const auto outlineInputs = DrawStateSortDeferred::Inputs(outlinedItems, lightingModel).asVarying(); - task.addJob("DrawOutlinedDepth", outlineInputs, shapePlumber); - - // Retrieve z value of the outlined objects - const auto outlinePrepareInputs = PrepareOutline::Inputs(outlinedItems, deferredFramebuffer).asVarying(); - const auto outlinedFrameBuffer = task.addJob("PrepareOutline", outlinePrepareInputs); // Render opaque objects in DeferredBuffer const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).asVarying(); @@ -173,12 +163,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto toneAndPostRangeTimer = task.addJob("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing"); // Lighting Buffer ready for tone mapping - const auto toneMappingInputs = render::Varying(ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer)); + const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer).asVarying(); task.addJob("ToneMapping", toneMappingInputs); - // Draw outline - const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, deferredFramebuffer, outlinedFrameBuffer, primaryFramebuffer).asVarying(); - task.addJob("DrawOutline", drawOutlineInputs); + const auto outlineInputs = DrawOutlineTask::Inputs(selectedMetas, shapePlumber, lightingModel, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); + task.addJob("DrawOutline", outlineInputs); { // DEbug the bounds of the rendered items, still look at the zbuffer task.addJob("DrawMetaBounds", metas); @@ -213,9 +202,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto debugAmbientOcclusionInputs = DebugAmbientOcclusion::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget, ambientOcclusionUniforms).asVarying(); task.addJob("DebugAmbientOcclusion", debugAmbientOcclusionInputs); - // Debug outline - task.addJob("DebugOutline", outlinedFrameBuffer); - // Scene Octree Debugging job { task.addJob("DrawSceneOctree", spatialSelection); diff --git a/libraries/render/src/task/Varying.h b/libraries/render/src/task/Varying.h index 0144801701..9ce234061e 100644 --- a/libraries/render/src/task/Varying.h +++ b/libraries/render/src/task/Varying.h @@ -238,6 +238,24 @@ public: const T5& get5() const { return std::get<5>((*this)).template get(); } T5& edit5() { return std::get<5>((*this)).template edit(); } + virtual Varying operator[] (uint8_t index) const { + switch (index) { + default: + return std::get<0>((*this)); + case 1: + return std::get<1>((*this)); + case 2: + return std::get<2>((*this)); + case 3: + return std::get<3>((*this)); + case 4: + return std::get<4>((*this)); + case 5: + return std::get<5>((*this)); + }; + } + virtual uint8_t length() const { return 6; } + Varying asVarying() const { return Varying((*this)); } }; From 10643feb7859543042773cd420110f34c95dfac1 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 6 Sep 2017 18:40:38 +0200 Subject: [PATCH 23/33] Working with specific zpass rendering for outline. Debug script needs relinking to correct config --- libraries/render-utils/src/OutlineEffect.cpp | 95 ++++++++++++++++--- libraries/render-utils/src/OutlineEffect.h | 14 ++- .../render-utils/src/RenderDeferredTask.cpp | 2 +- .../render-utils/src/RenderPipelines.cpp | 48 ++++++++-- .../render-utils/src/RenderShadowTask.cpp | 42 +------- libraries/render/src/render/FilterTask.cpp | 30 ++++-- libraries/render/src/render/FilterTask.h | 17 +++- 7 files changed, 175 insertions(+), 73 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index a99ced93f0..3876a87c02 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -13,8 +13,7 @@ #include "GeometryCache.h" #include - -#include "RenderDeferredTask.h" +#include #include "gpu/Context.h" #include "gpu/StandardShaderLib.h" @@ -24,6 +23,10 @@ #include "debug_deferred_buffer_frag.h" #include "Outline_frag.h" +using namespace render; + +extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); + OutlineFramebuffer::OutlineFramebuffer() { } @@ -299,6 +302,61 @@ const gpu::PipelinePointer& DebugOutline::getDebugPipeline() { return _debugPipeline; } +void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, const render::ShapeBounds& inShapes) { + assert(renderContext->args); + assert(renderContext->args->hasViewFrustum()); + + RenderArgs* args = renderContext->args; + ShapeKey::Builder defaultKeyBuilder; + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; + + // Setup camera, projection and viewport for all items + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + batch.clearFramebuffer( + gpu::Framebuffer::BUFFER_DEPTH, + vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, true); + + auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); + auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); + + std::vector skinnedShapeKeys{}; + + // Iterate through all inShapes and render the unskinned + args->_shapePipeline = shadowPipeline; + batch.setPipeline(shadowPipeline->pipeline); + for (auto items : inShapes) { + if (items.first.isSkinned()) { + skinnedShapeKeys.push_back(items.first); + } + else { + renderItems(renderContext, items.second); + } + } + + // Reiterate to render the skinned + args->_shapePipeline = shadowSkinnedPipeline; + batch.setPipeline(shadowSkinnedPipeline->pipeline); + for (const auto& key : skinnedShapeKeys) { + renderItems(renderContext, inShapes.at(key)); + } + + args->_shapePipeline = nullptr; + args->_batch = nullptr; + }); +} + DrawOutlineTask::DrawOutlineTask() { } @@ -311,25 +369,36 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende const auto input = inputs.get(); const auto selectedMetas = inputs.getN(0); const auto shapePlumber = input.get1(); - const auto lightingModel = inputs.getN(2); - const auto deferredFramebuffer = inputs.getN(3); - const auto primaryFramebuffer = inputs.getN(4); - const auto deferredFrameTransform = inputs.getN(5); + const auto deferredFramebuffer = inputs.getN(2); + const auto primaryFramebuffer = inputs.getN(3); + const auto deferredFrameTransform = inputs.getN(4); - const auto& outlinedItems = task.addJob("OutlinedMetaToSubItems", selectedMetas); + // Prepare the ShapePipeline + ShapePlumberPointer shapePlumberZPass = std::make_shared(); + { + auto state = std::make_shared(); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + state->setColorWriteMask(0); - // Render opaque outline objects first in DeferredBuffer - const auto outlineInputs = DrawStateSortDeferred::Inputs(outlinedItems, lightingModel).asVarying(); - task.addJob("DrawOutlinedDepth", outlineInputs, shapePlumber); + initZPassPipelines(*shapePlumberZPass, state); + } + + const auto& outlinedItemIDs = task.addJob("MetaToSubItemIDs", selectedMetas); + const auto& outlinedItems = task.addJob("MetaToSubItems", outlinedItemIDs, true); + + // Sort + const auto& sortedPipelines = task.addJob("PipelineSort", outlinedItems); + const auto& sortedShapes = task.addJob("DepthSort", sortedPipelines); + task.addJob("Depth", sortedShapes, shapePlumberZPass); // Retrieve z value of the outlined objects const auto outlinePrepareInputs = PrepareOutline::Inputs(outlinedItems, deferredFramebuffer).asVarying(); - const auto outlinedFrameBuffer = task.addJob("CopyOutlineDepth", outlinePrepareInputs); + const auto outlinedFrameBuffer = task.addJob("CopyDepth", outlinePrepareInputs); // Draw outline const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, deferredFramebuffer, outlinedFrameBuffer, primaryFramebuffer).asVarying(); - task.addJob("DrawOutlineEffect", drawOutlineInputs); + task.addJob("Effect", drawOutlineInputs); // Debug outline - task.addJob("DebugOutline", outlinedFrameBuffer); + task.addJob("Debug", outlinedFrameBuffer); } diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index ccc1e03fdd..a0e1823a56 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -165,11 +165,21 @@ private: bool _isDisplayDepthEnabled{ false }; }; -#include "LightingModel.h" +class DrawOutlineDepth { +public: + using JobModel = render::Job::ModelI; + + DrawOutlineDepth(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + void run(const render::RenderContextPointer& renderContext, + const render::ShapeBounds& inShapes); + +protected: + render::ShapePlumberPointer _shapePlumber; +}; class DrawOutlineTask { public: - using Inputs = render::VaryingSet6; + using Inputs = render::VaryingSet5; using Config = render::Task::Config; using JobModel = render::Task::ModelI; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 5ea506e18f..d396377969 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -166,7 +166,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer).asVarying(); task.addJob("ToneMapping", toneMappingInputs); - const auto outlineInputs = DrawOutlineTask::Inputs(selectedMetas, shapePlumber, lightingModel, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); + const auto outlineInputs = DrawOutlineTask::Inputs(selectedMetas, shapePlumber, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); task.addJob("DrawOutline", outlineInputs); { // DEbug the bounds of the rendered items, still look at the zbuffer diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 0353e10407..7f644add72 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -21,19 +21,15 @@ #include "render/DrawTask.h" #include "model_vert.h" -#include "model_shadow_vert.h" #include "model_normal_map_vert.h" #include "model_lightmap_vert.h" #include "model_lightmap_normal_map_vert.h" #include "skin_model_vert.h" -#include "skin_model_shadow_vert.h" #include "skin_model_normal_map_vert.h" -#include "model_shadow_fade_vert.h" #include "model_lightmap_fade_vert.h" #include "model_lightmap_normal_map_fade_vert.h" #include "skin_model_fade_vert.h" -#include "skin_model_shadow_fade_vert.h" #include "skin_model_normal_map_fade_vert.h" #include "simple_vert.h" @@ -50,7 +46,6 @@ #include "model_frag.h" #include "model_unlit_frag.h" -#include "model_shadow_frag.h" #include "model_normal_map_frag.h" #include "model_normal_specular_map_frag.h" #include "model_specular_map_frag.h" @@ -59,7 +54,6 @@ #include "model_normal_map_fade_vert.h" #include "model_fade_frag.h" -#include "model_shadow_fade_frag.h" #include "model_unlit_fade_frag.h" #include "model_normal_map_fade_frag.h" #include "model_normal_specular_map_fade_frag.h" @@ -95,6 +89,17 @@ #include "overlay3D_model_unlit_frag.h" #include "overlay3D_model_translucent_unlit_frag.h" +#include "model_shadow_vert.h" +#include "skin_model_shadow_vert.h" + +#include "model_shadow_frag.h" +#include "skin_model_shadow_frag.h" + +#include "model_shadow_fade_vert.h" +#include "skin_model_shadow_fade_vert.h" + +#include "model_shadow_fade_frag.h" +#include "skin_model_shadow_fade_frag.h" using namespace render; using namespace std::placeholders; @@ -102,6 +107,7 @@ using namespace std::placeholders; void initOverlay3DPipelines(ShapePlumber& plumber, bool depthTest = false); void initDeferredPipelines(ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter); void initForwardPipelines(ShapePlumber& plumber); +void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); void addPlumberPipeline(ShapePlumber& plumber, const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel, @@ -566,3 +572,33 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderAr pipeline.locations->lightAmbientMapUnit); } } + +void initZPassPipelines(ShapePlumber& shapePlumber, gpu::StatePointer state) { + auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); + auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); + gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withoutSkinned().withoutFade(), + modelProgram, state); + + auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); + auto skinPixel = gpu::Shader::createPixel(std::string(skin_model_shadow_frag)); + gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, skinPixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withSkinned().withoutFade(), + skinProgram, state); + + auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_shadow_fade_vert)); + auto modelFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag)); + gpu::ShaderPointer modelFadeProgram = gpu::Shader::createProgram(modelFadeVertex, modelFadePixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withoutSkinned().withFade(), + modelFadeProgram, state); + + auto skinFadeVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_fade_vert)); + auto skinFadePixel = gpu::Shader::createPixel(std::string(skin_model_shadow_fade_frag)); + gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skinFadeVertex, skinFadePixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withSkinned().withFade(), + skinFadeProgram, state); +} diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index ac80c03873..d32857bc65 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -22,20 +22,10 @@ #include "DeferredLightingEffect.h" #include "FramebufferCache.h" -#include "model_shadow_vert.h" -#include "skin_model_shadow_vert.h" - -#include "model_shadow_frag.h" -#include "skin_model_shadow_frag.h" - -#include "model_shadow_fade_vert.h" -#include "skin_model_shadow_fade_vert.h" - -#include "model_shadow_fade_frag.h" -#include "skin_model_shadow_fade_frag.h" - using namespace render; +extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); + void RenderShadowMap::run(const render::RenderContextPointer& renderContext, const render::ShapeBounds& inShapes) { assert(renderContext->args); @@ -108,33 +98,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende state->setCullMode(gpu::State::CULL_BACK); state->setDepthTest(true, true, gpu::LESS_EQUAL); - auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); - auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); - gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel); - shapePlumber->addPipeline( - ShapeKey::Filter::Builder().withoutSkinned().withoutFade(), - modelProgram, state); - - auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); - auto skinPixel = gpu::Shader::createPixel(std::string(skin_model_shadow_frag)); - gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, skinPixel); - shapePlumber->addPipeline( - ShapeKey::Filter::Builder().withSkinned().withoutFade(), - skinProgram, state); - - auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_shadow_fade_vert)); - auto modelFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag)); - gpu::ShaderPointer modelFadeProgram = gpu::Shader::createProgram(modelFadeVertex, modelFadePixel); - shapePlumber->addPipeline( - ShapeKey::Filter::Builder().withoutSkinned().withFade(), - modelFadeProgram, state); - - auto skinFadeVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_fade_vert)); - auto skinFadePixel = gpu::Shader::createPixel(std::string(skin_model_shadow_fade_frag)); - gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skinFadeVertex, skinFadePixel); - shapePlumber->addPipeline( - ShapeKey::Filter::Builder().withSkinned().withFade(), - skinFadeProgram, state); + initZPassPipelines(*shapePlumber, state); } const auto cachedMode = task.addJob("ShadowSetup"); diff --git a/libraries/render/src/render/FilterTask.cpp b/libraries/render/src/render/FilterTask.cpp index b4da280697..39bc19adc7 100644 --- a/libraries/render/src/render/FilterTask.cpp +++ b/libraries/render/src/render/FilterTask.cpp @@ -98,9 +98,8 @@ void SelectSortItems::run(const RenderContextPointer& renderContext, const ItemB } } -void MetaToSubItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { +void MetaToSubItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemIDs& outItems) { auto& scene = renderContext->_scene; - ItemIDs outItemIds; // Now we have a selection of items to render outItems.clear(); @@ -108,14 +107,25 @@ void MetaToSubItems::run(const RenderContextPointer& renderContext, const ItemBo for (auto idBound : inItems) { auto& item = scene->getItem(idBound.id); - item.fetchMetaSubItems(outItemIds); - } - - // Transform Item IDs to ItemBounds - for (auto id : outItemIds) { - auto& item = scene->getItem(id); - - outItems.emplace_back(ItemBound{ id, item.getBound() }); + item.fetchMetaSubItems(outItems); } } +void IDsToBounds::run(const RenderContextPointer& renderContext, const ItemIDs& inItems, ItemBounds& outItems) { + auto& scene = renderContext->_scene; + + // Now we have a selection of items to render + outItems.clear(); + + if (!_disableAABBs) { + for (auto id : inItems) { + auto& item = scene->getItem(id); + + outItems.emplace_back(ItemBound{ id, item.getBound() }); + } + } else { + for (auto id : inItems) { + outItems.emplace_back(ItemBound{ id }); + } + } +} diff --git a/libraries/render/src/render/FilterTask.h b/libraries/render/src/render/FilterTask.h index b9b02017da..2f8b53722f 100644 --- a/libraries/render/src/render/FilterTask.h +++ b/libraries/render/src/render/FilterTask.h @@ -135,11 +135,24 @@ namespace render { // From meta-Items, generate the sub-items class MetaToSubItems { public: - using JobModel = Job::ModelIO; + using JobModel = Job::ModelIO; MetaToSubItems() {} - void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems); + void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemIDs& outItems); + }; + + // From item IDs build item bounds + class IDsToBounds { + public: + using JobModel = Job::ModelIO; + + IDsToBounds(bool disableAABBs = false) : _disableAABBs(disableAABBs) {} + + void run(const RenderContextPointer& renderContext, const ItemIDs& inItems, ItemBounds& outItems); + + private: + bool _disableAABBs{ false }; }; } From 25ff132fc7028d57ef0c8a44cfa54f1207723b3c Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 6 Sep 2017 19:05:15 +0200 Subject: [PATCH 24/33] Debugging scripts working again with correct occlusion management --- libraries/render-utils/src/OutlineEffect.cpp | 40 +++++++++--------- libraries/render-utils/src/OutlineEffect.h | 2 +- .../utilities/lib/plotperf/PlotPerf.qmlc | Bin 0 -> 44724 bytes .../render/configSlider/ConfigSlider.qmlc | Bin 0 -> 11559 bytes scripts/developer/utilities/render/fade.qmlc | Bin 0 -> 41940 bytes .../developer/utilities/render/outline.qml | 12 +----- .../developer/utilities/render/outline.qmlc | Bin 0 -> 13063 bytes 7 files changed, 23 insertions(+), 31 deletions(-) create mode 100644 scripts/developer/utilities/lib/plotperf/PlotPerf.qmlc create mode 100644 scripts/developer/utilities/render/configSlider/ConfigSlider.qmlc create mode 100644 scripts/developer/utilities/render/fade.qmlc create mode 100644 scripts/developer/utilities/render/outline.qmlc diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 3876a87c02..f7cb72b8ef 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -145,12 +145,12 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I auto mainFrameBuffer = inputs.get1(); if (mainFrameBuffer) { - auto sceneDepthBuffer = mainFrameBuffer->getPrimaryDepthTexture(); + auto sceneDepthBuffer = inputs.get2(); const auto frameTransform = inputs.get0(); - auto outlinedDepthBuffer = inputs.get2(); + auto outlinedDepthBuffer = mainFrameBuffer->getPrimaryDepthTexture(); auto destinationFrameBuffer = inputs.get3(); auto pipeline = getPipeline(); - auto framebufferSize = glm::ivec2(sceneDepthBuffer->getDimensions()); + auto framebufferSize = glm::ivec2(outlinedDepthBuffer->getDimensions()); if (!_primaryWithoutDepthBuffer || framebufferSize!=_frameBufferSize) { // Failing to recreate this frame buffer when the screen has been resized creates a bug on Mac @@ -159,7 +159,7 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I _frameBufferSize = framebufferSize; } - if (outlinedDepthBuffer) { + if (sceneDepthBuffer) { auto args = renderContext->args; { auto& configuration = _configuration.edit(); @@ -185,8 +185,8 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); - batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer); - batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthBuffer->getDepthTexture()); + batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getDepthTexture()); + batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthBuffer); batch.draw(gpu::TRIANGLE_STRIP, 4); // Restore previous frame buffer @@ -255,7 +255,7 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const batch.setModelTransform(Transform()); batch.setPipeline(getDebugPipeline()); - batch.setResourceTexture(0, outlineFramebuffer->getDepthTexture()); + batch.setResourceTexture(0, outlineFramebuffer->getPrimaryDepthTexture()); const glm::vec4 color(1.0f, 0.5f, 0.2f, 1.0f); const glm::vec2 bottomLeft(-1.0f, -1.0f); @@ -369,7 +369,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende const auto input = inputs.get(); const auto selectedMetas = inputs.getN(0); const auto shapePlumber = input.get1(); - const auto deferredFramebuffer = inputs.getN(2); + const auto outlinedFrameBuffer = inputs.getN(2); const auto primaryFramebuffer = inputs.getN(3); const auto deferredFrameTransform = inputs.getN(4); @@ -383,22 +383,22 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende initZPassPipelines(*shapePlumberZPass, state); } - const auto& outlinedItemIDs = task.addJob("MetaToSubItemIDs", selectedMetas); - const auto& outlinedItems = task.addJob("MetaToSubItems", outlinedItemIDs, true); + const auto& outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", selectedMetas); + const auto& outlinedItems = task.addJob("OutlineMetaToSubItems", outlinedItemIDs, true); + + // Retrieve z value of the scene objects + const auto outlinePrepareInputs = PrepareOutline::Inputs(outlinedItems, outlinedFrameBuffer).asVarying(); + const auto sceneFrameBuffer = task.addJob("OutlineCopyDepth", outlinePrepareInputs); // Sort - const auto& sortedPipelines = task.addJob("PipelineSort", outlinedItems); - const auto& sortedShapes = task.addJob("DepthSort", sortedPipelines); - task.addJob("Depth", sortedShapes, shapePlumberZPass); - - // Retrieve z value of the outlined objects - const auto outlinePrepareInputs = PrepareOutline::Inputs(outlinedItems, deferredFramebuffer).asVarying(); - const auto outlinedFrameBuffer = task.addJob("CopyDepth", outlinePrepareInputs); + const auto& sortedPipelines = task.addJob("OutlinePipelineSort", outlinedItems); + const auto& sortedShapes = task.addJob("OutlineDepthSort", sortedPipelines); + task.addJob("OutlineDepth", sortedShapes, shapePlumberZPass); // Draw outline - const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, deferredFramebuffer, outlinedFrameBuffer, primaryFramebuffer).asVarying(); - task.addJob("Effect", drawOutlineInputs); + const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, primaryFramebuffer).asVarying(); + task.addJob("OutlineEffect", drawOutlineInputs); // Debug outline - task.addJob("Debug", outlinedFrameBuffer); + task.addJob("OutlineDebug", outlinedFrameBuffer); } diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index a0e1823a56..4cbfb5851c 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -146,7 +146,7 @@ signals: class DebugOutline { public: - using Inputs = OutlineFramebufferPointer; + using Inputs = DeferredFramebufferPointer; using Config = DebugOutlineConfig; using JobModel = render::Job::ModelI; diff --git a/scripts/developer/utilities/lib/plotperf/PlotPerf.qmlc b/scripts/developer/utilities/lib/plotperf/PlotPerf.qmlc new file mode 100644 index 0000000000000000000000000000000000000000..e23e6334ff9ae336ad0005b7f1dfbddcae57622d GIT binary patch literal 44724 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 MbK$!2Xo6h&fBtFeW&i*H literal 0 HcmV?d00001 diff --git a/scripts/developer/utilities/render/configSlider/ConfigSlider.qmlc b/scripts/developer/utilities/render/configSlider/ConfigSlider.qmlc new file mode 100644 index 0000000000000000000000000000000000000000..2fdd99273a98086d918b117e8f8112243822071b GIT binary patch literal 11559 zcmd^_U2I%O6@b5MJC2jO*}H4!uLQbHw$L^|j+->|-+j|E*NUnp+U;pFlKl;Vn z-RIuUZhq-sUv0b}*aiIN%1{3j`T5n?-}=kfewAqY{*S)|>;~Rn1M7g(7?_^(%-gYh z?gXlUsgWWLpdA9!%hgL|srL={X{L9`kMt6{tvHq<~*4UE-*zXA@ffb%PW zT6m@w&ep=sT1c#fpR6>rQz9VnUGt#XJ`;hb$aEXNeX}r3T6*uuBA~&d2k8lHWZbh; zw}dkr&Fha!uIL?x-g?W`idiDpUE~oIC+~dF`nmG*RWCws4#q8AC#O|IK^`a9W(K`V zo4=!gXnFaTVwcvt z3|*(k`RuZ_Lc1K?Tug61yKJw}E+@8>-?!+f(l{@}KD4#q_M$ z1v-x2Zgy5gul0+D-WD6zmVAMZqxS$TNYDAtpd{}y`EV)zlecugVdcEnuqnvrtkkZ~j)(A9`Vzp@x*b1yA#ahmLw?nJQ zB7Mj@QmiBA`S#rdzc5Nv~FiP8$!l$}midFq4+Qn|oR3d{X#~ zTPiCHvjTUL(w~8q1w9GeLrQ;c&hRzROiF)l&bBQI50TPeL`QW+yVyvIjkdEADP^7L zBS;&y(yW~XTpR|Uq8&HxRxATM)Q4*4@XZ%`o3-jw0$!0n2snDdr^xBXC#=q*IkQNFtqIKSCa1OBv`@9%9+=xj zPWuKajb=^FlH`^=@Gv>+gU;V}tKJ?Z$D{b3v2(4>6$Vz>pC zu|=a>1iBxow--WiF$C|1;KLBq`>@G}Z9cU4u-}JnA71g{hd!M1;i3;$e37-BBNzLg}euorS{A^Gu50d668D1{X@1v9FN$X0<`?KR>i3LPnk@mQiPkM%amB4_+ z+7NvzvGAEoLFgO&UiulPpQlykVbV&#(CaMpECyf3x5k(F7asi#>Tc7j3+b!Sv7757 zt#Z3sD)~-!Av#Gj#1OrTALS4O93?u>YOzN$pf9;=SeQ;wTc#)I=ELp87r??NODd&`ONMFTYAcJ__y+U)Bhd|c%I~}h4}`tjlEvdNIarD zm3=%J@Oz23A+`M=Ptwb`t$&x7_g1T<=PoB-FiV*I9W7*uO4bLlP5jKhDfR&Y@ej!_ z5_iGa5^dWs><6hky=UhL%SrNWbP)$%|&a%Lh@F%J4_?(QzJR56`iO-E6m#WK?6% z>Ha0MBzMSMAA^b~@%@7Ccov>YWdE8NnNB6M>6^)He?FNVo@)Q4ng4L6J^R~^(L;5K zLbn}%Q;gZ3t%u^VpdD?*+8_UTkbfO zjGdhoH$L`|<#pch+BtWhKLf0Z>kBpwa>80ll93`=Y^3r<`xRTfOwnGT0?(;TC8pXXpVgbE z4kbcI^2I^~3|!(V|8@yVmn^_uK9B?mm9Uqa_eA!ccy@nmEPkmic2R0tT(aKD@zAT% zJ2zkbK#rJi$_+~ZEn1D>Pq;tyL-wIW=)3u3^OWSy%Qxa7zb!U)BOVI3#U@2iDe~iQ zHpziiI;f{xrF|;&K`N^BQZDH}W0UUn^RK7{6e2YFS2z*@XRU&(!@^)*fKK)3E%>oTd zNvCtBQfrm#biOHU=k0W4GjGYU{sZZAn*Wr&*8Y~7CR$B$)wO_G3*AU!^gwAd^82OT zH!W3{EsN6S_bSz;+!Y6mQj$L(4S2r2%xFE>Dn0Dw8=+@^x9DK_xcL9F*So!ovRB3Z en%u=NWUo(5y_2uL#rZt2t&-eOv3{1RU;8h3EWUsM literal 0 HcmV?d00001 diff --git a/scripts/developer/utilities/render/fade.qmlc b/scripts/developer/utilities/render/fade.qmlc new file mode 100644 index 0000000000000000000000000000000000000000..8c69d76eff64d74d6a36bcfd97b16413bfa65dc8 GIT binary patch literal 41940 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 EFUMI0bN~PV literal 0 HcmV?d00001 diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index 321dd9271b..e17f7c1f1c 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -14,20 +14,12 @@ import "configSlider" Item { id: root - property var pickConfig: Render.getConfig("RenderMainView.PickOutlined") - property var debugConfig: Render.getConfig("RenderMainView.DebugOutline") - property var drawConfig: Render.getConfig("RenderMainView.DrawOutline") + property var debugConfig: Render.getConfig("RenderMainView.OutlineDebug") + property var drawConfig: Render.getConfig("RenderMainView.OutlineEffect") Column { spacing: 8 - CheckBox { - text: "Edit Outline" - checked: root.pickConfig["pick"] - onCheckedChanged: { - root.pickConfig["pick"] = checked; - } - } CheckBox { text: "View Outlined Depth" checked: root.debugConfig["viewOutlinedDepth"] diff --git a/scripts/developer/utilities/render/outline.qmlc b/scripts/developer/utilities/render/outline.qmlc new file mode 100644 index 0000000000000000000000000000000000000000..e85e72ad3c452e3c85bb7b199b398fba1350cbc5 GIT binary patch literal 13063 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 literal 0 HcmV?d00001 From fe357671e1b479156550cec306d771f3dac7f6ff Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 6 Sep 2017 19:06:40 +0200 Subject: [PATCH 25/33] Removed qmlc files --- .../utilities/lib/plotperf/PlotPerf.qmlc | Bin 44724 -> 0 bytes .../render/configSlider/ConfigSlider.qmlc | Bin 11559 -> 0 bytes scripts/developer/utilities/render/fade.qmlc | Bin 41940 -> 0 bytes scripts/developer/utilities/render/outline.qmlc | Bin 13063 -> 0 bytes 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 scripts/developer/utilities/lib/plotperf/PlotPerf.qmlc delete mode 100644 scripts/developer/utilities/render/configSlider/ConfigSlider.qmlc delete mode 100644 scripts/developer/utilities/render/fade.qmlc delete mode 100644 scripts/developer/utilities/render/outline.qmlc diff --git a/scripts/developer/utilities/lib/plotperf/PlotPerf.qmlc b/scripts/developer/utilities/lib/plotperf/PlotPerf.qmlc deleted file mode 100644 index e23e6334ff9ae336ad0005b7f1dfbddcae57622d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44724 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 MbK$!2Xo6h&fBtFeW&i*H diff --git a/scripts/developer/utilities/render/configSlider/ConfigSlider.qmlc b/scripts/developer/utilities/render/configSlider/ConfigSlider.qmlc deleted file mode 100644 index 2fdd99273a98086d918b117e8f8112243822071b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11559 zcmd^_U2I%O6@b5MJC2jO*}H4!uLQbHw$L^|j+->|-+j|E*NUnp+U;pFlKl;Vn z-RIuUZhq-sUv0b}*aiIN%1{3j`T5n?-}=kfewAqY{*S)|>;~Rn1M7g(7?_^(%-gYh z?gXlUsgWWLpdA9!%hgL|srL={X{L9`kMt6{tvHq<~*4UE-*zXA@ffb%PW zT6m@w&ep=sT1c#fpR6>rQz9VnUGt#XJ`;hb$aEXNeX}r3T6*uuBA~&d2k8lHWZbh; zw}dkr&Fha!uIL?x-g?W`idiDpUE~oIC+~dF`nmG*RWCws4#q8AC#O|IK^`a9W(K`V zo4=!gXnFaTVwcvt z3|*(k`RuZ_Lc1K?Tug61yKJw}E+@8>-?!+f(l{@}KD4#q_M$ z1v-x2Zgy5gul0+D-WD6zmVAMZqxS$TNYDAtpd{}y`EV)zlecugVdcEnuqnvrtkkZ~j)(A9`Vzp@x*b1yA#ahmLw?nJQ zB7Mj@QmiBA`S#rdzc5Nv~FiP8$!l$}midFq4+Qn|oR3d{X#~ zTPiCHvjTUL(w~8q1w9GeLrQ;c&hRzROiF)l&bBQI50TPeL`QW+yVyvIjkdEADP^7L zBS;&y(yW~XTpR|Uq8&HxRxATM)Q4*4@XZ%`o3-jw0$!0n2snDdr^xBXC#=q*IkQNFtqIKSCa1OBv`@9%9+=xj zPWuKajb=^FlH`^=@Gv>+gU;V}tKJ?Z$D{b3v2(4>6$Vz>pC zu|=a>1iBxow--WiF$C|1;KLBq`>@G}Z9cU4u-}JnA71g{hd!M1;i3;$e37-BBNzLg}euorS{A^Gu50d668D1{X@1v9FN$X0<`?KR>i3LPnk@mQiPkM%amB4_+ z+7NvzvGAEoLFgO&UiulPpQlykVbV&#(CaMpECyf3x5k(F7asi#>Tc7j3+b!Sv7757 zt#Z3sD)~-!Av#Gj#1OrTALS4O93?u>YOzN$pf9;=SeQ;wTc#)I=ELp87r??NODd&`ONMFTYAcJ__y+U)Bhd|c%I~}h4}`tjlEvdNIarD zm3=%J@Oz23A+`M=Ptwb`t$&x7_g1T<=PoB-FiV*I9W7*uO4bLlP5jKhDfR&Y@ej!_ z5_iGa5^dWs><6hky=UhL%SrNWbP)$%|&a%Lh@F%J4_?(QzJR56`iO-E6m#WK?6% z>Ha0MBzMSMAA^b~@%@7Ccov>YWdE8NnNB6M>6^)He?FNVo@)Q4ng4L6J^R~^(L;5K zLbn}%Q;gZ3t%u^VpdD?*+8_UTkbfO zjGdhoH$L`|<#pch+BtWhKLf0Z>kBpwa>80ll93`=Y^3r<`xRTfOwnGT0?(;TC8pXXpVgbE z4kbcI^2I^~3|!(V|8@yVmn^_uK9B?mm9Uqa_eA!ccy@nmEPkmic2R0tT(aKD@zAT% zJ2zkbK#rJi$_+~ZEn1D>Pq;tyL-wIW=)3u3^OWSy%Qxa7zb!U)BOVI3#U@2iDe~iQ zHpziiI;f{xrF|;&K`N^BQZDH}W0UUn^RK7{6e2YFS2z*@XRU&(!@^)*fKK)3E%>oTd zNvCtBQfrm#biOHU=k0W4GjGYU{sZZAn*Wr&*8Y~7CR$B$)wO_G3*AU!^gwAd^82OT zH!W3{EsN6S_bSz;+!Y6mQj$L(4S2r2%xFE>Dn0Dw8=+@^x9DK_xcL9F*So!ovRB3Z en%u=NWUo(5y_2uL#rZt2t&-eOv3{1RU;8h3EWUsM diff --git a/scripts/developer/utilities/render/fade.qmlc b/scripts/developer/utilities/render/fade.qmlc deleted file mode 100644 index 8c69d76eff64d74d6a36bcfd97b16413bfa65dc8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41940 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 EFUMI0bN~PV diff --git a/scripts/developer/utilities/render/outline.qmlc b/scripts/developer/utilities/render/outline.qmlc deleted file mode 100644 index e85e72ad3c452e3c85bb7b199b398fba1350cbc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13063 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 From b9eb317d9b2f0f49e9d9de0a553c63fdf9e4616e Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 7 Sep 2017 10:33:55 +0200 Subject: [PATCH 26/33] Fixed non working outline in stereo with new changes --- libraries/render-utils/src/OutlineEffect.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index f7cb72b8ef..adbfed2775 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -119,6 +119,10 @@ void PrepareOutline::run(const render::RenderContextPointer& renderContext, cons // Restore previous frame buffer batch.setFramebuffer(deferredFrameBuffer->getDeferredFramebuffer()); + // Clear it + batch.clearFramebuffer( + gpu::Framebuffer::BUFFER_DEPTH, + vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, false); }); output = _outlineFramebuffer; @@ -324,10 +328,6 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - batch.clearFramebuffer( - gpu::Framebuffer::BUFFER_DEPTH, - vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, true); - auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); From b43514fb8bfd2cc90c617f615adaf88fd7066dc2 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 7 Sep 2017 12:14:32 +0200 Subject: [PATCH 27/33] Modified outline shader to do fill branch on CPU. Fixed assymetric outline due to depth sample not offset by a half texel in shader. --- libraries/render-utils/src/Outline.slf | 87 +---------------- libraries/render-utils/src/Outline.slh | 95 +++++++++++++++++++ libraries/render-utils/src/OutlineEffect.cpp | 85 +++++++++-------- libraries/render-utils/src/OutlineEffect.h | 3 +- libraries/render-utils/src/Outline_filled.slf | 13 +++ 5 files changed, 162 insertions(+), 121 deletions(-) create mode 100644 libraries/render-utils/src/Outline.slh create mode 100644 libraries/render-utils/src/Outline_filled.slf diff --git a/libraries/render-utils/src/Outline.slf b/libraries/render-utils/src/Outline.slf index 1d3d21a3c7..68ef870cba 100644 --- a/libraries/render-utils/src/Outline.slf +++ b/libraries/render-utils/src/Outline.slf @@ -1,8 +1,7 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// +// Outline.slf // Add outline effect based on two zbuffers : one containing the total scene z and another -// with the z of only the objects to be outlined +// with the z of only the objects to be outlined. +// This is the version without the fill effect inside the silhouette. // // Created by Olivier Prat on 08/09/2017 // Copyright 2017 High Fidelity, Inc. @@ -10,81 +9,5 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredTransform.slh@> -<$declareDeferredFrameTransform()$> - -<@include Outline_shared.slh@> - -uniform outlineParamsBuffer { - OutlineParameters params; -}; - -uniform sampler2D sceneDepthMap; -uniform sampler2D outlinedDepthMap; - -in vec2 varTexCoord0; -out vec4 outFragColor; - -const float FAR_Z = 1.0; -const float LINEAR_DEPTH_BIAS = 5e-3; -const float OPACITY_EPSILON = 5e-3; - -void main(void) { - float outlinedDepth = texture(outlinedDepthMap, varTexCoord0).x; - float intensity = 0.0; - - if (outlinedDepth < FAR_Z) { - // We're not on the far plane so we are on the outlined object, thus no outline to do! - - // But maybe we need to fill the interior - // TODO: this should be done as another shader with switch done on CPU - if (params._fillOpacityUnoccluded>OPACITY_EPSILON && params._fillOpacityUnoccluded>OPACITY_EPSILON) { - float sceneDepth = texture(sceneDepthMap, varTexCoord0).x; - // Transform to linear depth for better precision - outlinedDepth = -evalZeyeFromZdb(outlinedDepth); - sceneDepth = -evalZeyeFromZdb(sceneDepth); - - // Are we occluded? - if (sceneDepth < (outlinedDepth-LINEAR_DEPTH_BIAS)) { - intensity = params._fillOpacityOccluded; - } else { - intensity = params._fillOpacityUnoccluded; - } - } else { - discard; - } - } else { - float weight = 0.0; - vec2 deltaUv = params._size / params._blurKernelSize; - vec2 lineStartUv = varTexCoord0 - params._size / 2.0; - vec2 uv; - int x; - int y; - - for (y=0 ; y=0.0 && uv.y<=1.0) { - for (x=0 ; x=0.0 && uv.x<=1.0) - { - outlinedDepth = texture(outlinedDepthMap, uv).x; - intensity += (outlinedDepth < FAR_Z) ? 1.0 : 0.0; - weight += 1.f; - } - uv.x += deltaUv.x; - } - } - } - - intensity /= weight; - if (intensity < OPACITY_EPSILON) { - discard; - } - - intensity = min(1.0, intensity / params._threshold) * params._intensity; - } - - outFragColor = vec4(params._color.rgb, intensity); -} +<@include Outline.slh@> +<$main(0)$> diff --git a/libraries/render-utils/src/Outline.slh b/libraries/render-utils/src/Outline.slh new file mode 100644 index 0000000000..6e510581b4 --- /dev/null +++ b/libraries/render-utils/src/Outline.slh @@ -0,0 +1,95 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> + +<@include DeferredTransform.slh@> +<$declareDeferredFrameTransform()$> + +<@include Outline_shared.slh@> + +uniform outlineParamsBuffer { + OutlineParameters params; +}; + +uniform sampler2D sceneDepthMap; +uniform sampler2D outlinedDepthMap; + +in vec2 varTexCoord0; +out vec4 outFragColor; + +const float FAR_Z = 1.0; +const float LINEAR_DEPTH_BIAS = 5e-3; +const float OPACITY_EPSILON = 5e-3; + +<@func main(IS_FILLED)@> + +void main(void) { + float outlinedDepth = texture(outlinedDepthMap, varTexCoord0).x; + float intensity = 0.0; + + if (outlinedDepth < FAR_Z) { + // We're not on the far plane so we are on the outlined object, thus no outline to do! +<@if IS_FILLED@> + // But we need to fill the interior + float sceneDepth = texture(sceneDepthMap, varTexCoord0).x; + // Transform to linear depth for better precision + outlinedDepth = -evalZeyeFromZdb(outlinedDepth); + sceneDepth = -evalZeyeFromZdb(sceneDepth); + + // Are we occluded? + if (sceneDepth < (outlinedDepth-LINEAR_DEPTH_BIAS)) { + intensity = params._fillOpacityOccluded; + } else { + intensity = params._fillOpacityUnoccluded; + } +<@else@> + discard; +<@endif@> + } else { + float weight = 0.0; + vec2 deltaUv = params._size / params._blurKernelSize; + // We offset by half a texel to be centered on the depth sample. If we don't do this + // the blur will have a different width between the left / right sides and top / bottom + // sides of the silhouette + vec2 lineStartUv = varTexCoord0 + (getInvWidthHeight() - params._size) / 2.0; + vec2 uv; + int x; + int y; + + for (y=0 ; y=0.0 && uv.y<=1.0) { + for (x=0 ; x=0.0 && uv.x<=1.0) + { + outlinedDepth = texture(outlinedDepthMap, uv).x; + intensity += (outlinedDepth < FAR_Z) ? 1.0 : 0.0; + weight += 1.f; + } + uv.x += deltaUv.x; + } + } + } + + intensity /= weight; + if (intensity < OPACITY_EPSILON) { + discard; + } + + intensity = min(1.0, intensity / params._threshold) * params._intensity; + } + + outFragColor = vec4(params._color.rgb, intensity); +} + +<@endfunc@> diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index adbfed2775..289405b127 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -22,6 +22,7 @@ #include "debug_deferred_buffer_vert.h" #include "debug_deferred_buffer_frag.h" #include "Outline_frag.h" +#include "Outline_filled_frag.h" using namespace render; @@ -153,7 +154,6 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I const auto frameTransform = inputs.get0(); auto outlinedDepthBuffer = mainFrameBuffer->getPrimaryDepthTexture(); auto destinationFrameBuffer = inputs.get3(); - auto pipeline = getPipeline(); auto framebufferSize = glm::ivec2(outlinedDepthBuffer->getDimensions()); if (!_primaryWithoutDepthBuffer || framebufferSize!=_frameBufferSize) { @@ -164,6 +164,8 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I } if (sceneDepthBuffer) { + const auto OPACITY_EPSILON = 5e-3f; + auto pipeline = getPipeline(_fillOpacityUnoccluded>OPACITY_EPSILON || _fillOpacityOccluded>OPACITY_EPSILON); auto args = renderContext->args; { auto& configuration = _configuration.edit(); @@ -200,7 +202,7 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I } } -const gpu::PipelinePointer& DrawOutline::getPipeline() { +const gpu::PipelinePointer& DrawOutline::getPipeline(bool isFilled) { if (!_pipeline) { auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); auto ps = gpu::Shader::createPixel(std::string(Outline_frag)); @@ -217,8 +219,13 @@ const gpu::PipelinePointer& DrawOutline::getPipeline() { state->setDepthTest(gpu::State::DepthTest(false, false)); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); _pipeline = gpu::Pipeline::create(program, state); + + ps = gpu::Shader::createPixel(std::string(Outline_filled_frag)); + program = gpu::Shader::createProgram(vs, ps); + gpu::Shader::makeProgram(*program, slotBindings); + _pipelineFilled = gpu::Pipeline::create(program, state); } - return _pipeline; + return isFilled ? _pipelineFilled : _pipeline; } DebugOutline::DebugOutline() { @@ -310,51 +317,53 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); - RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder; + if (!inShapes.empty()) { + RenderArgs* args = renderContext->args; + ShapeKey::Builder defaultKeyBuilder; - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - args->_batch = &batch; + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; - // Setup camera, projection and viewport for all items - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); + // Setup camera, projection and viewport for all items + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); - glm::mat4 projMat; - Transform viewMat; - args->getViewFrustum().evalProjectionMatrix(projMat); - args->getViewFrustum().evalViewTransform(viewMat); + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); - auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); - auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); + auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); + auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); - std::vector skinnedShapeKeys{}; + std::vector skinnedShapeKeys{}; - // Iterate through all inShapes and render the unskinned - args->_shapePipeline = shadowPipeline; - batch.setPipeline(shadowPipeline->pipeline); - for (auto items : inShapes) { - if (items.first.isSkinned()) { - skinnedShapeKeys.push_back(items.first); + // Iterate through all inShapes and render the unskinned + args->_shapePipeline = shadowPipeline; + batch.setPipeline(shadowPipeline->pipeline); + for (auto items : inShapes) { + if (items.first.isSkinned()) { + skinnedShapeKeys.push_back(items.first); + } + else { + renderItems(renderContext, items.second); + } } - else { - renderItems(renderContext, items.second); + + // Reiterate to render the skinned + args->_shapePipeline = shadowSkinnedPipeline; + batch.setPipeline(shadowSkinnedPipeline->pipeline); + for (const auto& key : skinnedShapeKeys) { + renderItems(renderContext, inShapes.at(key)); } - } - // Reiterate to render the skinned - args->_shapePipeline = shadowSkinnedPipeline; - batch.setPipeline(shadowSkinnedPipeline->pipeline); - for (const auto& key : skinnedShapeKeys) { - renderItems(renderContext, inShapes.at(key)); - } - - args->_shapePipeline = nullptr; - args->_batch = nullptr; - }); + args->_shapePipeline = nullptr; + args->_batch = nullptr; + }); + } } DrawOutlineTask::DrawOutlineTask() { diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 4cbfb5851c..7e7cf83d19 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -117,11 +117,12 @@ private: using OutlineConfigurationBuffer = gpu::StructBuffer; - const gpu::PipelinePointer& getPipeline(); + const gpu::PipelinePointer& getPipeline(bool isFilled); gpu::FramebufferPointer _primaryWithoutDepthBuffer; glm::ivec2 _frameBufferSize {0, 0}; gpu::PipelinePointer _pipeline; + gpu::PipelinePointer _pipelineFilled; OutlineConfigurationBuffer _configuration; glm::vec3 _color; float _size; diff --git a/libraries/render-utils/src/Outline_filled.slf b/libraries/render-utils/src/Outline_filled.slf new file mode 100644 index 0000000000..aaa3396bac --- /dev/null +++ b/libraries/render-utils/src/Outline_filled.slf @@ -0,0 +1,13 @@ +// Outline_filled.slf +// Add outline effect based on two zbuffers : one containing the total scene z and another +// with the z of only the objects to be outlined. +// This is the version with the fill effect inside the silhouette. +// +// Created by Olivier Prat on 09/07/2017 +// Copyright 2017 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 +// +<@include Outline.slh@> +<$main(1)$> From 2003495166c81366c8a60c9e196d42f8e160eba0 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 7 Sep 2017 12:30:20 +0200 Subject: [PATCH 28/33] Adjustments to half texel fix --- libraries/render-utils/src/Outline.slh | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/Outline.slh b/libraries/render-utils/src/Outline.slh index 6e510581b4..ac56e4c95c 100644 --- a/libraries/render-utils/src/Outline.slh +++ b/libraries/render-utils/src/Outline.slh @@ -32,14 +32,19 @@ const float OPACITY_EPSILON = 5e-3; <@func main(IS_FILLED)@> void main(void) { - float outlinedDepth = texture(outlinedDepthMap, varTexCoord0).x; + // We offset by half a texel to be centered on the depth sample. If we don't do this + // the blur will have a different width between the left / right sides and top / bottom + // sides of the silhouette + vec2 halfTexel = getInvWidthHeight() / 2; + vec2 texCoord0 = varTexCoord0+halfTexel; + float outlinedDepth = texture(outlinedDepthMap, texCoord0).x; float intensity = 0.0; if (outlinedDepth < FAR_Z) { // We're not on the far plane so we are on the outlined object, thus no outline to do! <@if IS_FILLED@> // But we need to fill the interior - float sceneDepth = texture(sceneDepthMap, varTexCoord0).x; + float sceneDepth = texture(sceneDepthMap, texCoord0).x; // Transform to linear depth for better precision outlinedDepth = -evalZeyeFromZdb(outlinedDepth); sceneDepth = -evalZeyeFromZdb(sceneDepth); @@ -56,10 +61,7 @@ void main(void) { } else { float weight = 0.0; vec2 deltaUv = params._size / params._blurKernelSize; - // We offset by half a texel to be centered on the depth sample. If we don't do this - // the blur will have a different width between the left / right sides and top / bottom - // sides of the silhouette - vec2 lineStartUv = varTexCoord0 + (getInvWidthHeight() - params._size) / 2.0; + vec2 lineStartUv = texCoord0 - params._size / 2.0; vec2 uv; int x; int y; From 6b5ca0c6cee78567675ae60b0a416590fe8bc6f7 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 7 Sep 2017 18:33:00 +0200 Subject: [PATCH 29/33] Optimized by removing unnecessary Z buffer copy --- libraries/render-utils/src/OutlineEffect.cpp | 185 +++++++----------- libraries/render-utils/src/OutlineEffect.h | 37 ++-- .../render-utils/src/RenderDeferredTask.cpp | 2 + 3 files changed, 86 insertions(+), 138 deletions(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 289405b127..dda371be80 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -18,6 +18,7 @@ #include "gpu/Context.h" #include "gpu/StandardShaderLib.h" + #include "surfaceGeometry_copyDepth_frag.h" #include "debug_deferred_buffer_vert.h" #include "debug_deferred_buffer_frag.h" @@ -31,11 +32,11 @@ extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); OutlineFramebuffer::OutlineFramebuffer() { } -void OutlineFramebuffer::update(const gpu::TexturePointer& linearDepthBuffer) { +void OutlineFramebuffer::update(const gpu::TexturePointer& colorBuffer) { // If the depth buffer or size changed, we need to delete our FBOs and recreate them at the // new correct dimensions. if (_depthTexture) { - auto newFrameSize = glm::ivec2(linearDepthBuffer->getDimensions()); + auto newFrameSize = glm::ivec2(colorBuffer->getDimensions()); if (_frameSize != newFrameSize) { _frameSize = newFrameSize; clear(); @@ -52,11 +53,11 @@ void OutlineFramebuffer::allocate() { auto width = _frameSize.x; auto height = _frameSize.y; - auto format = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED); - + auto format = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); + _depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(format, width, height)); _depthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); - _depthFramebuffer->setRenderBuffer(0, _depthTexture); + _depthFramebuffer->setDepthStencilBuffer(_depthTexture, format); } gpu::FramebufferPointer OutlineFramebuffer::getDepthFramebuffer() { @@ -73,57 +74,69 @@ gpu::TexturePointer OutlineFramebuffer::getDepthTexture() { return _depthTexture; } -void PrepareOutline::run(const render::RenderContextPointer& renderContext, const PrepareOutline::Inputs& inputs, PrepareOutline::Output& output) { - auto outlinedItems = inputs.get0(); +void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) { + assert(renderContext->args); + assert(renderContext->args->hasViewFrustum()); + auto& inShapes = inputs.get0(); + auto& deferredFrameBuffer = inputs.get1(); - if (!outlinedItems.empty()) { - auto args = renderContext->args; - auto deferredFrameBuffer = inputs.get1(); + if (!inShapes.empty()) { auto frameSize = deferredFrameBuffer->getFrameSize(); + RenderArgs* args = renderContext->args; + ShapeKey::Builder defaultKeyBuilder; if (!_outlineFramebuffer) { _outlineFramebuffer = std::make_shared(); } - _outlineFramebuffer->update(deferredFrameBuffer->getPrimaryDepthTexture()); + _outlineFramebuffer->update(deferredFrameBuffer->getDeferredColorTexture()); - if (!_copyDepthPipeline) { - auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); - auto ps = gpu::Shader::createPixel(std::string(surfaceGeometry_copyDepth_frag)); - gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); - - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), 0)); - gpu::Shader::makeProgram(*program, slotBindings); - - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - - state->setColorWriteMask(true, false, false, false); - - // Good to go add the brand new pipeline - _copyDepthPipeline = gpu::Pipeline::create(program, state); - } - - // TODO : Instead of copying entire buffer, we should only copy the sub rect containing the outlined object - // grown to take into account blur width gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - batch.enableStereo(false); - - batch.setViewportTransform(args->_viewport); - batch.setProjectionTransform(glm::mat4()); - batch.resetViewTransform(); - batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(frameSize, args->_viewport)); + args->_batch = &batch; batch.setFramebuffer(_outlineFramebuffer->getDepthFramebuffer()); - batch.setPipeline(_copyDepthPipeline); - batch.setResourceTexture(0, deferredFrameBuffer->getPrimaryDepthTexture()); - batch.draw(gpu::TRIANGLE_STRIP, 4); - - // Restore previous frame buffer - batch.setFramebuffer(deferredFrameBuffer->getDeferredFramebuffer()); // Clear it batch.clearFramebuffer( gpu::Framebuffer::BUFFER_DEPTH, vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, false); + + // Setup camera, projection and viewport for all items + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); + auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); + + std::vector skinnedShapeKeys{}; + + // Iterate through all inShapes and render the unskinned + args->_shapePipeline = shadowPipeline; + batch.setPipeline(shadowPipeline->pipeline); + for (auto items : inShapes) { + if (items.first.isSkinned()) { + skinnedShapeKeys.push_back(items.first); + } + else { + renderItems(renderContext, items.second); + } + } + + // Reiterate to render the skinned + args->_shapePipeline = shadowSkinnedPipeline; + batch.setPipeline(shadowSkinnedPipeline->pipeline); + for (const auto& key : skinnedShapeKeys) { + renderItems(renderContext, inShapes.at(key)); + } + + args->_shapePipeline = nullptr; + args->_batch = nullptr; }); output = _outlineFramebuffer; @@ -147,14 +160,14 @@ void DrawOutline::configure(const Config& config) { } void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { - auto mainFrameBuffer = inputs.get1(); + auto outlineFrameBuffer = inputs.get1(); - if (mainFrameBuffer) { + if (outlineFrameBuffer) { auto sceneDepthBuffer = inputs.get2(); const auto frameTransform = inputs.get0(); - auto outlinedDepthBuffer = mainFrameBuffer->getPrimaryDepthTexture(); + auto outlinedDepthTexture = outlineFrameBuffer->getDepthTexture(); auto destinationFrameBuffer = inputs.get3(); - auto framebufferSize = glm::ivec2(outlinedDepthBuffer->getDimensions()); + auto framebufferSize = glm::ivec2(outlinedDepthTexture->getDimensions()); if (!_primaryWithoutDepthBuffer || framebufferSize!=_frameBufferSize) { // Failing to recreate this frame buffer when the screen has been resized creates a bug on Mac @@ -191,8 +204,8 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration); batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer()); - batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getDepthTexture()); - batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthBuffer); + batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture()); + batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture); batch.draw(gpu::TRIANGLE_STRIP, 4); // Restore previous frame buffer @@ -266,7 +279,7 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const batch.setModelTransform(Transform()); batch.setPipeline(getDebugPipeline()); - batch.setResourceTexture(0, outlineFramebuffer->getPrimaryDepthTexture()); + batch.setResourceTexture(0, outlineFramebuffer->getDepthTexture()); const glm::vec4 color(1.0f, 0.5f, 0.2f, 1.0f); const glm::vec2 bottomLeft(-1.0f, -1.0f); @@ -313,59 +326,6 @@ const gpu::PipelinePointer& DebugOutline::getDebugPipeline() { return _debugPipeline; } -void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, const render::ShapeBounds& inShapes) { - assert(renderContext->args); - assert(renderContext->args->hasViewFrustum()); - - if (!inShapes.empty()) { - RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder; - - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - args->_batch = &batch; - - // Setup camera, projection and viewport for all items - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - - glm::mat4 projMat; - Transform viewMat; - args->getViewFrustum().evalProjectionMatrix(projMat); - args->getViewFrustum().evalViewTransform(viewMat); - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - - auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); - auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); - - std::vector skinnedShapeKeys{}; - - // Iterate through all inShapes and render the unskinned - args->_shapePipeline = shadowPipeline; - batch.setPipeline(shadowPipeline->pipeline); - for (auto items : inShapes) { - if (items.first.isSkinned()) { - skinnedShapeKeys.push_back(items.first); - } - else { - renderItems(renderContext, items.second); - } - } - - // Reiterate to render the skinned - args->_shapePipeline = shadowSkinnedPipeline; - batch.setPipeline(shadowSkinnedPipeline->pipeline); - for (const auto& key : skinnedShapeKeys) { - renderItems(renderContext, inShapes.at(key)); - } - - args->_shapePipeline = nullptr; - args->_batch = nullptr; - }); - } -} - DrawOutlineTask::DrawOutlineTask() { } @@ -378,7 +338,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende const auto input = inputs.get(); const auto selectedMetas = inputs.getN(0); const auto shapePlumber = input.get1(); - const auto outlinedFrameBuffer = inputs.getN(2); + const auto sceneFrameBuffer = inputs.getN(2); const auto primaryFramebuffer = inputs.getN(3); const auto deferredFrameTransform = inputs.getN(4); @@ -387,22 +347,21 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende { auto state = std::make_shared(); state->setDepthTest(true, true, gpu::LESS_EQUAL); - state->setColorWriteMask(0); + state->setColorWriteMask(false, false, false, false); initZPassPipelines(*shapePlumberZPass, state); } - const auto& outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", selectedMetas); - const auto& outlinedItems = task.addJob("OutlineMetaToSubItems", outlinedItemIDs, true); - - // Retrieve z value of the scene objects - const auto outlinePrepareInputs = PrepareOutline::Inputs(outlinedItems, outlinedFrameBuffer).asVarying(); - const auto sceneFrameBuffer = task.addJob("OutlineCopyDepth", outlinePrepareInputs); + const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", selectedMetas); + const auto outlinedItems = task.addJob("OutlineMetaToSubItems", outlinedItemIDs, true); // Sort - const auto& sortedPipelines = task.addJob("OutlinePipelineSort", outlinedItems); - const auto& sortedShapes = task.addJob("OutlineDepthSort", sortedPipelines); - task.addJob("OutlineDepth", sortedShapes, shapePlumberZPass); + const auto sortedPipelines = task.addJob("OutlinePipelineSort", outlinedItems); + const auto sortedShapes = task.addJob("OutlineDepthSort", sortedPipelines); + + // Draw depth of outlined objects in separate buffer + const auto drawOutlineDepthInputs = DrawOutlineDepth::Inputs(sortedShapes, sceneFrameBuffer).asVarying(); + const auto outlinedFrameBuffer = task.addJob("OutlineDepth", drawOutlineDepthInputs, shapePlumberZPass); // Draw outline const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, primaryFramebuffer).asVarying(); diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index 7e7cf83d19..36dc59f29e 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -24,7 +24,7 @@ public: gpu::TexturePointer getDepthTexture(); // Update the source framebuffer size which will drive the allocation of all the other resources. - void update(const gpu::TexturePointer& linearDepthBuffer); + void update(const gpu::TexturePointer& colorBuffer); const glm::ivec2& getSourceFrameSize() const { return _frameSize; } protected: @@ -40,23 +40,22 @@ protected: using OutlineFramebufferPointer = std::shared_ptr; -class PrepareOutline { - +class DrawOutlineDepth { public: - using Inputs = render::VaryingSet2; - // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer - using Output = OutlineFramebufferPointer; - using JobModel = render::Job::ModelIO; + using Inputs = render::VaryingSet2; + // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer + using Outputs = OutlineFramebufferPointer; + using JobModel = render::Job::ModelIO; - PrepareOutline() {} + DrawOutlineDepth(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void run(const render::RenderContextPointer& renderContext, const PrepareOutline::Inputs& input, PrepareOutline::Output& output); + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output); -private: +protected: + render::ShapePlumberPointer _shapePlumber; OutlineFramebufferPointer _outlineFramebuffer; - gpu::PipelinePointer _copyDepthPipeline; }; class DrawOutlineConfig : public render::Job::Config { @@ -94,7 +93,7 @@ signals: class DrawOutline { public: - using Inputs = render::VaryingSet4; + using Inputs = render::VaryingSet4; using Config = DrawOutlineConfig; using JobModel = render::Job::ModelI; @@ -147,7 +146,7 @@ signals: class DebugOutline { public: - using Inputs = DeferredFramebufferPointer; + using Inputs = OutlineFramebufferPointer; using Config = DebugOutlineConfig; using JobModel = render::Job::ModelI; @@ -166,18 +165,6 @@ private: bool _isDisplayDepthEnabled{ false }; }; -class DrawOutlineDepth { -public: - using JobModel = render::Job::ModelI; - - DrawOutlineDepth(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void run(const render::RenderContextPointer& renderContext, - const render::ShapeBounds& inShapes); - -protected: - render::ShapePlumberPointer _shapePlumber; -}; - class DrawOutlineTask { public: using Inputs = render::VaryingSet5; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index d396377969..b6e17b6fae 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -166,8 +166,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer).asVarying(); task.addJob("ToneMapping", toneMappingInputs); + const auto outlineRangeTimer = task.addJob("BeginOutlineRangeTimer", "Outline"); const auto outlineInputs = DrawOutlineTask::Inputs(selectedMetas, shapePlumber, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); task.addJob("DrawOutline", outlineInputs); + task.addJob("EndOutlineRangeTimer", outlineRangeTimer); { // DEbug the bounds of the rendered items, still look at the zbuffer task.addJob("DrawMetaBounds", metas); From 7fb7ebca5728eda7e91853bcd2b0a85c4f8542a4 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 7 Sep 2017 19:03:22 +0200 Subject: [PATCH 30/33] Fixed warning on Mac --- libraries/render-utils/src/OutlineEffect.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index dda371be80..d5b3b1c3bb 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -81,7 +81,6 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co auto& deferredFrameBuffer = inputs.get1(); if (!inShapes.empty()) { - auto frameSize = deferredFrameBuffer->getFrameSize(); RenderArgs* args = renderContext->args; ShapeKey::Builder defaultKeyBuilder; From d6d36cbd43802776946375406eaa8f0a15fb7f0c Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 8 Sep 2017 11:14:06 +0200 Subject: [PATCH 31/33] Outline working on voxels --- libraries/render-utils/src/RenderDeferredTask.cpp | 12 +++++++++--- libraries/render/src/render/FilterTask.cpp | 13 ++++++++++--- libraries/render/src/render/FilterTask.h | 9 +++++---- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index b6e17b6fae..c67a1c7875 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -95,7 +95,13 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("PrepareStencil", primaryFramebuffer); // Select items that need to be outlined - const auto selectedMetas = task.addJob("PassTestSelection", metas, "contextOverlayHighlightList"); + const auto selectionName = "contextOverlayHighlightList"; + const auto selectMetaInput = SelectItems::Inputs(metas, Varying()).asVarying(); + const auto selectedMetas = task.addJob("PassTestMetaSelection", selectMetaInput, selectionName); + const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas).asVarying(); + const auto selectedMetasAndOpaques = task.addJob("PassTestOpaqueSelection", selectMetaAndOpaqueInput, selectionName); + const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques).asVarying(); + const auto selectedItems = task.addJob("PassTestTransparentSelection", selectItemInput, selectionName); // Render opaque objects in DeferredBuffer const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).asVarying(); @@ -167,7 +173,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("ToneMapping", toneMappingInputs); const auto outlineRangeTimer = task.addJob("BeginOutlineRangeTimer", "Outline"); - const auto outlineInputs = DrawOutlineTask::Inputs(selectedMetas, shapePlumber, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); + const auto outlineInputs = DrawOutlineTask::Inputs(selectedItems, shapePlumber, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); task.addJob("DrawOutline", outlineInputs); task.addJob("EndOutlineRangeTimer", outlineRangeTimer); @@ -221,7 +227,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawZoneStack", deferredFrameTransform); // Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true - task.addJob("DrawSelectionBounds", selectedMetas); + task.addJob("DrawSelectionBounds", selectedItems); } // AA job to be revisited diff --git a/libraries/render/src/render/FilterTask.cpp b/libraries/render/src/render/FilterTask.cpp index 39bc19adc7..e0298c2a44 100644 --- a/libraries/render/src/render/FilterTask.cpp +++ b/libraries/render/src/render/FilterTask.cpp @@ -51,13 +51,20 @@ void SliceItems::run(const RenderContextPointer& renderContext, const ItemBounds } -void SelectItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { +void SelectItems::run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems) { auto selection = renderContext->_scene->getSelection(_name); const auto& selectedItems = selection.getItems(); - outItems.clear(); + const auto& inItems = inputs.get0(); + const auto itemsToAppend = inputs[1]; + + if (itemsToAppend.isNull()) { + outItems.clear(); + } else { + outItems = itemsToAppend.get(); + } if (!selectedItems.empty()) { - outItems.reserve(selectedItems.size()); + outItems.reserve(outItems.size()+selectedItems.size()); for (auto src : inItems) { if (selection.contains(src.id)) { diff --git a/libraries/render/src/render/FilterTask.h b/libraries/render/src/render/FilterTask.h index 2f8b53722f..1e023a8bb9 100644 --- a/libraries/render/src/render/FilterTask.h +++ b/libraries/render/src/render/FilterTask.h @@ -113,22 +113,23 @@ namespace render { // Keep items belonging to the job selection class SelectItems { public: - using JobModel = Job::ModelIO; + using Inputs = VaryingSet2; + using JobModel = Job::ModelIO; std::string _name; SelectItems(const Selection::Name& name) : _name(name) {} - void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems); + void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems); }; // Same as SelectItems but reorder the output to match the selection order class SelectSortItems { public: using JobModel = Job::ModelIO; - + std::string _name; SelectSortItems(const Selection::Name& name) : _name(name) {} - + void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems); }; From 559ac6786d14b3c406d6baa17bf86b79b795ca78 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 8 Sep 2017 11:44:06 -0700 Subject: [PATCH 32/33] Fix MyAvatar getting stuck in T-pose on loading Before this change, there was a race condition between the main thread calling Model::initWhenReady, and the render thread calling Avatar::fixupModelsInScene(). They both would end up setting the Model::_addedToScene flag. This race caused Model::initWhenReady() to never return true, which resulted in the MyAvatar class never initializing the animation system. --- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 7f4ebf39e1..bc6bb2a0ec 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -648,7 +648,9 @@ void Avatar::render(RenderArgs* renderArgs) { return; } - fixupModelsInScene(renderArgs->_scene); + if (!isMyAvatar()) { + fixupModelsInScene(renderArgs->_scene); + } if (showCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); From 967d3f69d3dfa7ff54faedf358f761bc75eb33f2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 8 Sep 2017 14:13:58 -0700 Subject: [PATCH 33/33] suppress repeated 'item could not be rendered' messages --- libraries/render/src/render/DrawTask.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 8372231597..710507bd79 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "DrawTask.h" #include "Logging.h" @@ -48,12 +50,14 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons if (args->_shapePipeline) { args->_shapePipeline->prepareShapeItem(args, key, item); item.render(args); - } + } args->_shapePipeline = nullptr; } else if (key.hasOwnPipeline()) { item.render(args); } else { qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key; + static QString repeatedCouldNotBeRendered = LogHandler::getInstance().addRepeatedMessageRegex( + "Item could not be rendered with invalid key.*"); } args->_itemShapeKey = 0; } @@ -62,7 +66,7 @@ void render::renderShapes(const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems, const ShapeKey& globalKey) { auto& scene = renderContext->_scene; RenderArgs* args = renderContext->args; - + int numItemsToDraw = (int)inItems.size(); if (maxDrawnItems != -1) { numItemsToDraw = glm::min(numItemsToDraw, maxDrawnItems); @@ -104,6 +108,8 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext, } else if (key.hasOwnPipeline()) { ownPipelineBucket.push_back( std::make_tuple(item, key) ); } else { + static QString repeatedCouldNotBeRendered = LogHandler::getInstance().addRepeatedMessageRegex( + "Item could not be rendered with invalid key.*"); qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key; } } @@ -113,7 +119,7 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext, for (auto& pipelineKey : sortedPipelines) { auto& bucket = sortedShapes[pipelineKey]; args->_shapePipeline = shapeContext->pickPipeline(args, pipelineKey); - if (!args->_shapePipeline) { + if (!args->_shapePipeline) { continue; } args->_itemShapeKey = pipelineKey._flags.to_ulong(); @@ -182,7 +188,7 @@ void DrawBounds::run(const RenderContextPointer& renderContext, if (!_drawBuffer) { _drawBuffer = std::make_shared(sizeOfItemBound); } - + _drawBuffer->setData(numItems * sizeOfItemBound, (const gpu::Byte*) items.data()); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {