mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 04:13:11 +02:00
Created FadeEffect singleton to be able to get fade item & batch setters for every special entity render
This commit is contained in:
parent
76dd421ecd
commit
3f8daa21ec
6 changed files with 1012 additions and 940 deletions
|
@ -1,730 +1,46 @@
|
||||||
|
//
|
||||||
|
// FadeEffect.cpp
|
||||||
|
|
||||||
|
// Created by Olivier Prat on 17/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 "FadeEffect.h"
|
#include "FadeEffect.h"
|
||||||
|
#include "FadeEffectJobs.h"
|
||||||
#include "TextureCache.h"
|
#include "TextureCache.h"
|
||||||
#include "render/Logging.h"
|
|
||||||
#include "render/TransitionStage.h"
|
#include "render/TransitionStage.h"
|
||||||
|
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
#include <NumericalConstants.h>
|
|
||||||
#include <Interpolate.h>
|
|
||||||
#include <gpu/Context.h>
|
|
||||||
|
|
||||||
#include <QJsonArray>
|
FadeEffect::FadeEffect() {
|
||||||
|
auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png";
|
||||||
#define FADE_MIN_SCALE 0.001
|
_maskMap = DependencyManager::get<TextureCache>()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE);
|
||||||
#define FADE_MAX_SCALE 10000.0
|
|
||||||
#define FADE_MAX_SPEED 50.f
|
|
||||||
|
|
||||||
inline float parameterToValuePow(float parameter, const double minValue, const double maxOverMinValue) {
|
|
||||||
return (float)(minValue * pow(maxOverMinValue, double(parameter)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float valueToParameterPow(float value, const double minValue, const double maxOverMinValue) {
|
void FadeEffect::build(render::Task::TaskConcept& task, const task::Varying& editableItems) {
|
||||||
return (float)(log(double(value) / minValue) / log(maxOverMinValue));
|
auto editedFadeCategory = task.addJob<FadeJob>("Fade");
|
||||||
|
auto& fadeJob = task._jobs.back();
|
||||||
|
_configurations = fadeJob.get<FadeJob>().getConfigurationBuffer();
|
||||||
|
|
||||||
|
const auto fadeEditInput = FadeEditJob::Input(editableItems, editedFadeCategory).asVarying();
|
||||||
|
task.addJob<FadeEditJob>("FadeEdit", fadeEditInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FadeEditJob::configure(const Config& config) {
|
render::ShapePipeline::BatchSetter FadeEffect::getBatchSetter() const {
|
||||||
_isEditEnabled = config.editFade;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeEditJob::run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& inputs) {
|
|
||||||
auto scene = renderContext->_scene;
|
|
||||||
|
|
||||||
if (_isEditEnabled) {
|
|
||||||
float minIsectDistance = std::numeric_limits<float>::max();
|
|
||||||
auto& itemBounds = inputs.get0();
|
|
||||||
auto editedItem = findNearestItem(renderContext, itemBounds, minIsectDistance);
|
|
||||||
render::Transaction transaction;
|
|
||||||
bool hasTransaction{ false };
|
|
||||||
|
|
||||||
if (editedItem != _editedItem && render::Item::isValidID(_editedItem)) {
|
|
||||||
// Remove transition from previously edited item as we've changed edited item
|
|
||||||
hasTransaction = true;
|
|
||||||
transaction.removeTransitionFromItem(_editedItem);
|
|
||||||
}
|
|
||||||
_editedItem = editedItem;
|
|
||||||
|
|
||||||
if (render::Item::isValidID(_editedItem)) {
|
|
||||||
static const render::Transition::Type categoryToTransition[FadeConfig::CATEGORY_COUNT] = {
|
|
||||||
render::Transition::ELEMENT_ENTER_DOMAIN,
|
|
||||||
render::Transition::BUBBLE_ISECT_OWNER,
|
|
||||||
render::Transition::BUBBLE_ISECT_TRESPASSER,
|
|
||||||
render::Transition::USER_ENTER_DOMAIN,
|
|
||||||
render::Transition::AVATAR_CHANGE
|
|
||||||
};
|
|
||||||
|
|
||||||
auto transitionType = categoryToTransition[inputs.get1()];
|
|
||||||
|
|
||||||
transaction.queryTransitionOnItem(_editedItem, [transitionType, scene](render::ItemID id, const render::Transition* transition) {
|
|
||||||
if (transition == nullptr || transition->isFinished || transition->eventType!=transitionType) {
|
|
||||||
// Relaunch transition
|
|
||||||
render::Transaction transaction;
|
|
||||||
transaction.addTransitionToItem(id, transitionType);
|
|
||||||
scene->enqueueTransaction(transaction);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
hasTransaction = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasTransaction) {
|
|
||||||
scene->enqueueTransaction(transaction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (render::Item::isValidID(_editedItem)) {
|
|
||||||
// Remove transition from previously edited item as we've disabled fade edition
|
|
||||||
render::Transaction transaction;
|
|
||||||
transaction.removeTransitionFromItem(_editedItem);
|
|
||||||
scene->enqueueTransaction(transaction);
|
|
||||||
_editedItem = render::Item::INVALID_ITEM_ID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
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) {
|
|
||||||
nearestItem = itemBound.id;
|
|
||||||
minIsectDistance = isectDistance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nearestItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
FadeConfig::FadeConfig()
|
|
||||||
{
|
|
||||||
events[ELEMENT_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 0.75f, 0.75f, 0.75f };
|
|
||||||
events[ELEMENT_ENTER_LEAVE_DOMAIN].noiseLevel = 1.f;
|
|
||||||
events[ELEMENT_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f };
|
|
||||||
events[ELEMENT_ENTER_LEAVE_DOMAIN].timing = FadeConfig::LINEAR;
|
|
||||||
events[ELEMENT_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 1.0f, 1.0f, 1.0f };
|
|
||||||
events[ELEMENT_ENTER_LEAVE_DOMAIN].baseLevel = 0.f;
|
|
||||||
events[ELEMENT_ENTER_LEAVE_DOMAIN].isInverted = false;
|
|
||||||
events[ELEMENT_ENTER_LEAVE_DOMAIN].duration = 4.f;
|
|
||||||
events[ELEMENT_ENTER_LEAVE_DOMAIN].edgeWidth = 0.1f;
|
|
||||||
events[ELEMENT_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f };
|
|
||||||
events[ELEMENT_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f };
|
|
||||||
|
|
||||||
events[BUBBLE_ISECT_OWNER].noiseSize = glm::vec3{ 1.5f, 1.0f/25.f, 0.5f };
|
|
||||||
events[BUBBLE_ISECT_OWNER].noiseLevel = 0.37f;
|
|
||||||
events[BUBBLE_ISECT_OWNER].noiseSpeed = glm::vec3{ 1.0f, 0.2f, 1.0f };
|
|
||||||
events[BUBBLE_ISECT_OWNER].timing = FadeConfig::LINEAR;
|
|
||||||
events[BUBBLE_ISECT_OWNER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f };
|
|
||||||
events[BUBBLE_ISECT_OWNER].baseLevel = 1.f;
|
|
||||||
events[BUBBLE_ISECT_OWNER].isInverted = false;
|
|
||||||
events[BUBBLE_ISECT_OWNER].duration = 4.f;
|
|
||||||
events[BUBBLE_ISECT_OWNER].edgeWidth = 0.02f;
|
|
||||||
events[BUBBLE_ISECT_OWNER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f };
|
|
||||||
events[BUBBLE_ISECT_OWNER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f };
|
|
||||||
|
|
||||||
events[BUBBLE_ISECT_TRESPASSER].noiseSize = glm::vec3{ 0.5f, 1.0f / 25.f, 0.5f };
|
|
||||||
events[BUBBLE_ISECT_TRESPASSER].noiseLevel = 1.f;
|
|
||||||
events[BUBBLE_ISECT_TRESPASSER].noiseSpeed = glm::vec3{ 1.0f, -5.f, 1.0f };
|
|
||||||
events[BUBBLE_ISECT_TRESPASSER].timing = FadeConfig::LINEAR;
|
|
||||||
events[BUBBLE_ISECT_TRESPASSER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f };
|
|
||||||
events[BUBBLE_ISECT_TRESPASSER].baseLevel = 0.f;
|
|
||||||
events[BUBBLE_ISECT_TRESPASSER].isInverted = false;
|
|
||||||
events[BUBBLE_ISECT_TRESPASSER].duration = 4.f;
|
|
||||||
events[BUBBLE_ISECT_TRESPASSER].edgeWidth = 0.025f;
|
|
||||||
events[BUBBLE_ISECT_TRESPASSER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f };
|
|
||||||
events[BUBBLE_ISECT_TRESPASSER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f };
|
|
||||||
|
|
||||||
events[USER_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 10.f, 0.01f, 10.0f };
|
|
||||||
events[USER_ENTER_LEAVE_DOMAIN].noiseLevel = 0.3f;
|
|
||||||
events[USER_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, -0.5f, 0.0f };
|
|
||||||
events[USER_ENTER_LEAVE_DOMAIN].timing = FadeConfig::LINEAR;
|
|
||||||
events[USER_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 10000.f, 1.0f, 10000.0f };
|
|
||||||
events[USER_ENTER_LEAVE_DOMAIN].baseLevel = 1.f;
|
|
||||||
events[USER_ENTER_LEAVE_DOMAIN].isInverted = true;
|
|
||||||
events[USER_ENTER_LEAVE_DOMAIN].duration = 2.f;
|
|
||||||
events[USER_ENTER_LEAVE_DOMAIN].edgeWidth = 0.229f;
|
|
||||||
events[USER_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 1.f, 0.63f, 0.13f, 0.5f };
|
|
||||||
events[USER_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 1.f, 1.f, 1.f, 1.0f };
|
|
||||||
|
|
||||||
events[AVATAR_CHANGE].noiseSize = glm::vec3{ 0.4f, 0.4f, 0.4f };
|
|
||||||
events[AVATAR_CHANGE].noiseLevel = 1.f;
|
|
||||||
events[AVATAR_CHANGE].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f };
|
|
||||||
events[AVATAR_CHANGE].timing = FadeConfig::LINEAR;
|
|
||||||
events[AVATAR_CHANGE].baseSize = glm::vec3{ 0.4f, 0.4f, 0.4f };
|
|
||||||
events[AVATAR_CHANGE].baseLevel = 1.f;
|
|
||||||
events[AVATAR_CHANGE].isInverted = false;
|
|
||||||
events[AVATAR_CHANGE].duration = 3.f;
|
|
||||||
events[AVATAR_CHANGE].edgeWidth = 0.05f;
|
|
||||||
events[AVATAR_CHANGE].edgeInnerColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f };
|
|
||||||
events[AVATAR_CHANGE].edgeOuterColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f };
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setEditedCategory(int value) {
|
|
||||||
assert(value < CATEGORY_COUNT);
|
|
||||||
editedCategory = std::min<int>(CATEGORY_COUNT, value);
|
|
||||||
emit dirtyCategory();
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setDuration(float value) {
|
|
||||||
events[editedCategory].duration = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeConfig::getDuration() const {
|
|
||||||
return events[editedCategory].duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setBaseSizeX(float value) {
|
|
||||||
events[editedCategory].baseSize.x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE/ FADE_MIN_SCALE);
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeConfig::getBaseSizeX() const {
|
|
||||||
return valueToParameterPow(events[editedCategory].baseSize.x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setBaseSizeY(float value) {
|
|
||||||
events[editedCategory].baseSize.y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeConfig::getBaseSizeY() const {
|
|
||||||
return valueToParameterPow(events[editedCategory].baseSize.y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setBaseSizeZ(float value) {
|
|
||||||
events[editedCategory].baseSize.z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeConfig::getBaseSizeZ() const {
|
|
||||||
return valueToParameterPow(events[editedCategory].baseSize.z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setBaseLevel(float value) {
|
|
||||||
events[editedCategory].baseLevel = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setInverted(bool value) {
|
|
||||||
events[editedCategory].isInverted = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FadeConfig::isInverted() const {
|
|
||||||
return events[editedCategory].isInverted;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setNoiseSizeX(float value) {
|
|
||||||
events[editedCategory].noiseSize.x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeConfig::getNoiseSizeX() const {
|
|
||||||
return valueToParameterPow(events[editedCategory].noiseSize.x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setNoiseSizeY(float value) {
|
|
||||||
events[editedCategory].noiseSize.y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeConfig::getNoiseSizeY() const {
|
|
||||||
return valueToParameterPow(events[editedCategory].noiseSize.y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setNoiseSizeZ(float value) {
|
|
||||||
events[editedCategory].noiseSize.z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeConfig::getNoiseSizeZ() const {
|
|
||||||
return valueToParameterPow(events[editedCategory].noiseSize.z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setNoiseLevel(float value) {
|
|
||||||
events[editedCategory].noiseLevel = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setNoiseSpeedX(float value) {
|
|
||||||
events[editedCategory].noiseSpeed.x = powf(value, 3.f)*FADE_MAX_SPEED;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeConfig::getNoiseSpeedX() const {
|
|
||||||
return powf(events[editedCategory].noiseSpeed.x / FADE_MAX_SPEED, 1.f / 3.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setNoiseSpeedY(float value) {
|
|
||||||
events[editedCategory].noiseSpeed.y = powf(value, 3.f)*FADE_MAX_SPEED;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeConfig::getNoiseSpeedY() const {
|
|
||||||
return powf(events[editedCategory].noiseSpeed.y / FADE_MAX_SPEED, 1.f / 3.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setNoiseSpeedZ(float value) {
|
|
||||||
events[editedCategory].noiseSpeed.z = powf(value, 3.f)*FADE_MAX_SPEED;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeConfig::getNoiseSpeedZ() const {
|
|
||||||
return powf(events[editedCategory].noiseSpeed.z / FADE_MAX_SPEED, 1.f / 3.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setEdgeWidth(float value) {
|
|
||||||
events[editedCategory].edgeWidth = value * value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeConfig::getEdgeWidth() const {
|
|
||||||
return sqrtf(events[editedCategory].edgeWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setEdgeInnerColorR(float value) {
|
|
||||||
events[editedCategory].edgeInnerColor.r = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setEdgeInnerColorG(float value) {
|
|
||||||
events[editedCategory].edgeInnerColor.g = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setEdgeInnerColorB(float value) {
|
|
||||||
events[editedCategory].edgeInnerColor.b = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setEdgeInnerIntensity(float value) {
|
|
||||||
events[editedCategory].edgeInnerColor.a = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setEdgeOuterColorR(float value) {
|
|
||||||
events[editedCategory].edgeOuterColor.r = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setEdgeOuterColorG(float value) {
|
|
||||||
events[editedCategory].edgeOuterColor.g = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setEdgeOuterColorB(float value) {
|
|
||||||
events[editedCategory].edgeOuterColor.b = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setEdgeOuterIntensity(float value) {
|
|
||||||
events[editedCategory].edgeOuterColor.a = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::setTiming(int value) {
|
|
||||||
assert(value < TIMING_COUNT);
|
|
||||||
events[editedCategory].timing = value;
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString FadeConfig::eventNames[FadeConfig::CATEGORY_COUNT] = {
|
|
||||||
"element_enter_leave_domain",
|
|
||||||
"bubble_isect_owner",
|
|
||||||
"bubble_isect_trespasser",
|
|
||||||
"user_enter_leave_domain",
|
|
||||||
"avatar_change",
|
|
||||||
};
|
|
||||||
|
|
||||||
void FadeConfig::save() const {
|
|
||||||
assert(editedCategory < FadeConfig::CATEGORY_COUNT);
|
|
||||||
QJsonObject lProperties;
|
|
||||||
const QString configFile = "config/" + eventNames[editedCategory] + ".json";
|
|
||||||
QUrl path(PathUtils::resourcesPath() + configFile);
|
|
||||||
QFile file(path.toString());
|
|
||||||
if (!file.open(QFile::WriteOnly | QFile::Text)) {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " cannot be opened";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const auto& event = events[editedCategory];
|
|
||||||
|
|
||||||
lProperties["edgeInnerColor"] = QJsonArray{ event.edgeInnerColor.r, event.edgeInnerColor.g, event.edgeInnerColor.b, event.edgeInnerColor.a };
|
|
||||||
lProperties["edgeOuterColor"] = QJsonArray{ event.edgeOuterColor.r, event.edgeOuterColor.g, event.edgeOuterColor.b, event.edgeOuterColor.a };
|
|
||||||
lProperties["noiseSize"] = QJsonArray{ event.noiseSize.x, event.noiseSize.y, event.noiseSize.z };
|
|
||||||
lProperties["noiseSpeed"] = QJsonArray{ event.noiseSpeed.x, event.noiseSpeed.y, event.noiseSpeed.z };
|
|
||||||
lProperties["baseSize"] = QJsonArray{ event.baseSize.x, event.baseSize.y, event.baseSize.z };
|
|
||||||
lProperties["noiseLevel"] = event.noiseLevel;
|
|
||||||
lProperties["baseLevel"] = event.baseLevel;
|
|
||||||
lProperties["duration"] = event.duration;
|
|
||||||
lProperties["edgeWidth"] = event.edgeWidth;
|
|
||||||
lProperties["timing"] = event.timing;
|
|
||||||
lProperties["isInverted"] = event.isInverted;
|
|
||||||
|
|
||||||
file.write( QJsonDocument(lProperties).toJson() );
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeConfig::load() {
|
|
||||||
const QString configFile = "config/" + eventNames[editedCategory] + ".json";
|
|
||||||
|
|
||||||
QUrl path(PathUtils::resourcesPath() + configFile);
|
|
||||||
QFile file(path.toString());
|
|
||||||
if (!file.exists()) {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " does not exist";
|
|
||||||
}
|
|
||||||
else if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " cannot be opened";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
QString fileData = file.readAll();
|
|
||||||
file.close();
|
|
||||||
QJsonParseError error;
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(fileData.toUtf8(), &error);
|
|
||||||
if (error.error == error.NoError) {
|
|
||||||
QJsonObject jsonObject = doc.object();
|
|
||||||
QJsonValue value;
|
|
||||||
auto& event = events[editedCategory];
|
|
||||||
|
|
||||||
qCDebug(renderlogging) << "Fade event configuration file" << path << "loaded";
|
|
||||||
|
|
||||||
value = jsonObject["edgeInnerColor"];
|
|
||||||
if (value.isArray()) {
|
|
||||||
QJsonArray data = value.toArray();
|
|
||||||
|
|
||||||
if (data.size() < 4) {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeInnerColor' field. Expected array of size 4";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
event.edgeInnerColor.r = (float)data.at(0).toDouble();
|
|
||||||
event.edgeInnerColor.g = (float)data.at(1).toDouble();
|
|
||||||
event.edgeInnerColor.b = (float)data.at(2).toDouble();
|
|
||||||
event.edgeInnerColor.a = (float)data.at(3).toDouble();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeInnerColor' field. Expected array of size 4";
|
|
||||||
}
|
|
||||||
|
|
||||||
value = jsonObject["edgeOuterColor"];
|
|
||||||
if (value.isArray()) {
|
|
||||||
QJsonArray data = value.toArray();
|
|
||||||
|
|
||||||
if (data.size() < 4) {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeOuterColor' field. Expected array of size 4";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
event.edgeOuterColor.r = (float)data.at(0).toDouble();
|
|
||||||
event.edgeOuterColor.g = (float)data.at(1).toDouble();
|
|
||||||
event.edgeOuterColor.b = (float)data.at(2).toDouble();
|
|
||||||
event.edgeOuterColor.a = (float)data.at(3).toDouble();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeOuterColor' field. Expected array of size 4";
|
|
||||||
}
|
|
||||||
|
|
||||||
value = jsonObject["noiseSize"];
|
|
||||||
if (value.isArray()) {
|
|
||||||
QJsonArray data = value.toArray();
|
|
||||||
|
|
||||||
if (data.size() < 3) {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSize' field. Expected array of size 3";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
event.noiseSize.x = (float)data.at(0).toDouble();
|
|
||||||
event.noiseSize.y = (float)data.at(1).toDouble();
|
|
||||||
event.noiseSize.z = (float)data.at(2).toDouble();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSize' field. Expected array of size 3";
|
|
||||||
}
|
|
||||||
|
|
||||||
value = jsonObject["noiseSpeed"];
|
|
||||||
if (value.isArray()) {
|
|
||||||
QJsonArray data = value.toArray();
|
|
||||||
|
|
||||||
if (data.size() < 3) {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSpeed' field. Expected array of size 3";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
event.noiseSpeed.x = (float)data.at(0).toDouble();
|
|
||||||
event.noiseSpeed.y = (float)data.at(1).toDouble();
|
|
||||||
event.noiseSpeed.z = (float)data.at(2).toDouble();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSpeed' field. Expected array of size 3";
|
|
||||||
}
|
|
||||||
|
|
||||||
value = jsonObject["baseSize"];
|
|
||||||
if (value.isArray()) {
|
|
||||||
QJsonArray data = value.toArray();
|
|
||||||
|
|
||||||
if (data.size() < 3) {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'baseSize' field. Expected array of size 3";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
event.baseSize.x = (float)data.at(0).toDouble();
|
|
||||||
event.baseSize.y = (float)data.at(1).toDouble();
|
|
||||||
event.baseSize.z = (float)data.at(2).toDouble();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'baseSize' field. Expected array of size 3";
|
|
||||||
}
|
|
||||||
|
|
||||||
value = jsonObject["noiseLevel"];
|
|
||||||
if (value.isDouble()) {
|
|
||||||
event.noiseLevel = (float)value.toDouble();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseLevel' field. Expected float value";
|
|
||||||
}
|
|
||||||
|
|
||||||
value = jsonObject["baseLevel"];
|
|
||||||
if (value.isDouble()) {
|
|
||||||
event.baseLevel = (float)value.toDouble();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'baseLevel' field. Expected float value";
|
|
||||||
}
|
|
||||||
|
|
||||||
value = jsonObject["duration"];
|
|
||||||
if (value.isDouble()) {
|
|
||||||
event.duration = (float)value.toDouble();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'duration' field. Expected float value";
|
|
||||||
}
|
|
||||||
|
|
||||||
value = jsonObject["edgeWidth"];
|
|
||||||
if (value.isDouble()) {
|
|
||||||
event.edgeWidth = std::min(1.f, std::max(0.f, (float)value.toDouble()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeWidth' field. Expected float value";
|
|
||||||
}
|
|
||||||
|
|
||||||
value = jsonObject["timing"];
|
|
||||||
if (value.isDouble()) {
|
|
||||||
event.timing = std::max(0, std::min(TIMING_COUNT - 1, value.toInt()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'timing' field. Expected integer value";
|
|
||||||
}
|
|
||||||
|
|
||||||
value = jsonObject["isInverted"];
|
|
||||||
if (value.isBool()) {
|
|
||||||
event.isInverted = value.toBool();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file " << path << " contains an invalid 'isInverted' field. Expected boolean value";
|
|
||||||
}
|
|
||||||
|
|
||||||
emit dirty();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "Fade event configuration file" << path << "failed to load:" <<
|
|
||||||
error.errorString() << "at offset" << error.offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FadeJob::FadeJob()
|
|
||||||
{
|
|
||||||
auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png";
|
|
||||||
_fadeMaskMap = DependencyManager::get<TextureCache>()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE);
|
|
||||||
_previousTime = usecTimestampNow();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeJob::configure(const Config& config) {
|
|
||||||
auto& configurations = _configurations.edit();
|
|
||||||
|
|
||||||
for (auto i = 0; i < FadeConfig::CATEGORY_COUNT; i++) {
|
|
||||||
auto& eventParameters = configurations.parameters[i];
|
|
||||||
const auto& eventConfig = config.events[i];
|
|
||||||
|
|
||||||
eventParameters._baseLevel = eventConfig.baseLevel;
|
|
||||||
eventParameters._noiseInvSizeAndLevel.x = 1.f / eventConfig.noiseSize.x;
|
|
||||||
eventParameters._noiseInvSizeAndLevel.y = 1.f / eventConfig.noiseSize.y;
|
|
||||||
eventParameters._noiseInvSizeAndLevel.z = 1.f / eventConfig.noiseSize.z;
|
|
||||||
eventParameters._noiseInvSizeAndLevel.w = eventConfig.noiseLevel;
|
|
||||||
eventParameters._isInverted = eventConfig.isInverted & 1;
|
|
||||||
eventParameters._edgeWidthInvWidth.x = eventConfig.edgeWidth;
|
|
||||||
eventParameters._edgeWidthInvWidth.y = 1.f / eventParameters._edgeWidthInvWidth.x;
|
|
||||||
eventParameters._innerEdgeColor = eventConfig.edgeInnerColor;
|
|
||||||
eventParameters._outerEdgeColor = eventConfig.edgeOuterColor;
|
|
||||||
_thresholdScale[i] = 1.f + (eventParameters._edgeWidthInvWidth.x + std::max(0.f, (eventConfig.noiseLevel + eventConfig.baseLevel)*0.5f - 0.5f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FadeJob::run(const render::RenderContextPointer& renderContext, FadeJob::Output& output) {
|
|
||||||
Config* jobConfig = static_cast<Config*>(renderContext->jobConfig.get());
|
|
||||||
auto scene = renderContext->args->_scene;
|
|
||||||
auto transitionStage = scene->getStage<render::TransitionStage>(render::TransitionStage::getName());
|
|
||||||
uint64_t now = usecTimestampNow();
|
|
||||||
const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND);
|
|
||||||
bool isFirstItem = true;
|
|
||||||
|
|
||||||
output = (FadeConfig::Category) jobConfig->editedCategory;
|
|
||||||
|
|
||||||
// And now update fade effect
|
|
||||||
for (auto transitionId : *transitionStage) {
|
|
||||||
auto& state = transitionStage->editTransition(transitionId);
|
|
||||||
update(*jobConfig, scene, state, deltaTime);
|
|
||||||
if (isFirstItem) {
|
|
||||||
jobConfig->setProperty("threshold", state.threshold);
|
|
||||||
isFirstItem = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_previousTime = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
const FadeConfig::Category FadeJob::transitionToCategory[render::Transition::TYPE_COUNT] = {
|
|
||||||
FadeConfig::ELEMENT_ENTER_LEAVE_DOMAIN,
|
|
||||||
FadeConfig::ELEMENT_ENTER_LEAVE_DOMAIN,
|
|
||||||
FadeConfig::BUBBLE_ISECT_OWNER,
|
|
||||||
FadeConfig::BUBBLE_ISECT_TRESPASSER,
|
|
||||||
FadeConfig::USER_ENTER_LEAVE_DOMAIN,
|
|
||||||
FadeConfig::USER_ENTER_LEAVE_DOMAIN,
|
|
||||||
FadeConfig::AVATAR_CHANGE
|
|
||||||
};
|
|
||||||
|
|
||||||
void FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const {
|
|
||||||
const auto fadeCategory = transitionToCategory[transition.eventType];
|
|
||||||
auto& eventConfig = config.events[fadeCategory];
|
|
||||||
auto& item = scene->getItem(transition.itemId);
|
|
||||||
const double eventDuration = (double)eventConfig.duration;
|
|
||||||
const FadeConfig::Timing timing = (FadeConfig::Timing) eventConfig.timing;
|
|
||||||
|
|
||||||
if (item.exist()) {
|
|
||||||
auto aabb = item.getBound();
|
|
||||||
if (render::Item::isValidID(transition.boundItemId)) {
|
|
||||||
auto& boundItem = scene->getItem(transition.boundItemId);
|
|
||||||
if (boundItem.exist()) {
|
|
||||||
aabb = boundItem.getBound();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto& dimensions = aabb.getDimensions();
|
|
||||||
|
|
||||||
assert(timing < FadeConfig::TIMING_COUNT);
|
|
||||||
|
|
||||||
transition.noiseOffset = aabb.calcCenter();
|
|
||||||
transition.baseInvSize.x = 1.f / eventConfig.baseSize.x;
|
|
||||||
transition.baseInvSize.y = 1.f / eventConfig.baseSize.y;
|
|
||||||
transition.baseInvSize.z = 1.f / eventConfig.baseSize.z;
|
|
||||||
|
|
||||||
switch (transition.eventType) {
|
|
||||||
case render::Transition::ELEMENT_ENTER_DOMAIN:
|
|
||||||
case render::Transition::ELEMENT_LEAVE_DOMAIN:
|
|
||||||
{
|
|
||||||
transition.threshold = computeElementEnterRatio(transition.time, eventDuration, timing);
|
|
||||||
transition.baseOffset = transition.noiseOffset;
|
|
||||||
transition.baseInvSize.x = 1.f / dimensions.x;
|
|
||||||
transition.baseInvSize.y = 1.f / dimensions.y;
|
|
||||||
transition.baseInvSize.z = 1.f / dimensions.z;
|
|
||||||
transition.isFinished += (transition.threshold >= 1.f) & 1;
|
|
||||||
if (transition.eventType == render::Transition::ELEMENT_ENTER_DOMAIN) {
|
|
||||||
transition.threshold = 1.f - transition.threshold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case render::Transition::BUBBLE_ISECT_OWNER:
|
|
||||||
{
|
|
||||||
transition.threshold = 0.5f;
|
|
||||||
transition.baseOffset = transition.noiseOffset;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case render::Transition::BUBBLE_ISECT_TRESPASSER:
|
|
||||||
{
|
|
||||||
transition.threshold = 0.5f;
|
|
||||||
transition.baseOffset = transition.noiseOffset;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case render::Transition::USER_ENTER_DOMAIN:
|
|
||||||
case render::Transition::USER_LEAVE_DOMAIN:
|
|
||||||
{
|
|
||||||
transition.threshold = computeElementEnterRatio(transition.time, eventDuration, timing);
|
|
||||||
transition.baseOffset = transition.noiseOffset - dimensions.y / 2.f;
|
|
||||||
transition.baseInvSize.y = 1.f / dimensions.y;
|
|
||||||
transition.isFinished += (transition.threshold >= 1.f) & 1;
|
|
||||||
if (transition.eventType == render::Transition::USER_LEAVE_DOMAIN) {
|
|
||||||
transition.threshold = 1.f - transition.threshold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case render::Transition::AVATAR_CHANGE:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
transition.noiseOffset += eventConfig.noiseSpeed * (float)transition.time;
|
|
||||||
if (config.manualFade) {
|
|
||||||
transition.threshold = config.manualThreshold;
|
|
||||||
}
|
|
||||||
transition.threshold = std::max(0.f, std::min(1.f, transition.threshold));
|
|
||||||
transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[fadeCategory] + 0.5f;
|
|
||||||
transition.time += deltaTime;
|
|
||||||
|
|
||||||
// If the transition is finished for more than a number of frames (here 3), garbage collect it.
|
|
||||||
if (transition.isFinished > 3) {
|
|
||||||
render::Transaction transaction;
|
|
||||||
transaction.removeTransitionFromItem(transition.itemId);
|
|
||||||
scene->enqueueTransaction(transaction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float FadeJob::computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing) {
|
|
||||||
assert(period > 0.0);
|
|
||||||
float fadeAlpha = 1.0f;
|
|
||||||
const double INV_FADE_PERIOD = 1.0 / period;
|
|
||||||
double fraction = time * INV_FADE_PERIOD;
|
|
||||||
fraction = std::max(fraction, 0.0);
|
|
||||||
if (fraction < 1.0) {
|
|
||||||
switch (timing) {
|
|
||||||
default:
|
|
||||||
fadeAlpha = (float)fraction;
|
|
||||||
break;
|
|
||||||
case FadeConfig::EASE_IN:
|
|
||||||
fadeAlpha = (float)(fraction*fraction*fraction);
|
|
||||||
break;
|
|
||||||
case FadeConfig::EASE_OUT:
|
|
||||||
fadeAlpha = 1.f - (float)fraction;
|
|
||||||
fadeAlpha = 1.f- fadeAlpha*fadeAlpha*fadeAlpha;
|
|
||||||
break;
|
|
||||||
case FadeConfig::EASE_IN_OUT:
|
|
||||||
fadeAlpha = (float)(fraction*fraction*fraction*(fraction*(fraction * 6 - 15) + 10));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fadeAlpha;
|
|
||||||
}
|
|
||||||
|
|
||||||
render::ShapePipeline::BatchSetter FadeJob::getBatchSetter() const {
|
|
||||||
return [this](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args*) {
|
return [this](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args*) {
|
||||||
auto program = shapePipeline.pipeline->getProgram();
|
auto program = shapePipeline.pipeline->getProgram();
|
||||||
auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap");
|
auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap");
|
||||||
auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer");
|
auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer");
|
||||||
batch.setResourceTexture(maskMapLocation, _fadeMaskMap);
|
batch.setResourceTexture(maskMapLocation, _maskMap);
|
||||||
batch.setUniformBuffer(bufferLocation, _configurations);
|
batch.setUniformBuffer(bufferLocation, _configurations);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render::ShapePipeline::ItemSetter FadeJob::getItemSetter() const {
|
render::ShapePipeline::ItemSetter FadeEffect::getItemSetter() const {
|
||||||
return [this](const render::ShapePipeline& shapePipeline, render::Args* args, const render::Item& item) {
|
return [](const render::ShapePipeline& shapePipeline, render::Args* args, const render::Item& item) {
|
||||||
if (!render::TransitionStage::isIndexInvalid(item.getTransitionId())) {
|
if (!render::TransitionStage::isIndexInvalid(item.getTransitionId())) {
|
||||||
auto scene = args->_scene;
|
auto scene = args->_scene;
|
||||||
auto batch = args->_batch;
|
auto batch = args->_batch;
|
||||||
|
@ -732,7 +48,6 @@ render::ShapePipeline::ItemSetter FadeJob::getItemSetter() const {
|
||||||
auto& transitionState = transitionStage->getTransition(item.getTransitionId());
|
auto& transitionState = transitionStage->getTransition(item.getTransitionId());
|
||||||
render::ShapeKey shapeKey(args->_globalShapeKey);
|
render::ShapeKey shapeKey(args->_globalShapeKey);
|
||||||
|
|
||||||
// TODO test various cases: polyvox... etc
|
|
||||||
// This is the normal case where we need to push the parameters in uniforms
|
// This is the normal case where we need to push the parameters in uniforms
|
||||||
{
|
{
|
||||||
auto program = shapePipeline.pipeline->getProgram();
|
auto program = shapePipeline.pipeline->getProgram();
|
||||||
|
@ -744,7 +59,7 @@ render::ShapePipeline::ItemSetter FadeJob::getItemSetter() const {
|
||||||
auto fadeCategoryLocation = uniforms.findLocation("fadeCategory");
|
auto fadeCategoryLocation = uniforms.findLocation("fadeCategory");
|
||||||
|
|
||||||
if (fadeNoiseOffsetLocation >= 0 || fadeBaseInvSizeLocation >= 0 || fadeBaseOffsetLocation >= 0 || fadeThresholdLocation >= 0 || fadeCategoryLocation >= 0) {
|
if (fadeNoiseOffsetLocation >= 0 || fadeBaseInvSizeLocation >= 0 || fadeBaseOffsetLocation >= 0 || fadeThresholdLocation >= 0 || fadeCategoryLocation >= 0) {
|
||||||
const auto fadeCategory = transitionToCategory[transitionState.eventType];
|
const auto fadeCategory = FadeJob::transitionToCategory[transitionState.eventType];
|
||||||
|
|
||||||
batch->_glUniform1i(fadeCategoryLocation, fadeCategory);
|
batch->_glUniform1i(fadeCategoryLocation, fadeCategory);
|
||||||
batch->_glUniform1f(fadeThresholdLocation, transitionState.threshold);
|
batch->_glUniform1f(fadeThresholdLocation, transitionState.threshold);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// FadeEffect.h
|
// FadeEffect.h
|
||||||
|
|
||||||
// Created by Olivier Prat on 07/07/2017.
|
// Created by Olivier Prat on 17/07/2017.
|
||||||
// Copyright 2017 High Fidelity, Inc.
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
@ -11,238 +11,26 @@
|
||||||
#ifndef hifi_render_utils_FadeEffect_h
|
#ifndef hifi_render_utils_FadeEffect_h
|
||||||
#define hifi_render_utils_FadeEffect_h
|
#define hifi_render_utils_FadeEffect_h
|
||||||
|
|
||||||
#include <gpu/Pipeline.h>
|
#include <DependencyManager.h>
|
||||||
#include <render/ShapePipeline.h>
|
#include <render/Engine.h>
|
||||||
#include <render/RenderFetchCullSortTask.h>
|
|
||||||
#include <render/Transition.h>
|
|
||||||
|
|
||||||
class FadeEditConfig : public render::Job::Config {
|
class FadeEffect : public Dependency {
|
||||||
Q_OBJECT
|
SINGLETON_DEPENDENCY;
|
||||||
Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool editFade{ false };
|
void build(render::Task::TaskConcept& task, const task::Varying& editableItems);
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
void dirty();
|
|
||||||
};
|
|
||||||
|
|
||||||
class FadeConfig : public render::Job::Config {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(int editedCategory MEMBER editedCategory WRITE setEditedCategory NOTIFY dirtyCategory)
|
|
||||||
Q_PROPERTY(float duration READ getDuration WRITE setDuration NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float baseSizeX READ getBaseSizeX WRITE setBaseSizeX NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float baseSizeY READ getBaseSizeY WRITE setBaseSizeY NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float baseSizeZ READ getBaseSizeZ WRITE setBaseSizeZ NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float baseLevel READ getBaseLevel WRITE setBaseLevel NOTIFY dirty)
|
|
||||||
Q_PROPERTY(bool _isInverted READ isInverted WRITE setInverted NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float noiseSizeX READ getNoiseSizeX WRITE setNoiseSizeX NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float noiseSizeY READ getNoiseSizeY WRITE setNoiseSizeY NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float noiseSizeZ READ getNoiseSizeZ WRITE setNoiseSizeZ NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float noiseLevel READ getNoiseLevel WRITE setNoiseLevel NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float edgeWidth READ getEdgeWidth WRITE setEdgeWidth NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float edgeInnerColorR READ getEdgeInnerColorR WRITE setEdgeInnerColorR NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float edgeInnerColorG READ getEdgeInnerColorG WRITE setEdgeInnerColorG NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float edgeInnerColorB READ getEdgeInnerColorB WRITE setEdgeInnerColorB NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float edgeInnerIntensity READ getEdgeInnerIntensity WRITE setEdgeInnerIntensity NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float edgeOuterColorR READ getEdgeOuterColorR WRITE setEdgeOuterColorR NOTIFY dirty)
|
|
||||||
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(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 manualFade MEMBER manualFade NOTIFY dirty)
|
|
||||||
Q_PROPERTY(float manualThreshold MEMBER manualThreshold NOTIFY dirty)
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum Category {
|
|
||||||
ELEMENT_ENTER_LEAVE_DOMAIN = 0,
|
|
||||||
BUBBLE_ISECT_OWNER,
|
|
||||||
BUBBLE_ISECT_TRESPASSER,
|
|
||||||
USER_ENTER_LEAVE_DOMAIN,
|
|
||||||
AVATAR_CHANGE,
|
|
||||||
|
|
||||||
// Don't forget to modify Fade.slh to reflect the change in number of categories
|
|
||||||
CATEGORY_COUNT,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Timing {
|
|
||||||
LINEAR,
|
|
||||||
EASE_IN,
|
|
||||||
EASE_OUT,
|
|
||||||
EASE_IN_OUT,
|
|
||||||
|
|
||||||
TIMING_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
FadeConfig();
|
|
||||||
|
|
||||||
void setEditedCategory(int value);
|
|
||||||
|
|
||||||
void setDuration(float value);
|
|
||||||
float getDuration() const;
|
|
||||||
|
|
||||||
void setBaseSizeX(float value);
|
|
||||||
float getBaseSizeX() const;
|
|
||||||
|
|
||||||
void setBaseSizeY(float value);
|
|
||||||
float getBaseSizeY() const;
|
|
||||||
|
|
||||||
void setBaseSizeZ(float value);
|
|
||||||
float getBaseSizeZ() const;
|
|
||||||
|
|
||||||
void setBaseLevel(float value);
|
|
||||||
float getBaseLevel() const { return events[editedCategory].baseLevel; }
|
|
||||||
|
|
||||||
void setInverted(bool value);
|
|
||||||
bool isInverted() const;
|
|
||||||
|
|
||||||
void setNoiseSizeX(float value);
|
|
||||||
float getNoiseSizeX() const;
|
|
||||||
|
|
||||||
void setNoiseSizeY(float value);
|
|
||||||
float getNoiseSizeY() const;
|
|
||||||
|
|
||||||
void setNoiseSizeZ(float value);
|
|
||||||
float getNoiseSizeZ() const;
|
|
||||||
|
|
||||||
void setNoiseLevel(float value);
|
|
||||||
float getNoiseLevel() const { return events[editedCategory].noiseLevel; }
|
|
||||||
|
|
||||||
void setNoiseSpeedX(float value);
|
|
||||||
float getNoiseSpeedX() const;
|
|
||||||
|
|
||||||
void setNoiseSpeedY(float value);
|
|
||||||
float getNoiseSpeedY() const;
|
|
||||||
|
|
||||||
void setNoiseSpeedZ(float value);
|
|
||||||
float getNoiseSpeedZ() const;
|
|
||||||
|
|
||||||
void setEdgeWidth(float value);
|
|
||||||
float getEdgeWidth() const;
|
|
||||||
|
|
||||||
void setEdgeInnerColorR(float value);
|
|
||||||
float getEdgeInnerColorR() const { return events[editedCategory].edgeInnerColor.r; }
|
|
||||||
|
|
||||||
void setEdgeInnerColorG(float value);
|
|
||||||
float getEdgeInnerColorG() const { return events[editedCategory].edgeInnerColor.g; }
|
|
||||||
|
|
||||||
void setEdgeInnerColorB(float value);
|
|
||||||
float getEdgeInnerColorB() const { return events[editedCategory].edgeInnerColor.b; }
|
|
||||||
|
|
||||||
void setEdgeInnerIntensity(float value);
|
|
||||||
float getEdgeInnerIntensity() const { return events[editedCategory].edgeInnerColor.a; }
|
|
||||||
|
|
||||||
void setEdgeOuterColorR(float value);
|
|
||||||
float getEdgeOuterColorR() const { return events[editedCategory].edgeOuterColor.r; }
|
|
||||||
|
|
||||||
void setEdgeOuterColorG(float value);
|
|
||||||
float getEdgeOuterColorG() const { return events[editedCategory].edgeOuterColor.g; }
|
|
||||||
|
|
||||||
void setEdgeOuterColorB(float value);
|
|
||||||
float getEdgeOuterColorB() const { return events[editedCategory].edgeOuterColor.b; }
|
|
||||||
|
|
||||||
void setEdgeOuterIntensity(float value);
|
|
||||||
float getEdgeOuterIntensity() const { return events[editedCategory].edgeOuterColor.a; }
|
|
||||||
|
|
||||||
void setTiming(int value);
|
|
||||||
int getTiming() const { return events[editedCategory].timing; }
|
|
||||||
|
|
||||||
struct Event {
|
|
||||||
glm::vec4 edgeInnerColor;
|
|
||||||
glm::vec4 edgeOuterColor;
|
|
||||||
glm::vec3 noiseSize;
|
|
||||||
glm::vec3 noiseSpeed;
|
|
||||||
glm::vec3 baseSize;
|
|
||||||
float noiseLevel;
|
|
||||||
float baseLevel;
|
|
||||||
float duration;
|
|
||||||
float edgeWidth;
|
|
||||||
int timing;
|
|
||||||
bool isInverted;
|
|
||||||
};
|
|
||||||
|
|
||||||
Event events[CATEGORY_COUNT];
|
|
||||||
int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN };
|
|
||||||
float threshold{ 0.f };
|
|
||||||
float manualThreshold{ 0.f };
|
|
||||||
bool manualFade{ false };
|
|
||||||
|
|
||||||
Q_INVOKABLE void save() const;
|
|
||||||
Q_INVOKABLE void load();
|
|
||||||
|
|
||||||
static QString eventNames[CATEGORY_COUNT];
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
void dirty();
|
|
||||||
void dirtyCategory();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class FadeEditJob {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
using Config = FadeEditConfig;
|
|
||||||
using Input = render::VaryingSet2<render::ItemBounds, FadeConfig::Category>;
|
|
||||||
using JobModel = render::Job::ModelI<FadeEditJob, Input, Config>;
|
|
||||||
|
|
||||||
FadeEditJob() {}
|
|
||||||
|
|
||||||
void configure(const Config& config);
|
|
||||||
void run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& inputs);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool _isEditEnabled{ false };
|
|
||||||
render::ItemID _editedItem{ render::Item::INVALID_ITEM_ID };
|
|
||||||
|
|
||||||
render::ItemID findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FadeJob {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
using Config = FadeConfig;
|
|
||||||
using Output = FadeConfig::Category;
|
|
||||||
using JobModel = render::Job::ModelO<FadeJob, Output, Config>;
|
|
||||||
|
|
||||||
FadeJob();
|
|
||||||
|
|
||||||
void configure(const Config& config);
|
|
||||||
void run(const render::RenderContextPointer& renderContext, FadeJob::Output& output);
|
|
||||||
|
|
||||||
render::ShapePipeline::BatchSetter getBatchSetter() const;
|
render::ShapePipeline::BatchSetter getBatchSetter() const;
|
||||||
render::ShapePipeline::ItemSetter getItemSetter() const;
|
render::ShapePipeline::ItemSetter getItemSetter() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static const FadeConfig::Category transitionToCategory[render::Transition::TYPE_COUNT];
|
gpu::BufferView _configurations;
|
||||||
|
gpu::TexturePointer _maskMap;
|
||||||
|
|
||||||
#include "Fade_shared.slh"
|
explicit FadeEffect();
|
||||||
|
virtual ~FadeEffect() { }
|
||||||
|
|
||||||
struct FadeConfiguration
|
|
||||||
{
|
|
||||||
FadeParameters parameters[FadeConfig::CATEGORY_COUNT];
|
|
||||||
};
|
|
||||||
|
|
||||||
gpu::StructBuffer<FadeConfiguration> _configurations;
|
|
||||||
gpu::TexturePointer _fadeMaskMap;
|
|
||||||
float _thresholdScale[FadeConfig::CATEGORY_COUNT];
|
|
||||||
uint64_t _previousTime{ 0 };
|
|
||||||
|
|
||||||
void update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const;
|
|
||||||
static float computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing);
|
|
||||||
|
|
||||||
const render::Item* findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_render_utils_FadeEffect_h
|
#endif // hifi_render_utils_FadeEffect_h
|
||||||
|
|
720
libraries/render-utils/src/FadeEffectJobs.cpp
Normal file
720
libraries/render-utils/src/FadeEffectJobs.cpp
Normal file
|
@ -0,0 +1,720 @@
|
||||||
|
//
|
||||||
|
// FadeEffectJobs.cpp
|
||||||
|
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
#include "FadeEffectJobs.h"
|
||||||
|
#include "render/Logging.h"
|
||||||
|
#include "render/TransitionStage.h"
|
||||||
|
|
||||||
|
#include <NumericalConstants.h>
|
||||||
|
#include <Interpolate.h>
|
||||||
|
#include <gpu/Context.h>
|
||||||
|
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
#include <PathUtils.h>
|
||||||
|
|
||||||
|
#define FADE_MIN_SCALE 0.001
|
||||||
|
#define FADE_MAX_SCALE 10000.0
|
||||||
|
#define FADE_MAX_SPEED 50.f
|
||||||
|
|
||||||
|
inline float parameterToValuePow(float parameter, const double minValue, const double maxOverMinValue) {
|
||||||
|
return (float)(minValue * pow(maxOverMinValue, double(parameter)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float valueToParameterPow(float value, const double minValue, const double maxOverMinValue) {
|
||||||
|
return (float)(log(double(value) / minValue) / log(maxOverMinValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeEditJob::configure(const Config& config) {
|
||||||
|
_isEditEnabled = config.editFade;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeEditJob::run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& inputs) {
|
||||||
|
auto scene = renderContext->_scene;
|
||||||
|
|
||||||
|
if (_isEditEnabled) {
|
||||||
|
float minIsectDistance = std::numeric_limits<float>::max();
|
||||||
|
auto& itemBounds = inputs.get0();
|
||||||
|
auto editedItem = findNearestItem(renderContext, itemBounds, minIsectDistance);
|
||||||
|
render::Transaction transaction;
|
||||||
|
bool hasTransaction{ false };
|
||||||
|
|
||||||
|
if (editedItem != _editedItem && render::Item::isValidID(_editedItem)) {
|
||||||
|
// Remove transition from previously edited item as we've changed edited item
|
||||||
|
hasTransaction = true;
|
||||||
|
transaction.removeTransitionFromItem(_editedItem);
|
||||||
|
}
|
||||||
|
_editedItem = editedItem;
|
||||||
|
|
||||||
|
if (render::Item::isValidID(_editedItem)) {
|
||||||
|
static const render::Transition::Type categoryToTransition[FADE_CATEGORY_COUNT] = {
|
||||||
|
render::Transition::ELEMENT_ENTER_DOMAIN,
|
||||||
|
render::Transition::BUBBLE_ISECT_OWNER,
|
||||||
|
render::Transition::BUBBLE_ISECT_TRESPASSER,
|
||||||
|
render::Transition::USER_ENTER_DOMAIN,
|
||||||
|
render::Transition::AVATAR_CHANGE
|
||||||
|
};
|
||||||
|
|
||||||
|
auto transitionType = categoryToTransition[inputs.get1()];
|
||||||
|
|
||||||
|
transaction.queryTransitionOnItem(_editedItem, [transitionType, scene](render::ItemID id, const render::Transition* transition) {
|
||||||
|
if (transition == nullptr || transition->isFinished || transition->eventType!=transitionType) {
|
||||||
|
// Relaunch transition
|
||||||
|
render::Transaction transaction;
|
||||||
|
transaction.addTransitionToItem(id, transitionType);
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
hasTransaction = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTransaction) {
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (render::Item::isValidID(_editedItem)) {
|
||||||
|
// Remove transition from previously edited item as we've disabled fade edition
|
||||||
|
render::Transaction transaction;
|
||||||
|
transaction.removeTransitionFromItem(_editedItem);
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
|
_editedItem = render::Item::INVALID_ITEM_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
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) {
|
||||||
|
nearestItem = itemBound.id;
|
||||||
|
minIsectDistance = isectDistance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nearestItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
FadeConfig::FadeConfig()
|
||||||
|
{
|
||||||
|
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 0.75f, 0.75f, 0.75f };
|
||||||
|
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].noiseLevel = 1.f;
|
||||||
|
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f };
|
||||||
|
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].timing = FadeConfig::LINEAR;
|
||||||
|
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 1.0f, 1.0f, 1.0f };
|
||||||
|
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].baseLevel = 0.f;
|
||||||
|
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].isInverted = false;
|
||||||
|
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].duration = 4.f;
|
||||||
|
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].edgeWidth = 0.1f;
|
||||||
|
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f };
|
||||||
|
events[FADE_ELEMENT_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f };
|
||||||
|
|
||||||
|
events[FADE_BUBBLE_ISECT_OWNER].noiseSize = glm::vec3{ 1.5f, 1.0f / 25.f, 0.5f };
|
||||||
|
events[FADE_BUBBLE_ISECT_OWNER].noiseLevel = 0.37f;
|
||||||
|
events[FADE_BUBBLE_ISECT_OWNER].noiseSpeed = glm::vec3{ 1.0f, 0.2f, 1.0f };
|
||||||
|
events[FADE_BUBBLE_ISECT_OWNER].timing = FadeConfig::LINEAR;
|
||||||
|
events[FADE_BUBBLE_ISECT_OWNER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f };
|
||||||
|
events[FADE_BUBBLE_ISECT_OWNER].baseLevel = 1.f;
|
||||||
|
events[FADE_BUBBLE_ISECT_OWNER].isInverted = false;
|
||||||
|
events[FADE_BUBBLE_ISECT_OWNER].duration = 4.f;
|
||||||
|
events[FADE_BUBBLE_ISECT_OWNER].edgeWidth = 0.02f;
|
||||||
|
events[FADE_BUBBLE_ISECT_OWNER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f };
|
||||||
|
events[FADE_BUBBLE_ISECT_OWNER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f };
|
||||||
|
|
||||||
|
events[FADE_BUBBLE_ISECT_TRESPASSER].noiseSize = glm::vec3{ 0.5f, 1.0f / 25.f, 0.5f };
|
||||||
|
events[FADE_BUBBLE_ISECT_TRESPASSER].noiseLevel = 1.f;
|
||||||
|
events[FADE_BUBBLE_ISECT_TRESPASSER].noiseSpeed = glm::vec3{ 1.0f, -5.f, 1.0f };
|
||||||
|
events[FADE_BUBBLE_ISECT_TRESPASSER].timing = FadeConfig::LINEAR;
|
||||||
|
events[FADE_BUBBLE_ISECT_TRESPASSER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f };
|
||||||
|
events[FADE_BUBBLE_ISECT_TRESPASSER].baseLevel = 0.f;
|
||||||
|
events[FADE_BUBBLE_ISECT_TRESPASSER].isInverted = false;
|
||||||
|
events[FADE_BUBBLE_ISECT_TRESPASSER].duration = 4.f;
|
||||||
|
events[FADE_BUBBLE_ISECT_TRESPASSER].edgeWidth = 0.025f;
|
||||||
|
events[FADE_BUBBLE_ISECT_TRESPASSER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f };
|
||||||
|
events[FADE_BUBBLE_ISECT_TRESPASSER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f };
|
||||||
|
|
||||||
|
events[FADE_USER_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 10.f, 0.01f, 10.0f };
|
||||||
|
events[FADE_USER_ENTER_LEAVE_DOMAIN].noiseLevel = 0.3f;
|
||||||
|
events[FADE_USER_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, -0.5f, 0.0f };
|
||||||
|
events[FADE_USER_ENTER_LEAVE_DOMAIN].timing = FadeConfig::LINEAR;
|
||||||
|
events[FADE_USER_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 10000.f, 1.0f, 10000.0f };
|
||||||
|
events[FADE_USER_ENTER_LEAVE_DOMAIN].baseLevel = 1.f;
|
||||||
|
events[FADE_USER_ENTER_LEAVE_DOMAIN].isInverted = true;
|
||||||
|
events[FADE_USER_ENTER_LEAVE_DOMAIN].duration = 2.f;
|
||||||
|
events[FADE_USER_ENTER_LEAVE_DOMAIN].edgeWidth = 0.229f;
|
||||||
|
events[FADE_USER_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 1.f, 0.63f, 0.13f, 0.5f };
|
||||||
|
events[FADE_USER_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 1.f, 1.f, 1.f, 1.0f };
|
||||||
|
|
||||||
|
events[FADE_AVATAR_CHANGE].noiseSize = glm::vec3{ 0.4f, 0.4f, 0.4f };
|
||||||
|
events[FADE_AVATAR_CHANGE].noiseLevel = 1.f;
|
||||||
|
events[FADE_AVATAR_CHANGE].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f };
|
||||||
|
events[FADE_AVATAR_CHANGE].timing = FadeConfig::LINEAR;
|
||||||
|
events[FADE_AVATAR_CHANGE].baseSize = glm::vec3{ 0.4f, 0.4f, 0.4f };
|
||||||
|
events[FADE_AVATAR_CHANGE].baseLevel = 1.f;
|
||||||
|
events[FADE_AVATAR_CHANGE].isInverted = false;
|
||||||
|
events[FADE_AVATAR_CHANGE].duration = 3.f;
|
||||||
|
events[FADE_AVATAR_CHANGE].edgeWidth = 0.05f;
|
||||||
|
events[FADE_AVATAR_CHANGE].edgeInnerColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
events[FADE_AVATAR_CHANGE].edgeOuterColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setEditedCategory(int value) {
|
||||||
|
assert(value < CATEGORY_COUNT);
|
||||||
|
editedCategory = std::min<int>(FADE_CATEGORY_COUNT, value);
|
||||||
|
emit dirtyCategory();
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setDuration(float value) {
|
||||||
|
events[editedCategory].duration = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeConfig::getDuration() const {
|
||||||
|
return events[editedCategory].duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setBaseSizeX(float value) {
|
||||||
|
events[editedCategory].baseSize.x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE/ FADE_MIN_SCALE);
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeConfig::getBaseSizeX() const {
|
||||||
|
return valueToParameterPow(events[editedCategory].baseSize.x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setBaseSizeY(float value) {
|
||||||
|
events[editedCategory].baseSize.y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeConfig::getBaseSizeY() const {
|
||||||
|
return valueToParameterPow(events[editedCategory].baseSize.y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setBaseSizeZ(float value) {
|
||||||
|
events[editedCategory].baseSize.z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeConfig::getBaseSizeZ() const {
|
||||||
|
return valueToParameterPow(events[editedCategory].baseSize.z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setBaseLevel(float value) {
|
||||||
|
events[editedCategory].baseLevel = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setInverted(bool value) {
|
||||||
|
events[editedCategory].isInverted = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FadeConfig::isInverted() const {
|
||||||
|
return events[editedCategory].isInverted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setNoiseSizeX(float value) {
|
||||||
|
events[editedCategory].noiseSize.x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeConfig::getNoiseSizeX() const {
|
||||||
|
return valueToParameterPow(events[editedCategory].noiseSize.x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setNoiseSizeY(float value) {
|
||||||
|
events[editedCategory].noiseSize.y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeConfig::getNoiseSizeY() const {
|
||||||
|
return valueToParameterPow(events[editedCategory].noiseSize.y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setNoiseSizeZ(float value) {
|
||||||
|
events[editedCategory].noiseSize.z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeConfig::getNoiseSizeZ() const {
|
||||||
|
return valueToParameterPow(events[editedCategory].noiseSize.z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setNoiseLevel(float value) {
|
||||||
|
events[editedCategory].noiseLevel = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setNoiseSpeedX(float value) {
|
||||||
|
events[editedCategory].noiseSpeed.x = powf(value, 3.f)*FADE_MAX_SPEED;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeConfig::getNoiseSpeedX() const {
|
||||||
|
return powf(events[editedCategory].noiseSpeed.x / FADE_MAX_SPEED, 1.f / 3.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setNoiseSpeedY(float value) {
|
||||||
|
events[editedCategory].noiseSpeed.y = powf(value, 3.f)*FADE_MAX_SPEED;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeConfig::getNoiseSpeedY() const {
|
||||||
|
return powf(events[editedCategory].noiseSpeed.y / FADE_MAX_SPEED, 1.f / 3.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setNoiseSpeedZ(float value) {
|
||||||
|
events[editedCategory].noiseSpeed.z = powf(value, 3.f)*FADE_MAX_SPEED;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeConfig::getNoiseSpeedZ() const {
|
||||||
|
return powf(events[editedCategory].noiseSpeed.z / FADE_MAX_SPEED, 1.f / 3.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setEdgeWidth(float value) {
|
||||||
|
events[editedCategory].edgeWidth = value * value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeConfig::getEdgeWidth() const {
|
||||||
|
return sqrtf(events[editedCategory].edgeWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setEdgeInnerColorR(float value) {
|
||||||
|
events[editedCategory].edgeInnerColor.r = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setEdgeInnerColorG(float value) {
|
||||||
|
events[editedCategory].edgeInnerColor.g = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setEdgeInnerColorB(float value) {
|
||||||
|
events[editedCategory].edgeInnerColor.b = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setEdgeInnerIntensity(float value) {
|
||||||
|
events[editedCategory].edgeInnerColor.a = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setEdgeOuterColorR(float value) {
|
||||||
|
events[editedCategory].edgeOuterColor.r = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setEdgeOuterColorG(float value) {
|
||||||
|
events[editedCategory].edgeOuterColor.g = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setEdgeOuterColorB(float value) {
|
||||||
|
events[editedCategory].edgeOuterColor.b = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setEdgeOuterIntensity(float value) {
|
||||||
|
events[editedCategory].edgeOuterColor.a = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::setTiming(int value) {
|
||||||
|
assert(value < TIMING_COUNT);
|
||||||
|
events[editedCategory].timing = value;
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FadeConfig::eventNames[FADE_CATEGORY_COUNT] = {
|
||||||
|
"element_enter_leave_domain",
|
||||||
|
"bubble_isect_owner",
|
||||||
|
"bubble_isect_trespasser",
|
||||||
|
"user_enter_leave_domain",
|
||||||
|
"avatar_change",
|
||||||
|
};
|
||||||
|
|
||||||
|
void FadeConfig::save() const {
|
||||||
|
assert(editedCategory < FADE_CATEGORY_COUNT);
|
||||||
|
QJsonObject lProperties;
|
||||||
|
const QString configFile = "config/" + eventNames[editedCategory] + ".json";
|
||||||
|
QUrl path(PathUtils::resourcesPath() + configFile);
|
||||||
|
QFile file(path.toString());
|
||||||
|
if (!file.open(QFile::WriteOnly | QFile::Text)) {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " cannot be opened";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const auto& event = events[editedCategory];
|
||||||
|
|
||||||
|
lProperties["edgeInnerColor"] = QJsonArray{ event.edgeInnerColor.r, event.edgeInnerColor.g, event.edgeInnerColor.b, event.edgeInnerColor.a };
|
||||||
|
lProperties["edgeOuterColor"] = QJsonArray{ event.edgeOuterColor.r, event.edgeOuterColor.g, event.edgeOuterColor.b, event.edgeOuterColor.a };
|
||||||
|
lProperties["noiseSize"] = QJsonArray{ event.noiseSize.x, event.noiseSize.y, event.noiseSize.z };
|
||||||
|
lProperties["noiseSpeed"] = QJsonArray{ event.noiseSpeed.x, event.noiseSpeed.y, event.noiseSpeed.z };
|
||||||
|
lProperties["baseSize"] = QJsonArray{ event.baseSize.x, event.baseSize.y, event.baseSize.z };
|
||||||
|
lProperties["noiseLevel"] = event.noiseLevel;
|
||||||
|
lProperties["baseLevel"] = event.baseLevel;
|
||||||
|
lProperties["duration"] = event.duration;
|
||||||
|
lProperties["edgeWidth"] = event.edgeWidth;
|
||||||
|
lProperties["timing"] = event.timing;
|
||||||
|
lProperties["isInverted"] = event.isInverted;
|
||||||
|
|
||||||
|
file.write( QJsonDocument(lProperties).toJson() );
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeConfig::load() {
|
||||||
|
const QString configFile = "config/" + eventNames[editedCategory] + ".json";
|
||||||
|
|
||||||
|
QUrl path(PathUtils::resourcesPath() + configFile);
|
||||||
|
QFile file(path.toString());
|
||||||
|
if (!file.exists()) {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " does not exist";
|
||||||
|
}
|
||||||
|
else if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " cannot be opened";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QString fileData = file.readAll();
|
||||||
|
file.close();
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(fileData.toUtf8(), &error);
|
||||||
|
if (error.error == error.NoError) {
|
||||||
|
QJsonObject jsonObject = doc.object();
|
||||||
|
QJsonValue value;
|
||||||
|
auto& event = events[editedCategory];
|
||||||
|
|
||||||
|
qCDebug(renderlogging) << "Fade event configuration file" << path << "loaded";
|
||||||
|
|
||||||
|
value = jsonObject["edgeInnerColor"];
|
||||||
|
if (value.isArray()) {
|
||||||
|
QJsonArray data = value.toArray();
|
||||||
|
|
||||||
|
if (data.size() < 4) {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeInnerColor' field. Expected array of size 4";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
event.edgeInnerColor.r = (float)data.at(0).toDouble();
|
||||||
|
event.edgeInnerColor.g = (float)data.at(1).toDouble();
|
||||||
|
event.edgeInnerColor.b = (float)data.at(2).toDouble();
|
||||||
|
event.edgeInnerColor.a = (float)data.at(3).toDouble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeInnerColor' field. Expected array of size 4";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = jsonObject["edgeOuterColor"];
|
||||||
|
if (value.isArray()) {
|
||||||
|
QJsonArray data = value.toArray();
|
||||||
|
|
||||||
|
if (data.size() < 4) {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeOuterColor' field. Expected array of size 4";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
event.edgeOuterColor.r = (float)data.at(0).toDouble();
|
||||||
|
event.edgeOuterColor.g = (float)data.at(1).toDouble();
|
||||||
|
event.edgeOuterColor.b = (float)data.at(2).toDouble();
|
||||||
|
event.edgeOuterColor.a = (float)data.at(3).toDouble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeOuterColor' field. Expected array of size 4";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = jsonObject["noiseSize"];
|
||||||
|
if (value.isArray()) {
|
||||||
|
QJsonArray data = value.toArray();
|
||||||
|
|
||||||
|
if (data.size() < 3) {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSize' field. Expected array of size 3";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
event.noiseSize.x = (float)data.at(0).toDouble();
|
||||||
|
event.noiseSize.y = (float)data.at(1).toDouble();
|
||||||
|
event.noiseSize.z = (float)data.at(2).toDouble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSize' field. Expected array of size 3";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = jsonObject["noiseSpeed"];
|
||||||
|
if (value.isArray()) {
|
||||||
|
QJsonArray data = value.toArray();
|
||||||
|
|
||||||
|
if (data.size() < 3) {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSpeed' field. Expected array of size 3";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
event.noiseSpeed.x = (float)data.at(0).toDouble();
|
||||||
|
event.noiseSpeed.y = (float)data.at(1).toDouble();
|
||||||
|
event.noiseSpeed.z = (float)data.at(2).toDouble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseSpeed' field. Expected array of size 3";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = jsonObject["baseSize"];
|
||||||
|
if (value.isArray()) {
|
||||||
|
QJsonArray data = value.toArray();
|
||||||
|
|
||||||
|
if (data.size() < 3) {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'baseSize' field. Expected array of size 3";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
event.baseSize.x = (float)data.at(0).toDouble();
|
||||||
|
event.baseSize.y = (float)data.at(1).toDouble();
|
||||||
|
event.baseSize.z = (float)data.at(2).toDouble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'baseSize' field. Expected array of size 3";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = jsonObject["noiseLevel"];
|
||||||
|
if (value.isDouble()) {
|
||||||
|
event.noiseLevel = (float)value.toDouble();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'noiseLevel' field. Expected float value";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = jsonObject["baseLevel"];
|
||||||
|
if (value.isDouble()) {
|
||||||
|
event.baseLevel = (float)value.toDouble();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'baseLevel' field. Expected float value";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = jsonObject["duration"];
|
||||||
|
if (value.isDouble()) {
|
||||||
|
event.duration = (float)value.toDouble();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'duration' field. Expected float value";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = jsonObject["edgeWidth"];
|
||||||
|
if (value.isDouble()) {
|
||||||
|
event.edgeWidth = std::min(1.f, std::max(0.f, (float)value.toDouble()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'edgeWidth' field. Expected float value";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = jsonObject["timing"];
|
||||||
|
if (value.isDouble()) {
|
||||||
|
event.timing = std::max(0, std::min(TIMING_COUNT - 1, value.toInt()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'timing' field. Expected integer value";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = jsonObject["isInverted"];
|
||||||
|
if (value.isBool()) {
|
||||||
|
event.isInverted = value.toBool();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file " << path << " contains an invalid 'isInverted' field. Expected boolean value";
|
||||||
|
}
|
||||||
|
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarning() << "Fade event configuration file" << path << "failed to load:" <<
|
||||||
|
error.errorString() << "at offset" << error.offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FadeJob::FadeJob() {
|
||||||
|
_previousTime = usecTimestampNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeJob::configure(const Config& config) {
|
||||||
|
auto& configurations = _configurations.edit();
|
||||||
|
|
||||||
|
for (auto i = 0; i < FADE_CATEGORY_COUNT; i++) {
|
||||||
|
auto& eventParameters = configurations.parameters[i];
|
||||||
|
const auto& eventConfig = config.events[i];
|
||||||
|
|
||||||
|
eventParameters._baseLevel = eventConfig.baseLevel;
|
||||||
|
eventParameters._noiseInvSizeAndLevel.x = 1.f / eventConfig.noiseSize.x;
|
||||||
|
eventParameters._noiseInvSizeAndLevel.y = 1.f / eventConfig.noiseSize.y;
|
||||||
|
eventParameters._noiseInvSizeAndLevel.z = 1.f / eventConfig.noiseSize.z;
|
||||||
|
eventParameters._noiseInvSizeAndLevel.w = eventConfig.noiseLevel;
|
||||||
|
eventParameters._isInverted = eventConfig.isInverted & 1;
|
||||||
|
eventParameters._edgeWidthInvWidth.x = eventConfig.edgeWidth;
|
||||||
|
eventParameters._edgeWidthInvWidth.y = 1.f / eventParameters._edgeWidthInvWidth.x;
|
||||||
|
eventParameters._innerEdgeColor = eventConfig.edgeInnerColor;
|
||||||
|
eventParameters._outerEdgeColor = eventConfig.edgeOuterColor;
|
||||||
|
_thresholdScale[i] = 1.f + (eventParameters._edgeWidthInvWidth.x + std::max(0.f, (eventConfig.noiseLevel + eventConfig.baseLevel)*0.5f - 0.5f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FadeJob::run(const render::RenderContextPointer& renderContext, FadeJob::Output& output) {
|
||||||
|
Config* jobConfig = static_cast<Config*>(renderContext->jobConfig.get());
|
||||||
|
auto scene = renderContext->args->_scene;
|
||||||
|
auto transitionStage = scene->getStage<render::TransitionStage>(render::TransitionStage::getName());
|
||||||
|
uint64_t now = usecTimestampNow();
|
||||||
|
const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND);
|
||||||
|
bool isFirstItem = true;
|
||||||
|
|
||||||
|
output = (FadeCategory) jobConfig->editedCategory;
|
||||||
|
|
||||||
|
// And now update fade effect
|
||||||
|
for (auto transitionId : *transitionStage) {
|
||||||
|
auto& state = transitionStage->editTransition(transitionId);
|
||||||
|
update(*jobConfig, scene, state, deltaTime);
|
||||||
|
if (isFirstItem) {
|
||||||
|
jobConfig->setProperty("threshold", state.threshold);
|
||||||
|
isFirstItem = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_previousTime = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FadeCategory FadeJob::transitionToCategory[render::Transition::TYPE_COUNT] = {
|
||||||
|
FADE_ELEMENT_ENTER_LEAVE_DOMAIN,
|
||||||
|
FADE_ELEMENT_ENTER_LEAVE_DOMAIN,
|
||||||
|
FADE_BUBBLE_ISECT_OWNER,
|
||||||
|
FADE_BUBBLE_ISECT_TRESPASSER,
|
||||||
|
FADE_USER_ENTER_LEAVE_DOMAIN,
|
||||||
|
FADE_USER_ENTER_LEAVE_DOMAIN,
|
||||||
|
FADE_AVATAR_CHANGE
|
||||||
|
};
|
||||||
|
|
||||||
|
void FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const {
|
||||||
|
const auto fadeCategory = transitionToCategory[transition.eventType];
|
||||||
|
auto& eventConfig = config.events[fadeCategory];
|
||||||
|
auto& item = scene->getItem(transition.itemId);
|
||||||
|
const double eventDuration = (double)eventConfig.duration;
|
||||||
|
const FadeConfig::Timing timing = (FadeConfig::Timing) eventConfig.timing;
|
||||||
|
|
||||||
|
if (item.exist()) {
|
||||||
|
auto aabb = item.getBound();
|
||||||
|
if (render::Item::isValidID(transition.boundItemId)) {
|
||||||
|
auto& boundItem = scene->getItem(transition.boundItemId);
|
||||||
|
if (boundItem.exist()) {
|
||||||
|
aabb = boundItem.getBound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto& dimensions = aabb.getDimensions();
|
||||||
|
|
||||||
|
assert(timing < FadeConfig::TIMING_COUNT);
|
||||||
|
|
||||||
|
transition.noiseOffset = aabb.calcCenter();
|
||||||
|
transition.baseInvSize.x = 1.f / eventConfig.baseSize.x;
|
||||||
|
transition.baseInvSize.y = 1.f / eventConfig.baseSize.y;
|
||||||
|
transition.baseInvSize.z = 1.f / eventConfig.baseSize.z;
|
||||||
|
|
||||||
|
switch (transition.eventType) {
|
||||||
|
case render::Transition::ELEMENT_ENTER_DOMAIN:
|
||||||
|
case render::Transition::ELEMENT_LEAVE_DOMAIN:
|
||||||
|
{
|
||||||
|
transition.threshold = computeElementEnterRatio(transition.time, eventDuration, timing);
|
||||||
|
transition.baseOffset = transition.noiseOffset;
|
||||||
|
transition.baseInvSize.x = 1.f / dimensions.x;
|
||||||
|
transition.baseInvSize.y = 1.f / dimensions.y;
|
||||||
|
transition.baseInvSize.z = 1.f / dimensions.z;
|
||||||
|
transition.isFinished += (transition.threshold >= 1.f) & 1;
|
||||||
|
if (transition.eventType == render::Transition::ELEMENT_ENTER_DOMAIN) {
|
||||||
|
transition.threshold = 1.f - transition.threshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case render::Transition::BUBBLE_ISECT_OWNER:
|
||||||
|
{
|
||||||
|
transition.threshold = 0.5f;
|
||||||
|
transition.baseOffset = transition.noiseOffset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case render::Transition::BUBBLE_ISECT_TRESPASSER:
|
||||||
|
{
|
||||||
|
transition.threshold = 0.5f;
|
||||||
|
transition.baseOffset = transition.noiseOffset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case render::Transition::USER_ENTER_DOMAIN:
|
||||||
|
case render::Transition::USER_LEAVE_DOMAIN:
|
||||||
|
{
|
||||||
|
transition.threshold = computeElementEnterRatio(transition.time, eventDuration, timing);
|
||||||
|
transition.baseOffset = transition.noiseOffset - dimensions.y / 2.f;
|
||||||
|
transition.baseInvSize.y = 1.f / dimensions.y;
|
||||||
|
transition.isFinished += (transition.threshold >= 1.f) & 1;
|
||||||
|
if (transition.eventType == render::Transition::USER_LEAVE_DOMAIN) {
|
||||||
|
transition.threshold = 1.f - transition.threshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case render::Transition::AVATAR_CHANGE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transition.noiseOffset += eventConfig.noiseSpeed * (float)transition.time;
|
||||||
|
if (config.manualFade) {
|
||||||
|
transition.threshold = config.manualThreshold;
|
||||||
|
}
|
||||||
|
transition.threshold = std::max(0.f, std::min(1.f, transition.threshold));
|
||||||
|
transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[fadeCategory] + 0.5f;
|
||||||
|
transition.time += deltaTime;
|
||||||
|
|
||||||
|
// If the transition is finished for more than a number of frames (here 3), garbage collect it.
|
||||||
|
if (transition.isFinished > 3) {
|
||||||
|
render::Transaction transaction;
|
||||||
|
transaction.removeTransitionFromItem(transition.itemId);
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float FadeJob::computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing) {
|
||||||
|
assert(period > 0.0);
|
||||||
|
float fadeAlpha = 1.0f;
|
||||||
|
const double INV_FADE_PERIOD = 1.0 / period;
|
||||||
|
double fraction = time * INV_FADE_PERIOD;
|
||||||
|
fraction = std::max(fraction, 0.0);
|
||||||
|
if (fraction < 1.0) {
|
||||||
|
switch (timing) {
|
||||||
|
default:
|
||||||
|
fadeAlpha = (float)fraction;
|
||||||
|
break;
|
||||||
|
case FadeConfig::EASE_IN:
|
||||||
|
fadeAlpha = (float)(fraction*fraction*fraction);
|
||||||
|
break;
|
||||||
|
case FadeConfig::EASE_OUT:
|
||||||
|
fadeAlpha = 1.f - (float)fraction;
|
||||||
|
fadeAlpha = 1.f- fadeAlpha*fadeAlpha*fadeAlpha;
|
||||||
|
break;
|
||||||
|
case FadeConfig::EASE_IN_OUT:
|
||||||
|
fadeAlpha = (float)(fraction*fraction*fraction*(fraction*(fraction * 6 - 15) + 10));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fadeAlpha;
|
||||||
|
}
|
248
libraries/render-utils/src/FadeEffectJobs.h
Normal file
248
libraries/render-utils/src/FadeEffectJobs.h
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
//
|
||||||
|
// FadeEffectJobs.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_FadeEffectJobs_h
|
||||||
|
#define hifi_render_utils_FadeEffectJobs_h
|
||||||
|
|
||||||
|
#include "FadeEffect.h"
|
||||||
|
|
||||||
|
#include <gpu/Pipeline.h>
|
||||||
|
#include <render/ShapePipeline.h>
|
||||||
|
#include <render/RenderFetchCullSortTask.h>
|
||||||
|
#include <render/Transition.h>
|
||||||
|
|
||||||
|
enum FadeCategory {
|
||||||
|
FADE_ELEMENT_ENTER_LEAVE_DOMAIN = 0,
|
||||||
|
FADE_BUBBLE_ISECT_OWNER,
|
||||||
|
FADE_BUBBLE_ISECT_TRESPASSER,
|
||||||
|
FADE_USER_ENTER_LEAVE_DOMAIN,
|
||||||
|
FADE_AVATAR_CHANGE,
|
||||||
|
|
||||||
|
// Don't forget to modify Fade.slh to reflect the change in number of categories
|
||||||
|
FADE_CATEGORY_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
class FadeEditConfig : public render::Job::Config {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool editFade{ false };
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void dirty();
|
||||||
|
};
|
||||||
|
|
||||||
|
class FadeConfig : public render::Job::Config {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int editedCategory MEMBER editedCategory WRITE setEditedCategory NOTIFY dirtyCategory)
|
||||||
|
Q_PROPERTY(float duration READ getDuration WRITE setDuration NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float baseSizeX READ getBaseSizeX WRITE setBaseSizeX NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float baseSizeY READ getBaseSizeY WRITE setBaseSizeY NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float baseSizeZ READ getBaseSizeZ WRITE setBaseSizeZ NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float baseLevel READ getBaseLevel WRITE setBaseLevel NOTIFY dirty)
|
||||||
|
Q_PROPERTY(bool _isInverted READ isInverted WRITE setInverted NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float noiseSizeX READ getNoiseSizeX WRITE setNoiseSizeX NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float noiseSizeY READ getNoiseSizeY WRITE setNoiseSizeY NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float noiseSizeZ READ getNoiseSizeZ WRITE setNoiseSizeZ NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float noiseLevel READ getNoiseLevel WRITE setNoiseLevel NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float edgeWidth READ getEdgeWidth WRITE setEdgeWidth NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float edgeInnerColorR READ getEdgeInnerColorR WRITE setEdgeInnerColorR NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float edgeInnerColorG READ getEdgeInnerColorG WRITE setEdgeInnerColorG NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float edgeInnerColorB READ getEdgeInnerColorB WRITE setEdgeInnerColorB NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float edgeInnerIntensity READ getEdgeInnerIntensity WRITE setEdgeInnerIntensity NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float edgeOuterColorR READ getEdgeOuterColorR WRITE setEdgeOuterColorR NOTIFY dirty)
|
||||||
|
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(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 manualFade MEMBER manualFade NOTIFY dirty)
|
||||||
|
Q_PROPERTY(float manualThreshold MEMBER manualThreshold NOTIFY dirty)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum Timing {
|
||||||
|
LINEAR,
|
||||||
|
EASE_IN,
|
||||||
|
EASE_OUT,
|
||||||
|
EASE_IN_OUT,
|
||||||
|
|
||||||
|
TIMING_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
FadeConfig();
|
||||||
|
|
||||||
|
void setEditedCategory(int value);
|
||||||
|
|
||||||
|
void setDuration(float value);
|
||||||
|
float getDuration() const;
|
||||||
|
|
||||||
|
void setBaseSizeX(float value);
|
||||||
|
float getBaseSizeX() const;
|
||||||
|
|
||||||
|
void setBaseSizeY(float value);
|
||||||
|
float getBaseSizeY() const;
|
||||||
|
|
||||||
|
void setBaseSizeZ(float value);
|
||||||
|
float getBaseSizeZ() const;
|
||||||
|
|
||||||
|
void setBaseLevel(float value);
|
||||||
|
float getBaseLevel() const { return events[editedCategory].baseLevel; }
|
||||||
|
|
||||||
|
void setInverted(bool value);
|
||||||
|
bool isInverted() const;
|
||||||
|
|
||||||
|
void setNoiseSizeX(float value);
|
||||||
|
float getNoiseSizeX() const;
|
||||||
|
|
||||||
|
void setNoiseSizeY(float value);
|
||||||
|
float getNoiseSizeY() const;
|
||||||
|
|
||||||
|
void setNoiseSizeZ(float value);
|
||||||
|
float getNoiseSizeZ() const;
|
||||||
|
|
||||||
|
void setNoiseLevel(float value);
|
||||||
|
float getNoiseLevel() const { return events[editedCategory].noiseLevel; }
|
||||||
|
|
||||||
|
void setNoiseSpeedX(float value);
|
||||||
|
float getNoiseSpeedX() const;
|
||||||
|
|
||||||
|
void setNoiseSpeedY(float value);
|
||||||
|
float getNoiseSpeedY() const;
|
||||||
|
|
||||||
|
void setNoiseSpeedZ(float value);
|
||||||
|
float getNoiseSpeedZ() const;
|
||||||
|
|
||||||
|
void setEdgeWidth(float value);
|
||||||
|
float getEdgeWidth() const;
|
||||||
|
|
||||||
|
void setEdgeInnerColorR(float value);
|
||||||
|
float getEdgeInnerColorR() const { return events[editedCategory].edgeInnerColor.r; }
|
||||||
|
|
||||||
|
void setEdgeInnerColorG(float value);
|
||||||
|
float getEdgeInnerColorG() const { return events[editedCategory].edgeInnerColor.g; }
|
||||||
|
|
||||||
|
void setEdgeInnerColorB(float value);
|
||||||
|
float getEdgeInnerColorB() const { return events[editedCategory].edgeInnerColor.b; }
|
||||||
|
|
||||||
|
void setEdgeInnerIntensity(float value);
|
||||||
|
float getEdgeInnerIntensity() const { return events[editedCategory].edgeInnerColor.a; }
|
||||||
|
|
||||||
|
void setEdgeOuterColorR(float value);
|
||||||
|
float getEdgeOuterColorR() const { return events[editedCategory].edgeOuterColor.r; }
|
||||||
|
|
||||||
|
void setEdgeOuterColorG(float value);
|
||||||
|
float getEdgeOuterColorG() const { return events[editedCategory].edgeOuterColor.g; }
|
||||||
|
|
||||||
|
void setEdgeOuterColorB(float value);
|
||||||
|
float getEdgeOuterColorB() const { return events[editedCategory].edgeOuterColor.b; }
|
||||||
|
|
||||||
|
void setEdgeOuterIntensity(float value);
|
||||||
|
float getEdgeOuterIntensity() const { return events[editedCategory].edgeOuterColor.a; }
|
||||||
|
|
||||||
|
void setTiming(int value);
|
||||||
|
int getTiming() const { return events[editedCategory].timing; }
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
glm::vec4 edgeInnerColor;
|
||||||
|
glm::vec4 edgeOuterColor;
|
||||||
|
glm::vec3 noiseSize;
|
||||||
|
glm::vec3 noiseSpeed;
|
||||||
|
glm::vec3 baseSize;
|
||||||
|
float noiseLevel;
|
||||||
|
float baseLevel;
|
||||||
|
float duration;
|
||||||
|
float edgeWidth;
|
||||||
|
int timing;
|
||||||
|
bool isInverted;
|
||||||
|
};
|
||||||
|
|
||||||
|
Event events[FADE_CATEGORY_COUNT];
|
||||||
|
int editedCategory{ FADE_ELEMENT_ENTER_LEAVE_DOMAIN };
|
||||||
|
float threshold{ 0.f };
|
||||||
|
float manualThreshold{ 0.f };
|
||||||
|
bool manualFade{ false };
|
||||||
|
|
||||||
|
Q_INVOKABLE void save() const;
|
||||||
|
Q_INVOKABLE void load();
|
||||||
|
|
||||||
|
static QString eventNames[FADE_CATEGORY_COUNT];
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void dirty();
|
||||||
|
void dirtyCategory();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class FadeEditJob {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using Config = FadeEditConfig;
|
||||||
|
using Input = render::VaryingSet2<render::ItemBounds, FadeCategory>;
|
||||||
|
using JobModel = render::Job::ModelI<FadeEditJob, Input, Config>;
|
||||||
|
|
||||||
|
FadeEditJob() {}
|
||||||
|
|
||||||
|
void configure(const Config& config);
|
||||||
|
void run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& inputs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool _isEditEnabled{ false };
|
||||||
|
render::ItemID _editedItem{ render::Item::INVALID_ITEM_ID };
|
||||||
|
|
||||||
|
render::ItemID findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FadeJob {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static const FadeCategory transitionToCategory[render::Transition::TYPE_COUNT];
|
||||||
|
|
||||||
|
using Config = FadeConfig;
|
||||||
|
using Output = FadeCategory;
|
||||||
|
using JobModel = render::Job::ModelO<FadeJob, Output, Config>;
|
||||||
|
|
||||||
|
FadeJob();
|
||||||
|
|
||||||
|
void configure(const Config& config);
|
||||||
|
void run(const render::RenderContextPointer& renderContext, FadeJob::Output& output);
|
||||||
|
|
||||||
|
gpu::BufferView getConfigurationBuffer() const { return _configurations; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
#include "Fade_shared.slh"
|
||||||
|
|
||||||
|
struct FadeConfiguration
|
||||||
|
{
|
||||||
|
FadeParameters parameters[FADE_CATEGORY_COUNT];
|
||||||
|
};
|
||||||
|
using FadeConfigurationBuffer = gpu::StructBuffer<FadeConfiguration>;
|
||||||
|
|
||||||
|
FadeConfigurationBuffer _configurations;
|
||||||
|
float _thresholdScale[FADE_CATEGORY_COUNT];
|
||||||
|
uint64_t _previousTime{ 0 };
|
||||||
|
|
||||||
|
void update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const;
|
||||||
|
static float computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_render_utils_FadeEffectJobs_h
|
|
@ -48,19 +48,21 @@ using namespace render;
|
||||||
extern void initOverlay3DPipelines(render::ShapePlumber& plumber);
|
extern void initOverlay3DPipelines(render::ShapePlumber& plumber);
|
||||||
extern void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
|
extern void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);
|
||||||
|
|
||||||
|
RenderDeferredTask::RenderDeferredTask() {
|
||||||
|
DependencyManager::set<FadeEffect>();
|
||||||
|
}
|
||||||
|
|
||||||
void RenderDeferredTask::configure(const Config& config)
|
void RenderDeferredTask::configure(const Config& config)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
||||||
const auto& items = input.get<Input>();
|
const auto& items = input.get<Input>();
|
||||||
|
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||||
auto editedFadeCategory = task.addJob<FadeJob>("Fade");
|
|
||||||
auto& fadeJob = task._jobs.back().get<FadeJob>();
|
|
||||||
|
|
||||||
// Prepare the ShapePipelines
|
// Prepare the ShapePipelines
|
||||||
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
|
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
|
||||||
initDeferredPipelines(*shapePlumber, fadeJob.getBatchSetter(), fadeJob.getItemSetter());
|
initDeferredPipelines(*shapePlumber, fadeEffect->getBatchSetter(), fadeEffect->getItemSetter());
|
||||||
|
|
||||||
// Extract opaques / transparents / lights / metas / overlays / background
|
// Extract opaques / transparents / lights / metas / overlays / background
|
||||||
const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE];
|
const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE];
|
||||||
|
@ -72,8 +74,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
||||||
//const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND];
|
//const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND];
|
||||||
const auto& spatialSelection = items[1];
|
const auto& spatialSelection = items[1];
|
||||||
|
|
||||||
const auto fadeEditInput = FadeEditJob::Input(opaques, editedFadeCategory).asVarying();
|
fadeEffect->build(task, opaques);
|
||||||
task.addJob<FadeEditJob>("FadeEdit", fadeEditInput);
|
|
||||||
|
|
||||||
// Filter the non antialiaased overlays
|
// Filter the non antialiaased overlays
|
||||||
const int LAYER_NO_AA = 3;
|
const int LAYER_NO_AA = 3;
|
||||||
|
|
|
@ -185,7 +185,7 @@ public:
|
||||||
using Config = RenderDeferredTaskConfig;
|
using Config = RenderDeferredTaskConfig;
|
||||||
using JobModel = render::Task::ModelI<RenderDeferredTask, Input, Config>;
|
using JobModel = render::Task::ModelI<RenderDeferredTask, Input, Config>;
|
||||||
|
|
||||||
RenderDeferredTask() {}
|
RenderDeferredTask();
|
||||||
|
|
||||||
void configure(const Config& config);
|
void configure(const Config& config);
|
||||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs);
|
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs);
|
||||||
|
|
Loading…
Reference in a new issue