From 2658d658148ce359ebd9fd6903bafce0747dcc5d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 13 Oct 2017 12:02:21 +0200 Subject: [PATCH] Preparing for outline color mask --- libraries/render-utils/src/OutlineEffect.cpp | 145 ++++++++++++------ libraries/render-utils/src/OutlineEffect.h | 20 ++- .../render-utils/src/RenderDeferredTask.cpp | 2 +- libraries/render-utils/src/model_outline.slf | 21 +++ .../render-utils/src/model_outline_fade.slf | 31 ++++ .../developer/utilities/render/outline.qml | 6 +- 6 files changed, 166 insertions(+), 59 deletions(-) create mode 100644 libraries/render-utils/src/model_outline.slf create mode 100644 libraries/render-utils/src/model_outline_fade.slf diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index 375ba462b9..68f1759437 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -76,7 +76,7 @@ gpu::TexturePointer OutlineRessources::getDepthTexture() { return _depthTexture; } -gpu::TexturePointer OutlineRessources::getIDTexture() { +gpu::TexturePointer OutlineRessources::getIdTexture() { if (!_idTexture) { allocate(); } @@ -123,10 +123,13 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); std::vector skinnedShapeKeys{}; + auto colorLoc = maskPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color"); + glm::vec4 idColor{ 1.0f, 0.0f, 0.0f, 0.0f }; // Iterate through all inShapes and render the unskinned args->_shapePipeline = maskPipeline; batch.setPipeline(maskPipeline->pipeline); + batch._glUniform4f(colorLoc, idColor.r, idColor.g, idColor.b, idColor.a); for (auto items : inShapes) { if (items.first.isSkinned()) { skinnedShapeKeys.push_back(items.first); @@ -136,9 +139,11 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con } } + colorLoc = maskSkinnedPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color"); // Reiterate to render the skinned args->_shapePipeline = maskSkinnedPipeline; batch.setPipeline(maskSkinnedPipeline->pipeline); + batch._glUniform4f(colorLoc, idColor.r, idColor.g, idColor.b, idColor.a); for (const auto& key : skinnedShapeKeys) { renderItems(renderContext, inShapes.at(key)); } @@ -250,24 +255,26 @@ const gpu::PipelinePointer& DrawOutline::getPipeline(bool isFilled) { } DebugOutline::DebugOutline() { - _geometryId = DependencyManager::get()->allocateID(); + _geometryDepthId = DependencyManager::get()->allocateID(); + _geometryColorId = DependencyManager::get()->allocateID(); } DebugOutline::~DebugOutline() { auto geometryCache = DependencyManager::get(); if (geometryCache) { - geometryCache->releaseID(_geometryId); + geometryCache->releaseID(_geometryDepthId); + geometryCache->releaseID(_geometryColorId); } } void DebugOutline::configure(const Config& config) { - _isDisplayDepthEnabled = config.viewOutlinedDepth; + _isDisplayEnabled = config.viewMask; } void DebugOutline::run(const render::RenderContextPointer& renderContext, const Inputs& input) { const auto outlineFramebuffer = input; - if (_isDisplayDepthEnabled && outlineFramebuffer) { + if (_isDisplayEnabled && outlineFramebuffer) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; @@ -286,52 +293,101 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const batch.setViewTransform(viewMat, true); batch.setModelTransform(Transform()); - batch.setPipeline(getDebugPipeline()); - batch.setResourceTexture(0, outlineFramebuffer->getDepthTexture()); + const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); - 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.setPipeline(getDepthPipeline()); + batch.setResourceTexture(0, outlineFramebuffer->getDepthTexture()); + { + const glm::vec2 bottomLeft(-1.0f, -1.0f); + const glm::vec2 topRight(0.0f, 1.0f); + geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryDepthId); + } + + batch.setPipeline(getIdPipeline()); + batch.setResourceTexture(0, outlineFramebuffer->getIdTexture()); + { + const glm::vec2 bottomLeft(0.0f, -1.0f); + const glm::vec2 topRight(1.0f, 1.0f); + geometryBuffer->renderQuad(batch, bottomLeft, topRight, color, _geometryColorId); + } 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{ +void DebugOutline::initializePipelines() { + 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"); + + auto state = std::make_shared(); + state->setDepthTest(gpu::State::DepthTest(false)); + + const auto vs = gpu::Shader::createVertex(VERTEX_SHADER); + + // Depth shader + { + static const std::string DEPTH_SHADER{ "vec4 getFragmentColor() {" " float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;" " Zdb = 1.0-(1.0-Zdb)*100;" - " return vec4(Zdb, Zdb, Zdb, 1.0);" - " }" + " return vec4(Zdb, Zdb, Zdb, 1.0); " + "}" }; - auto bakedFragmentShader = FRAGMENT_SHADER; - bakedFragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(), DEFAULT_DEPTH_SHADER); + auto fragmentShader = FRAGMENT_SHADER; + fragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(), DEPTH_SHADER); - static const auto vs = gpu::Shader::createVertex(VERTEX_SHADER); - const auto ps = gpu::Shader::createPixel(bakedFragmentShader); + const auto ps = gpu::Shader::createPixel(fragmentShader); 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)); - _debugPipeline = gpu::Pipeline::create(program, state); + _depthPipeline = gpu::Pipeline::create(program, state); } - return _debugPipeline; + // ID shader + { + static const std::string ID_SHADER{ + "vec4 getFragmentColor() {" + " return texelFetch(albedoMap, ivec2(gl_FragCoord.xy), 0); " + "}" + }; + + auto fragmentShader = FRAGMENT_SHADER; + fragmentShader.replace(SOURCE_PLACEHOLDER_INDEX, SOURCE_PLACEHOLDER.size(), ID_SHADER); + + const auto ps = gpu::Shader::createPixel(fragmentShader); + const auto program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding("albedoMap", 0)); + gpu::Shader::makeProgram(*program, slotBindings); + + _idPipeline = gpu::Pipeline::create(program, state); + } +} + +const gpu::PipelinePointer& DebugOutline::getDepthPipeline() { + if (!_depthPipeline) { + initializePipelines(); + } + + return _depthPipeline; +} + +const gpu::PipelinePointer& DebugOutline::getIdPipeline() { + if (!_idPipeline) { + initializePipelines(); + } + + return _idPipeline; } DrawOutlineTask::DrawOutlineTask() { @@ -345,19 +401,18 @@ 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 sceneFrameBuffer = inputs.getN(2); - const auto primaryFramebuffer = inputs.getN(3); - const auto deferredFrameTransform = inputs.getN(4); + const auto sceneFrameBuffer = inputs.getN(1); + const auto primaryFramebuffer = inputs.getN(2); + const auto deferredFrameTransform = inputs.getN(3); // Prepare the ShapePipeline - ShapePlumberPointer shapePlumberZPass = std::make_shared(); + ShapePlumberPointer shapePlumber = std::make_shared(); { auto state = std::make_shared(); state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setColorWriteMask(false, false, false, false); - initMaskPipelines(*shapePlumberZPass, state); + initMaskPipelines(*shapePlumber, state); } const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", selectedMetas); @@ -369,7 +424,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende // Draw depth of outlined objects in separate buffer const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedShapes, sceneFrameBuffer).asVarying(); - const auto outlinedFrameBuffer = task.addJob("OutlineMask", drawMaskInputs, shapePlumberZPass); + const auto outlinedFrameBuffer = task.addJob("OutlineMask", drawMaskInputs, shapePlumber); // Draw outline const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, primaryFramebuffer).asVarying(); @@ -384,36 +439,32 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende #include "skin_model_shadow_vert.h" #include "skin_model_shadow_fade_vert.h" -#include "model_shadow_frag.h" -#include "model_shadow_fade_frag.h" -#include "skin_model_shadow_frag.h" -#include "skin_model_shadow_fade_frag.h" +#include "model_outline_frag.h" +#include "model_outline_fade_frag.h" void DrawOutlineTask::initMaskPipelines(render::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)); + auto modelPixel = gpu::Shader::createPixel(std::string(model_outline_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); + gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, modelPixel); 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)); + auto modelFadePixel = gpu::Shader::createPixel(std::string(model_outline_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); + gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skinFadeVertex, modelFadePixel); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withSkinned().withFade(), skinFadeProgram, state); diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index b04f102a83..511ed4a992 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -21,7 +21,7 @@ public: OutlineRessources(); gpu::FramebufferPointer getFramebuffer(); - gpu::TexturePointer getIDTexture(); + gpu::TexturePointer getIdTexture(); gpu::TexturePointer getDepthTexture(); // Update the source framebuffer size which will drive the allocation of all the other resources. @@ -136,11 +136,11 @@ private: class DebugOutlineConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(bool viewOutlinedDepth MEMBER viewOutlinedDepth NOTIFY dirty) + Q_PROPERTY(bool viewMask MEMBER viewMask NOTIFY dirty) public: - bool viewOutlinedDepth{ false }; + bool viewMask{ false }; signals: void dirty(); @@ -160,16 +160,20 @@ public: private: - const gpu::PipelinePointer& getDebugPipeline(); + gpu::PipelinePointer _depthPipeline; + gpu::PipelinePointer _idPipeline; + int _geometryDepthId{ 0 }; + int _geometryColorId{ 0 }; + bool _isDisplayEnabled{ false }; - gpu::PipelinePointer _debugPipeline; - int _geometryId{ 0 }; - bool _isDisplayDepthEnabled{ false }; + const gpu::PipelinePointer& getDepthPipeline(); + const gpu::PipelinePointer& getIdPipeline(); + void initializePipelines(); }; class DrawOutlineTask { public: - using Inputs = render::VaryingSet5; + using Inputs = render::VaryingSet4; 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 45e6fd4ba4..1739f67748 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -173,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(selectedItems, shapePlumber, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); + const auto outlineInputs = DrawOutlineTask::Inputs(selectedItems, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying(); task.addJob("DrawOutline", outlineInputs); task.addJob("EndOutlineRangeTimer", outlineRangeTimer); diff --git a/libraries/render-utils/src/model_outline.slf b/libraries/render-utils/src/model_outline.slf new file mode 100644 index 0000000000..8c11b2b295 --- /dev/null +++ b/libraries/render-utils/src/model_outline.slf @@ -0,0 +1,21 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_outline.frag +// fragment shader +// +// Created by Olivier Prat on 10/13/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 +// + +layout(location = 0) out vec4 _fragColor; + +uniform vec4 color; + +void main(void) { + _fragColor = color; +} diff --git a/libraries/render-utils/src/model_outline_fade.slf b/libraries/render-utils/src/model_outline_fade.slf new file mode 100644 index 0000000000..69ff54dea6 --- /dev/null +++ b/libraries/render-utils/src/model_outline_fade.slf @@ -0,0 +1,31 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_outline_fade.frag +// fragment shader +// +// Created by Olivier Prat on 10/13/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 Fade.slh@> +<$declareFadeFragment()$> + +layout(location = 0) out vec4 _fragColor; + +uniform vec4 color; + +in vec4 _worldPosition; + +void main(void) { + FadeObjectParams fadeParams; + + <$fetchFadeObjectParams(fadeParams)$> + applyFadeClip(fadeParams, _worldPosition.xyz); + + _fragColor = color; +} diff --git a/scripts/developer/utilities/render/outline.qml b/scripts/developer/utilities/render/outline.qml index e17f7c1f1c..1b5cbf6e1c 100644 --- a/scripts/developer/utilities/render/outline.qml +++ b/scripts/developer/utilities/render/outline.qml @@ -21,10 +21,10 @@ Item { spacing: 8 CheckBox { - text: "View Outlined Depth" - checked: root.debugConfig["viewOutlinedDepth"] + text: "View Mask" + checked: root.debugConfig["viewMask"] onCheckedChanged: { - root.debugConfig["viewOutlinedDepth"] = checked; + root.debugConfig["viewMask"] = checked; } } CheckBox {