diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 2c897a25f4..8c64710fde 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -9,11 +9,18 @@ <@if not FADE_SLH@> <@def FADE_SLH@> -<@func declareFade()@> +<@func transformModelToFadePos(objectTransform, objectPosition, fadePosition)@> + { + <$transformModelToWorldPos($objectTransform$, $objectPosition$, $fadePosition$)$> + <$fadePosition$> -= vec4(<$objectTransform$>._model[3].xyz, 0.f); + } +<@endfunc@> + +<@func declareFadeFragment()@> struct Fade { vec3 _Offset; - float _Percent; + float _Percent; }; uniform fadeBuffer { @@ -30,8 +37,8 @@ float evalFadeMask(vec3 position, vec3 normal) { const float FADE_MASK_INV_SCALE = 1.0; // Do tri-linear interpolation - vec3 noisePosition = position * FADE_MASK_INV_SCALE; - vec3 noisePositionFloored = floor(noisePosition) + fade._Offset; + vec3 noisePosition = position * FADE_MASK_INV_SCALE + fade._Offset; + vec3 noisePositionFloored = floor(noisePosition); vec3 noisePositionFraction = fract(noisePosition); float noiseLowXLowYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored), 0).r; float noiseLowXHighYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(0,1,0)), 0).r; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 276e6652be..5503f4a49d 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -523,37 +523,40 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline: batch.setModelTransform(_transform); } -float ModelMeshPartPayload::computeFadePercent(bool isDebugEnabled) const { - if (!isDebugEnabled) { - if (_fadeState == FADE_WAITING_TO_START) { - return 0.0f; - } - float fadeAlpha = 1.0f; - const float INV_FADE_PERIOD = 1.0f / (float)(3 * USECS_PER_SECOND); - float fraction = (float)(usecTimestampNow() - _fadeStartTime) * INV_FADE_PERIOD; - if (fraction < 1.0f) { - fadeAlpha = Interpolate::simpleNonLinearBlend(fraction); - } - if (fadeAlpha >= 1.0f) { - _fadeState = FADE_COMPLETE; - // when fade-in completes we flag model for one last "render item update" - _model->setRenderItemsNeedUpdate(); - return 1.0f; - } - return Interpolate::simpleNonLinearBlend(fadeAlpha); +float ModelMeshPartPayload::computeFadePercent() const { + if (_fadeState == FADE_WAITING_TO_START) { + return 0.0f; } - else { - // Animate fade for debugging purposes during repeated 3 second cycles - return (usecTimestampNow() % (3 * USECS_PER_SECOND)) / (float)(3 * USECS_PER_SECOND); + float fadeAlpha = 1.0f; + const float INV_FADE_PERIOD = 1.0f / (float)(3 * USECS_PER_SECOND); + float fraction = (float)(usecTimestampNow() - _fadeStartTime) * INV_FADE_PERIOD; + if (fraction < 1.0f) { + fadeAlpha = Interpolate::simpleNonLinearBlend(fraction); } + if (fadeAlpha >= 1.0f) { + _fadeState = FADE_COMPLETE; + // when fade-in completes we flag model for one last "render item update" + _model->setRenderItemsNeedUpdate(); + return 1.0f; + } + return Interpolate::simpleNonLinearBlend(fadeAlpha); } -void ModelMeshPartPayload::bindFade(gpu::Batch& batch, bool isDebugEnabled) const { +void ModelMeshPartPayload::bindFade(gpu::Batch& batch, const RenderArgs* args) const { + const bool isDebugEnabled = (args->_debugFlags & RenderArgs::RENDER_DEBUG_FADE) != 0; + if (_fadeState != FADE_COMPLETE || isDebugEnabled) { auto& fade = _fadeBuffer.edit(); glm::vec3 offset = _transform.getTranslation(); - fade._percent = computeFadePercent(isDebugEnabled); + // A bit ugly to have the test at every bind... + if (!isDebugEnabled) { + fade._percent = computeFadePercent(); + } + else { + fade._percent = args->_debugFadePercent; + } + fade._offset = offset; batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::FADE, _fadeBuffer); } @@ -605,7 +608,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { bindMaterial(batch, locations, args->_enableTexturing); // Apply fade effect - bindFade(batch, (args->_debugFlags & RenderArgs::RENDER_DEBUG_FADE) != 0); + bindFade(batch, args); args->_details._materialSwitches++; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 359cfe086c..2f6b62f94d 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -93,7 +93,7 @@ public: const Transform& boundTransform, const gpu::BufferPointer& buffer); - float computeFadePercent(bool isDebugEnabled) const; + float computeFadePercent() const; // Render Item interface render::ItemKey getKey() const override; @@ -104,7 +104,7 @@ public: // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) override; void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; - void bindFade(gpu::Batch& batch, bool isDebugEnabled) const; + void bindFade(gpu::Batch& batch, const RenderArgs* args) const; void initCache(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 1dd212fea3..a9232300e7 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -325,6 +325,7 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const if (_debugFade) { args->_debugFlags = static_cast(args->_debugFlags | static_cast(RenderArgs::RENDER_DEBUG_FADE)); + args->_debugFadePercent = _debugFadePercent; // Force fade for everyone keyBuilder.withFade(); } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index c8f3326486..4ab4915358 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -87,12 +87,14 @@ class DrawStateSortConfig : public render::Job::Config { Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) Q_PROPERTY(bool stateSort MEMBER stateSort NOTIFY dirty) Q_PROPERTY(bool debugFade MEMBER debugFade NOTIFY dirty) + Q_PROPERTY(float debugFadePercent MEMBER debugFadePercent NOTIFY dirty) public: int getNumDrawn() { return numDrawn; } void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } int maxDrawn{ -1 }; + float debugFadePercent{ 0.f }; bool stateSort{ true }; bool debugFade{ false }; @@ -113,13 +115,14 @@ public: DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber, gpu::TexturePointer fadeMaskMap) : _shapePlumber{ shapePlumber }, _fadeMaskMap{ fadeMaskMap } {} - void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; _debugFade = config.debugFade; } + void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; _debugFadePercent = config.debugFadePercent; _debugFade = config.debugFade; } void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: render::ShapePlumberPointer _shapePlumber; gpu::TexturePointer _fadeMaskMap; int _maxDrawn; // initialized by Config + float _debugFadePercent; bool _stateSort; bool _debugFade; }; diff --git a/libraries/render-utils/src/model_fade.slf b/libraries/render-utils/src/model_fade.slf index 06b2695d2b..4c497228c8 100644 --- a/libraries/render-utils/src/model_fade.slf +++ b/libraries/render-utils/src/model_fade.slf @@ -19,10 +19,10 @@ <$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> <@include Fade.slh@> -<$declareFade()$> +<$declareFadeFragment()$> in vec4 _position; -in vec4 _worldPosition; +in vec4 _worldFadePosition; in vec3 _normal; in vec3 _color; in vec2 _texCoord0; @@ -30,7 +30,7 @@ in vec2 _texCoord1; void main(void) { - applyFade(_worldPosition.xyz, _normal); + applyFade(_worldFadePosition.xyz, _normal); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_fade.slv b/libraries/render-utils/src/model_fade.slv index 4e6e02c1ad..1db3103553 100644 --- a/libraries/render-utils/src/model_fade.slv +++ b/libraries/render-utils/src/model_fade.slv @@ -19,12 +19,14 @@ <@include MaterialTextures.slh@> <$declareMaterialTexMapArrayBuffer()$> +<@include Fade.slh@> + out vec3 _color; out float _alpha; out vec2 _texCoord0; out vec2 _texCoord1; out vec4 _position; -out vec4 _worldPosition; +out vec4 _worldFadePosition; out vec3 _normal; void main(void) { @@ -39,6 +41,6 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> - <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> + <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> } diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf index 4586fe555a..9f85a956d0 100644 --- a/libraries/render-utils/src/model_normal_map_fade.slf +++ b/libraries/render-utils/src/model_normal_map_fade.slf @@ -20,10 +20,10 @@ <$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION, SCATTERING)$> <@include Fade.slh@> -<$declareFade()$> +<$declareFadeFragment()$> in vec4 _position; -in vec4 _worldPosition; +in vec4 _worldFadePosition; in vec2 _texCoord0; in vec2 _texCoord1; in vec3 _normal; @@ -31,7 +31,7 @@ in vec3 _tangent; in vec3 _color; void main(void) { - applyFade(_worldPosition.xyz, _normal); + applyFade(_worldFadePosition.xyz, _normal); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_normal_map_fade.slv b/libraries/render-utils/src/model_normal_map_fade.slv index a71900d5c3..7250c1e842 100644 --- a/libraries/render-utils/src/model_normal_map_fade.slv +++ b/libraries/render-utils/src/model_normal_map_fade.slv @@ -20,8 +20,10 @@ <@include MaterialTextures.slh@> <$declareMaterialTexMapArrayBuffer()$> +<@include Fade.slh@> + out vec4 _position; -out vec4 _worldPosition; +out vec4 _worldFadePosition; out vec2 _texCoord0; out vec2 _texCoord1; out vec3 _normal; @@ -42,7 +44,7 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> - <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> + <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> <$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$> } diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 8fe65fb5a6..ce31013918 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -133,6 +133,7 @@ public: RenderDetails _details; render::ScenePointer _scene; // HACK int8_t _cameraMode { -1 }; // HACK + float _debugFadePercent{ 0.f }; // HACK too }; #endif // hifi_RenderArgs_h diff --git a/scripts/developer/utilities/render/debugFade.js b/scripts/developer/utilities/render/debugFade.js new file mode 100644 index 0000000000..8b79905e11 --- /dev/null +++ b/scripts/developer/utilities/render/debugFade.js @@ -0,0 +1,21 @@ +// +// debugFade.js +// developer/utilities/render +// +// Olivier Prat, created on 30/04/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 +// + +// Set up the qml ui +var qml = Script.resolvePath('fade.qml'); +var window = new OverlayWindow({ + title: 'Fade', + source: qml, + width: 400, + height: 80 +}); +window.setPosition(50, 50); +window.closed.connect(function() { Script.stop(); }); \ No newline at end of file diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml new file mode 100644 index 0000000000..3d391923ff --- /dev/null +++ b/scripts/developer/utilities/render/fade.qml @@ -0,0 +1,33 @@ +// +// fade.qml +// developer/utilities/render +// +// Olivier Prat, created on 30/04/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import "configSlider" + +Column { + id: root + spacing: 8 + property var drawOpaqueConfig: Render.getConfig("DrawOpaqueDeferred"); + + CheckBox { + text: "Force Fade" + checked: drawOpaqueConfig["debugFade"] + onCheckedChanged: { drawOpaqueConfig["debugFade"] = checked } + } + ConfigSlider { + label: "Percent" + integral: false + config: drawOpaqueConfig + property: "debugFadePercent" + max: 1.0 + min: 0.0 + } +}