From af7957491b21507b11c8914b70d2ce5f3f0a595e Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 3 Jul 2017 12:40:58 +0200 Subject: [PATCH] Working avater enter/leaves + manual threshold --- libraries/render-utils/src/Fade.slh | 26 +++---- libraries/render-utils/src/FadeEffect.cpp | 67 +++++++++++-------- libraries/render-utils/src/FadeEffect.h | 18 +++-- .../src/model_normal_map_fade.slf | 2 +- scripts/developer/utilities/render/fade.qml | 19 ++++++ 5 files changed, 85 insertions(+), 47 deletions(-) diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index e3a801ff8b..cc79c26f07 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -66,14 +66,14 @@ float evalFadeNoiseGradient(vec3 position) { vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z); vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x); - return mix(maskY.x, maskY.y, noisePositionFraction.y) * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.w; + float noise = mix(maskY.x, maskY.y, noisePositionFraction.y); + noise -= 0.5; // Center on value 0 + return noise * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.w; } float evalFadeBaseGradient(vec3 position) { float gradient = length((position - fadeBaseOffset) * fadeParameters[fadeCategory]._baseInvSizeAndLevel.xyz); - if (fadeParameters[fadeCategory]._invertBase!=0) { - gradient = 1.0 - gradient; - } + gradient = mod(gradient, 1.0)-0.5; // Center on value 0.5 gradient *= fadeParameters[fadeCategory]._baseInvSizeAndLevel.w; return gradient; } @@ -81,17 +81,15 @@ float evalFadeBaseGradient(vec3 position) { float evalFadeGradient(vec3 position) { float baseGradient = evalFadeBaseGradient(position); float noiseGradient = evalFadeNoiseGradient(position); - float gradient = (noiseGradient-0.5*fadeParameters[fadeCategory]._baseInvSizeAndLevel.w); + float gradient = noiseGradient+baseGradient+0.5; - // This is to be sure the noise is zero at the start of the gradient - gradient *= (1-baseGradient*baseGradient); - gradient += baseGradient; return gradient; } float evalFadeAlpha(vec3 position) { - float edgeWidth = fadeParameters[fadeCategory]._edgeWidthInvWidth.x; - float cutoff = mix(-edgeWidth, 1.0+edgeWidth, fadeThreshold); + //float edgeWidth = fadeParameters[fadeCategory]._edgeWidthInvWidth.x; + //float cutoff = mix(-edgeWidth, 1.0+edgeWidth, fadeThreshold); + float cutoff = fadeThreshold; return evalFadeGradient(position)-cutoff; } @@ -104,6 +102,10 @@ void applyFadeClip(vec3 position) { void applyFade(vec3 position, out vec3 emissive) { float alpha = evalFadeAlpha(position); + if (fadeParameters[fadeCategory]._invertBase!=0) { + alpha = -alpha; + } + if (alpha < 0) { discard; } @@ -111,12 +113,12 @@ void applyFade(vec3 position, out vec3 emissive) { float edgeMask = alpha * fadeParameters[fadeCategory]._edgeWidthInvWidth.y; float edgeAlpha = 1.0-clamp(edgeMask, 0, 1); - //edgeMask = step(edgeMask, 1.f); - edgeMask = edgeMask > 1.f ? 0.f : 1.f; + edgeMask = step(edgeMask, 1.f); edgeAlpha *= edgeAlpha; // Square to have a nice ease out vec4 color = mix(fadeParameters[fadeCategory]._innerEdgeColor, fadeParameters[fadeCategory]._outerEdgeColor, edgeAlpha); emissive = color.rgb * edgeMask * color.a; } + <@endfunc@> <@endif@> \ No newline at end of file diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 82dc684d2f..64c2fedfc6 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -250,6 +250,9 @@ FadeConfigureJob::FadeConfigureJob(FadeCommonParameters::Pointer commonParams) : void FadeConfigureJob::configure(const Config& config) { assert(_parameters); _parameters->_editedCategory = config.editedCategory; + _parameters->_isManualThresholdEnabled = config.manualFade; + _parameters->_manualThreshold = config.manualThreshold; + for (auto i = 0; i < FadeJobConfig::EVENT_CATEGORY_COUNT; i++) { auto& configuration = _configurations[i]; @@ -267,6 +270,7 @@ void FadeConfigureJob::configure(const Config& config) { configuration._edgeWidthInvWidth.y = 1.f / configuration._edgeWidthInvWidth.x; configuration._innerEdgeColor = config.edgeInnerColor[i]; configuration._outerEdgeColor = config.edgeOuterColor[i]; + _parameters->_thresholdScale[i] = 1.f + 2.f*(configuration._edgeWidthInvWidth.x + std::max(0.f, (config.noiseLevel[i] + config.baseLevel[i])*0.5f-0.5f)); } _isBufferDirty = true; } @@ -276,7 +280,7 @@ void FadeConfigureJob::run(const render::RenderContextPointer& renderContext, co auto& configurations = output.edit1().edit(); std::copy(_configurations, _configurations + FadeJobConfig::EVENT_CATEGORY_COUNT, configurations.parameters); if (_parameters->_editedCategory == FadeJobConfig::USER_ENTER_LEAVE_DOMAIN) { - configurations.parameters[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN]._baseInvSizeAndLevel.y = 2.f / input.getDimensions().y; + configurations.parameters[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN]._baseInvSizeAndLevel.y = 1.0f / input.getDimensions().y; } _isBufferDirty = false; } @@ -314,10 +318,10 @@ void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const // Update interactive edit effect if (_parameters->_isEditEnabled) { - updateFadeEdit(inItems.front()); + updateFadeEdit(renderContext, inItems.front()); } else { - _editStartTime = 0; + _editPreviousTime = 0; } // Setup camera, projection and viewport for all items @@ -362,9 +366,10 @@ void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const } } -float FadeRenderJob::computeElementEnterThreshold(double time) const { +float FadeRenderJob::computeElementEnterThreshold(double time, const double period) const { + assert(period > 0.0); float fadeAlpha = 1.0f; - const double INV_FADE_PERIOD = 1.0 / (double)(_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]); + const double INV_FADE_PERIOD = 1.0 / period; double fraction = time * INV_FADE_PERIOD; fraction = std::max(fraction, 0.0); if (fraction < 1.0) { @@ -376,31 +381,35 @@ float FadeRenderJob::computeElementEnterThreshold(double time) const { float FadeRenderJob::computeFadePercent(quint64 startTime) { const double time = (double)(int64_t(usecTimestampNow()) - int64_t(startTime)) / (double)(USECS_PER_SECOND); assert(_currentInstance); - return _currentInstance->computeElementEnterThreshold(time); + return _currentInstance->computeElementEnterThreshold(time, _currentInstance->_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]); } -void FadeRenderJob::updateFadeEdit(const render::ItemBound& itemBounds) { - if (_editStartTime == 0) { - _editStartTime = usecTimestampNow(); +void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderContext, const render::ItemBound& itemBounds) { + if (_editPreviousTime == 0) { + _editPreviousTime = usecTimestampNow(); + _editTime = 0.0; } - const double time = (int64_t(usecTimestampNow()) - int64_t(_editStartTime)) / double(USECS_PER_SECOND); + uint64_t now = usecTimestampNow(); + const double deltaTime = (int64_t(now) - int64_t(_editPreviousTime)) / double(USECS_PER_SECOND); const float eventDuration = _parameters->_durations[_parameters->_editedCategory]; + const double waitTime = 0.5; // Wait between fade in and out + double cycleTime = fmod(_editTime, (eventDuration + waitTime) * 2.0); + + _editTime += deltaTime; + _editPreviousTime = now; switch (_parameters->_editedCategory) { case FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN: { - const double waitTime = 0.5; // Wait between fade in and out - double cycleTime = fmod(time, (eventDuration+waitTime) * 2.0); - if (cycleTime < eventDuration) { - _editThreshold = 1.f-computeElementEnterThreshold(cycleTime); + _editThreshold = 1.f-computeElementEnterThreshold(cycleTime, eventDuration); } else if (cycleTime < (eventDuration + waitTime)) { _editThreshold = 0.f; } else if (cycleTime < (2 * eventDuration + waitTime)) { - _editThreshold = computeElementEnterThreshold(cycleTime- (eventDuration + waitTime)); + _editThreshold = computeElementEnterThreshold(cycleTime- (eventDuration + waitTime), eventDuration); } else { _editThreshold = 1.f; @@ -416,28 +425,21 @@ void FadeRenderJob::updateFadeEdit(const render::ItemBound& itemBounds) { case FadeJobConfig::USER_ENTER_LEAVE_DOMAIN: { - const double waitTime = 0.5; // Wait between fade in and out - double cycleTime = fmod(time, (eventDuration + waitTime) * 2.0); - - _editNoiseOffset.x = time*0.5; + _editNoiseOffset.x = _editTime*0.5; _editNoiseOffset.y = 0.f; - _editNoiseOffset.z = time*0.75; + _editNoiseOffset.z = _editTime*0.75; - _editBaseOffset.x = 0.f; - _editBaseOffset.y = -itemBounds.bound.getDimensions().y; - _editBaseOffset.z = 0.f; - { - - } + _editBaseOffset = itemBounds.bound.calcCenter(); + _editBaseOffset.y -= itemBounds.bound.getDimensions().y/2.f; if (cycleTime < eventDuration) { - _editThreshold = 1.f - computeElementEnterThreshold(cycleTime); + _editThreshold = 1.f - computeElementEnterThreshold(cycleTime, eventDuration); } else if (cycleTime < (eventDuration + waitTime)) { _editThreshold = 0.f; } else if (cycleTime < (2 * eventDuration + waitTime)) { - _editThreshold = computeElementEnterThreshold(cycleTime - (eventDuration + waitTime)); + _editThreshold = computeElementEnterThreshold(cycleTime - (eventDuration + waitTime), eventDuration); } else { _editThreshold = 1.f; @@ -451,6 +453,10 @@ void FadeRenderJob::updateFadeEdit(const render::ItemBound& itemBounds) { default: assert(false); } + + if (_parameters->_isManualThresholdEnabled) { + _editThreshold = _parameters->_manualThreshold; + } } void FadeRenderJob::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation) { @@ -496,9 +502,12 @@ bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline eventCategory = _currentInstance->_parameters->_editedCategory; threshold = _currentInstance->_editThreshold; noiseOffset += _currentInstance->_editNoiseOffset; - baseOffset += _currentInstance->_editBaseOffset; + // This works supposing offset is the world position of the object that is fading. + baseOffset = _currentInstance->_editBaseOffset - offset; } + threshold = (threshold-0.5f)*_currentInstance->_parameters->_thresholdScale[eventCategory] + 0.5f; + batch._glUniform1i(fadeCategoryLocation, eventCategory); batch._glUniform1f(fadeThresholdLocation, threshold); // This is really temporary diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index dce5687151..a441ce831d 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -52,6 +52,8 @@ class FadeJobConfig : public render::Job::Config { Q_PROPERTY(float edgeOuterColorG READ getEdgeOuterColorG WRITE setEdgeOuterColorG NOTIFY dirty) Q_PROPERTY(float edgeOuterColorB READ getEdgeOuterColorB WRITE setEdgeOuterColorB NOTIFY dirty) Q_PROPERTY(float edgeOuterIntensity READ getEdgeOuterIntensity WRITE setEdgeOuterIntensity NOTIFY dirty) + Q_PROPERTY(bool manualFade MEMBER manualFade NOTIFY dirty) + Q_PROPERTY(float manualThreshold MEMBER manualThreshold NOTIFY dirty) public: @@ -124,10 +126,12 @@ public: void setEdgeOuterIntensity(float value); float getEdgeOuterIntensity() const { return edgeOuterColor[editedCategory].a; } - + + bool manualFade{ false }; + float manualThreshold{ 0.f }; int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]{ - { 1.f, 1.f, 1.f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 0.75f, 0.75f, 0.75f }, // ELEMENT_ENTER_LEAVE_DOMAIN { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER { 10.f, 0.01f, 10.0f }, // USER_ENTER_LEAVE_DOMAIN @@ -201,6 +205,9 @@ struct FadeCommonParameters using Pointer = std::shared_ptr; bool _isEditEnabled{ false }; + bool _isManualThresholdEnabled{ false }; + float _manualThreshold{ 0.f }; + float _thresholdScale[FadeJobConfig::EVENT_CATEGORY_COUNT]; int _editedCategory{ FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN }; float _durations[FadeJobConfig::EVENT_CATEGORY_COUNT]{ 30.0f, // ELEMENT_ENTER_LEAVE_DOMAIN @@ -312,15 +319,16 @@ private: render::ShapePlumberPointer _shapePlumber; FadeCommonParameters::Pointer _parameters; - float computeElementEnterThreshold(double time) const; + float computeElementEnterThreshold(double time, const double period) const; // Everything needed for interactive edition - uint64_t _editStartTime{ 0 }; + uint64_t _editPreviousTime{ 0 }; + double _editTime{ 0.0 }; float _editThreshold{ 0.f }; glm::vec3 _editNoiseOffset{ 0.f, 0.f, 0.f }; glm::vec3 _editBaseOffset{ 0.f, 0.f, 0.f }; - void updateFadeEdit(const render::ItemBound& itemBounds); + void updateFadeEdit(const render::RenderContextPointer& renderContext, const render::ItemBound& itemBounds); }; #endif // hifi_FadeEffect_h diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf index 7c70dabda2..d5f0c56b4b 100644 --- a/libraries/render-utils/src/model_normal_map_fade.slf +++ b/libraries/render-utils/src/model_normal_map_fade.slf @@ -66,7 +66,7 @@ void main(void) { albedo, roughness, getMaterialMetallic(mat), - emissive, + emissive+fadeEmissive, occlusionTex, scattering); } diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index 9b6ef95837..8b3885d230 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -46,6 +46,25 @@ Column { } } } + Row { + CheckBox { + text: "Manual" + checked: root.config["manualFade"] + onCheckedChanged: { + root.config["manualFade"] = checked; + } + } + ConfigSlider { + label: "Threshold" + integral: false + config: root.config + property: "manualThreshold" + max: 1.0 + min: 0.0 + width: 400 + } + } + Component { id: paramWidgets