Added OutlineStyleStage

This commit is contained in:
Olivier Prat 2017-11-06 15:55:57 +01:00
parent 09ee69db30
commit 9e6472b577
13 changed files with 427 additions and 119 deletions

View file

@ -68,11 +68,15 @@ ContextOverlayInterface::ContextOverlayInterface() {
connect(&qApp->getOverlays(), &Overlays::hoverEnterOverlay, this, &ContextOverlayInterface::contextOverlays_hoverEnterOverlay);
connect(&qApp->getOverlays(), &Overlays::hoverLeaveOverlay, this, &ContextOverlayInterface::contextOverlays_hoverLeaveOverlay);
_selectionToSceneHandlers[0].initialize("contextOverlayHighlightList");
connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandlers[0], &SelectionToSceneHandler::selectedItemsListChanged);
for (auto i = 1; i < render::Scene::MAX_OUTLINE_COUNT; i++) {
_selectionToSceneHandlers[i].initialize(QString("contextOverlayHighlightList") + QString::number(i));
connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandlers[i], &SelectionToSceneHandler::selectedItemsListChanged);
{
render::Transaction transaction;
initializeSelectionToSceneHandler(_selectionToSceneHandlers[0], "contextOverlayHighlightList", transaction);
for (auto i = 1; i < MAX_SELECTION_COUNT; i++) {
auto selectionName = QString("contextOverlayHighlightList") + QString::number(i);
initializeSelectionToSceneHandler(_selectionToSceneHandlers[i], selectionName, transaction);
}
const render::ScenePointer& scene = qApp->getMain3DScene();
scene->enqueueTransaction(transaction);
}
auto nodeList = DependencyManager::get<NodeList>();
@ -81,6 +85,12 @@ ContextOverlayInterface::ContextOverlayInterface() {
_challengeOwnershipTimeoutTimer.setSingleShot(true);
}
void ContextOverlayInterface::initializeSelectionToSceneHandler(SelectionToSceneHandler& handler, const QString& selectionName, render::Transaction& transaction) {
handler.initialize(selectionName);
connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &handler, &SelectionToSceneHandler::selectedItemsListChanged);
transaction.resetSelectionOutline(selectionName.toStdString());
}
static const uint32_t MOUSE_HW_ID = 0;
static const uint32_t LEFT_HAND_HW_ID = 1;
static const xColor CONTEXT_OVERLAY_COLOR = { 255, 255, 255 };

View file

@ -76,6 +76,11 @@ private slots:
void handleChallengeOwnershipReplyPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
private:
enum {
MAX_SELECTION_COUNT = 16
};
bool _verboseLogging { true };
bool _enabled { true };
EntityItemID _currentEntityWithContextOverlay{};
@ -91,8 +96,9 @@ private:
void disableEntityHighlight(const EntityItemID& entityItemID);
void deletingEntity(const EntityItemID& entityItemID);
void initializeSelectionToSceneHandler(SelectionToSceneHandler& handler, const QString& selectionName, render::Transaction& transaction);
SelectionToSceneHandler _selectionToSceneHandlers[render::Scene::MAX_OUTLINE_COUNT];
SelectionToSceneHandler _selectionToSceneHandlers[MAX_SELECTION_COUNT];
Q_INVOKABLE void startChallengeOwnershipTimer();
QTimer _challengeOwnershipTimeoutTimer;

View file

@ -83,7 +83,11 @@ gpu::FramebufferPointer OutlineRessources::getColorFramebuffer() {
}
OutlineSharedParameters::OutlineSharedParameters() {
std::fill(_blurPixelWidths.begin(), _blurPixelWidths.end(), 0);
_outlineIds.fill(render::OutlineStyleStage::INVALID_INDEX);
}
float OutlineSharedParameters::getBlurPixelWidth(const render::OutlineStyle& style, int frameBufferHeight) {
return ceilf(style.width * frameBufferHeight / 400.0f);
}
PrepareDrawOutline::PrepareDrawOutline() {
@ -141,8 +145,12 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con
_boundsBuffer = std::make_shared<gpu::Buffer>(sizeof(render::ItemBound));
}
if (!inShapes.empty()) {
auto outlineStage = renderContext->_scene->getStage<render::OutlineStyleStage>(render::OutlineStyleStage::getName());
auto outlineId = _sharedParameters->_outlineIds[_outlineIndex];
if (!inShapes.empty() && !render::OutlineStyleStage::isIndexInvalid(outlineId)) {
auto ressources = inputs.get1();
auto& outline = outlineStage->getOutline(outlineId);
RenderArgs* args = renderContext->args;
ShapeKey::Builder defaultKeyBuilder;
@ -213,10 +221,10 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con
// Draw stencil mask with object bounding boxes
const auto outlineWidthLoc = _stencilMaskPipeline->getProgram()->getUniforms().findLocation("outlineWidth");
const auto sqrt3 = 1.74f;
const float blurPixelWidth = 2.0f * sqrt3 *_sharedParameters->_blurPixelWidths[_outlineIndex];
const float blurPixelWidth = 2.0f * sqrt3 * OutlineSharedParameters::getBlurPixelWidth(outline._style, args->_viewport.w);
const auto framebufferSize = ressources->getSourceFrameSize();
auto stencilPipeline = _sharedParameters->_isFilled.test(_outlineIndex) ? _stencilMaskFillPipeline : _stencilMaskPipeline;
auto stencilPipeline = outline._style.isFilled() ? _stencilMaskFillPipeline : _stencilMaskPipeline;
batch.setPipeline(stencilPipeline);
batch.setResourceBuffer(0, _boundsBuffer);
batch._glUniform2f(outlineWidthLoc, blurPixelWidth / framebufferSize.x, blurPixelWidth / framebufferSize.y);
@ -237,24 +245,6 @@ DrawOutline::DrawOutline(unsigned int outlineIndex, OutlineSharedParametersPoint
_sharedParameters{ parameters } {
}
void DrawOutline::configure(const Config& config) {
const auto OPACITY_EPSILON = 5e-3f;
_parameters._color = config.color;
_parameters._intensity = config.intensity * (config.glow ? 2.0f : 1.0f);
_parameters._unoccludedFillOpacity = config.unoccludedFillOpacity;
_parameters._occludedFillOpacity = config.occludedFillOpacity;
_parameters._threshold = config.glow ? 1.0f : 1e-3f;
_parameters._blurKernelSize = std::min(7, std::max(2, (int)floorf(config.width * 3 + 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.0f;
_parameters._size.x = (_size * _framebufferSize.y) / _framebufferSize.x;
_parameters._size.y = _size;
_sharedParameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y);
_sharedParameters->_isFilled.set(_outlineIndex, (config.unoccludedFillOpacity > OPACITY_EPSILON || config.occludedFillOpacity > OPACITY_EPSILON));
_configuration.edit() = _parameters;
}
void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
auto outlineFrameBuffer = inputs.get1();
auto outlineRect = inputs.get3();
@ -267,39 +257,50 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I
auto framebufferSize = glm::ivec2(outlinedDepthTexture->getDimensions());
if (sceneDepthBuffer) {
auto pipeline = getPipeline();
auto args = renderContext->args;
if (_framebufferSize != framebufferSize)
{
_parameters._size.x = (_size * framebufferSize.y) / framebufferSize.x;
_parameters._size.y = _size;
_framebufferSize = framebufferSize;
_sharedParameters->_blurPixelWidths[_outlineIndex] = (int)ceilf(_size * _framebufferSize.y);
_configuration.edit() = _parameters;
auto outlineStage = renderContext->_scene->getStage<render::OutlineStyleStage>(render::OutlineStyleStage::getName());
auto outlineId = _sharedParameters->_outlineIds[_outlineIndex];
if (!render::OutlineStyleStage::isIndexInvalid(outlineId)) {
auto& outline = outlineStage->getOutline(_sharedParameters->_outlineIds[_outlineIndex]);
auto pipeline = getPipeline(outline._style);
{
auto& shaderParameters = _configuration.edit();
shaderParameters._color = outline._style.color;
shaderParameters._intensity = outline._style.intensity * (outline._style.glow ? 2.0f : 1.0f);
shaderParameters._unoccludedFillOpacity = outline._style.unoccludedFillOpacity;
shaderParameters._occludedFillOpacity = outline._style.occludedFillOpacity;
shaderParameters._threshold = outline._style.glow ? 1.0f : 1e-3f;
shaderParameters._blurKernelSize = std::min(7, std::max(2, (int)floorf(outline._style.width * 3 + 0.5f)));
// Size is in normalized screen height. We decide that for outline width = 1, this is equal to 1/400.
auto size = outline._style.width / 400.0f;
shaderParameters._size.x = (size * framebufferSize.y) / framebufferSize.x;
shaderParameters._size.y = size;
}
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
batch.enableStereo(false);
batch.setFramebuffer(destinationFrameBuffer);
batch.setViewportTransform(args->_viewport);
batch.setProjectionTransform(glm::mat4());
batch.resetViewTransform();
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport));
batch.setPipeline(pipeline);
batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration);
batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer());
batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture());
batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture);
batch.draw(gpu::TRIANGLE_STRIP, 4);
});
}
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
batch.enableStereo(false);
batch.setFramebuffer(destinationFrameBuffer);
batch.setViewportTransform(args->_viewport);
batch.setProjectionTransform(glm::mat4());
batch.resetViewTransform();
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport));
batch.setPipeline(pipeline);
batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration);
batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer());
batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture());
batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture);
batch.draw(gpu::TRIANGLE_STRIP, 4);
});
}
}
}
const gpu::PipelinePointer& DrawOutline::getPipeline() {
const gpu::PipelinePointer& DrawOutline::getPipeline(const render::OutlineStyle& style) {
if (!_pipeline) {
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setDepthTest(gpu::State::DepthTest(false, false));
@ -324,7 +325,7 @@ const gpu::PipelinePointer& DrawOutline::getPipeline() {
gpu::Shader::makeProgram(*program, slotBindings);
_pipelineFilled = gpu::Pipeline::create(program, state);
}
return _sharedParameters->_isFilled.test(_outlineIndex) ? _pipelineFilled : _pipeline;
return style.isFilled() ? _pipelineFilled : _pipeline;
}
DebugOutline::DebugOutline() {
@ -424,6 +425,35 @@ const gpu::PipelinePointer& DebugOutline::getDepthPipeline() {
return _depthPipeline;
}
void SelectionToOutline::run(const render::RenderContextPointer& renderContext, Outputs& outputs) {
auto outlineStage = renderContext->_scene->getStage<render::OutlineStyleStage>(render::OutlineStyleStage::getName());
outputs.clear();
_sharedParameters->_outlineIds.fill(render::OutlineStyleStage::INVALID_INDEX);
for (auto i = 0; i < OutlineSharedParameters::MAX_OUTLINE_COUNT; i++) {
std::ostringstream stream;
stream << "contextOverlayHighlightList";
if (i > 0) {
stream << i;
}
auto selectionName = stream.str();
auto outlineId = outlineStage->getOutlineIdBySelection(selectionName);
if (!render::OutlineStyleStage::isIndexInvalid(outlineId)) {
_sharedParameters->_outlineIds[outputs.size()] = outlineId;
outputs.emplace_back(selectionName);
}
}
}
void ExtractSelectionName::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
if (_outlineIndex < inputs.size()) {
outputs = inputs[_outlineIndex];
} else {
outputs.clear();
}
}
DrawOutlineTask::DrawOutlineTask() {
}
@ -433,7 +463,7 @@ void DrawOutlineTask::configure(const Config& config) {
}
void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) {
const auto groups = inputs.getN<Inputs>(0).get<Groups>();
const auto items = inputs.getN<Inputs>(0).get<RenderFetchCullSortTask::BucketList>();
const auto sceneFrameBuffer = inputs.getN<Inputs>(1);
const auto primaryFramebuffer = inputs.getN<Inputs>(2);
const auto deferredFrameTransform = inputs.getN<Inputs>(3);
@ -449,12 +479,15 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende
}
auto sharedParameters = std::make_shared<OutlineSharedParameters>();
const auto outlineSelectionNames = task.addJob<SelectionToOutline>("SelectionToOutline", sharedParameters);
// Prepare for outline group rendering.
const auto outlineRessources = task.addJob<PrepareDrawOutline>("PrepareOutline", primaryFramebuffer);
render::Varying outline0Rect;
for (auto i = 0; i < render::Scene::MAX_OUTLINE_COUNT; i++) {
const auto groupItems = groups[i];
for (auto i = 0; i < OutlineSharedParameters::MAX_OUTLINE_COUNT; i++) {
const auto selectionName = task.addJob<ExtractSelectionName>("ExtractSelectionName", outlineSelectionNames, i);
const auto groupItems = addSelectItemJobs(task, selectionName, items);
const auto outlinedItemIDs = task.addJob<render::MetaToSubItems>("OutlineMetaToSubItemIDs", groupItems);
const auto outlinedItems = task.addJob<render::IDsToBounds>("OutlineMetaToSubItems", outlinedItemIDs);
@ -490,6 +523,20 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende
task.addJob<DebugOutline>("OutlineDebug", debugInputs);
}
const render::Varying DrawOutlineTask::addSelectItemJobs(JobModel& task, const render::Varying& selectionName,
const RenderFetchCullSortTask::BucketList& items) {
const auto& opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE];
const auto& transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE];
const auto& metas = items[RenderFetchCullSortTask::META];
const auto selectMetaInput = SelectItems::Inputs(metas, Varying(), selectionName).asVarying();
const auto selectedMetas = task.addJob<SelectItems>("MetaSelection", selectMetaInput);
const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas, selectionName).asVarying();
const auto selectedMetasAndOpaques = task.addJob<SelectItems>("OpaqueSelection", selectMetaAndOpaqueInput);
const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques, selectionName).asVarying();
return task.addJob<SelectItems>("TransparentSelection", selectItemInput);
}
#include "model_shadow_vert.h"
#include "skin_model_shadow_vert.h"

View file

@ -13,6 +13,9 @@
#define hifi_render_utils_OutlineEffect_h
#include <render/Engine.h>
#include <render/OutlineStyleStage.h>
#include <render/RenderFetchCullSortTask.h>
#include "DeferredFramebuffer.h"
#include "DeferredFrameTransform.h"
@ -46,10 +49,15 @@ using OutlineRessourcesPointer = std::shared_ptr<OutlineRessources>;
class OutlineSharedParameters {
public:
enum {
MAX_OUTLINE_COUNT = 8
};
OutlineSharedParameters();
std::array<int, render::Scene::MAX_OUTLINE_COUNT> _blurPixelWidths;
std::bitset<render::Scene::MAX_OUTLINE_COUNT> _isFilled;
std::array<render::OutlineStyleStage::Index, MAX_OUTLINE_COUNT> _outlineIds;
static float getBlurPixelWidth(const render::OutlineStyle& style, int frameBufferHeight);
};
using OutlineSharedParametersPointer = std::shared_ptr<OutlineSharedParameters>;
@ -70,6 +78,38 @@ private:
};
class SelectionToOutline {
public:
using Outputs = std::vector<std::string>;
using JobModel = render::Job::ModelO<SelectionToOutline, Outputs>;
SelectionToOutline(OutlineSharedParametersPointer parameters) : _sharedParameters{ parameters } {}
void run(const render::RenderContextPointer& renderContext, Outputs& outputs);
private:
OutlineSharedParametersPointer _sharedParameters;
};
class ExtractSelectionName {
public:
using Inputs = SelectionToOutline::Outputs;
using Outputs = std::string;
using JobModel = render::Job::ModelIO<ExtractSelectionName, Inputs, Outputs>;
ExtractSelectionName(unsigned int outlineIndex) : _outlineIndex{ outlineIndex } {}
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs);
private:
unsigned int _outlineIndex;
};
class DrawOutlineMask {
public:
@ -92,49 +132,15 @@ protected:
static gpu::PipelinePointer _stencilMaskFillPipeline;
};
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 unoccludedFillOpacity MEMBER unoccludedFillOpacity NOTIFY dirty)
Q_PROPERTY(float occludedFillOpacity MEMBER occludedFillOpacity NOTIFY dirty)
public:
void setColorR(float value) { color.r = value; emit dirty(); }
float getColorR() const { return color.r; }
void setColorG(float value) { color.g = value; emit dirty(); }
float getColorG() const { return color.g; }
void setColorB(float value) { color.b = value; emit dirty(); }
float getColorB() const { return color.b; }
glm::vec3 color{ 1.f, 0.7f, 0.2f };
float width{ 2.0f };
float intensity{ 0.9f };
float unoccludedFillOpacity{ 0.0f };
float occludedFillOpacity{ 0.0f };
bool glow{ false };
signals:
void dirty();
};
class DrawOutline {
public:
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, OutlineRessourcesPointer, DeferredFramebufferPointer, glm::ivec4>;
using Config = DrawOutlineConfig;
using Config = render::Job::Config;
using JobModel = render::Job::ModelI<DrawOutline, Inputs, Config>;
DrawOutline(unsigned int outlineIndex, OutlineSharedParametersPointer parameters);
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
private:
@ -151,7 +157,7 @@ private:
using OutlineConfigurationBuffer = gpu::StructBuffer<OutlineParameters>;
const gpu::PipelinePointer& getPipeline();
static const gpu::PipelinePointer& getPipeline(const render::OutlineStyle& style);
static gpu::PipelinePointer _pipeline;
static gpu::PipelinePointer _pipelineFilled;
@ -160,8 +166,6 @@ private:
OutlineParameters _parameters;
OutlineSharedParametersPointer _sharedParameters;
OutlineConfigurationBuffer _configuration;
glm::ivec2 _framebufferSize{ 0,0 };
float _size;
};
class DebugOutlineConfig : public render::Job::Config {
@ -201,8 +205,7 @@ private:
class DrawOutlineTask {
public:
using Groups = render::VaryingArray<render::ItemBounds, render::Scene::MAX_OUTLINE_COUNT>;
using Inputs = render::VaryingSet4<Groups, DeferredFramebufferPointer, gpu::FramebufferPointer, DeferredFrameTransformPointer>;
using Inputs = render::VaryingSet4<RenderFetchCullSortTask::BucketList, DeferredFramebufferPointer, gpu::FramebufferPointer, DeferredFrameTransformPointer>;
using Config = render::Task::Config;
using JobModel = render::Task::ModelI<DrawOutlineTask, Inputs, Config>;
@ -214,6 +217,8 @@ public:
private:
static void initMaskPipelines(render::ShapePlumber& plumber, gpu::StatePointer state);
static const render::Varying addSelectItemJobs(JobModel& task, const render::Varying& selectionName, const RenderFetchCullSortTask::BucketList& items);
};
#endif // hifi_render_utils_OutlineEffect_h

View file

@ -64,11 +64,11 @@ const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, cons
const render::Varying& metas,
const render::Varying& opaques,
const render::Varying& transparents) {
const auto selectMetaInput = SelectItems::Inputs(metas, Varying()).asVarying();
const auto selectMetaInput = SelectItems::Inputs(metas, Varying(), std::string()).asVarying();
const auto selectedMetas = task.addJob<SelectItems>("MetaSelection", selectMetaInput, selectionName);
const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas).asVarying();
const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas, std::string()).asVarying();
const auto selectedMetasAndOpaques = task.addJob<SelectItems>("OpaqueSelection", selectMetaAndOpaqueInput, selectionName);
const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques).asVarying();
const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques, std::string()).asVarying();
return task.addJob<SelectItems>("TransparentSelection", selectItemInput, selectionName);
}
@ -187,16 +187,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
// Select items that need to be outlined
const auto selectionBaseName = "contextOverlayHighlightList";
const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents);
DrawOutlineTask::Groups outlineGroups;
outlineGroups[0] = selectedItems;
for (auto i = 1; i < render::Scene::MAX_OUTLINE_COUNT; i++) {
std::ostringstream selectionName;
selectionName << selectionBaseName;
selectionName << i;
outlineGroups[i] = addSelectItemJobs(task, selectionName.str().c_str(), metas, opaques, transparents);
}
const auto outlineInputs = DrawOutlineTask::Inputs(outlineGroups, deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying();
const auto outlineInputs = DrawOutlineTask::Inputs(items.get0(), deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying();
task.addJob<DrawOutlineTask>("DrawOutline", outlineInputs);
task.addJob<EndGPURangeTimer>("OutlineRangeTimer", outlineRangeTimer);

View file

@ -15,6 +15,7 @@
#include "BackgroundStage.h"
#include "HazeStage.h"
#include <render/TransitionStage.h>
#include <render/OutlineStyleStage.h>
#include "DeferredLightingEffect.h"
void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
@ -22,6 +23,7 @@ void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render
task.addJob<BackgroundStageSetup>("BackgroundStageSetup");
task.addJob<HazeStageSetup>("HazeStageSetup");
task.addJob<render::TransitionStageSetup>("TransitionStageSetup");
task.addJob<render::OutlineStyleStageSetup>("OutlineStyleStageSetup");
task.addJob<DefaultLightingSetup>("DefaultLightingSetup");

View file

@ -57,7 +57,12 @@ void SliceItems::run(const RenderContextPointer& renderContext, const ItemBounds
}
void SelectItems::run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems) {
auto selection = renderContext->_scene->getSelection(_name);
auto selectionName{ _name };
if (!inputs.get2().empty()) {
selectionName = inputs.get2();
}
auto selection = renderContext->_scene->getSelection(selectionName);
const auto& selectedItems = selection.getItems();
const auto& inItems = inputs.get0();
const auto itemsToAppend = inputs[1];

View file

@ -113,12 +113,13 @@ namespace render {
// Keep items belonging to the job selection
class SelectItems {
public:
using Inputs = VaryingSet2<ItemBounds, ItemBounds>;
using Inputs = VaryingSet3<ItemBounds, ItemBounds, std::string>;
using JobModel = Job::ModelIO<SelectItems, Inputs, ItemBounds>;
std::string _name;
SelectItems() {}
SelectItems(const Selection::Name& name) : _name(name) {}
void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems);
};

View file

@ -0,0 +1,39 @@
//
// OutlineStyle.h
// Created by Olivier Prat on 11/06/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
//
#ifndef hifi_render_utils_OutlineStyle_h
#define hifi_render_utils_OutlineStyle_h
#include <glm/vec3.hpp>
#include <string>
namespace render {
// This holds the configuration for a particular outline style
class OutlineStyle {
public:
bool isFilled() const {
return unoccludedFillOpacity > 5e-3f || occludedFillOpacity > 5e-3f;
}
glm::vec3 color{ 1.f, 0.7f, 0.2f };
float width{ 2.0f };
float intensity{ 0.9f };
float unoccludedFillOpacity{ 0.0f };
float occludedFillOpacity{ 0.0f };
bool glow{ false };
std::string selectionName;
};
}
#endif // hifi_render_utils_OutlineStyle_h

View file

@ -0,0 +1,46 @@
#include "OutlineStyleStage.h"
using namespace render;
std::string OutlineStyleStage::_name("OutlineStyle");
OutlineStyleStage::Index OutlineStyleStage::addOutline(const std::string& selectionName, const OutlineStyle& style) {
Outline outline{ selectionName, style };
Index id;
id = _outlines.newElement(outline);
_activeOutlineIds.push_back(id);
return id;
}
void OutlineStyleStage::removeOutline(Index index) {
OutlineIdList::iterator idIterator = std::find(_activeOutlineIds.begin(), _activeOutlineIds.end(), index);
if (idIterator != _activeOutlineIds.end()) {
_activeOutlineIds.erase(idIterator);
}
if (!_outlines.isElementFreed(index)) {
_outlines.freeElement(index);
}
}
Index OutlineStyleStage::getOutlineIdBySelection(const std::string& selectionName) const {
for (auto outlineId : _activeOutlineIds) {
const auto& outline = _outlines.get(outlineId);
if (outline._selectionName == selectionName) {
return outlineId;
}
}
return INVALID_INDEX;
}
OutlineStyleStageSetup::OutlineStyleStageSetup() {
}
void OutlineStyleStageSetup::run(const render::RenderContextPointer& renderContext) {
if (!renderContext->_scene->getStage(OutlineStyleStage::getName())) {
auto stage = std::make_shared<OutlineStyleStage>();
renderContext->_scene->resetStage(OutlineStyleStage::getName(), stage);
}
}

View file

@ -0,0 +1,77 @@
//
// OutlineStyleStage.h
// Created by Olivier Prat on 07/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
//
#ifndef hifi_render_utils_outlinestage_h
#define hifi_render_utils_outlinestage_h
#include "Stage.h"
#include "Engine.h"
#include "IndexedContainer.h"
#include "OutlineStyle.h"
namespace render {
// OutlineStyle stage to set up OutlineStyle-related effects
class OutlineStyleStage : public Stage {
public:
class Outline {
public:
Outline(const std::string& selectionName, const OutlineStyle& style) : _selectionName{ selectionName }, _style{ style } { }
std::string _selectionName;
OutlineStyle _style;
};
static const std::string& getName() { return _name; }
using Index = render::indexed_container::Index;
static const Index INVALID_INDEX{ render::indexed_container::INVALID_INDEX };
using OutlineIdList = render::indexed_container::Indices;
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
bool checkOutlineId(Index index) const { return _outlines.checkIndex(index); }
const Outline& getOutline(Index OutlineStyleId) const { return _outlines.get(OutlineStyleId); }
Outline& editOutline(Index OutlineStyleId) { return _outlines.edit(OutlineStyleId); }
Index addOutline(const std::string& selectionName, const OutlineStyle& style = OutlineStyle());
Index getOutlineIdBySelection(const std::string& selectionName) const;
void removeOutline(Index index);
OutlineIdList::iterator begin() { return _activeOutlineIds.begin(); }
OutlineIdList::iterator end() { return _activeOutlineIds.end(); }
private:
using Outlines = render::indexed_container::IndexedVector<Outline>;
static std::string _name;
Outlines _outlines;
OutlineIdList _activeOutlineIds;
};
using OutlineStyleStagePointer = std::shared_ptr<OutlineStyleStage>;
class OutlineStyleStageSetup {
public:
using JobModel = render::Job::Model<OutlineStyleStageSetup>;
OutlineStyleStageSetup();
void run(const RenderContextPointer& renderContext);
protected:
};
}
#endif // hifi_render_utils_outlinestage_h

View file

@ -14,6 +14,7 @@
#include <gpu/Batch.h>
#include "Logging.h"
#include "TransitionStage.h"
#include "OutlineStyleStage.h"
using namespace render;
@ -54,6 +55,18 @@ void Transaction::resetSelection(const Selection& selection) {
_resetSelections.emplace_back(selection);
}
void Transaction::resetSelectionOutline(const std::string& selectionName, const OutlineStyle& style) {
_outlineResets.emplace_back(OutlineReset{ selectionName, style });
}
void Transaction::removeOutlineFromSelection(const std::string& selectionName) {
_outlineRemoves.emplace_back(selectionName);
}
void Transaction::querySelectionOutline(const std::string& selectionName, SelectionOutlineQueryFunc func) {
_outlineQueries.emplace_back(OutlineQuery{ selectionName, func });
}
void Transaction::merge(const Transaction& transaction) {
_resetItems.insert(_resetItems.end(), transaction._resetItems.begin(), transaction._resetItems.end());
_removedItems.insert(_removedItems.end(), transaction._removedItems.begin(), transaction._removedItems.end());
@ -62,6 +75,9 @@ void Transaction::merge(const Transaction& transaction) {
_addedTransitions.insert(_addedTransitions.end(), transaction._addedTransitions.begin(), transaction._addedTransitions.end());
_queriedTransitions.insert(_queriedTransitions.end(), transaction._queriedTransitions.begin(), transaction._queriedTransitions.end());
_reAppliedTransitions.insert(_reAppliedTransitions.end(), transaction._reAppliedTransitions.begin(), transaction._reAppliedTransitions.end());
_outlineResets.insert(_outlineResets.end(), transaction._outlineResets.begin(), transaction._outlineResets.end());
_outlineRemoves.insert(_outlineRemoves.end(), transaction._outlineRemoves.begin(), transaction._outlineRemoves.end());
_outlineQueries.insert(_outlineQueries.end(), transaction._outlineQueries.begin(), transaction._outlineQueries.end());
}
@ -176,6 +192,10 @@ void Scene::processTransactionFrame(const Transaction& transaction) {
// resets and potential NEW items
resetSelections(transaction._resetSelections);
}
resetOutlines(transaction._outlineResets);
removeOutlines(transaction._outlineRemoves);
queryOutlines(transaction._outlineQueries);
}
void Scene::resetItems(const Transaction::Resets& transactions) {
@ -316,6 +336,50 @@ void Scene::queryTransitionItems(const Transaction::TransitionQueries& transacti
}
}
void Scene::resetOutlines(const Transaction::OutlineResets& transactions) {
auto outlineStage = getStage<OutlineStyleStage>(OutlineStyleStage::getName());
for (auto& transaction : transactions) {
const auto& selectionName = std::get<0>(transaction);
const auto& newStyle = std::get<1>(transaction);
auto outlineId = outlineStage->getOutlineIdBySelection(selectionName);
if (OutlineStyleStage::isIndexInvalid(outlineId)) {
outlineStage->addOutline(selectionName, newStyle);
} else {
outlineStage->editOutline(outlineId)._style = newStyle;
}
}
}
void Scene::removeOutlines(const Transaction::OutlineRemoves& transactions) {
auto outlineStage = getStage<OutlineStyleStage>(OutlineStyleStage::getName());
for (auto& selectionName : transactions) {
auto outlineId = outlineStage->getOutlineIdBySelection(selectionName);
if (!OutlineStyleStage::isIndexInvalid(outlineId)) {
outlineStage->removeOutline(outlineId);
}
}
}
void Scene::queryOutlines(const Transaction::OutlineQueries& transactions) {
auto outlineStage = getStage<OutlineStyleStage>(OutlineStyleStage::getName());
for (auto& transaction : transactions) {
const auto& selectionName = std::get<0>(transaction);
const auto& func = std::get<1>(transaction);
auto outlineId = outlineStage->getOutlineIdBySelection(selectionName);
if (!OutlineStyleStage::isIndexInvalid(outlineId)) {
func(&outlineStage->editOutline(outlineId)._style);
} else {
func(nullptr);
}
}
}
void Scene::collectSubItems(ItemID parentId, ItemIDs& subItems) const {
// Access the true item
auto& item = _items[parentId];

View file

@ -17,6 +17,7 @@
#include "Stage.h"
#include "Selection.h"
#include "Transition.h"
#include "OutlineStyle.h"
namespace render {
@ -37,6 +38,7 @@ class Transaction {
public:
typedef std::function<void(ItemID, const Transition*)> TransitionQueryFunc;
typedef std::function<void(OutlineStyle const*)> SelectionOutlineQueryFunc;
Transaction() {}
~Transaction() {}
@ -61,6 +63,10 @@ public:
// Selection transactions
void resetSelection(const Selection& selection);
void resetSelectionOutline(const std::string& selectionName, const OutlineStyle& style = OutlineStyle());
void removeOutlineFromSelection(const std::string& selectionName);
void querySelectionOutline(const std::string& selectionName, SelectionOutlineQueryFunc func);
void merge(const Transaction& transaction);
// Checkers if there is work to do when processing the transaction
@ -75,6 +81,9 @@ protected:
using TransitionQuery = std::tuple<ItemID, TransitionQueryFunc>;
using TransitionReApply = ItemID;
using SelectionReset = Selection;
using OutlineReset = std::tuple<std::string, OutlineStyle>;
using OutlineRemove = std::string;
using OutlineQuery = std::tuple<std::string, SelectionOutlineQueryFunc>;
using Resets = std::vector<Reset>;
using Removes = std::vector<Remove>;
@ -83,6 +92,9 @@ protected:
using TransitionQueries = std::vector<TransitionQuery>;
using TransitionReApplies = std::vector<TransitionReApply>;
using SelectionResets = std::vector<SelectionReset>;
using OutlineResets = std::vector<OutlineReset>;
using OutlineRemoves = std::vector<OutlineRemove>;
using OutlineQueries = std::vector<OutlineQuery>;
Resets _resetItems;
Removes _removedItems;
@ -91,6 +103,9 @@ protected:
TransitionQueries _queriedTransitions;
TransitionReApplies _reAppliedTransitions;
SelectionResets _resetSelections;
OutlineResets _outlineResets;
OutlineRemoves _outlineRemoves;
OutlineQueries _outlineQueries;
};
typedef std::queue<Transaction> TransactionQueue;
@ -103,10 +118,6 @@ typedef std::queue<Transaction> TransactionQueue;
class Scene {
public:
enum {
MAX_OUTLINE_COUNT = 8
};
Scene(glm::vec3 origin, float size);
~Scene();
@ -192,6 +203,9 @@ protected:
void transitionItems(const Transaction::TransitionAdds& transactions);
void reApplyTransitions(const Transaction::TransitionReApplies& transactions);
void queryTransitionItems(const Transaction::TransitionQueries& transactions);
void resetOutlines(const Transaction::OutlineResets& transactions);
void removeOutlines(const Transaction::OutlineRemoves& transactions);
void queryOutlines(const Transaction::OutlineQueries& transactions);
void collectSubItems(ItemID parentId, ItemIDs& subItems) const;