Merge branch 'fadevoxel' into fadeshape

This commit is contained in:
Olivier Prat 2017-07-17 14:33:00 +02:00
commit db7871fca7
37 changed files with 1072 additions and 1027 deletions

View file

@ -20,6 +20,8 @@
#include <model-networking/SimpleMeshProxy.h>
#include "ModelScriptingInterface.h"
#include <FadeEffect.h>
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdouble-promotion"
@ -860,11 +862,12 @@ render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render::
}
if (key.isFaded()) {
const auto& fadeEffect = DependencyManager::get<FadeEffect>();
if (key.isWireframe()) {
return std::make_shared<render::ShapePipeline>(_wireframePipelines[1], nullptr, nullptr, nullptr);
return std::make_shared<render::ShapePipeline>(_wireframePipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemSetter());
}
else {
return std::make_shared<render::ShapePipeline>(_pipelines[1], nullptr, nullptr, nullptr);
return std::make_shared<render::ShapePipeline>(_pipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemSetter());
}
}
else {

View file

@ -19,7 +19,6 @@
in vec3 _normal;
in vec4 _position;
in vec4 _worldPosition;
in vec4 _worldFadePosition;
uniform sampler2D xMap;
uniform sampler2D yMap;
@ -31,7 +30,7 @@ uniform vec3 voxelVolumeSize;
void main(void) {
vec3 emissive;
applyFade(_worldFadePosition.xyz, emissive);
applyFade(_worldPosition.xyz, emissive);
vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz));
worldNormal = normalize(worldNormal);

View file

@ -17,12 +17,9 @@
<$declareStandardTransform()$>
<@include Fade.slh@>
out vec4 _position;
out vec4 _worldPosition;
out vec3 _normal;
out vec4 _worldFadePosition;
void main(void) {
// standard transform
@ -30,6 +27,5 @@ void main(void) {
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
<$transformModelToWorldPos(obj, inPosition, _worldFadePosition)$>
_worldPosition = inPosition;
}

View file

@ -9,13 +9,6 @@
<@if not FADE_SLH@>
<@def FADE_SLH@>
<@func transformModelToFadePos(objectTransform, objectPosition, fadePosition)@>
{
vec4 objectVector = vec4(<$objectPosition$>.xyz, 1.f);
<$transformModelToWorldPos($objectTransform$, objectVector, $fadePosition$)$>
}
<@endfunc@>
<@func declareFadeFragment()@>

View file

@ -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 "FadeEffectJobs.h"
#include "TextureCache.h"
#include "render/Logging.h"
#include "render/TransitionStage.h"
#include <PathUtils.h>
#include <NumericalConstants.h>
#include <Interpolate.h>
#include <gpu/Context.h>
#include <QJsonArray>
#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)));
FadeEffect::FadeEffect() {
auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png";
_maskMap = DependencyManager::get<TextureCache>()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE);
}
inline float valueToParameterPow(float value, const double minValue, const double maxOverMinValue) {
return (float)(log(double(value) / minValue) / log(maxOverMinValue));
void FadeEffect::build(render::Task::TaskConcept& task, const task::Varying& editableItems) {
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) {
_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 {
render::ShapePipeline::BatchSetter FadeEffect::getBatchSetter() const {
return [this](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args*) {
auto program = shapePipeline.pipeline->getProgram();
auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap");
auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer");
batch.setResourceTexture(maskMapLocation, _fadeMaskMap);
batch.setResourceTexture(maskMapLocation, _maskMap);
batch.setUniformBuffer(bufferLocation, _configurations);
};
}
render::ShapePipeline::ItemSetter FadeJob::getItemSetter() const {
return [this](const render::ShapePipeline& shapePipeline, render::Args* args, const render::Item& item) {
render::ShapePipeline::ItemSetter FadeEffect::getItemSetter() const {
return [](const render::ShapePipeline& shapePipeline, render::Args* args, const render::Item& item) {
if (!render::TransitionStage::isIndexInvalid(item.getTransitionId())) {
auto scene = args->_scene;
auto batch = args->_batch;
@ -732,7 +48,6 @@ render::ShapePipeline::ItemSetter FadeJob::getItemSetter() const {
auto& transitionState = transitionStage->getTransition(item.getTransitionId());
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
{
auto program = shapePipeline.pipeline->getProgram();
@ -744,7 +59,7 @@ render::ShapePipeline::ItemSetter FadeJob::getItemSetter() const {
auto fadeCategoryLocation = uniforms.findLocation("fadeCategory");
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->_glUniform1f(fadeThresholdLocation, transitionState.threshold);

View file

@ -1,7 +1,7 @@
//
// FadeEffect.h
// Created by Olivier Prat on 07/07/2017.
// Created by Olivier Prat on 17/07/2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
@ -11,238 +11,26 @@
#ifndef hifi_render_utils_FadeEffect_h
#define hifi_render_utils_FadeEffect_h
#include <gpu/Pipeline.h>
#include <render/ShapePipeline.h>
#include <render/RenderFetchCullSortTask.h>
#include <render/Transition.h>
#include <DependencyManager.h>
#include <render/Engine.h>
class FadeEditConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty)
class FadeEffect : public Dependency {
SINGLETON_DEPENDENCY;
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 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);
void build(render::Task::TaskConcept& task, const task::Varying& editableItems);
render::ShapePipeline::BatchSetter getBatchSetter() const;
render::ShapePipeline::ItemSetter getItemSetter() const;
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

View 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;
}

View 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

View file

@ -48,19 +48,21 @@ using namespace render;
extern void initOverlay3DPipelines(render::ShapePlumber& plumber);
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::build(JobModel& task, const render::Varying& input, render::Varying& output) {
const auto& items = input.get<Input>();
auto editedFadeCategory = task.addJob<FadeJob>("Fade");
auto& fadeJob = task._jobs.back().get<FadeJob>();
auto fadeEffect = DependencyManager::get<FadeEffect>();
// Prepare the ShapePipelines
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
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& spatialSelection = items[1];
const auto fadeEditInput = FadeEditJob::Input(opaques, editedFadeCategory).asVarying();
task.addJob<FadeEditJob>("FadeEdit", fadeEditInput);
fadeEffect->build(task, opaques);
// Filter the non antialiaased overlays
const int LAYER_NO_AA = 3;

View file

@ -185,7 +185,7 @@ public:
using Config = RenderDeferredTaskConfig;
using JobModel = render::Task::ModelI<RenderDeferredTask, Input, Config>;
RenderDeferredTask() {}
RenderDeferredTask();
void configure(const Config& config);
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs);

View file

@ -22,7 +22,7 @@
<$declareFadeFragment()$>
in vec4 _position;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
in vec3 _normal;
in vec3 _color;
in vec2 _texCoord0;
@ -32,7 +32,7 @@ in vec2 _texCoord1;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);

View file

@ -19,13 +19,11 @@
<@include MaterialTextures.slh@>
<$declareMaterialTexMapArrayBuffer()$>
<@include Fade.slh@>
out float _alpha;
out vec2 _texCoord0;
out vec2 _texCoord1;
out vec4 _position;
out vec4 _worldFadePosition;
out vec4 _worldPosition;
out vec3 _normal;
out vec3 _color;
@ -41,6 +39,6 @@ void main(void) {
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToFadePos(obj, inPosition, _worldFadePosition)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
}

View file

@ -28,12 +28,12 @@ in vec2 _texCoord0;
in vec2 _texCoord1;
in vec3 _normal;
in vec3 _color;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);

View file

@ -17,8 +17,6 @@
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
<@include Fade.slh@>
<@include MaterialTextures.slh@>
<$declareMaterialTexMapArrayBuffer()$>
@ -27,7 +25,7 @@ out vec2 _texCoord0;
out vec2 _texCoord1;
out vec3 _normal;
out vec3 _color;
out vec4 _worldFadePosition;
out vec4 _worldPosition;
void main(void) {
// pass along the color in linear space
@ -42,7 +40,7 @@ void main(void) {
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToFadePos(obj, inPosition, _worldFadePosition)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
}

View file

@ -29,12 +29,12 @@ in vec2 _texCoord1;
in vec3 _normal;
in vec3 _tangent;
in vec3 _color;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);

View file

@ -17,8 +17,6 @@
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
<@include Fade.slh@>
<@include MaterialTextures.slh@>
<$declareMaterialTexMapArrayBuffer()$>
@ -28,7 +26,7 @@ out vec2 _texCoord1;
out vec3 _normal;
out vec3 _tangent;
out vec3 _color;
out vec4 _worldFadePosition;
out vec4 _worldPosition;
void main(void) {
// pass along the color in linear space
@ -42,7 +40,7 @@ void main(void) {
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToFadePos(obj, inPosition, _worldFadePosition)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
<$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$>
}

View file

@ -29,12 +29,12 @@ in vec2 _texCoord1;
in vec3 _normal;
in vec3 _tangent;
in vec3 _color;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);

View file

@ -28,12 +28,12 @@ in vec2 _texCoord0;
in vec2 _texCoord1;
in vec3 _normal;
in vec3 _color;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);

View file

@ -23,7 +23,7 @@
<$declareFadeFragment()$>
in vec4 _position;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
in vec2 _texCoord0;
in vec2 _texCoord1;
in vec3 _normal;
@ -33,7 +33,7 @@ in vec3 _color;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);

View file

@ -20,10 +20,8 @@
<@include MaterialTextures.slh@>
<$declareMaterialTexMapArrayBuffer()$>
<@include Fade.slh@>
out vec4 _position;
out vec4 _worldFadePosition;
out vec4 _worldPosition;
out vec2 _texCoord0;
out vec2 _texCoord1;
out vec3 _normal;
@ -44,7 +42,7 @@ void main(void) {
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToFadePos(obj, inPosition, _worldFadePosition)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
<$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$>
}

View file

@ -28,12 +28,12 @@ in vec2 _texCoord1;
in vec3 _normal;
in vec3 _tangent;
in vec3 _color;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);

View file

@ -17,10 +17,10 @@
layout(location = 0) out vec4 _fragColor;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
void main(void) {
applyFadeClip(_worldFadePosition.xyz);
applyFadeClip(_worldPosition.xyz);
// pass-through to set z-buffer
_fragColor = vec4(1.0, 1.0, 1.0, 0.0);

View file

@ -16,16 +16,14 @@
<@include gpu/Transform.slh@>
<@include Fade.slh@>
<$declareStandardTransform()$>
out vec4 _worldFadePosition;
out vec4 _worldPosition;
void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformModelToFadePos(obj, inPosition, _worldFadePosition)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
}

View file

@ -27,12 +27,12 @@ in vec2 _texCoord0;
in vec2 _texCoord1;
in vec3 _normal;
in vec3 _color;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);

View file

@ -33,14 +33,14 @@ in vec4 _position;
in vec3 _normal;
in vec3 _color;
in float _alpha;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
out vec4 _fragColor;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);

View file

@ -24,14 +24,14 @@
in vec2 _texCoord0;
in vec3 _color;
in float _alpha;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
out vec4 _fragColor;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);

View file

@ -26,12 +26,12 @@ in vec2 _texCoord0;
in vec3 _normal;
in vec3 _color;
in float _alpha;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material mat = getMaterial();
int matKey = getMaterialKey(mat);

View file

@ -24,7 +24,7 @@ in vec3 _modelNormal;
in vec4 _color;
in vec2 _texCoord0;
in vec4 _position;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
//PROCEDURAL_COMMON_BLOCK
@ -35,7 +35,7 @@ in vec4 _worldFadePosition;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
Material material = getMaterial();
vec3 normal = normalize(_normal.xyz);

View file

@ -17,15 +17,13 @@
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
<@include Fade.slh@>
// the interpolated normal
out vec3 _normal;
out vec3 _modelNormal;
out vec4 _color;
out vec2 _texCoord0;
out vec4 _position;
out vec4 _worldFadePosition;
out vec4 _worldPosition;
void main(void) {
_color = colorToLinearRGBA(inColor);
@ -37,6 +35,6 @@ void main(void) {
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformModelToFadePos(obj, inPosition, _worldFadePosition)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
}

View file

@ -26,12 +26,12 @@ uniform sampler2D originalTexture;
in vec3 _normal;
in vec4 _color;
in vec2 _texCoord0;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
vec4 texel = texture(originalTexture, _texCoord0);
float colorAlpha = _color.a;

View file

@ -25,12 +25,12 @@ uniform sampler2D originalTexture;
in vec3 _normal;
in vec4 _color;
in vec2 _texCoord0;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
vec4 texel = texture(originalTexture, _texCoord0.st);
float colorAlpha = _color.a;

View file

@ -32,12 +32,12 @@ in vec4 _position;
in vec3 _normal;
in vec4 _color;
in vec2 _texCoord0;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
vec4 texel = texture(originalTexture, _texCoord0.st);
float opacity = _color.a;

View file

@ -24,14 +24,14 @@ uniform sampler2D originalTexture;
in vec3 _normal;
in vec4 _color;
in vec2 _texCoord0;
in vec4 _worldFadePosition;
in vec4 _worldPosition;
layout(location = 0) out vec4 _fragColor0;
void main(void) {
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
applyFade(_worldPosition.xyz, fadeEmissive);
vec4 texel = texture(originalTexture, _texCoord0.st);
float colorAlpha = _color.a;

View file

@ -22,15 +22,13 @@
<@include MaterialTextures.slh@>
<$declareMaterialTexMapArrayBuffer()$>
<@include Fade.slh@>
out vec4 _position;
out vec2 _texCoord0;
out vec2 _texCoord1;
out vec3 _normal;
out vec3 _color;
out float _alpha;
out vec4 _worldFadePosition;
out vec4 _worldPosition;
void main(void) {
vec4 position = vec4(0.0, 0.0, 0.0, 0.0);
@ -50,6 +48,6 @@ void main(void) {
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$>
<$transformModelToFadePos(obj, position, _worldFadePosition)$>
<$transformModelToWorldPos(obj, position, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, _normal.xyz)$>
}

View file

@ -22,8 +22,6 @@
<@include MaterialTextures.slh@>
<$declareMaterialTexMapArrayBuffer()$>
<@include Fade.slh@>
out vec4 _position;
out vec2 _texCoord0;
out vec2 _texCoord1;
@ -31,7 +29,7 @@ out vec3 _normal;
out vec3 _tangent;
out vec3 _color;
out float _alpha;
out vec4 _worldFadePosition;
out vec4 _worldPosition;
void main(void) {
vec4 position = vec4(0.0, 0.0, 0.0, 0.0);
@ -55,7 +53,7 @@ void main(void) {
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$>
<$transformModelToFadePos(obj, position, _worldFadePosition)$>
<$transformModelToWorldPos(obj, position, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$>
<$transformModelToWorldDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$>

View file

@ -15,12 +15,12 @@
<@include Fade.slh@>
<$declareFadeFragment()$>
in vec4 _worldFadePosition;
in vec4 _worldPosition;
layout(location = 0) out vec4 _fragColor;
void main(void) {
applyFadeClip(_worldFadePosition.xyz);
applyFadeClip(_worldPosition.xyz);
// pass-through to set z-buffer
_fragColor = vec4(1.0, 1.0, 1.0, 0.0);

View file

@ -16,11 +16,9 @@
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
<@include Fade.slh@>
<@include Skinning.slh@>
out vec4 _worldFadePosition;
out vec4 _worldPosition;
void main(void) {
vec4 position = vec4(0.0, 0.0, 0.0, 0.0);
@ -30,5 +28,5 @@ void main(void) {
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, position, gl_Position)$>
<$transformModelToFadePos(obj, position, _worldFadePosition)$>
<$transformModelToWorldPos(obj, position, _worldPosition)$>
}