diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 9067f4ff09..2fc3d8bb02 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -22,6 +22,52 @@ inline float valueToParameterPow(float value, const double minValue, const doubl return (float)(log(double(value) / minValue) / log(maxOverMinValue)); } +void FadeEditJob::run(const render::RenderContextPointer& renderContext, const Input& inputs) { + auto jobConfig = static_cast(renderContext->jobConfig.get()); + auto& itemBounds = inputs.get0(); + + if (jobConfig->editFade) { + float minIsectDistance = std::numeric_limits::max(); + auto itemId = findNearestItem(renderContext, itemBounds, minIsectDistance); + + if (itemId != render::Item::INVALID_ITEM_ID) { + const auto& item = renderContext->_scene->getItem(itemId); + + if (item.getTransitionId() == render::TransitionStage::INVALID_INDEX) { + // Relaunch transition + render::Transaction transaction; + transaction.transitionItem(itemId, inputs.get1()); + renderContext->_scene->enqueueTransaction(transaction); + } + } + } +} + +render::ItemID FadeEditJob::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(); + auto& scene = renderContext->_scene; + BoxFace face; + glm::vec3 normal; + float isectDistance; + render::ItemID nearestItem = render::Item::INVALID_ITEM_ID; + const float minDistance = 2.f; + + for (const auto& itemBound : inputs) { + if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { + if (isectDistance>minDistance && isectDistance < minIsectDistance) { + auto& item = scene->getItem(itemBound.id); + + if (item.getKey().isShape() && !item.getKey().isMeta()) { + nearestItem = itemBound.id; + minIsectDistance = isectDistance; + } + } + } + } + return nearestItem; +} + FadeConfig::FadeConfig() { events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 0.75f, 0.75f, 0.75f }; @@ -488,14 +534,16 @@ void FadeJob::configure(const Config& config) { } } -void FadeJob::run(const render::RenderContextPointer& renderContext) { - const Config* jobConfig = static_cast(renderContext->jobConfig.get()); +void FadeJob::run(const render::RenderContextPointer& renderContext, Output& output) { + Config* jobConfig = static_cast(renderContext->jobConfig.get()); auto scene = renderContext->args->_scene; auto transitionStage = scene->getStage(render::TransitionStage::getName()); uint64_t now = usecTimestampNow(); const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND); render::Transaction transaction; bool hasTransactions = false; + + output = (render::Transition::Type) jobConfig->editedCategory; // And now update fade effect for (auto transitionId : *transitionStage) { @@ -505,6 +553,8 @@ void FadeJob::run(const render::RenderContextPointer& renderContext) { transaction.transitionItem(state.itemId, render::Transition::NONE); hasTransactions = true; } + + jobConfig->setProperty("threshold", state.threshold); } if (hasTransactions) { @@ -574,7 +624,6 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re transition.time += deltaTime; -// renderContext->jobConfig->setProperty("threshold", threshold); return continueTransition; } @@ -645,29 +694,3 @@ render::ShapePipeline::ItemSetter FadeJob::getItemSetter() const { } }; } - -const render::Item* FadeJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const { - const glm::vec3 rayOrigin = renderContext->args->getViewFrustum().getPosition(); - const glm::vec3 rayDirection = renderContext->args->getViewFrustum().getDirection(); - const auto& inputItems = input.get(); - auto& scene = renderContext->_scene; - BoxFace face; - glm::vec3 normal; - float isectDistance; - const render::Item* nearestItem = nullptr; - const float minDistance = 2.f; - - for (const auto& itemBound : inputItems) { - if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { - if (isectDistance>minDistance && isectDistance < minIsectDistance) { - auto& item = scene->getItem(itemBound.id); - - if (item.getKey().isShape() && !item.getKey().isMeta()) { - nearestItem = &item; - minIsectDistance = isectDistance; - } - } - } - } - return nearestItem; -} diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 413d4124ce..b0f7577c6a 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -16,6 +16,41 @@ #include #include +class FadeEditConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(bool manualFade MEMBER manualFade NOTIFY dirty) + Q_PROPERTY(float manualThreshold MEMBER manualThreshold NOTIFY dirty) + Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty) + +public: + + float manualThreshold{ 0.f }; + bool editFade{ false }; + bool manualFade{ false }; + +signals: + + void dirty(); +}; + +class FadeEditJob { + +public: + + using Config = FadeEditConfig; + using Input = render::VaryingSet2; + using JobModel = render::Job::ModelI; + + FadeEditJob() {} + + void configure(const Config& config) {} + void run(const render::RenderContextPointer& renderContext, const Input& inputs); + +private: + + render::ItemID findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const; +}; + class FadeConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int editedCategory MEMBER editedCategory WRITE setEditedCategory NOTIFY dirtyCategory) @@ -38,14 +73,11 @@ class FadeConfig : public render::Job::Config { Q_PROPERTY(float edgeOuterColorG READ getEdgeOuterColorG WRITE setEdgeOuterColorG NOTIFY dirty) Q_PROPERTY(float edgeOuterColorB READ getEdgeOuterColorB WRITE setEdgeOuterColorB NOTIFY dirty) Q_PROPERTY(float edgeOuterIntensity READ getEdgeOuterIntensity WRITE setEdgeOuterIntensity NOTIFY dirty) - Q_PROPERTY(bool manualFade MEMBER manualFade NOTIFY dirty) - Q_PROPERTY(float manualThreshold MEMBER manualThreshold NOTIFY dirty) Q_PROPERTY(int timing READ getTiming WRITE setTiming NOTIFY dirty) Q_PROPERTY(float noiseSpeedX READ getNoiseSpeedX WRITE setNoiseSpeedX NOTIFY dirty) Q_PROPERTY(float noiseSpeedY READ getNoiseSpeedY WRITE setNoiseSpeedY NOTIFY dirty) Q_PROPERTY(float noiseSpeedZ READ getNoiseSpeedZ WRITE setNoiseSpeedZ NOTIFY dirty) Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty) - Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty) public: @@ -146,11 +178,8 @@ public: }; Event events[render::Transition::EVENT_CATEGORY_COUNT]; - float threshold{ 0.f }; - float manualThreshold{ 0.f }; int editedCategory{ render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN }; - bool editFade{ false }; - bool manualFade{ false }; + float threshold{ 0.f }; Q_INVOKABLE void save() const; Q_INVOKABLE void load(); @@ -169,12 +198,13 @@ class FadeJob { public: using Config = FadeConfig; - using JobModel = render::Job::Model; + using Output = render::Transition::Type; + using JobModel = render::Job::ModelO; FadeJob(); void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext); + void run(const render::RenderContextPointer& renderContext, Output& output); render::ShapePipeline::BatchSetter getBatchSetter() const; render::ShapePipeline::ItemSetter getItemSetter() const; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 2bb1f50774..de6460b9ff 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -55,7 +55,7 @@ void RenderDeferredTask::configure(const Config& config) void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { const auto& items = input.get(); - task.addJob("Fade"); + auto editedTransitionType = task.addJob("Fade"); auto& fadeJob = task._jobs.back().get(); // Prepare the ShapePipelines @@ -72,6 +72,9 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren //const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND]; const auto& spatialSelection = items[1]; + const auto fadeEditInput = FadeEditJob::Input(opaques, editedTransitionType).asVarying(); + task.addJob("FadeEdit", fadeEditInput); + // Filter the non antialiaased overlays const int LAYER_NO_AA = 3; const auto nonAAOverlays = task.addJob("Filter2DWebOverlays", overlayOpaques, LAYER_NO_AA); diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 0e2adca3f4..3657b9611b 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -84,7 +84,7 @@ void Item::resetPayload(const PayloadPointer& payload) { const ShapeKey Item::getShapeKey() const { auto shapeKey = _payload->getShapeKey(); if (_transitionId != TransitionStage::INVALID_INDEX) { - return ShapeKey::Builder(shapeKey).withFade(); + return ShapeKey::Builder(shapeKey).withFade().withoutCullFace(); } return shapeKey; } \ No newline at end of file diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index d6606bcd68..1b5ba129b3 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -245,7 +245,7 @@ void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types) { const auto& item = _items[itemId]; // Remove pre-existing transition, if need be - if (item.getTransitionId() == render::TransitionStage::INVALID_INDEX) { + if (item.getTransitionId() != render::TransitionStage::INVALID_INDEX) { transitionStage->removeTransition(item.getTransitionId()); } // Add a new one. diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index 698b2384da..cc25cdfde6 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -15,8 +15,8 @@ import "../lib/plotperf" Column { id: root - property var config: Render.getConfig("RenderMainView.FadeConfigure"); - property var switchConfig: Render.getConfig("RenderMainView.FadeSwitch"); + property var config: Render.getConfig("RenderMainView.Fade"); + property var configEdit: Render.getConfig("RenderMainView.FadeEdit"); spacing: 8 Row { @@ -24,9 +24,9 @@ Column { CheckBox { text: "Edit Fade" - checked: root.switchConfig["editFade"] + checked: root.configEdit["editFade"] onCheckedChanged: { - root.switchConfig["editFade"] = checked; + root.configEdit["editFade"] = checked; Render.getConfig("RenderMainView.DrawFadedOpaqueBounds").enabled = checked; } } @@ -54,15 +54,15 @@ Column { CheckBox { text: "Manual" - checked: root.config["manualFade"] + checked: root.configEdit["manualFade"] onCheckedChanged: { - root.config["manualFade"] = checked; + root.configEdit["manualFade"] = checked; } } ConfigSlider { label: "Threshold" integral: false - config: root.config + config: root.configEdit property: "manualThreshold" max: 1.0 min: 0.0 @@ -359,7 +359,7 @@ Column { PlotPerf { title: "Threshold" height: parent.evalEvenHeight() - object: Render.getConfig("RenderMainView.DrawFadeOpaque") + object: config valueUnit: "%" valueScale: 0.01 valueNumDigits: "1"