From 8071c04e98d1837ae2f2bef4c28b0c6c1f121e47 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 27 Apr 2017 10:31:06 +0200 Subject: [PATCH 01/86] Added fade effect prototype version --- interface/resources/images/fadeMask.png | Bin 0 -> 68932 bytes libraries/render-utils/src/Fade.slh | 59 +++++++++++++++ .../render-utils/src/MeshPartPayload.cpp | 68 +++++++++++------ libraries/render-utils/src/MeshPartPayload.h | 7 +- .../render-utils/src/RenderDeferredTask.cpp | 25 ++++++- .../render-utils/src/RenderDeferredTask.h | 8 +- .../render-utils/src/RenderPipelines.cpp | 22 ++++++ libraries/render-utils/src/model_fade.slf | 65 ++++++++++++++++ libraries/render-utils/src/model_fade.slv | 44 +++++++++++ .../src/model_normal_map_fade.slf | 70 ++++++++++++++++++ .../src/model_normal_map_fade.slv | 48 ++++++++++++ libraries/render/src/render/ShapePipeline.cpp | 4 + libraries/render/src/render/ShapePipeline.h | 11 +++ libraries/shared/src/RenderArgs.h | 3 +- 14 files changed, 407 insertions(+), 27 deletions(-) create mode 100644 interface/resources/images/fadeMask.png create mode 100644 libraries/render-utils/src/Fade.slh create mode 100644 libraries/render-utils/src/model_fade.slf create mode 100644 libraries/render-utils/src/model_fade.slv create mode 100644 libraries/render-utils/src/model_normal_map_fade.slf create mode 100644 libraries/render-utils/src/model_normal_map_fade.slv diff --git a/interface/resources/images/fadeMask.png b/interface/resources/images/fadeMask.png new file mode 100644 index 0000000000000000000000000000000000000000..9c342ba7888ab0d66a59dc448e30d9bdfd8204d7 GIT binary patch literal 68932 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 literal 0 HcmV?d00001 diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh new file mode 100644 index 0000000000..a40f1048a8 --- /dev/null +++ b/libraries/render-utils/src/Fade.slh @@ -0,0 +1,59 @@ +// Generated on <$_SCRIBE_DATE$> +// +// Created by Olivier Prat on 04/12/17. +// 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 +// +<@if not FADE_SLH@> +<@def FADE_SLH@> + +<@func declareFade()@> + +struct Fade { + vec3 _Offset; + float _Percent; +}; + +uniform fadeBuffer { + Fade fade; +}; + +uniform sampler2D fadeMaskMap; + +vec2 hash2D(vec3 position) { + return position.xy* vec2(0.1677, 0.221765) + position.z*0.561; +} + +float evalFadeMask(vec3 position, vec3 normal) { + const float FADE_MASK_INV_SCALE = 3.0; + + // Do tri-linear interpolation + vec3 noisePosition = position * FADE_MASK_INV_SCALE; + vec3 noisePositionFloored = floor(noisePosition) + fade._Offset; + vec3 noisePositionFraction = fract(noisePosition); + float noiseLowXLowYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored), 0).r; + float noiseLowXHighYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(0,1,0)), 0).r; + float noiseHighXLowYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,0,0)), 0).r; + float noiseHighXHighYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,1,0)), 0).r; + float noiseLowXLowYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(0,0,1)), 0).r; + float noiseLowXHighYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(0,1,1)), 0).r; + float noiseHighXLowYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,0,1)), 0).r; + float noiseHighXHighYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,1,1)), 0).r; + vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ); + vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ); + vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z); + vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x); + + return mix(maskY.x, maskY.y, noisePositionFraction.y); +} + +void applyFade(vec3 position, vec3 normal) { + if (evalFadeMask(position, normal) < fade._Percent) { + discard; + } +} +<@endfunc@> + +<@endif@> \ No newline at end of file diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 51ce0fffa7..57070479b6 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -321,11 +321,20 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren } } +struct ModelMeshPartPayload::Fade +{ + glm::vec3 _offset; // The noise offset + float _percent; // The fade percent +}; + ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : _model(model), _meshIndex(_meshIndex), _shapeID(shapeIndex) { + Fade fade; + _fadeBuffer = gpu::BufferView(std::make_shared(sizeof(Fade), (const gpu::Byte*) &fade)); + assert(_model && _model->isLoaded()); auto& modelMesh = _model->getGeometry()->getMeshes().at(_meshIndex); updateMeshPart(modelMesh, partIndex); @@ -461,7 +470,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { ShapeKey::Builder builder; builder.withMaterial(); - if (isTranslucent || _fadeState != FADE_COMPLETE) { + if (isTranslucent) { builder.withTranslucent(); } if (hasTangents) { @@ -482,6 +491,9 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { if (wireframe) { builder.withWireframe(); } + if (_fadeState != FADE_COMPLETE) { + builder.withFade(); + } return builder.build(); } @@ -501,12 +513,6 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { batch.setInputBuffer(1, _model->_blendedVertexBuffers[_meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3)); batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); } - - if (_fadeState != FADE_COMPLETE) { - batch._glColor4f(1.0f, 1.0f, 1.0f, computeFadeAlpha()); - } else if (!_hasColorAttrib) { - batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } } void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { @@ -517,23 +523,40 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline: batch.setModelTransform(_transform); } -float ModelMeshPartPayload::computeFadeAlpha() const { - if (_fadeState == FADE_WAITING_TO_START) { - return 0.0f; +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)(1 * 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 fadeAlpha = 1.0f; - const float INV_FADE_PERIOD = 1.0f / (float)(1 * USECS_PER_SECOND); - float fraction = (float)(usecTimestampNow() - _fadeStartTime) * INV_FADE_PERIOD; - if (fraction < 1.0f) { - fadeAlpha = Interpolate::simpleNonLinearBlend(fraction); + else { + // Animate fade for debugging purposes during repeated 3 second cycles + return (usecTimestampNow() % (3 * USECS_PER_SECOND)) / (float)(3 * USECS_PER_SECOND); } - 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; +} + +void ModelMeshPartPayload::bindFade(gpu::Batch& batch, bool isDebugEnabled) const { + if (_fadeState != FADE_COMPLETE || isDebugEnabled) { + auto& fade = _fadeBuffer.edit(); + glm::vec3 offset = _transform.getTranslation(); + + fade._percent = computeFadePercent(isDebugEnabled); + fade._offset = offset; + batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::FADE, _fadeBuffer); } - return Interpolate::simpleNonLinearBlend(fadeAlpha); } void ModelMeshPartPayload::render(RenderArgs* args) const { @@ -576,6 +599,9 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { // apply material properties bindMaterial(batch, locations, args->_enableTexturing); + // Apply fade effect + bindFade(batch, (args->_debugFlags & RenderArgs::RENDER_DEBUG_FADE) != 0); + args->_details._materialSwitches++; // Draw! diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index ef74011c40..ffffb9ec88 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 computeFadeAlpha() const; + float computeFadePercent(bool isDebugEnabled) const; // Render Item interface render::ItemKey getKey() const override; @@ -104,6 +104,7 @@ public: // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) const 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 initCache(); @@ -119,6 +120,10 @@ public: bool _isBlendShaped{ false }; private: + + struct Fade; + + mutable gpu::BufferView _fadeBuffer; mutable quint64 _fadeStartTime { 0 }; mutable uint8_t _fadeState { FADE_WAITING_TO_START }; }; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 313b176f19..1dd212fea3 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -86,9 +86,13 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto deferredFramebuffer = prepareDeferredOutputs.getN(0); const auto lightingFramebuffer = prepareDeferredOutputs.getN(1); + // Fade texture mask + auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png"; + auto fadeMaskMap = DependencyManager::get()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); + // Render opaque objects in DeferredBuffer const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying(); - task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber); + task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber, fadeMaskMap); // Once opaque is all rendered create stencil background task.addJob("DrawOpaqueStencil", deferredFramebuffer); @@ -310,11 +314,21 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const // Setup lighting model for all items; batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); - // From the lighting model define a global shapKey ORED with individiual keys + // From the lighting model define a global shapeKey ORED with individiual keys ShapeKey::Builder keyBuilder; if (lightingModel->isWireframeEnabled()) { keyBuilder.withWireframe(); } + + // Prepare fade effect + batch.setResourceTexture(ShapePipeline::Slot::MAP::FADE_MASK, _fadeMaskMap); + if (_debugFade) { + args->_debugFlags = static_cast(args->_debugFlags | + static_cast(RenderArgs::RENDER_DEBUG_FADE)); + // Force fade for everyone + keyBuilder.withFade(); + } + ShapeKey globalKey = keyBuilder.build(); args->_globalShapeKey = globalKey._flags.to_ulong(); @@ -325,6 +339,13 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const } args->_batch = nullptr; args->_globalShapeKey = 0; + + // Not sure this is really needed... + if (_debugFade) { + // Turn off fade debug + args->_debugFlags = static_cast(args->_debugFlags & + ~static_cast(RenderArgs::RENDER_DEBUG_FADE)); + } }); config->setNumDrawn((int)inItems.size()); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 12ecd5ecaf..c8f3326486 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -86,6 +86,7 @@ class DrawStateSortConfig : public render::Job::Config { Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) Q_PROPERTY(bool stateSort MEMBER stateSort NOTIFY dirty) + Q_PROPERTY(bool debugFade MEMBER debugFade NOTIFY dirty) public: int getNumDrawn() { return numDrawn; } @@ -93,6 +94,7 @@ public: int maxDrawn{ -1 }; bool stateSort{ true }; + bool debugFade{ false }; signals: void numDrawnChanged(); @@ -109,15 +111,17 @@ public: using Config = DrawStateSortConfig; using JobModel = render::Job::ModelI; - DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber, gpu::TexturePointer fadeMaskMap) : _shapePlumber{ shapePlumber }, _fadeMaskMap{ fadeMaskMap } {} - void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; } + void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; _debugFade = config.debugFade; } void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: render::ShapePlumberPointer _shapePlumber; + gpu::TexturePointer _fadeMaskMap; int _maxDrawn; // initialized by Config bool _stateSort; + bool _debugFade; }; class DeferredFramebuffer; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index da264cbf7d..763fca04ed 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -41,6 +41,12 @@ #include "model_normal_specular_map_frag.h" #include "model_specular_map_frag.h" +#include "model_fade_vert.h" +#include "model_normal_map_fade_vert.h" + +#include "model_fade_frag.h" +#include "model_normal_map_fade_frag.h" + #include "forward_model_frag.h" #include "forward_model_unlit_frag.h" #include "forward_model_normal_map_frag.h" @@ -151,6 +157,10 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)); auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); + // Only models can have fade applied to them (?) + auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_fade_vert)); + auto modelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_normal_map_fade_vert)); + // Pixel shaders auto simplePixel = gpu::Shader::createPixel(std::string(simple_textured_frag)); auto simpleUnlitPixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag)); @@ -169,6 +179,10 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag)); auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)); + // Only models can have fade applied to them (?) + auto modelFadePixel = gpu::Shader::createPixel(std::string(model_fade_frag)); + auto modelNormalMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_map_fade_frag)); + using Key = render::ShapeKey; auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3); // TODO: Refactor this to use a filter @@ -194,6 +208,14 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withMaterial().withTangents().withSpecular(), modelNormalMapVertex, modelNormalSpecularMapPixel); + // Same thing but with Fade on + addPipeline( + Key::Builder().withMaterial().withFade(), + modelFadeVertex, modelFadePixel); + addPipeline( + Key::Builder().withMaterial().withTangents().withFade(), + modelNormalMapFadeVertex, modelNormalMapFadePixel); + // Translucents addPipeline( Key::Builder().withMaterial().withTranslucent(), diff --git a/libraries/render-utils/src/model_fade.slf b/libraries/render-utils/src/model_fade.slf new file mode 100644 index 0000000000..06b2695d2b --- /dev/null +++ b/libraries/render-utils/src/model_fade.slf @@ -0,0 +1,65 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// model_fade.frag +// fragment shader +// +// Created by Olivier Prat on 04/19/17. +// 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 DeferredBufferWrite.slh@> + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +<@include Fade.slh@> +<$declareFade()$> + +in vec4 _position; +in vec4 _worldPosition; +in vec3 _normal; +in vec3 _color; +in vec2 _texCoord0; +in vec2 _texCoord1; + + +void main(void) { + applyFade(_worldPosition.xyz, _normal); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + float scattering = getMaterialScattering(mat); + + packDeferredFragment( + normalize(_normal.xyz), + opacity, + albedo, + roughness, + getMaterialMetallic(mat), + emissive, + occlusionTex, + scattering); +} diff --git a/libraries/render-utils/src/model_fade.slv b/libraries/render-utils/src/model_fade.slv new file mode 100644 index 0000000000..4e6e02c1ad --- /dev/null +++ b/libraries/render-utils/src/model_fade.slv @@ -0,0 +1,44 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// model_fade.slv +// vertex shader +// +// Created by Olivier Prat on 04/24/17. +// 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out vec3 _color; +out float _alpha; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec4 _position; +out vec4 _worldPosition; +out vec3 _normal; + +void main(void) { + _color = colorToLinearRGB(inColor.xyz); + _alpha = inColor.w; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> + <$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 new file mode 100644 index 0000000000..4586fe555a --- /dev/null +++ b/libraries/render-utils/src/model_normal_map_fade.slf @@ -0,0 +1,70 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_normal_map_fade.frag +// fragment shader +// +// Created by Olivier Prat on 04/19/17. +// 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 DeferredBufferWrite.slh@> + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION, SCATTERING)$> + +<@include Fade.slh@> +<$declareFade()$> + +in vec4 _position; +in vec4 _worldPosition; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; + +void main(void) { + applyFade(_worldPosition.xyz, _normal); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, scatteringTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + vec3 viewNormal; + <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> + + float scattering = getMaterialScattering(mat); + <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; + + packDeferredFragment( + viewNormal, + opacity, + albedo, + roughness, + getMaterialMetallic(mat), + emissive, + occlusionTex, + scattering); +} diff --git a/libraries/render-utils/src/model_normal_map_fade.slv b/libraries/render-utils/src/model_normal_map_fade.slv new file mode 100644 index 0000000000..a71900d5c3 --- /dev/null +++ b/libraries/render-utils/src/model_normal_map_fade.slv @@ -0,0 +1,48 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_normal_map_fade.vert +// vertex shader +// +// Created by Olivier Prat on 04/24/17. +// 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out vec4 _position; +out vec4 _worldPosition; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec3 _normal; +out vec3 _tangent; +out vec3 _color; +out float _alpha; + +void main(void) { + // pass along the color + _color = colorToLinearRGB(inColor.rgb); + _alpha = inColor.a; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$> +} diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index d51d7f8cb6..77f7f61801 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -69,6 +69,8 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::BUFFER::LIGHT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK)); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeBuffer"), Slot::BUFFER::FADE)); gpu::Shader::makeProgram(*program, slotBindings); @@ -87,6 +89,8 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->lightBufferUnit = program->getUniformBuffers().findLocation("lightBuffer"); locations->lightAmbientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer"); locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap"); + locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap"); + locations->fadeBufferUnit = program->getUniformBuffers().findLocation("fadeBuffer"); ShapeKey key{filter._flags}; auto gpuPipeline = gpu::Pipeline::create(program, state); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 73e8f82f24..b8045dfbcc 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -33,6 +33,7 @@ public: DEPTH_BIAS, WIREFRAME, NO_CULL_FACE, + FADE, OWN_PIPELINE, INVALID, @@ -68,6 +69,7 @@ public: Builder& withDepthBias() { _flags.set(DEPTH_BIAS); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } Builder& withoutCullFace() { _flags.set(NO_CULL_FACE); return (*this); } + Builder& withFade() { _flags.set(FADE); return (*this); } Builder& withOwnPipeline() { _flags.set(OWN_PIPELINE); return (*this); } Builder& invalidate() { _flags.set(INVALID); return (*this); } @@ -126,6 +128,9 @@ public: Builder& withCullFace() { _flags.reset(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); } Builder& withoutCullFace() { _flags.set(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); } + Builder& withFade() { _flags.reset(FADE); _mask.set(FADE); return (*this); } + Builder& withoutFade() { _flags.set(FADE); _mask.set(FADE); return (*this); } + protected: friend class Filter; Flags _flags{0}; @@ -150,6 +155,7 @@ public: bool isDepthBiased() const { return _flags[DEPTH_BIAS]; } bool isWireframe() const { return _flags[WIREFRAME]; } bool isCullFace() const { return !_flags[NO_CULL_FACE]; } + bool isFaded() const { return _flags[FADE]; } bool hasOwnPipeline() const { return _flags[OWN_PIPELINE]; } bool isValid() const { return !_flags[INVALID]; } @@ -186,6 +192,7 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& key) { << "isDepthBiased:" << key.isDepthBiased() << "isWireframe:" << key.isWireframe() << "isCullFace:" << key.isCullFace() + << "isFaded:" << key.isFaded() << "]"; } } else { @@ -207,6 +214,7 @@ public: LIGHTING_MODEL, LIGHT, LIGHT_AMBIENT_BUFFER, + FADE, }; enum MAP { @@ -218,6 +226,7 @@ public: OCCLUSION, SCATTERING, LIGHT_AMBIENT, + FADE_MASK, }; }; @@ -236,6 +245,8 @@ public: int lightBufferUnit; int lightAmbientBufferUnit; int lightAmbientMapUnit; + int fadeBufferUnit; + int fadeMaskTextureUnit; }; using LocationsPointer = std::shared_ptr; diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 10a9a20287..8fe65fb5a6 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -79,7 +79,8 @@ public: enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT }; enum DebugFlags { RENDER_DEBUG_NONE = 0, - RENDER_DEBUG_HULLS = 1 + RENDER_DEBUG_HULLS = 1, + RENDER_DEBUG_FADE = 2, }; RenderArgs(std::shared_ptr context = nullptr, From 111f0762eac9203aadc33be5db15fbc5b46e7367 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Sun, 30 Apr 2017 14:42:27 +0200 Subject: [PATCH 02/86] Added debug scripts and fade position is now stable --- libraries/render-utils/src/Fade.slh | 15 ++++-- .../render-utils/src/MeshPartPayload.cpp | 51 ++++++++++--------- libraries/render-utils/src/MeshPartPayload.h | 4 +- .../render-utils/src/RenderDeferredTask.cpp | 1 + .../render-utils/src/RenderDeferredTask.h | 5 +- libraries/render-utils/src/model_fade.slf | 6 +-- libraries/render-utils/src/model_fade.slv | 6 ++- .../src/model_normal_map_fade.slf | 6 +-- .../src/model_normal_map_fade.slv | 6 ++- libraries/shared/src/RenderArgs.h | 1 + .../developer/utilities/render/debugFade.js | 21 ++++++++ scripts/developer/utilities/render/fade.qml | 33 ++++++++++++ 12 files changed, 114 insertions(+), 41 deletions(-) create mode 100644 scripts/developer/utilities/render/debugFade.js create mode 100644 scripts/developer/utilities/render/fade.qml 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 + } +} From 08fcd6c357bfa41492307cdfe758aecf81d69983 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 5 Jun 2017 16:32:36 +0200 Subject: [PATCH 03/86] Added new shaders --- libraries/render-utils/src/Fade.slh | 6 +- .../render-utils/src/MeshPartPayload.cpp | 14 +-- .../render-utils/src/RenderDeferredTask.cpp | 19 +++- .../render-utils/src/RenderDeferredTask.h | 33 ++++--- .../render-utils/src/RenderPipelines.cpp | 78 ++++++++++++++- libraries/render-utils/src/model_fade.slf | 2 +- .../render-utils/src/model_lightmap_fade.slf | 50 ++++++++++ .../render-utils/src/model_lightmap_fade.slv | 48 +++++++++ .../src/model_lightmap_normal_map_fade.slf | 53 ++++++++++ .../src/model_lightmap_normal_map_fade.slv | 48 +++++++++ ...odel_lightmap_normal_specular_map_fade.slf | 53 ++++++++++ .../src/model_lightmap_specular_map_fade.slf | 49 ++++++++++ .../src/model_normal_map_fade.slf | 2 +- .../src/model_normal_specular_map_fade.slf | 72 ++++++++++++++ .../src/model_specular_map_fade.slf | 68 +++++++++++++ .../render-utils/src/model_unlit_fade.slf | 50 ++++++++++ libraries/render-utils/src/simple_fade.slf | 97 +++++++++++++++++++ libraries/render-utils/src/simple_fade.slv | 42 ++++++++ .../render-utils/src/simple_textured_fade.slf | 60 ++++++++++++ .../src/simple_textured_unlit_fade.slf | 54 +++++++++++ .../render-utils/src/skin_model_fade.slv | 55 +++++++++++ .../src/skin_model_normal_map_fade.slv | 64 ++++++++++++ plugins/openvr/src/ViveControllerManager.h | 2 +- .../developer/utilities/render/debugFade.js | 2 +- scripts/developer/utilities/render/fade.qml | 53 +++++++--- 25 files changed, 1030 insertions(+), 44 deletions(-) create mode 100644 libraries/render-utils/src/model_lightmap_fade.slf create mode 100644 libraries/render-utils/src/model_lightmap_fade.slv create mode 100644 libraries/render-utils/src/model_lightmap_normal_map_fade.slf create mode 100644 libraries/render-utils/src/model_lightmap_normal_map_fade.slv create mode 100644 libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf create mode 100644 libraries/render-utils/src/model_lightmap_specular_map_fade.slf create mode 100644 libraries/render-utils/src/model_normal_specular_map_fade.slf create mode 100644 libraries/render-utils/src/model_specular_map_fade.slf create mode 100644 libraries/render-utils/src/model_unlit_fade.slf create mode 100644 libraries/render-utils/src/simple_fade.slf create mode 100644 libraries/render-utils/src/simple_fade.slv create mode 100644 libraries/render-utils/src/simple_textured_fade.slf create mode 100644 libraries/render-utils/src/simple_textured_unlit_fade.slf create mode 100644 libraries/render-utils/src/skin_model_fade.slv create mode 100644 libraries/render-utils/src/skin_model_normal_map_fade.slv diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 8c64710fde..06eed5b21f 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -33,7 +33,7 @@ vec2 hash2D(vec3 position) { return position.xy* vec2(0.1677, 0.221765) + position.z*0.561; } -float evalFadeMask(vec3 position, vec3 normal) { +float evalFadeMask(vec3 position) { const float FADE_MASK_INV_SCALE = 1.0; // Do tri-linear interpolation @@ -56,8 +56,8 @@ float evalFadeMask(vec3 position, vec3 normal) { return mix(maskY.x, maskY.y, noisePositionFraction.y); } -void applyFade(vec3 position, vec3 normal) { - if (evalFadeMask(position, normal) < fade._Percent) { +void applyFade(vec3 position) { + if (evalFadeMask(position) > fade._Percent) { discard; } } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 81f8dc3228..39f07e0232 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -400,10 +400,6 @@ ItemKey ModelMeshPartPayload::getKey() const { builder.withTransparent(); } } - - if (_fadeState != FADE_COMPLETE) { - builder.withTransparent(); - } } return builder.build(); } @@ -537,9 +533,9 @@ float ModelMeshPartPayload::computeFadePercent() const { 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) { + const double INV_FADE_PERIOD = 1.0 / (double)(10 * USECS_PER_SECOND); + double fraction = (double)(usecTimestampNow() - _fadeStartTime) * INV_FADE_PERIOD; + if (fraction < 1.0) { fadeAlpha = Interpolate::simpleNonLinearBlend(fraction); } if (fadeAlpha >= 1.0f) { @@ -549,9 +545,9 @@ float ModelMeshPartPayload::computeFadePercent() const { if (model) { model->setRenderItemsNeedUpdate(); } - return 1.0f; + fadeAlpha = 1.0f; } - return Interpolate::simpleNonLinearBlend(fadeAlpha); + return fadeAlpha; } void ModelMeshPartPayload::bindFade(gpu::Batch& batch, const RenderArgs* args) const { diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index fa6f72f3b5..412d74fe87 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -147,7 +147,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Render transparent objects forward in LightingBuffer const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying(); - task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); + task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber, fadeMaskMap); // LIght Cluster Grid Debuging job { @@ -276,6 +276,16 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& if (lightingModel->isWireframeEnabled()) { keyBuilder.withWireframe(); } + // Prepare fade effect + batch.setResourceTexture(ShapePipeline::Slot::MAP::FADE_MASK, _fadeMaskMap); + if (_debugFade) { + args->_debugFlags = static_cast(args->_debugFlags | + static_cast(RenderArgs::RENDER_DEBUG_FADE)); + args->_debugFadePercent = _debugFadePercent; + // Force fade for everyone + keyBuilder.withFade(); + } + ShapeKey globalKey = keyBuilder.build(); args->_globalShapeKey = globalKey._flags.to_ulong(); @@ -283,6 +293,13 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& args->_batch = nullptr; args->_globalShapeKey = 0; + + // Not sure this is really needed... + if (_debugFade) { + // Turn off fade debug + args->_debugFlags = static_cast(args->_debugFlags & + ~static_cast(RenderArgs::RENDER_DEBUG_FADE)); + } }); config->setNumDrawn((int)inItems.size()); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 4ab4915358..ebb7d34606 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -45,17 +45,31 @@ protected: }; +class DrawFadableDeferred { +protected: + DrawFadableDeferred(gpu::TexturePointer fadeMaskMap) : _fadeMaskMap{ fadeMaskMap } {} + + gpu::TexturePointer _fadeMaskMap; + float _debugFadePercent; + bool _stateSort; + bool _debugFade; +}; + class DrawConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY newStats) - Q_PROPERTY(int maxDrawn MEMBER maxDrawn 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 numDrawn) { _numDrawn = numDrawn; emit newStats(); } int maxDrawn{ -1 }; + float debugFadePercent{ 0.f }; + bool debugFade{ false }; signals: void newStats(); @@ -65,15 +79,15 @@ protected: int _numDrawn{ 0 }; }; -class DrawDeferred { +class DrawDeferred : public DrawFadableDeferred { public: using Inputs = render::VaryingSet2 ; using Config = DrawConfig; using JobModel = render::Job::ModelI; - DrawDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + DrawDeferred(render::ShapePlumberPointer shapePlumber, gpu::TexturePointer fadeMaskMap) : _shapePlumber{ shapePlumber }, DrawFadableDeferred{ fadeMaskMap } {} - void configure(const Config& config) { _maxDrawn = config.maxDrawn; } + void configure(const Config& config) { _maxDrawn = config.maxDrawn; _debugFadePercent = config.debugFadePercent; _debugFade = config.debugFade; } void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: @@ -94,8 +108,8 @@ public: void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } int maxDrawn{ -1 }; - float debugFadePercent{ 0.f }; bool stateSort{ true }; + float debugFadePercent{ 0.f }; bool debugFade{ false }; signals: @@ -106,25 +120,21 @@ protected: int numDrawn{ 0 }; }; -class DrawStateSortDeferred { +class DrawStateSortDeferred : public DrawFadableDeferred { public: using Inputs = render::VaryingSet2 ; using Config = DrawStateSortConfig; using JobModel = render::Job::ModelI; - DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber, gpu::TexturePointer fadeMaskMap) : _shapePlumber{ shapePlumber }, _fadeMaskMap{ fadeMaskMap } {} + DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber, gpu::TexturePointer fadeMaskMap) : _shapePlumber{ shapePlumber }, DrawFadableDeferred{ fadeMaskMap } {} 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; }; class DeferredFramebuffer; @@ -207,6 +217,7 @@ public: RenderDeferredTask() {} void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); + }; #endif // hifi_RenderDeferredTask_h diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 763fca04ed..d771b0f5cc 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -28,12 +28,22 @@ #include "skin_model_shadow_vert.h" #include "skin_model_normal_map_vert.h" +#include "skin_model_fade_vert.h" +#include "skin_model_normal_map_fade_vert.h" + +#include "model_lightmap_fade_vert.h" +#include "model_lightmap_normal_map_fade_vert.h" + #include "simple_vert.h" #include "simple_textured_frag.h" #include "simple_textured_unlit_frag.h" #include "simple_transparent_textured_frag.h" #include "simple_transparent_textured_unlit_frag.h" +#include "simple_fade_vert.h" +#include "simple_textured_fade_frag.h" +#include "simple_textured_unlit_fade_frag.h" + #include "model_frag.h" #include "model_unlit_frag.h" #include "model_shadow_frag.h" @@ -45,7 +55,10 @@ #include "model_normal_map_fade_vert.h" #include "model_fade_frag.h" +#include "model_unlit_fade_frag.h" #include "model_normal_map_fade_frag.h" +#include "model_normal_specular_map_fade_frag.h" +#include "model_specular_map_fade_frag.h" #include "forward_model_frag.h" #include "forward_model_unlit_frag.h" @@ -60,6 +73,11 @@ #include "model_translucent_frag.h" #include "model_translucent_unlit_frag.h" +#include "model_lightmap_fade_frag.h" +#include "model_lightmap_normal_map_fade_frag.h" +#include "model_lightmap_normal_specular_map_fade_frag.h" +#include "model_lightmap_specular_map_fade_frag.h" + #include "overlay3D_vert.h" #include "overlay3D_frag.h" #include "overlay3D_model_frag.h" @@ -156,10 +174,15 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert)); auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)); auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); + auto modelLightmapFadeVertex = gpu::Shader::createVertex(std::string(model_lightmap_fade_vert)); + auto modelLightmapNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_fade_vert)); + auto skinModelFadeVertex = gpu::Shader::createVertex(std::string(skin_model_fade_vert)); + auto skinModelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_fade_vert)); // Only models can have fade applied to them (?) auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_fade_vert)); auto modelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_normal_map_fade_vert)); + auto simpleFadeVertex = gpu::Shader::createVertex(std::string(simple_fade_vert)); // Pixel shaders auto simplePixel = gpu::Shader::createPixel(std::string(simple_textured_frag)); @@ -178,10 +201,18 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag)); auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag)); auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)); + auto modelLightmapFadePixel = gpu::Shader::createPixel(std::string(model_lightmap_fade_frag)); + auto modelLightmapNormalMapFadePixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_fade_frag)); + auto modelLightmapSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_fade_frag)); + auto modelLightmapNormalSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_fade_frag)); - // Only models can have fade applied to them (?) auto modelFadePixel = gpu::Shader::createPixel(std::string(model_fade_frag)); + auto modelUnlitFadePixel = gpu::Shader::createPixel(std::string(model_unlit_fade_frag)); auto modelNormalMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_map_fade_frag)); + auto modelSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_specular_map_fade_frag)); + auto modelNormalSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_fade_frag)); + auto simpleFadePixel = gpu::Shader::createPixel(std::string(simple_textured_fade_frag)); + auto simpleUnlitFadePixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_fade_frag)); using Key = render::ShapeKey; auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3); @@ -212,9 +243,24 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withMaterial().withFade(), modelFadeVertex, modelFadePixel); + addPipeline( + Key::Builder().withFade(), + simpleFadeVertex, simpleFadePixel); + addPipeline( + Key::Builder().withMaterial().withUnlit().withFade(), + modelFadeVertex, modelUnlitFadePixel); + addPipeline( + Key::Builder().withUnlit().withFade(), + simpleFadeVertex, simpleUnlitFadePixel); addPipeline( Key::Builder().withMaterial().withTangents().withFade(), modelNormalMapFadeVertex, modelNormalMapFadePixel); + addPipeline( + Key::Builder().withMaterial().withSpecular().withFade(), + modelFadeVertex, modelSpecularMapFadePixel); + addPipeline( + Key::Builder().withMaterial().withTangents().withSpecular().withFade(), + modelNormalMapFadeVertex, modelNormalSpecularMapFadePixel); // Translucents addPipeline( @@ -242,6 +288,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap(), modelVertex, modelTranslucentPixel); + // Lightmapped addPipeline( Key::Builder().withMaterial().withLightmap(), @@ -255,6 +302,20 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withMaterial().withLightmap().withTangents().withSpecular(), modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); + // Same thing but with Fade on + addPipeline( + Key::Builder().withMaterial().withLightmap().withFade(), + modelLightmapFadeVertex, modelLightmapFadePixel); + addPipeline( + Key::Builder().withMaterial().withLightmap().withTangents().withFade(), + modelLightmapNormalMapFadeVertex, modelLightmapNormalMapFadePixel); + addPipeline( + Key::Builder().withMaterial().withLightmap().withSpecular().withFade(), + modelLightmapFadeVertex, modelLightmapSpecularMapFadePixel); + addPipeline( + Key::Builder().withMaterial().withLightmap().withTangents().withSpecular().withFade(), + modelLightmapNormalMapFadeVertex, modelLightmapNormalSpecularMapFadePixel); + // Skinned addPipeline( Key::Builder().withMaterial().withSkinned(), @@ -268,6 +329,20 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(), skinModelNormalMapVertex, modelNormalSpecularMapPixel); + // Same thing but with Fade on + addPipeline( + Key::Builder().withMaterial().withSkinned().withFade(), + skinModelFadeVertex, modelFadePixel); + addPipeline( + Key::Builder().withMaterial().withSkinned().withTangents().withFade(), + skinModelNormalMapFadeVertex, modelNormalMapFadePixel); + addPipeline( + Key::Builder().withMaterial().withSkinned().withSpecular().withFade(), + skinModelFadeVertex, modelSpecularMapFadePixel); + addPipeline( + Key::Builder().withMaterial().withSkinned().withTangents().withSpecular().withFade(), + skinModelNormalMapFadeVertex, modelNormalSpecularMapFadePixel); + // Skinned and Translucent addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent(), @@ -281,6 +356,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(), skinModelNormalMapVertex, modelTranslucentPixel); + // Depth-only addPipeline( Key::Builder().withDepthOnly(), diff --git a/libraries/render-utils/src/model_fade.slf b/libraries/render-utils/src/model_fade.slf index 4c497228c8..1526dea7c2 100644 --- a/libraries/render-utils/src/model_fade.slf +++ b/libraries/render-utils/src/model_fade.slf @@ -30,7 +30,7 @@ in vec2 _texCoord1; void main(void) { - applyFade(_worldFadePosition.xyz, _normal); + applyFade(_worldFadePosition.xyz); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_lightmap_fade.slf b/libraries/render-utils/src/model_lightmap_fade.slf new file mode 100644 index 0000000000..f2055e7ffc --- /dev/null +++ b/libraries/render-utils/src/model_lightmap_fade.slf @@ -0,0 +1,50 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_lightmap_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 DeferredBufferWrite.slh@> + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS)$> +<$declareMaterialLightmap()$> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +in vec4 _position; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _color; +in vec4 _worldFadePosition; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> + + + packDeferredFragmentLightmap( + normalize(_normal), + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), + getMaterialAlbedo(mat) * albedo.rgb * _color, + getMaterialRoughness(mat) * roughness, + getMaterialMetallic(mat), + getMaterialFresnel(mat), + lightmapVal); +} diff --git a/libraries/render-utils/src/model_lightmap_fade.slv b/libraries/render-utils/src/model_lightmap_fade.slv new file mode 100644 index 0000000000..8ba9717b4c --- /dev/null +++ b/libraries/render-utils/src/model_lightmap_fade.slv @@ -0,0 +1,48 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_lightmap_fade.vert +// vertex shader +// +// Created by Olivier Prat on 06/05/17. +// 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include Fade.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out vec4 _position; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec3 _normal; +out vec3 _color; +out vec4 _worldFadePosition; + +void main(void) { + // pass along the color in linear space + _color = colorToLinearRGB(inColor.xyz); + + // and the texture coordinates + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> +} + diff --git a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf new file mode 100644 index 0000000000..137e40dd3c --- /dev/null +++ b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf @@ -0,0 +1,53 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_lightmap_normal_map_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 DeferredBufferWrite.slh@> + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL)$> +<$declareMaterialLightmap()$> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +in vec4 _position; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; +in vec4 _worldFadePosition; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> + + vec3 viewNormal; + <$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$> + + packDeferredFragmentLightmap( + normalize(viewNormal.xyz), + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), + getMaterialAlbedo(mat) * albedo.rgb * _color, + getMaterialRoughness(mat), + getMaterialMetallic(mat), + getMaterialFresnel(mat), + lightmapVal); +} diff --git a/libraries/render-utils/src/model_lightmap_normal_map_fade.slv b/libraries/render-utils/src/model_lightmap_normal_map_fade.slv new file mode 100644 index 0000000000..e081db103b --- /dev/null +++ b/libraries/render-utils/src/model_lightmap_normal_map_fade.slv @@ -0,0 +1,48 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_lightmap_normal_map_fade.vert +// vertex shader +// +// Created by Olivier Prat on 06/05/17. +// 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include Fade.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out vec4 _position; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec3 _normal; +out vec3 _tangent; +out vec3 _color; +out vec4 _worldFadePosition; + +void main(void) { + // pass along the color in linear space + _color = colorToLinearRGB(inColor.xyz); + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$> +} diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf new file mode 100644 index 0000000000..b6cdfbd2a2 --- /dev/null +++ b/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf @@ -0,0 +1,53 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_lightmap_normal_specular_map_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 DeferredBufferWrite.slh@> + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> +<$declareMaterialLightmap()$> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +in vec4 _position; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; +in vec4 _worldFadePosition; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> + + vec3 viewNormal; + <$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$> + + packDeferredFragmentLightmap( + normalize(viewNormal.xyz), + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), + getMaterialAlbedo(mat) * albedo.rgb * _color, + getMaterialRoughness(mat) * roughness, + getMaterialMetallic(mat) * metallicTex, + /*specular, // no use of */ getMaterialFresnel(mat), + lightmapVal); +} diff --git a/libraries/render-utils/src/model_lightmap_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_specular_map_fade.slf new file mode 100644 index 0000000000..e6d82b778d --- /dev/null +++ b/libraries/render-utils/src/model_lightmap_specular_map_fade.slf @@ -0,0 +1,49 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_lightmap_specular_map_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 DeferredBufferWrite.slh@> + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> +<$declareMaterialLightmap()$> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +in vec4 _position; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _color; +in vec4 _worldFadePosition; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> + + packDeferredFragmentLightmap( + normalize(_normal), + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), + getMaterialAlbedo(mat) * albedo.rgb * _color, + getMaterialRoughness(mat) * roughness, + getMaterialMetallic(mat) * metallicTex, + /*metallicTex, // no use of */getMaterialFresnel(mat), + lightmapVal); +} diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf index 9f85a956d0..61314fc834 100644 --- a/libraries/render-utils/src/model_normal_map_fade.slf +++ b/libraries/render-utils/src/model_normal_map_fade.slf @@ -31,7 +31,7 @@ in vec3 _tangent; in vec3 _color; void main(void) { - applyFade(_worldFadePosition.xyz, _normal); + applyFade(_worldFadePosition.xyz); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_normal_specular_map_fade.slf b/libraries/render-utils/src/model_normal_specular_map_fade.slf new file mode 100644 index 0000000000..d9c4288e29 --- /dev/null +++ b/libraries/render-utils/src/model_normal_specular_map_fade.slf @@ -0,0 +1,72 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_normal_specular_map_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 DeferredBufferWrite.slh@> + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +in vec4 _position; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; +in vec4 _worldFadePosition; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + vec3 viewNormal; + <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> + + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + + float scattering = getMaterialScattering(mat); + + packDeferredFragment( + normalize(viewNormal.xyz), + opacity, + albedo, + roughness, + metallic, + emissive, + occlusionTex, + scattering); +} diff --git a/libraries/render-utils/src/model_specular_map_fade.slf b/libraries/render-utils/src/model_specular_map_fade.slf new file mode 100644 index 0000000000..3579cf1059 --- /dev/null +++ b/libraries/render-utils/src/model_specular_map_fade.slf @@ -0,0 +1,68 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_specular_map_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 DeferredBufferWrite.slh@> + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +in vec4 _position; +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec3 _normal; +in vec3 _color; +in vec4 _worldFadePosition; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + + float scattering = getMaterialScattering(mat); + + packDeferredFragment( + normalize(_normal), + opacity, + albedo, + roughness, + metallic, + emissive, + occlusionTex, + scattering); +} diff --git a/libraries/render-utils/src/model_unlit_fade.slf b/libraries/render-utils/src/model_unlit_fade.slf new file mode 100644 index 0000000000..be0af7afea --- /dev/null +++ b/libraries/render-utils/src/model_unlit_fade.slf @@ -0,0 +1,50 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_unlit_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 DeferredBufferWrite.slh@> +<@include LightingModel.slh@> +<@include model/Material.slh@> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO)$> + +in vec2 _texCoord0; +in vec3 _normal; +in vec3 _color; +in float _alpha; +in vec4 _worldFadePosition; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + packDeferredFragmentUnlit( + normalize(_normal), + opacity, + albedo * isUnlitEnabled()); +} diff --git a/libraries/render-utils/src/simple_fade.slf b/libraries/render-utils/src/simple_fade.slf new file mode 100644 index 0000000000..c082ea26f3 --- /dev/null +++ b/libraries/render-utils/src/simple_fade.slf @@ -0,0 +1,97 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 DeferredBufferWrite.slh@> +<@include model/Material.slh@> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +// the interpolated normal +in vec3 _normal; +in vec3 _modelNormal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _position; +in vec4 _worldFadePosition; + +//PROCEDURAL_COMMON_BLOCK + +#line 1001 +//PROCEDURAL_BLOCK + +#line 2030 +void main(void) { + applyFade(_worldFadePosition.xyz); + + Material material = getMaterial(); + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; + vec3 specular = DEFAULT_SPECULAR; + float shininess = DEFAULT_SHININESS; + float emissiveAmount = 0.0; + +#ifdef PROCEDURAL + +#ifdef PROCEDURAL_V1 + specular = getProceduralColor().rgb; + // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline + //specular = pow(specular, vec3(2.2)); + emissiveAmount = 1.0; +#else + emissiveAmount = getProceduralColors(diffuse, specular, shininess); +#endif + +#endif + + const float ALPHA_THRESHOLD = 0.999; + if (_color.a < ALPHA_THRESHOLD) { + if (emissiveAmount > 0.0) { + packDeferredFragmentTranslucent( + normal, + _color.a, + specular, + DEFAULT_FRESNEL, + DEFAULT_ROUGHNESS); + } else { + packDeferredFragmentTranslucent( + normal, + _color.a, + diffuse, + DEFAULT_FRESNEL, + DEFAULT_ROUGHNESS); + } + } else { + if (emissiveAmount > 0.0) { + packDeferredFragmentLightmap( + normal, + 1.0, + diffuse, + max(0, 1.0 - shininess / 128.0), + DEFAULT_METALLIC, + specular, + specular); + } else { + packDeferredFragment( + normal, + 1.0, + diffuse, + max(0, 1.0 - shininess / 128.0), + length(specular), + DEFAULT_EMISSIVE, + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); + } + } +} diff --git a/libraries/render-utils/src/simple_fade.slv b/libraries/render-utils/src/simple_fade.slv new file mode 100644 index 0000000000..866d4cc35e --- /dev/null +++ b/libraries/render-utils/src/simple_fade.slv @@ -0,0 +1,42 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_fade.vert +// vertex shader +// +// Created by Olivier Prat on 06/045/17. +// 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@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; + +void main(void) { + _color = colorToLinearRGBA(inColor); + _texCoord0 = inTexCoord0.st; + _position = inPosition; + _modelNormal = inNormal.xyz; + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> +} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf new file mode 100644 index 0000000000..c939a8d676 --- /dev/null +++ b/libraries/render-utils/src/simple_textured_fade.slf @@ -0,0 +1,60 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_textured_fade.slf +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 gpu/Color.slh@> +<@include DeferredBufferWrite.slh@> +<@include model/Material.slh@> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _worldFadePosition; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + vec4 texel = texture(originalTexture, _texCoord0); + float colorAlpha = _color.a; + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + colorAlpha = -_color.a; + } + + const float ALPHA_THRESHOLD = 0.999; + if (colorAlpha * texel.a < ALPHA_THRESHOLD) { + packDeferredFragmentTranslucent( + normalize(_normal), + colorAlpha * texel.a, + _color.rgb * texel.rgb, + DEFAULT_FRESNEL, + DEFAULT_ROUGHNESS); + } else { + packDeferredFragment( + normalize(_normal), + 1.0, + _color.rgb * texel.rgb, + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); + } +} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_unlit_fade.slf b/libraries/render-utils/src/simple_textured_unlit_fade.slf new file mode 100644 index 0000000000..2db2dfa222 --- /dev/null +++ b/libraries/render-utils/src/simple_textured_unlit_fade.slf @@ -0,0 +1,54 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_textured_unlit_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 gpu/Color.slh@> +<@include DeferredBufferWrite.slh@> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _worldFadePosition; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + vec4 texel = texture(originalTexture, _texCoord0.st); + float colorAlpha = _color.a; + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + colorAlpha = -_color.a; + } + + const float ALPHA_THRESHOLD = 0.999; + if (colorAlpha * texel.a < ALPHA_THRESHOLD) { + packDeferredFragmentTranslucent( + normalize(_normal), + colorAlpha * texel.a, + _color.rgb * texel.rgb, + DEFAULT_FRESNEL, + DEFAULT_ROUGHNESS); + } else { + packDeferredFragmentUnlit( + normalize(_normal), + 1.0, + _color.rgb * texel.rgb); + } +} \ No newline at end of file diff --git a/libraries/render-utils/src/skin_model_fade.slv b/libraries/render-utils/src/skin_model_fade.slv new file mode 100644 index 0000000000..a96c948470 --- /dev/null +++ b/libraries/render-utils/src/skin_model_fade.slv @@ -0,0 +1,55 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// skin_model_fade.vert +// vertex shader +// +// Created by Olivier Prat on 06/045/17. +// 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include Skinning.slh@> + +<@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; + +void main(void) { + vec4 position = vec4(0.0, 0.0, 0.0, 0.0); + vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0); + + skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal); + + // pass along the color + _color = colorToLinearRGB(inColor.rgb); + _alpha = inColor.a; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> + <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> + <$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, _normal.xyz)$> +} diff --git a/libraries/render-utils/src/skin_model_normal_map_fade.slv b/libraries/render-utils/src/skin_model_normal_map_fade.slv new file mode 100644 index 0000000000..5169aa5d75 --- /dev/null +++ b/libraries/render-utils/src/skin_model_normal_map_fade.slv @@ -0,0 +1,64 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// skin_model_normal_map_fade.vert +// vertex shader +// +// Created by Olivier Prat on 06/045/17. +// 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include Skinning.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +<@include Fade.slh@> + +out vec4 _position; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec3 _normal; +out vec3 _tangent; +out vec3 _color; +out float _alpha; +out vec4 _worldFadePosition; + +void main(void) { + vec4 position = vec4(0.0, 0.0, 0.0, 0.0); + vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0); + vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0); + + skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz); + + // pass along the color + _color = colorToLinearRGB(inColor.rgb); + _alpha = inColor.a; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> + <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> + <$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> + <$transformModelToWorldDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$> + + _normal = interpolatedNormal.xyz; + _tangent = interpolatedTangent.xyz; +} diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index c32579b0d8..f674fad50b 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -143,7 +143,7 @@ private: int _trackedControllers { 0 }; vr::IVRSystem*& _system; - quint64 _timeTilCalibration { 0.0f }; + quint64 _timeTilCalibration { 0 }; float _leftHapticStrength { 0.0f }; float _leftHapticDuration { 0.0f }; float _rightHapticStrength { 0.0f }; diff --git a/scripts/developer/utilities/render/debugFade.js b/scripts/developer/utilities/render/debugFade.js index 8b79905e11..064337dae1 100644 --- a/scripts/developer/utilities/render/debugFade.js +++ b/scripts/developer/utilities/render/debugFade.js @@ -14,7 +14,7 @@ var qml = Script.resolvePath('fade.qml'); var window = new OverlayWindow({ title: 'Fade', source: qml, - width: 400, + width: 500, height: 80 }); window.setPosition(50, 50); diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index 3d391923ff..d5622c353d 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -12,22 +12,45 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import "configSlider" -Column { - id: root - spacing: 8 - property var drawOpaqueConfig: Render.getConfig("DrawOpaqueDeferred"); +Row { + property var drawOpaqueConfig: Render.getConfig("DrawOpaqueDeferred"); + property var drawTransparentConfig: Render.getConfig("DrawDeferred"); + spacing: 4 + Column { + spacing: 8 - CheckBox { - text: "Force Fade" - checked: drawOpaqueConfig["debugFade"] - onCheckedChanged: { drawOpaqueConfig["debugFade"] = checked } + CheckBox { + text: "Force Fade Opaque" + checked: drawOpaqueConfig["debugFade"] + onCheckedChanged: { drawOpaqueConfig["debugFade"] = checked } + } + CheckBox { + text: "Force Fade Transparent" + checked: drawTransparentConfig["debugFade"] + onCheckedChanged: { drawTransparentConfig["debugFade"] = checked } + } } - ConfigSlider { - label: "Percent" - integral: false - config: drawOpaqueConfig - property: "debugFadePercent" - max: 1.0 - min: 0.0 + Column { + spacing: 8 + + ConfigSlider { + label: "Percent" + integral: false + config: drawOpaqueConfig + property: "debugFadePercent" + max: 1.0 + min: 0.0 + width: 250 + } + ConfigSlider { + label: "Percent" + integral: false + config: drawTransparentConfig + property: "debugFadePercent" + max: 1.0 + min: 0.0 + width: 250 + } } } + From 74bb3213e47de07e5b9a1ffa2b2ecb61ef619a4d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 5 Jun 2017 16:44:32 +0200 Subject: [PATCH 04/86] Added shadow shader variants --- .../render-utils/src/RenderPipelines.cpp | 18 ++++++++-- .../render-utils/src/model_shadow_fade.slf | 27 +++++++++++++++ .../render-utils/src/model_shadow_fade.slv | 31 +++++++++++++++++ .../src/skin_model_shadow_fade.slv | 34 +++++++++++++++++++ 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 libraries/render-utils/src/model_shadow_fade.slf create mode 100644 libraries/render-utils/src/model_shadow_fade.slv create mode 100644 libraries/render-utils/src/skin_model_shadow_fade.slv diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index d771b0f5cc..3a9464395a 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -28,11 +28,12 @@ #include "skin_model_shadow_vert.h" #include "skin_model_normal_map_vert.h" -#include "skin_model_fade_vert.h" -#include "skin_model_normal_map_fade_vert.h" - +#include "model_shadow_fade_vert.h" #include "model_lightmap_fade_vert.h" #include "model_lightmap_normal_map_fade_vert.h" +#include "skin_model_fade_vert.h" +#include "skin_model_shadow_fade_vert.h" +#include "skin_model_normal_map_fade_vert.h" #include "simple_vert.h" #include "simple_textured_frag.h" @@ -55,6 +56,7 @@ #include "model_normal_map_fade_vert.h" #include "model_fade_frag.h" +#include "model_shadow_fade_frag.h" #include "model_unlit_fade_frag.h" #include "model_normal_map_fade_frag.h" #include "model_normal_specular_map_fade_frag.h" @@ -183,6 +185,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_fade_vert)); auto modelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_normal_map_fade_vert)); auto simpleFadeVertex = gpu::Shader::createVertex(std::string(simple_fade_vert)); + auto modelShadowFadeVertex = gpu::Shader::createVertex(std::string(model_shadow_fade_vert)); + auto skinModelShadowFadeVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_fade_vert)); // Pixel shaders auto simplePixel = gpu::Shader::createPixel(std::string(simple_textured_frag)); @@ -211,6 +215,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto modelNormalMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_map_fade_frag)); auto modelSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_specular_map_fade_frag)); auto modelNormalSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_fade_frag)); + auto modelShadowFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag)); auto simpleFadePixel = gpu::Shader::createPixel(std::string(simple_textured_fade_frag)); auto simpleUnlitFadePixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_fade_frag)); @@ -364,6 +369,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withSkinned().withDepthOnly(), skinModelShadowVertex, modelShadowPixel); + // Same thing but with Fade on + addPipeline( + Key::Builder().withDepthOnly().withFade(), + modelShadowFadeVertex, modelShadowFadePixel); + addPipeline( + Key::Builder().withSkinned().withDepthOnly().withFade(), + skinModelShadowFadeVertex, modelShadowFadePixel); } void initForwardPipelines(render::ShapePlumber& plumber) { diff --git a/libraries/render-utils/src/model_shadow_fade.slf b/libraries/render-utils/src/model_shadow_fade.slf new file mode 100644 index 0000000000..635917b9f4 --- /dev/null +++ b/libraries/render-utils/src/model_shadow_fade.slf @@ -0,0 +1,27 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_shadow_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 Fade.slh@> +<$declareFadeFragment()$> + +layout(location = 0) out vec4 _fragColor; + +in vec4 _worldFadePosition; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + // pass-through to set z-buffer + _fragColor = vec4(1.0, 1.0, 1.0, 0.0); +} diff --git a/libraries/render-utils/src/model_shadow_fade.slv b/libraries/render-utils/src/model_shadow_fade.slv new file mode 100644 index 0000000000..4b6e2e1dc1 --- /dev/null +++ b/libraries/render-utils/src/model_shadow_fade.slv @@ -0,0 +1,31 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_shadow_fade.vert +// vertex shader +// +// Created by Olivier Prat on 06/045/17. +// 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 gpu/Inputs.slh@> + +<@include gpu/Transform.slh@> + +<@include Fade.slh@> + +<$declareStandardTransform()$> + +out vec4 _worldFadePosition; + +void main(void) { + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> +} diff --git a/libraries/render-utils/src/skin_model_shadow_fade.slv b/libraries/render-utils/src/skin_model_shadow_fade.slv new file mode 100644 index 0000000000..84d50ae754 --- /dev/null +++ b/libraries/render-utils/src/skin_model_shadow_fade.slv @@ -0,0 +1,34 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// skin_model_shadow_fade.vert +// vertex shader +// +// Created by Olivier Prat on 06/045/17. +// 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 gpu/Inputs.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include Fade.slh@> + +<@include Skinning.slh@> + +out vec4 _worldFadePosition; + +void main(void) { + vec4 position = vec4(0.0, 0.0, 0.0, 0.0); + skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position); + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, position, gl_Position)$> + <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> +} From cce99ef8c45576db84cb71efe154fe91c9ad3409 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 5 Jun 2017 16:56:57 +0200 Subject: [PATCH 05/86] Added translucent shaders --- .../render-utils/src/RenderPipelines.cpp | 47 ++++++++++ .../src/model_translucent_fade.slf | 87 +++++++++++++++++++ .../src/model_translucent_unlit_fade.slf | 46 ++++++++++ .../src/simple_transparent_textured_fade.slf | 68 +++++++++++++++ ...simple_transparent_textured_unlit_fade.slf | 41 +++++++++ 5 files changed, 289 insertions(+) create mode 100644 libraries/render-utils/src/model_translucent_fade.slf create mode 100644 libraries/render-utils/src/model_translucent_unlit_fade.slf create mode 100644 libraries/render-utils/src/simple_transparent_textured_fade.slf create mode 100644 libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 3a9464395a..2cdad86156 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -44,6 +44,8 @@ #include "simple_fade_vert.h" #include "simple_textured_fade_frag.h" #include "simple_textured_unlit_fade_frag.h" +#include "simple_transparent_textured_fade_frag.h" +#include "simple_transparent_textured_unlit_fade_frag.h" #include "model_frag.h" #include "model_unlit_frag.h" @@ -79,6 +81,8 @@ #include "model_lightmap_normal_map_fade_frag.h" #include "model_lightmap_normal_specular_map_fade_frag.h" #include "model_lightmap_specular_map_fade_frag.h" +#include "model_translucent_fade_frag.h" +#include "model_translucent_unlit_fade_frag.h" #include "overlay3D_vert.h" #include "overlay3D_frag.h" @@ -216,8 +220,12 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto modelSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_specular_map_fade_frag)); auto modelNormalSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_fade_frag)); auto modelShadowFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag)); + auto modelTranslucentFadePixel = gpu::Shader::createPixel(std::string(model_translucent_fade_frag)); + auto modelTranslucentUnlitFadePixel = gpu::Shader::createPixel(std::string(model_translucent_unlit_fade_frag)); auto simpleFadePixel = gpu::Shader::createPixel(std::string(simple_textured_fade_frag)); auto simpleUnlitFadePixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_fade_frag)); + auto simpleTranslucentFadePixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_fade_frag)); + auto simpleTranslucentUnlitFadePixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_unlit_fade_frag)); using Key = render::ShapeKey; auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3); @@ -293,6 +301,32 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap(), modelVertex, modelTranslucentPixel); + // Same thing but with Fade on + addPipeline( + Key::Builder().withMaterial().withTranslucent().withFade(), + modelFadeVertex, modelTranslucentFadePixel); + addPipeline( + Key::Builder().withTranslucent().withFade(), + simpleFadeVertex, simpleTranslucentFadePixel); + addPipeline( + Key::Builder().withMaterial().withTranslucent().withUnlit().withFade(), + modelFadeVertex, modelTranslucentUnlitFadePixel); + addPipeline( + Key::Builder().withTranslucent().withUnlit().withFade(), + simpleFadeVertex, simpleTranslucentUnlitFadePixel); + addPipeline( + Key::Builder().withMaterial().withTranslucent().withTangents().withFade(), + modelNormalMapFadeVertex, modelTranslucentFadePixel); + addPipeline( + Key::Builder().withMaterial().withTranslucent().withSpecular().withFade(), + modelFadeVertex, modelTranslucentFadePixel); + addPipeline( + Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular().withFade(), + modelNormalMapFadeVertex, modelTranslucentFadePixel); + addPipeline( + // FIXME: Ignore lightmap for translucents meshpart + Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(), + modelFadeVertex, modelTranslucentFadePixel); // Lightmapped addPipeline( @@ -361,6 +395,19 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(), skinModelNormalMapVertex, modelTranslucentPixel); + // Same thing but with Fade on + addPipeline( + Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(), + skinModelFadeVertex, modelTranslucentFadePixel); + addPipeline( + Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withFade(), + skinModelNormalMapFadeVertex, modelTranslucentFadePixel); + addPipeline( + Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular().withFade(), + skinModelFadeVertex, modelTranslucentFadePixel); + addPipeline( + Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular().withFade(), + skinModelNormalMapFadeVertex, modelTranslucentFadePixel); // Depth-only addPipeline( diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf new file mode 100644 index 0000000000..3bbfdabc7f --- /dev/null +++ b/libraries/render-utils/src/model_translucent_fade.slf @@ -0,0 +1,87 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_translucent_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 model/Material.slh@> + +<@include DeferredGlobalLight.slh@> + +<$declareEvalGlobalLightingAlphaBlended()$> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec4 _position; +in vec3 _normal; +in vec3 _color; +in float _alpha; +in vec4 _worldFadePosition; + +out vec4 _fragColor; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = getMaterialOpacity(mat) * _alpha; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + float metallic = getMaterialMetallic(mat); + vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value + if (metallic <= 0.5) { + metallic = 0.0; + } else { + fresnel = albedo; + metallic = 1.0; + } + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + vec3 fragPosition = _position.xyz; + vec3 fragNormal = normalize(_normal); + + TransformCamera cam = getTransformCamera(); + + _fragColor = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + occlusionTex, + fragPosition, + fragNormal, + albedo, + fresnel, + metallic, + emissive, + roughness, opacity), + opacity); +} diff --git a/libraries/render-utils/src/model_translucent_unlit_fade.slf b/libraries/render-utils/src/model_translucent_unlit_fade.slf new file mode 100644 index 0000000000..dd885f66d7 --- /dev/null +++ b/libraries/render-utils/src/model_translucent_unlit_fade.slf @@ -0,0 +1,46 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_translucent_unlit_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> +<@include LightingModel.slh@> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +in vec2 _texCoord0; +in vec3 _color; +in float _alpha; +in vec4 _worldFadePosition; + +out vec4 _fragColor; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> + + float opacity = getMaterialOpacity(mat) * _alpha; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + _fragColor = vec4(albedo * isUnlitEnabled(), opacity); +} diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf new file mode 100644 index 0000000000..84cdffeeec --- /dev/null +++ b/libraries/render-utils/src/simple_transparent_textured_fade.slf @@ -0,0 +1,68 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_transparent_textured_fade.slf +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 gpu/Color.slh@> + +<@include DeferredBufferWrite.slh@> +<@include DeferredGlobalLight.slh@> +<$declareEvalGlobalLightingAlphaBlended()$> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec4 _position; +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _worldFadePosition; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + vec4 texel = texture(originalTexture, _texCoord0.st); + float opacity = _color.a; + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + opacity = -_color.a; + } + opacity *= texel.a; + vec3 albedo = _color.rgb * texel.rgb; + + vec3 fragPosition = _position.xyz; + vec3 fragNormal = normalize(_normal); + + TransformCamera cam = getTransformCamera(); + + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + 1.0, + fragPosition, + fragNormal, + albedo, + DEFAULT_FRESNEL, + 0.0, + vec3(0.0f), + DEFAULT_ROUGHNESS, + opacity), + opacity); + +} \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf new file mode 100644 index 0000000000..688e1de422 --- /dev/null +++ b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf @@ -0,0 +1,41 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_transparent_textured_unlit_fade.slf +// fragment shader +// +// Created by Olivier Prat on 06/05/17. +// 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 gpu/Color.slh@> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _worldFadePosition; + +layout(location = 0) out vec4 _fragColor0; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + vec4 texel = texture(originalTexture, _texCoord0.st); + float colorAlpha = _color.a; + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + colorAlpha = -_color.a; + } + _fragColor0 = vec4(_color.rgb * texel.rgb, colorAlpha * texel.a); +} \ No newline at end of file From 1936c209a597040cde336a691b7a53ae4349a4d6 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 5 Jun 2017 17:21:33 +0200 Subject: [PATCH 06/86] Working fade debugging scripts for both opaque and transparents --- libraries/render-utils/src/RenderPipelines.cpp | 1 - scripts/developer/utilities/render/fade.qml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 2cdad86156..f199e10b95 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -185,7 +185,6 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto skinModelFadeVertex = gpu::Shader::createVertex(std::string(skin_model_fade_vert)); auto skinModelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_fade_vert)); - // Only models can have fade applied to them (?) auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_fade_vert)); auto modelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_normal_map_fade_vert)); auto simpleFadeVertex = gpu::Shader::createVertex(std::string(simple_fade_vert)); diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index d5622c353d..48316789ea 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -14,7 +14,7 @@ import "configSlider" Row { property var drawOpaqueConfig: Render.getConfig("DrawOpaqueDeferred"); - property var drawTransparentConfig: Render.getConfig("DrawDeferred"); + property var drawTransparentConfig: Render.getConfig("DrawTransparentDeferred"); spacing: 4 Column { spacing: 8 From e7eca7728f791f52457948bafbbdf668c055b6fd Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 6 Jun 2017 14:57:52 +0200 Subject: [PATCH 07/86] Debug fade management moved out of the inner render loop --- .../render-utils/src/MeshPartPayload.cpp | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 64 ++++++++++--------- .../render-utils/src/RenderDeferredTask.h | 2 +- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 39f07e0232..70adcdd98e 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -533,7 +533,7 @@ float ModelMeshPartPayload::computeFadePercent() const { return 0.0f; } float fadeAlpha = 1.0f; - const double INV_FADE_PERIOD = 1.0 / (double)(10 * USECS_PER_SECOND); + const double INV_FADE_PERIOD = 1.0 / (double)(3 * USECS_PER_SECOND); double fraction = (double)(usecTimestampNow() - _fadeStartTime) * INV_FADE_PERIOD; if (fraction < 1.0) { fadeAlpha = Interpolate::simpleNonLinearBlend(fraction); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 412d74fe87..8d4a92ff7d 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -252,6 +252,15 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& const auto& lightingModel = inputs.get1(); RenderArgs* args = renderContext->args; + ShapeKey::Builder defaultKeyBuilder; + + if (_debugFade) { + args->_debugFlags = static_cast(args->_debugFlags | + static_cast(RenderArgs::RENDER_DEBUG_FADE)); + args->_debugFadePercent = _debugFadePercent; + // Force fade for everyone + defaultKeyBuilder.withFade(); + } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -272,19 +281,12 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); // From the lighting model define a global shapKey ORED with individiual keys - ShapeKey::Builder keyBuilder; + ShapeKey::Builder keyBuilder = defaultKeyBuilder; if (lightingModel->isWireframeEnabled()) { keyBuilder.withWireframe(); } // Prepare fade effect batch.setResourceTexture(ShapePipeline::Slot::MAP::FADE_MASK, _fadeMaskMap); - if (_debugFade) { - args->_debugFlags = static_cast(args->_debugFlags | - static_cast(RenderArgs::RENDER_DEBUG_FADE)); - args->_debugFadePercent = _debugFadePercent; - // Force fade for everyone - keyBuilder.withFade(); - } ShapeKey globalKey = keyBuilder.build(); args->_globalShapeKey = globalKey._flags.to_ulong(); @@ -293,15 +295,15 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& args->_batch = nullptr; args->_globalShapeKey = 0; - - // Not sure this is really needed... - if (_debugFade) { - // Turn off fade debug - args->_debugFlags = static_cast(args->_debugFlags & - ~static_cast(RenderArgs::RENDER_DEBUG_FADE)); - } }); + // Not sure this is really needed... + if (_debugFade) { + // Turn off fade debug + args->_debugFlags = static_cast(args->_debugFlags & + ~static_cast(RenderArgs::RENDER_DEBUG_FADE)); + } + config->setNumDrawn((int)inItems.size()); } @@ -315,6 +317,15 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const const auto& lightingModel = inputs.get1(); RenderArgs* args = renderContext->args; + ShapeKey::Builder defaultKeyBuilder; + + if (_debugFade) { + args->_debugFlags = static_cast(args->_debugFlags | + static_cast(RenderArgs::RENDER_DEBUG_FADE)); + args->_debugFadePercent = _debugFadePercent; + // Force fade for everyone + defaultKeyBuilder.withFade(); + } gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -335,20 +346,13 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); // From the lighting model define a global shapeKey ORED with individiual keys - ShapeKey::Builder keyBuilder; + ShapeKey::Builder keyBuilder = defaultKeyBuilder; if (lightingModel->isWireframeEnabled()) { keyBuilder.withWireframe(); } // Prepare fade effect batch.setResourceTexture(ShapePipeline::Slot::MAP::FADE_MASK, _fadeMaskMap); - if (_debugFade) { - args->_debugFlags = static_cast(args->_debugFlags | - static_cast(RenderArgs::RENDER_DEBUG_FADE)); - args->_debugFadePercent = _debugFadePercent; - // Force fade for everyone - keyBuilder.withFade(); - } ShapeKey globalKey = keyBuilder.build(); args->_globalShapeKey = globalKey._flags.to_ulong(); @@ -360,15 +364,15 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const } args->_batch = nullptr; args->_globalShapeKey = 0; - - // Not sure this is really needed... - if (_debugFade) { - // Turn off fade debug - args->_debugFlags = static_cast(args->_debugFlags & - ~static_cast(RenderArgs::RENDER_DEBUG_FADE)); - } }); + // Not sure this is really needed... + if (_debugFade) { + // Turn off fade debug + args->_debugFlags = static_cast(args->_debugFlags & + ~static_cast(RenderArgs::RENDER_DEBUG_FADE)); + } + config->setNumDrawn((int)inItems.size()); } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index ebb7d34606..1f20615328 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -51,7 +51,6 @@ protected: gpu::TexturePointer _fadeMaskMap; float _debugFadePercent; - bool _stateSort; bool _debugFade; }; @@ -135,6 +134,7 @@ public: protected: render::ShapePlumberPointer _shapePlumber; int _maxDrawn; // initialized by Config + bool _stateSort; }; class DeferredFramebuffer; From 8af2f759968d8827f349d73e874a8abf070fc223 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 6 Jun 2017 16:11:12 +0200 Subject: [PATCH 08/86] Added FadeManager to centralize some common fade effect data and functions --- libraries/render-utils/src/FadeManager.cpp | 25 +++++++++ libraries/render-utils/src/FadeManager.h | 43 ++++++++++++++ .../render-utils/src/MeshPartPayload.cpp | 9 +-- libraries/render-utils/src/MeshPartPayload.h | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 56 ++++++------------- .../render-utils/src/RenderDeferredTask.h | 47 ++++++++-------- libraries/shared/src/RenderArgs.h | 2 - scripts/developer/utilities/render/fade.qml | 25 ++------- 8 files changed, 118 insertions(+), 91 deletions(-) create mode 100644 libraries/render-utils/src/FadeManager.cpp create mode 100644 libraries/render-utils/src/FadeManager.h diff --git a/libraries/render-utils/src/FadeManager.cpp b/libraries/render-utils/src/FadeManager.cpp new file mode 100644 index 0000000000..f70e2e94d0 --- /dev/null +++ b/libraries/render-utils/src/FadeManager.cpp @@ -0,0 +1,25 @@ +#include "FadeManager.h" +#include "TextureCache.h" + +#include + +FadeManager::FadeManager() : + _isDebugEnabled{ false }, + _debugFadePercent{ 0.f } +{ + auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png"; + _fadeMaskMap = DependencyManager::get()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); +} + +render::ShapeKey::Builder FadeManager::getKeyBuilder() const +{ + render::ShapeKey::Builder builder; + + if (_isDebugEnabled) { + // Force fade for everyone + builder.withFade(); + } + + return builder; +} + diff --git a/libraries/render-utils/src/FadeManager.h b/libraries/render-utils/src/FadeManager.h new file mode 100644 index 0000000000..d42447fc26 --- /dev/null +++ b/libraries/render-utils/src/FadeManager.h @@ -0,0 +1,43 @@ +// +// FadeManager.h +// libraries/render-utils/src/ +// +// Created by Olivier Prat on 06/06/17. +// 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_FadeManager_h +#define hifi_FadeManager_h + +#include +#include +#include + +// Centralizes fade effect data and functions +class FadeManager : public Dependency { + SINGLETON_DEPENDENCY +public: + + FadeManager(); + + const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; } + + void setDebugEnabled(bool isEnabled) { _isDebugEnabled = isEnabled; } + bool isDebugEnabled() const { return _isDebugEnabled; } + + void setDebugFadePercent(float value) { assert(value >= 0.f && value <= 1.f); _debugFadePercent = value; } + float getDebugFadePercent() const { return _debugFadePercent; } + + render::ShapeKey::Builder getKeyBuilder() const; + +private: + + gpu::TexturePointer _fadeMaskMap; + float _debugFadePercent; + bool _isDebugEnabled; + +}; + +#endif // hifi_FadeManager_h diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 70adcdd98e..87ac019030 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -15,6 +15,7 @@ #include "DeferredLightingEffect.h" #include "EntityItem.h" +#include "FadeManager.h" using namespace render; @@ -550,8 +551,8 @@ float ModelMeshPartPayload::computeFadePercent() const { return fadeAlpha; } -void ModelMeshPartPayload::bindFade(gpu::Batch& batch, const RenderArgs* args) const { - const bool isDebugEnabled = (args->_debugFlags & RenderArgs::RENDER_DEBUG_FADE) != 0; +void ModelMeshPartPayload::bindFade(gpu::Batch& batch) const { + const bool isDebugEnabled = DependencyManager::get()->isDebugEnabled(); if (_fadeState != FADE_COMPLETE || isDebugEnabled) { auto& fade = _fadeBuffer.edit(); @@ -562,7 +563,7 @@ void ModelMeshPartPayload::bindFade(gpu::Batch& batch, const RenderArgs* args) c fade._percent = computeFadePercent(); } else { - fade._percent = args->_debugFadePercent; + fade._percent = DependencyManager::get()->getDebugFadePercent(); } fade._offset = offset; @@ -617,7 +618,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { bindMaterial(batch, locations, args->_enableTexturing); // Apply fade effect - bindFade(batch, args); + bindFade(batch); args->_details._materialSwitches++; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index f29c482bd9..0d3a8df576 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -106,7 +106,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, const RenderArgs* args) const; + void bindFade(gpu::Batch& batch) const; void initCache(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 8d4a92ff7d..4d91d7d512 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -35,6 +35,7 @@ #include "HitEffect.h" #include "TextureCache.h" #include "ZoneRenderer.h" +#include "FadeManager.h" #include "AmbientOcclusionEffect.h" #include "AntialiasingEffect.h" @@ -50,6 +51,12 @@ using namespace render; extern void initOverlay3DPipelines(render::ShapePlumber& plumber); extern void initDeferredPipelines(render::ShapePlumber& plumber); +void RenderDeferredTask::configure(const Config& config) +{ + DependencyManager::get()->setDebugEnabled(config.debugFade); + DependencyManager::get()->setDebugFadePercent(config.debugFadePercent); +} + void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { auto items = input.get(); @@ -85,13 +92,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto deferredFramebuffer = prepareDeferredOutputs.getN(0); const auto lightingFramebuffer = prepareDeferredOutputs.getN(1); - // Fade texture mask - auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png"; - auto fadeMaskMap = DependencyManager::get()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); + DependencyManager::set(); // Render opaque objects in DeferredBuffer const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying(); - task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber, fadeMaskMap); + task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber); // Once opaque is all rendered create stencil background task.addJob("DrawOpaqueStencil", deferredFramebuffer); @@ -147,7 +152,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Render transparent objects forward in LightingBuffer const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying(); - task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber, fadeMaskMap); + task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); // LIght Cluster Grid Debuging job { @@ -252,15 +257,8 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& const auto& lightingModel = inputs.get1(); RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder; - - if (_debugFade) { - args->_debugFlags = static_cast(args->_debugFlags | - static_cast(RenderArgs::RENDER_DEBUG_FADE)); - args->_debugFadePercent = _debugFadePercent; - // Force fade for everyone - defaultKeyBuilder.withFade(); - } + ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); + gpu::TexturePointer fadeMaskMap = DependencyManager::get()->getFadeMaskMap(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -285,8 +283,9 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& if (lightingModel->isWireframeEnabled()) { keyBuilder.withWireframe(); } + // Prepare fade effect - batch.setResourceTexture(ShapePipeline::Slot::MAP::FADE_MASK, _fadeMaskMap); + batch.setResourceTexture(ShapePipeline::Slot::MAP::FADE_MASK, fadeMaskMap); ShapeKey globalKey = keyBuilder.build(); args->_globalShapeKey = globalKey._flags.to_ulong(); @@ -297,13 +296,6 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& args->_globalShapeKey = 0; }); - // Not sure this is really needed... - if (_debugFade) { - // Turn off fade debug - args->_debugFlags = static_cast(args->_debugFlags & - ~static_cast(RenderArgs::RENDER_DEBUG_FADE)); - } - config->setNumDrawn((int)inItems.size()); } @@ -317,15 +309,8 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const const auto& lightingModel = inputs.get1(); RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder; - - if (_debugFade) { - args->_debugFlags = static_cast(args->_debugFlags | - static_cast(RenderArgs::RENDER_DEBUG_FADE)); - args->_debugFadePercent = _debugFadePercent; - // Force fade for everyone - defaultKeyBuilder.withFade(); - } + ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); + gpu::TexturePointer fadeMaskMap = DependencyManager::get()->getFadeMaskMap(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -352,7 +337,7 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const } // Prepare fade effect - batch.setResourceTexture(ShapePipeline::Slot::MAP::FADE_MASK, _fadeMaskMap); + batch.setResourceTexture(ShapePipeline::Slot::MAP::FADE_MASK, fadeMaskMap); ShapeKey globalKey = keyBuilder.build(); args->_globalShapeKey = globalKey._flags.to_ulong(); @@ -366,13 +351,6 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const args->_globalShapeKey = 0; }); - // Not sure this is really needed... - if (_debugFade) { - // Turn off fade debug - args->_debugFlags = static_cast(args->_debugFlags & - ~static_cast(RenderArgs::RENDER_DEBUG_FADE)); - } - config->setNumDrawn((int)inItems.size()); } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 1f20615328..37f274896b 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -44,22 +44,10 @@ public: protected: }; - -class DrawFadableDeferred { -protected: - DrawFadableDeferred(gpu::TexturePointer fadeMaskMap) : _fadeMaskMap{ fadeMaskMap } {} - - gpu::TexturePointer _fadeMaskMap; - float _debugFadePercent; - bool _debugFade; -}; - class DrawConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY newStats) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) - Q_PROPERTY(bool debugFade MEMBER debugFade NOTIFY dirty) - Q_PROPERTY(float debugFadePercent MEMBER debugFadePercent NOTIFY dirty) public: @@ -67,8 +55,6 @@ public: void setNumDrawn(int numDrawn) { _numDrawn = numDrawn; emit newStats(); } int maxDrawn{ -1 }; - float debugFadePercent{ 0.f }; - bool debugFade{ false }; signals: void newStats(); @@ -78,15 +64,15 @@ protected: int _numDrawn{ 0 }; }; -class DrawDeferred : public DrawFadableDeferred { +class DrawDeferred { public: using Inputs = render::VaryingSet2 ; using Config = DrawConfig; using JobModel = render::Job::ModelI; - DrawDeferred(render::ShapePlumberPointer shapePlumber, gpu::TexturePointer fadeMaskMap) : _shapePlumber{ shapePlumber }, DrawFadableDeferred{ fadeMaskMap } {} + DrawDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void configure(const Config& config) { _maxDrawn = config.maxDrawn; _debugFadePercent = config.debugFadePercent; _debugFade = config.debugFade; } + void configure(const Config& config) { _maxDrawn = config.maxDrawn; } void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: @@ -99,8 +85,6 @@ class DrawStateSortConfig : public render::Job::Config { Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) 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; } @@ -108,8 +92,6 @@ public: int maxDrawn{ -1 }; bool stateSort{ true }; - float debugFadePercent{ 0.f }; - bool debugFade{ false }; signals: void numDrawnChanged(); @@ -119,16 +101,16 @@ protected: int numDrawn{ 0 }; }; -class DrawStateSortDeferred : public DrawFadableDeferred { +class DrawStateSortDeferred { public: using Inputs = render::VaryingSet2 ; using Config = DrawStateSortConfig; using JobModel = render::Job::ModelI; - DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber, gpu::TexturePointer fadeMaskMap) : _shapePlumber{ shapePlumber }, DrawFadableDeferred{ fadeMaskMap } {} + DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; _debugFadePercent = config.debugFadePercent; _debugFade = config.debugFade; } + void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; } void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: @@ -209,13 +191,28 @@ public: void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer); }; +class RenderDeferredTaskConfig : public render::Task::Config { + Q_OBJECT + Q_PROPERTY(bool debugFade MEMBER debugFade NOTIFY dirty) + Q_PROPERTY(float debugFadePercent MEMBER debugFadePercent NOTIFY dirty) +public: + float debugFadePercent{ 0.f }; + bool debugFade{ false }; + +signals: + void dirty(); + +}; + class RenderDeferredTask { public: using Input = RenderFetchCullSortTask::Output; - using JobModel = render::Task::ModelI; + using Config = RenderDeferredTaskConfig; + using JobModel = render::Task::ModelI; RenderDeferredTask() {} + void configure(const Config& config); void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); }; diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index ce31013918..7ad3672c08 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -80,7 +80,6 @@ public: enum DebugFlags { RENDER_DEBUG_NONE = 0, RENDER_DEBUG_HULLS = 1, - RENDER_DEBUG_FADE = 2, }; RenderArgs(std::shared_ptr context = nullptr, @@ -133,7 +132,6 @@ 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/fade.qml b/scripts/developer/utilities/render/fade.qml index 48316789ea..137e45d08d 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -13,21 +13,15 @@ import QtQuick.Controls 1.4 import "configSlider" Row { - property var drawOpaqueConfig: Render.getConfig("DrawOpaqueDeferred"); - property var drawTransparentConfig: Render.getConfig("DrawTransparentDeferred"); + property var taskConfig: Render.getConfig("RenderDeferredTask"); spacing: 4 Column { spacing: 8 CheckBox { - text: "Force Fade Opaque" - checked: drawOpaqueConfig["debugFade"] - onCheckedChanged: { drawOpaqueConfig["debugFade"] = checked } - } - CheckBox { - text: "Force Fade Transparent" - checked: drawTransparentConfig["debugFade"] - onCheckedChanged: { drawTransparentConfig["debugFade"] = checked } + text: "Force Fade" + checked: taskConfig["debugFade"] + onCheckedChanged: { taskConfig["debugFade"] = checked } } } Column { @@ -36,16 +30,7 @@ Row { ConfigSlider { label: "Percent" integral: false - config: drawOpaqueConfig - property: "debugFadePercent" - max: 1.0 - min: 0.0 - width: 250 - } - ConfigSlider { - label: "Percent" - integral: false - config: drawTransparentConfig + config: taskConfig property: "debugFadePercent" max: 1.0 min: 0.0 From a9ab9d247625c851889e54f689723cce05229bd7 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 6 Jun 2017 16:27:56 +0200 Subject: [PATCH 09/86] Renamed FadeManager to FadeEffect --- .../src/{FadeManager.cpp => FadeEffect.cpp} | 6 +++--- .../src/{FadeManager.h => FadeEffect.h} | 12 ++++++------ libraries/render-utils/src/MeshPartPayload.cpp | 6 +++--- .../render-utils/src/RenderDeferredTask.cpp | 16 ++++++++-------- 4 files changed, 20 insertions(+), 20 deletions(-) rename libraries/render-utils/src/{FadeManager.cpp => FadeEffect.cpp} (79%) rename libraries/render-utils/src/{FadeManager.h => FadeEffect.h} (86%) diff --git a/libraries/render-utils/src/FadeManager.cpp b/libraries/render-utils/src/FadeEffect.cpp similarity index 79% rename from libraries/render-utils/src/FadeManager.cpp rename to libraries/render-utils/src/FadeEffect.cpp index f70e2e94d0..f750798914 100644 --- a/libraries/render-utils/src/FadeManager.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -1,9 +1,9 @@ -#include "FadeManager.h" +#include "FadeEffect.h" #include "TextureCache.h" #include -FadeManager::FadeManager() : +FadeEffect::FadeEffect() : _isDebugEnabled{ false }, _debugFadePercent{ 0.f } { @@ -11,7 +11,7 @@ FadeManager::FadeManager() : _fadeMaskMap = DependencyManager::get()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); } -render::ShapeKey::Builder FadeManager::getKeyBuilder() const +render::ShapeKey::Builder FadeEffect::getKeyBuilder() const { render::ShapeKey::Builder builder; diff --git a/libraries/render-utils/src/FadeManager.h b/libraries/render-utils/src/FadeEffect.h similarity index 86% rename from libraries/render-utils/src/FadeManager.h rename to libraries/render-utils/src/FadeEffect.h index d42447fc26..6c5b2c90c8 100644 --- a/libraries/render-utils/src/FadeManager.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -1,5 +1,5 @@ // -// FadeManager.h +// FadeEffect.h // libraries/render-utils/src/ // // Created by Olivier Prat on 06/06/17. @@ -8,19 +8,19 @@ // 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_FadeManager_h -#define hifi_FadeManager_h +#ifndef hifi_FadeEffect_h +#define hifi_FadeEffect_h #include #include #include // Centralizes fade effect data and functions -class FadeManager : public Dependency { +class FadeEffect : public Dependency { SINGLETON_DEPENDENCY public: - FadeManager(); + FadeEffect(); const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; } @@ -40,4 +40,4 @@ private: }; -#endif // hifi_FadeManager_h +#endif // hifi_FadeEffect_h diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 87ac019030..1d6ddea70f 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -15,7 +15,7 @@ #include "DeferredLightingEffect.h" #include "EntityItem.h" -#include "FadeManager.h" +#include "FadeEffect.h" using namespace render; @@ -552,7 +552,7 @@ float ModelMeshPartPayload::computeFadePercent() const { } void ModelMeshPartPayload::bindFade(gpu::Batch& batch) const { - const bool isDebugEnabled = DependencyManager::get()->isDebugEnabled(); + const bool isDebugEnabled = DependencyManager::get()->isDebugEnabled(); if (_fadeState != FADE_COMPLETE || isDebugEnabled) { auto& fade = _fadeBuffer.edit(); @@ -563,7 +563,7 @@ void ModelMeshPartPayload::bindFade(gpu::Batch& batch) const { fade._percent = computeFadePercent(); } else { - fade._percent = DependencyManager::get()->getDebugFadePercent(); + fade._percent = DependencyManager::get()->getDebugFadePercent(); } fade._offset = offset; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 4d91d7d512..1e8673b385 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -35,7 +35,7 @@ #include "HitEffect.h" #include "TextureCache.h" #include "ZoneRenderer.h" -#include "FadeManager.h" +#include "FadeEffect.h" #include "AmbientOcclusionEffect.h" #include "AntialiasingEffect.h" @@ -53,8 +53,8 @@ extern void initDeferredPipelines(render::ShapePlumber& plumber); void RenderDeferredTask::configure(const Config& config) { - DependencyManager::get()->setDebugEnabled(config.debugFade); - DependencyManager::get()->setDebugFadePercent(config.debugFadePercent); + DependencyManager::get()->setDebugEnabled(config.debugFade); + DependencyManager::get()->setDebugFadePercent(config.debugFadePercent); } void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { @@ -92,7 +92,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto deferredFramebuffer = prepareDeferredOutputs.getN(0); const auto lightingFramebuffer = prepareDeferredOutputs.getN(1); - DependencyManager::set(); + DependencyManager::set(); // Render opaque objects in DeferredBuffer const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying(); @@ -257,8 +257,8 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& const auto& lightingModel = inputs.get1(); RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); - gpu::TexturePointer fadeMaskMap = DependencyManager::get()->getFadeMaskMap(); + ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); + gpu::TexturePointer fadeMaskMap = DependencyManager::get()->getFadeMaskMap(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -309,8 +309,8 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const const auto& lightingModel = inputs.get1(); RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); - gpu::TexturePointer fadeMaskMap = DependencyManager::get()->getFadeMaskMap(); + ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); + gpu::TexturePointer fadeMaskMap = DependencyManager::get()->getFadeMaskMap(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; From de143d0ea28592ade76fed5cdc8fc4904b0168f1 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 6 Jun 2017 17:07:20 +0200 Subject: [PATCH 10/86] Switched to uniforms for sending fade shader data. Moved more fade functions to FadeEffect class --- libraries/render-utils/src/Fade.slh | 15 ++--- libraries/render-utils/src/FadeEffect.cpp | 39 +++++++++++- libraries/render-utils/src/FadeEffect.h | 10 +++ .../render-utils/src/MeshPartPayload.cpp | 61 ++----------------- libraries/render-utils/src/MeshPartPayload.h | 13 +--- .../render-utils/src/RenderDeferredTask.cpp | 6 +- 6 files changed, 60 insertions(+), 84 deletions(-) diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 06eed5b21f..d634473dd0 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -18,15 +18,8 @@ <@func declareFadeFragment()@> -struct Fade { - vec3 _Offset; - float _Percent; -}; - -uniform fadeBuffer { - Fade fade; -}; - +uniform vec3 fadeOffset; +uniform float fadePercent; uniform sampler2D fadeMaskMap; vec2 hash2D(vec3 position) { @@ -37,7 +30,7 @@ float evalFadeMask(vec3 position) { const float FADE_MASK_INV_SCALE = 1.0; // Do tri-linear interpolation - vec3 noisePosition = position * FADE_MASK_INV_SCALE + fade._Offset; + vec3 noisePosition = position * FADE_MASK_INV_SCALE + fadeOffset; vec3 noisePositionFloored = floor(noisePosition); vec3 noisePositionFraction = fract(noisePosition); float noiseLowXLowYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored), 0).r; @@ -57,7 +50,7 @@ float evalFadeMask(vec3 position) { } void applyFade(vec3 position) { - if (evalFadeMask(position) > fade._Percent) { + if (evalFadeMask(position) > fadePercent) { discard; } } diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index f750798914..0bca42ad12 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -2,6 +2,9 @@ #include "TextureCache.h" #include +#include +#include +#include FadeEffect::FadeEffect() : _isDebugEnabled{ false }, @@ -11,8 +14,7 @@ FadeEffect::FadeEffect() : _fadeMaskMap = DependencyManager::get()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); } -render::ShapeKey::Builder FadeEffect::getKeyBuilder() const -{ +render::ShapeKey::Builder FadeEffect::getKeyBuilder() const { render::ShapeKey::Builder builder; if (_isDebugEnabled) { @@ -23,3 +25,36 @@ render::ShapeKey::Builder FadeEffect::getKeyBuilder() const return builder; } +void FadeEffect::bindPerBatch(gpu::Batch& batch) const +{ + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::FADE_MASK, _fadeMaskMap); +} + +float FadeEffect::computeFadePercent(quint64 startTime) const { + float fadeAlpha = 1.0f; + const double INV_FADE_PERIOD = 1.0 / (double)(3 * USECS_PER_SECOND); + double fraction = (double)(usecTimestampNow() - startTime) * INV_FADE_PERIOD; + if (fraction < 1.0) { + fadeAlpha = Interpolate::simpleNonLinearBlend(fraction); + } + return fadeAlpha; +} + +void FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, State state) const { + if (state != Complete || _isDebugEnabled) { + const gpu::ShaderPointer& program = args->_pipeline->pipeline->getProgram(); + int fadeOffsetLoc = program->getUniforms().findLocation("fadeOffset"); + int fadePercentLoc = program->getUniforms().findLocation("fadePercent"); + float percent; + + // A bit ugly to have the test at every bind... + if (!_isDebugEnabled) { + percent = computeFadePercent(startTime); + } + else { + percent = _debugFadePercent; + } + batch._glUniform1f(fadePercentLoc, percent); + batch._glUniform3f(fadeOffsetLoc, offset.x, offset.y, offset.z); + } +} diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 6c5b2c90c8..b1cbf0cb29 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -20,6 +20,12 @@ class FadeEffect : public Dependency { SINGLETON_DEPENDENCY public: + enum State : uint8_t { + WaitingToStart = 0, + InProgress = 1, + Complete = 2, + }; + FadeEffect(); const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; } @@ -32,6 +38,10 @@ public: render::ShapeKey::Builder getKeyBuilder() const; + void bindPerBatch(gpu::Batch& batch) const; + void bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, State state = InProgress) const; + float computeFadePercent(quint64 startTime) const; + private: gpu::TexturePointer _fadeMaskMap; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 1d6ddea70f..a44974cc92 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -321,19 +321,10 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren } } -struct ModelMeshPartPayload::Fade -{ - glm::vec3 _offset; // The noise offset - float _percent; // The fade percent -}; - ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : _meshIndex(_meshIndex), _shapeID(shapeIndex) { - Fade fade; - _fadeBuffer = gpu::BufferView(std::make_shared(sizeof(Fade), (const gpu::Byte*) &fade)); - assert(model && model->isLoaded()); _model = model; auto& modelMesh = model->getGeometry()->getMeshes().at(_meshIndex); @@ -493,7 +484,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { if (wireframe) { builder.withWireframe(); } - if (_fadeState != FADE_COMPLETE) { + if (_fadeState != FadeEffect::Complete) { builder.withFade(); } return builder.build(); @@ -529,48 +520,6 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline: batch.setModelTransform(_transform); } -float ModelMeshPartPayload::computeFadePercent() const { - if (_fadeState == FADE_WAITING_TO_START) { - return 0.0f; - } - float fadeAlpha = 1.0f; - const double INV_FADE_PERIOD = 1.0 / (double)(3 * USECS_PER_SECOND); - double fraction = (double)(usecTimestampNow() - _fadeStartTime) * INV_FADE_PERIOD; - if (fraction < 1.0) { - fadeAlpha = Interpolate::simpleNonLinearBlend(fraction); - } - if (fadeAlpha >= 1.0f) { - _fadeState = FADE_COMPLETE; - // when fade-in completes we flag model for one last "render item update" - ModelPointer model = _model.lock(); - if (model) { - model->setRenderItemsNeedUpdate(); - } - fadeAlpha = 1.0f; - } - return fadeAlpha; -} - -void ModelMeshPartPayload::bindFade(gpu::Batch& batch) const { - const bool isDebugEnabled = DependencyManager::get()->isDebugEnabled(); - - if (_fadeState != FADE_COMPLETE || isDebugEnabled) { - auto& fade = _fadeBuffer.edit(); - glm::vec3 offset = _transform.getTranslation(); - - // A bit ugly to have the test at every bind... - if (!isDebugEnabled) { - fade._percent = computeFadePercent(); - } - else { - fade._percent = DependencyManager::get()->getDebugFadePercent(); - } - - fade._offset = offset; - batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::FADE, _fadeBuffer); - } -} - void ModelMeshPartPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("ModelMeshPartPayload::render"); @@ -579,13 +528,13 @@ void ModelMeshPartPayload::render(RenderArgs* args) { return; // bail asap } - if (_fadeState == FADE_WAITING_TO_START) { + if (_fadeState == FadeEffect::WaitingToStart) { if (model->isLoaded()) { if (EntityItem::getEntitiesShouldFadeFunction()()) { _fadeStartTime = usecTimestampNow(); - _fadeState = FADE_IN_PROGRESS; + _fadeState = FadeEffect::InProgress; } else { - _fadeState = FADE_COMPLETE; + _fadeState = FadeEffect::Complete; } model->setRenderItemsNeedUpdate(); } else { @@ -618,7 +567,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { bindMaterial(batch, locations, args->_enableTexturing); // Apply fade effect - bindFade(batch); + DependencyManager::get()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState); args->_details._materialSwitches++; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 0d3a8df576..6762601738 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -22,10 +22,7 @@ #include #include "Model.h" - -const uint8_t FADE_WAITING_TO_START = 0; -const uint8_t FADE_IN_PROGRESS = 1; -const uint8_t FADE_COMPLETE = 2; +#include "FadeEffect.h" class Model; @@ -95,8 +92,6 @@ public: const Transform& boundTransform, const gpu::BufferPointer& buffer); - float computeFadePercent() const; - // Render Item interface render::ItemKey getKey() const override; int getLayer() const; @@ -106,7 +101,6 @@ 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) const; void initCache(); @@ -124,11 +118,8 @@ public: private: - struct Fade; - - mutable gpu::BufferView _fadeBuffer; mutable quint64 _fadeStartTime { 0 }; - mutable uint8_t _fadeState { FADE_WAITING_TO_START }; + mutable FadeEffect::State _fadeState { FadeEffect::WaitingToStart } ; }; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 1e8673b385..8b2a232c87 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -258,7 +258,6 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& RenderArgs* args = renderContext->args; ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); - gpu::TexturePointer fadeMaskMap = DependencyManager::get()->getFadeMaskMap(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -285,7 +284,7 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& } // Prepare fade effect - batch.setResourceTexture(ShapePipeline::Slot::MAP::FADE_MASK, fadeMaskMap); + DependencyManager::get()->bindPerBatch(batch); ShapeKey globalKey = keyBuilder.build(); args->_globalShapeKey = globalKey._flags.to_ulong(); @@ -310,7 +309,6 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const RenderArgs* args = renderContext->args; ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); - gpu::TexturePointer fadeMaskMap = DependencyManager::get()->getFadeMaskMap(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -337,7 +335,7 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const } // Prepare fade effect - batch.setResourceTexture(ShapePipeline::Slot::MAP::FADE_MASK, fadeMaskMap); + DependencyManager::get()->bindPerBatch(batch); ShapeKey globalKey = keyBuilder.build(); args->_globalShapeKey = globalKey._flags.to_ulong(); From 20d4fcbbc73de7cd7db13cb73200cf3017430544 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 8 Jun 2017 09:24:12 +0200 Subject: [PATCH 11/86] Fixed fading on skinned objects. Added initialiazeShapePipelines on GeometryCache to postpone simple pipeline creation after initializeGL --- interface/src/Application.cpp | 2 + .../src/RenderableShapeEntityItem.cpp | 6 +- libraries/render-utils/src/Fade.slh | 31 +++-- libraries/render-utils/src/FadeEffect.cpp | 38 +++--- libraries/render-utils/src/FadeEffect.h | 4 +- libraries/render-utils/src/GeometryCache.cpp | 119 ++++++++++++------ libraries/render-utils/src/GeometryCache.h | 22 +++- .../render-utils/src/skin_model_fade.slv | 2 +- 8 files changed, 151 insertions(+), 73 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 851c07c501..b798f10376 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -907,6 +907,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Make sure we don't time out during slow operations at startup updateHeartbeat(); + // Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success. + DependencyManager::get()->initializeShapePipelines(); // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value. // The value will be 0 if the user blew away settings this session, which is both a feature and a bug. diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 1ad60bf7c6..58ab8f5bc5 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -120,11 +121,14 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { DependencyManager::get()->renderShape(batch, MAPPING[_shape]); } } else { - // FIXME, support instanced multi-shape rendering using multidraw indirect color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; + // FIXME, support instanced multi-shape rendering using multidraw indirect auto geometryCache = DependencyManager::get(); + auto fadeEffect = DependencyManager::get(); auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); + assert(pipeline != nullptr); + if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { geometryCache->renderWireShapeInstance(batch, MAPPING[_shape], color, pipeline); } else { diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index d634473dd0..38fad9321a 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -11,8 +11,8 @@ <@func transformModelToFadePos(objectTransform, objectPosition, fadePosition)@> { - <$transformModelToWorldPos($objectTransform$, $objectPosition$, $fadePosition$)$> - <$fadePosition$> -= vec4(<$objectTransform$>._model[3].xyz, 0.f); + vec4 objectVector = vec4(<$objectPosition$>.xyz, 0.f); + <$transformModelToWorldPos($objectTransform$, objectVector, $fadePosition$)$> } <@endfunc@> @@ -26,6 +26,17 @@ vec2 hash2D(vec3 position) { return position.xy* vec2(0.1677, 0.221765) + position.z*0.561; } +float noise3D(vec3 position) { + return textureLod(fadeMaskMap, hash2D(position), 0).r; + /*const float ONE_OVER_MAX_POSITIVE_INT = (1.f / 2147483648.f); + int3 iPosition = int3(position); + int position = iPosition.x + (iPosition.y*57) + (iPosition.z*3023); + int bits = (position << 13) ^ position; + int pseudoRandomPositiveInt = (bits * ((bits*bits*15731)+789221)+1376312589) & 0x7fffffff; + float pseudoRandomFloatZeroToOne = ONE_OVER_MAX_POSITIVE_INT * (float)pseudoRandomPositiveInt; + return pseudoRandomFloatZeroToOne;*/ +} + float evalFadeMask(vec3 position) { const float FADE_MASK_INV_SCALE = 1.0; @@ -33,14 +44,14 @@ float evalFadeMask(vec3 position) { vec3 noisePosition = position * FADE_MASK_INV_SCALE + fadeOffset; 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; - float noiseHighXLowYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,0,0)), 0).r; - float noiseHighXHighYLowZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,1,0)), 0).r; - float noiseLowXLowYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(0,0,1)), 0).r; - float noiseLowXHighYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(0,1,1)), 0).r; - float noiseHighXLowYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,0,1)), 0).r; - float noiseHighXHighYHighZ = textureLod(fadeMaskMap, hash2D(noisePositionFloored+vec3(1,1,1)), 0).r; + float noiseLowXLowYLowZ = noise3D(noisePositionFloored); + float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0)); + float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0)); + float noiseHighXHighYLowZ = noise3D(noisePositionFloored+vec3(1,1,0)); + float noiseLowXLowYHighZ = noise3D(noisePositionFloored+vec3(0,0,1)); + float noiseLowXHighYHighZ = noise3D(noisePositionFloored+vec3(0,1,1)); + float noiseHighXLowYHighZ = noise3D(noisePositionFloored+vec3(1,0,1)); + float noiseHighXHighYHighZ = noise3D(noisePositionFloored+vec3(1,1,1)); vec4 maskLowZ = vec4(noiseLowXLowYLowZ, noiseLowXHighYLowZ, noiseHighXLowYLowZ, noiseHighXHighYLowZ); vec4 maskHighZ = vec4(noiseLowXLowYHighZ, noiseLowXHighYHighZ, noiseHighXLowYHighZ, noiseHighXHighYHighZ); vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z); diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 0bca42ad12..ceec55c448 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -14,14 +14,11 @@ FadeEffect::FadeEffect() : _fadeMaskMap = DependencyManager::get()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); } -render::ShapeKey::Builder FadeEffect::getKeyBuilder() const { - render::ShapeKey::Builder builder; - +render::ShapeKey::Builder FadeEffect::getKeyBuilder(render::ShapeKey::Builder builder) const { if (_isDebugEnabled) { // Force fade for everyone builder.withFade(); } - return builder; } @@ -41,20 +38,27 @@ float FadeEffect::computeFadePercent(quint64 startTime) const { } void FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, State state) const { - if (state != Complete || _isDebugEnabled) { - const gpu::ShaderPointer& program = args->_pipeline->pipeline->getProgram(); - int fadeOffsetLoc = program->getUniforms().findLocation("fadeOffset"); - int fadePercentLoc = program->getUniforms().findLocation("fadePercent"); - float percent; + bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime, state); +} - // A bit ugly to have the test at every bind... - if (!_isDebugEnabled) { - percent = computeFadePercent(startTime); +void FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, State state) const { + if (state != Complete || _isDebugEnabled) { + auto& program = pipeline->getProgram(); + auto fadeOffsetLoc = program->getUniforms().findLocation("fadeOffset"); + auto fadePercentLoc = program->getUniforms().findLocation("fadePercent"); + + if (fadeOffsetLoc >= 0 && fadePercentLoc >= 0) { + float percent; + + // A bit ugly to have the test at every bind... + if (!_isDebugEnabled) { + percent = computeFadePercent(startTime); + } + else { + percent = _debugFadePercent; + } + batch._glUniform1f(fadePercentLoc, percent); + batch._glUniform3f(fadeOffsetLoc, offset.x, offset.y, offset.z); } - else { - percent = _debugFadePercent; - } - batch._glUniform1f(fadePercentLoc, percent); - batch._glUniform3f(fadeOffsetLoc, offset.x, offset.y, offset.z); } } diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index b1cbf0cb29..dea14e5678 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -36,10 +36,12 @@ public: void setDebugFadePercent(float value) { assert(value >= 0.f && value <= 1.f); _debugFadePercent = value; } float getDebugFadePercent() const { return _debugFadePercent; } - render::ShapeKey::Builder getKeyBuilder() const; + render::ShapeKey::Builder getKeyBuilder(render::ShapeKey::Builder builder = render::ShapeKey::Builder()) const; void bindPerBatch(gpu::Batch& batch) const; void bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, State state = InProgress) const; + void bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, State state = InProgress) const; + float computeFadePercent(quint64 startTime) const; private: diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index f1c995b943..fae59491bc 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -24,6 +24,7 @@ #include "TextureCache.h" #include "RenderUtilsLogging.h" +#include "FadeEffect.h" #include "gpu/StandardShaderLib.h" @@ -35,6 +36,9 @@ #include "simple_vert.h" #include "simple_textured_frag.h" #include "simple_textured_unlit_frag.h" +#include "simple_fade_vert.h" +#include "simple_textured_fade_frag.h" +#include "simple_textured_unlit_fade_frag.h" #include "simple_opaque_web_browser_frag.h" #include "simple_opaque_web_browser_overlay_frag.h" #include "simple_transparent_web_browser_frag.h" @@ -403,30 +407,13 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() { render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline; render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline; +render::ShapePipelinePointer GeometryCache::_simpleOpaqueFadePipeline; +render::ShapePipelinePointer GeometryCache::_simpleTransparentFadePipeline; render::ShapePipelinePointer GeometryCache::_simpleWirePipeline; GeometryCache::GeometryCache() : _nextID(0) { buildShapes(); - GeometryCache::_simpleOpaquePipeline = - std::make_shared(getSimplePipeline(false, false, true, false), nullptr, - [](const render::ShapePipeline&, gpu::Batch& batch) { - // Set the defaults needed for a simple program - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, - DependencyManager::get()->getWhiteTexture()); - } - ); - GeometryCache::_simpleTransparentPipeline = - std::make_shared(getSimplePipeline(false, true, true, false), nullptr, - [](const render::ShapePipeline&, gpu::Batch& batch) { - // Set the defaults needed for a simple program - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, - DependencyManager::get()->getWhiteTexture()); - } - ); - GeometryCache::_simpleWirePipeline = - std::make_shared(getSimplePipeline(false, false, true, true), nullptr, - [](const render::ShapePipeline&, gpu::Batch& batch) {}); } GeometryCache::~GeometryCache() { @@ -471,6 +458,35 @@ void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { batch.setInputBuffer(gpu::Stream::COLOR, colorView); } +void GeometryCache::initializeShapePipelines() { + GeometryCache::_simpleOpaquePipeline = getShapePipeline(false, false, true, false); + GeometryCache::_simpleTransparentPipeline = getShapePipeline(false, true, true, false); + GeometryCache::_simpleOpaqueFadePipeline = getShapePipeline(false, false, true, false, false, true); + GeometryCache::_simpleTransparentFadePipeline = getShapePipeline(false, true, true, false, false, true); + GeometryCache::_simpleWirePipeline = getShapePipeline(false, false, true, true); +} + +render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool culled, + bool unlit, bool depthBias, bool fading) { + return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, fading), nullptr, + [](const render::ShapePipeline&, gpu::Batch& batch) { + // Set the defaults needed for a simple program + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, + DependencyManager::get()->getWhiteTexture()); + } + ); +} + +render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading) { + isFading = isFading || DependencyManager::get()->isDebugEnabled(); + return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline; +} + +render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) { + isFading = isFading || DependencyManager::get()->isDebugEnabled(); + return isFading ? _simpleTransparentFadePipeline : _simpleTransparentPipeline; +} + void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) { batch.setInputFormat(getSolidStreamFormat()); _shapes[shape].draw(batch); @@ -1714,6 +1730,7 @@ public: IS_CULLED_FLAG, IS_UNLIT_FLAG, HAS_DEPTH_BIAS_FLAG, + IS_FADING_FLAG, NUM_FLAGS, }; @@ -1724,6 +1741,7 @@ public: IS_CULLED = (1 << IS_CULLED_FLAG), IS_UNLIT = (1 << IS_UNLIT_FLAG), HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG), + IS_FADING = (1 << IS_FADING_FLAG), }; typedef unsigned short Flags; @@ -1734,6 +1752,7 @@ public: bool isCulled() const { return isFlag(IS_CULLED); } bool isUnlit() const { return isFlag(IS_UNLIT); } bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); } + bool isFading() const { return isFlag(IS_FADING); } Flags _flags = 0; short _spare = 0; @@ -1742,9 +1761,9 @@ public: SimpleProgramKey(bool textured = false, bool transparent = false, bool culled = true, - bool unlit = false, bool depthBias = false) { + bool unlit = false, bool depthBias = false, bool fading = false) { _flags = (textured ? IS_TEXTURED : 0) | (transparent ? IS_TRANSPARENT : 0) | (culled ? IS_CULLED : 0) | - (unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0); + (unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0) | (fading ? IS_FADING : 0); } SimpleProgramKey(int bitmask) : _flags(bitmask) {} @@ -1818,23 +1837,8 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool tra } } -gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased) { - SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased }; - - // Compile the shaders - static std::once_flag once; - std::call_once(once, [&]() { - auto VS = gpu::Shader::createVertex(std::string(simple_vert)); - auto PS = gpu::Shader::createPixel(std::string(simple_textured_frag)); - auto PSUnlit = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag)); - - _simpleShader = gpu::Shader::createProgram(VS, PS); - _unlitShader = gpu::Shader::createProgram(VS, PSUnlit); - - gpu::Shader::BindingSet slotBindings; - gpu::Shader::makeProgram(*_simpleShader, slotBindings); - gpu::Shader::makeProgram(*_unlitShader, slotBindings); - }); +gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool fading) { + SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased, fading }; // If the pipeline already exists, return it auto it = _simplePrograms.find(config); @@ -1842,6 +1846,37 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp return it.value(); } + // Compile the shaders + if (!fading) { + static std::once_flag once; + std::call_once(once, [&]() { + auto VS = gpu::Shader::createVertex(std::string(simple_vert)); + auto PS = gpu::Shader::createPixel(std::string(simple_textured_frag)); + auto PSUnlit = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag)); + + _simpleShader = gpu::Shader::createProgram(VS, PS); + _unlitShader = gpu::Shader::createProgram(VS, PSUnlit); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*_simpleShader, slotBindings); + gpu::Shader::makeProgram(*_unlitShader, slotBindings); + }); + } else { + static std::once_flag once; + std::call_once(once, [&]() { + auto VS = gpu::Shader::createVertex(std::string(simple_fade_vert)); + auto PS = gpu::Shader::createPixel(std::string(simple_textured_fade_frag)); + auto PSUnlit = gpu::Shader::createPixel(std::string(simple_textured_unlit_fade_frag)); + + _simpleFadeShader = gpu::Shader::createProgram(VS, PS); + _unlitFadeShader = gpu::Shader::createProgram(VS, PSUnlit); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*_simpleFadeShader, slotBindings); + gpu::Shader::makeProgram(*_unlitFadeShader, slotBindings); + }); + } + // If the pipeline did not exist, make it auto state = std::make_shared(); if (config.isCulled()) { @@ -1858,7 +1893,7 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - gpu::ShaderPointer program = (config.isUnlit()) ? _unlitShader : _simpleShader; + gpu::ShaderPointer program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) : (config.isFading() ? _simpleFadeShader : _simpleShader); gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state); _simplePrograms.insert(config, pipeline); return pipeline; @@ -1900,19 +1935,23 @@ void renderInstances(gpu::Batch& batch, const glm::vec4& color, bool isWire, } void GeometryCache::renderSolidShapeInstance(gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { + assert(pipeline != nullptr); renderInstances(batch, color, false, pipeline, shape); } void GeometryCache::renderWireShapeInstance(gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { + assert(pipeline != nullptr); renderInstances(batch, color, true, pipeline, shape); } void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { + assert(pipeline != nullptr); renderInstances(batch, color, false, pipeline, GeometryCache::Sphere); } void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { + assert(pipeline != nullptr); renderInstances(batch, color, true, pipeline, GeometryCache::Sphere); } @@ -1921,6 +1960,7 @@ void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& //#define DEBUG_SHAPES void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { + assert(pipeline != nullptr); #ifdef DEBUG_SHAPES static auto startTime = usecTimestampNow(); renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { @@ -1960,5 +2000,6 @@ void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { static const std::string INSTANCE_NAME = __FUNCTION__; + assert(pipeline != nullptr); renderInstances(batch, color, true, pipeline, GeometryCache::Cube); } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index e0a610a095..acaaf8eba3 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -156,7 +156,7 @@ public: bool unlit = false, bool depthBias = false); // Get the pipeline to render static geometry gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true, - bool unlit = false, bool depthBias = false); + bool unlit = false, bool depthBias = false, bool fading = false); void bindOpaqueWebBrowserProgram(gpu::Batch& batch, bool isAA); gpu::PipelinePointer getOpaqueWebBrowserProgram(bool isAA); @@ -164,9 +164,19 @@ public: void bindTransparentWebBrowserProgram(gpu::Batch& batch, bool isAA); gpu::PipelinePointer getTransparentWebBrowserProgram(bool isAA); - render::ShapePipelinePointer getOpaqueShapePipeline() { return GeometryCache::_simpleOpaquePipeline; } - render::ShapePipelinePointer getTransparentShapePipeline() { return GeometryCache::_simpleTransparentPipeline; } - render::ShapePipelinePointer getWireShapePipeline() { return GeometryCache::_simpleWirePipeline; } + void initializeShapePipelines(); + + render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true, + bool unlit = false, bool depthBias = false, bool fading = false); + + render::ShapePipelinePointer getOpaqueShapePipeline() { assert(_simpleOpaquePipeline != nullptr); return _simpleOpaquePipeline; } + render::ShapePipelinePointer getTransparentShapePipeline() { assert(_simpleTransparentPipeline != nullptr); return _simpleTransparentPipeline; } + render::ShapePipelinePointer getOpaqueFadeShapePipeline() { assert(_simpleOpaqueFadePipeline != nullptr); return _simpleOpaqueFadePipeline; } + render::ShapePipelinePointer getTransparentFadeShapePipeline() { assert(_simpleTransparentFadePipeline != nullptr); return _simpleTransparentFadePipeline; } + render::ShapePipelinePointer getOpaqueShapePipeline(bool isFading); + render::ShapePipelinePointer getTransparentShapePipeline(bool isFading); + render::ShapePipelinePointer getWireShapePipeline() { assert(_simpleWirePipeline != nullptr); return GeometryCache::_simpleWirePipeline; } + // Static (instanced) geometry void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); @@ -418,8 +428,12 @@ private: gpu::ShaderPointer _simpleShader; gpu::ShaderPointer _unlitShader; + gpu::ShaderPointer _simpleFadeShader; + gpu::ShaderPointer _unlitFadeShader; static render::ShapePipelinePointer _simpleOpaquePipeline; static render::ShapePipelinePointer _simpleTransparentPipeline; + static render::ShapePipelinePointer _simpleOpaqueFadePipeline; + static render::ShapePipelinePointer _simpleTransparentFadePipeline; static render::ShapePipelinePointer _simpleOpaqueOverlayPipeline; static render::ShapePipelinePointer _simpleTransparentOverlayPipeline; static render::ShapePipelinePointer _simpleWirePipeline; diff --git a/libraries/render-utils/src/skin_model_fade.slv b/libraries/render-utils/src/skin_model_fade.slv index a96c948470..bce60b4242 100644 --- a/libraries/render-utils/src/skin_model_fade.slv +++ b/libraries/render-utils/src/skin_model_fade.slv @@ -50,6 +50,6 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> - <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> + <$transformModelToFadePos(obj, position, _worldFadePosition)$> <$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, _normal.xyz)$> } From cba70e6be0e8728410edb3d40c4479401838f864 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 8 Jun 2017 14:57:09 +0200 Subject: [PATCH 12/86] Fade working on voxel objects --- .../src/RenderablePolyVoxEntityItem.cpp | 40 +++++++++---- .../src/RenderablePolyVoxEntityItem.h | 7 ++- .../entities-renderer/src/polyvox_fade.slf | 60 +++++++++++++++++++ .../entities-renderer/src/polyvox_fade.slv | 35 +++++++++++ libraries/render-utils/src/FadeEffect.cpp | 20 ++++--- libraries/render-utils/src/FadeEffect.h | 13 ++-- .../render-utils/src/MeshPartPayload.cpp | 10 ++-- libraries/render-utils/src/MeshPartPayload.h | 8 ++- libraries/render/src/render/ShapePipeline.cpp | 2 - libraries/render/src/render/ShapePipeline.h | 2 - 10 files changed, 155 insertions(+), 42 deletions(-) create mode 100644 libraries/entities-renderer/src/polyvox_fade.slf create mode 100644 libraries/entities-renderer/src/polyvox_fade.slv diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index fd5346093b..e5eecfd66c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -48,13 +48,17 @@ #include "model/Geometry.h" #include "EntityTreeRenderer.h" #include "polyvox_vert.h" +#include "polyvox_fade_vert.h" #include "polyvox_frag.h" +#include "polyvox_fade_frag.h" #include "RenderablePolyVoxEntityItem.h" #include "EntityEditPacketSender.h" #include "PhysicalEntitySimulation.h" -gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr; -gpu::PipelinePointer RenderablePolyVoxEntityItem::_wireframePipeline = nullptr; +#include "FadeEffect.h" + +gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipelines[2] = { nullptr, nullptr }; +gpu::PipelinePointer RenderablePolyVoxEntityItem::_wireframePipelines[2] = { nullptr, nullptr }; const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5; @@ -727,31 +731,34 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { return; } - if (!_pipeline) { - gpu::ShaderPointer vertexShader = gpu::Shader::createVertex(std::string(polyvox_vert)); - gpu::ShaderPointer pixelShader = gpu::Shader::createPixel(std::string(polyvox_frag)); + if (!_pipelines[0]) { + gpu::ShaderPointer vertexShaders[2] = { gpu::Shader::createVertex(std::string(polyvox_vert)), gpu::Shader::createVertex(std::string(polyvox_fade_vert)) }; + gpu::ShaderPointer pixelShaders[2] = { gpu::Shader::createPixel(std::string(polyvox_frag)), gpu::Shader::createPixel(std::string(polyvox_fade_frag)) }; gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0)); slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2)); - - gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); - gpu::Shader::makeProgram(*program, slotBindings); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), 3)); auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); state->setDepthTest(true, true, gpu::LESS_EQUAL); - _pipeline = gpu::Pipeline::create(program, state); - auto wireframeState = std::make_shared(); wireframeState->setCullMode(gpu::State::CULL_BACK); wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL); wireframeState->setFillMode(gpu::State::FILL_LINE); - _wireframePipeline = gpu::Pipeline::create(program, wireframeState); + // Two sets of pipelines: normal and fading + for (auto i = 0; i < 2; i++) { + gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShaders[i], pixelShaders[i]); + gpu::Shader::makeProgram(*program, slotBindings); + + _pipelines[i] = gpu::Pipeline::create(program, state); + _wireframePipelines[i] = gpu::Pipeline::create(program, wireframeState); + } } if (!_vertexFormat) { @@ -765,7 +772,8 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { // Pick correct Pipeline bool wireframe = (render::ShapeKey(args->_globalShapeKey).isWireframe()); - auto pipeline = (wireframe ? _wireframePipeline : _pipeline); + auto pipelineVariation = isFading() & 1; + auto pipeline = (wireframe ? _wireframePipelines[pipelineVariation]: _pipelines[pipelineVariation]); batch.setPipeline(pipeline); Transform transform(voxelToWorldMatrix()); @@ -809,6 +817,12 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { batch.setResourceTexture(2, DependencyManager::get()->getWhiteTexture()); } + // Apply fade effect + auto fadeEffect = DependencyManager::get(); + if (fadeEffect->bindPerItem(batch, pipeline.get(), glm::vec3(0, 0, 0), _fadeStartTime, isFading())) { + fadeEffect->bindPerBatch(batch, 3); + } + int voxelVolumeSizeLocation = pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize"); batch._glUniform3f(voxelVolumeSizeLocation, voxelVolumeSize.x, voxelVolumeSize.y, voxelVolumeSize.z); @@ -1611,7 +1625,7 @@ void RenderablePolyVoxEntityItem::bonkNeighbors() { void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) { EntityItem::locationChanged(tellPhysics); - if (!_pipeline || !render::Item::isValidID(_myItem)) { + if (!_pipelines[0] || !render::Item::isValidID(_myItem)) { return; } render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index ff97f09ee1..d6216f3eff 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -143,7 +143,7 @@ public: void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; _meshReady = false; }); } - // Transparent polyvox didn't seem to be working so disable for now + // Transparent polyvox didn't seem to be working so disable for now. bool isTransparent() override { return false; } bool getMeshes(MeshProxyList& result) override; @@ -166,8 +166,9 @@ private: const int MATERIAL_GPU_SLOT = 3; render::ItemID _myItem{ render::Item::INVALID_ITEM_ID }; - static gpu::PipelinePointer _pipeline; - static gpu::PipelinePointer _wireframePipeline; + + static gpu::PipelinePointer _pipelines[2]; + static gpu::PipelinePointer _wireframePipelines[2]; ShapeInfo _shapeInfo; diff --git a/libraries/entities-renderer/src/polyvox_fade.slf b/libraries/entities-renderer/src/polyvox_fade.slf new file mode 100644 index 0000000000..ac2d77564b --- /dev/null +++ b/libraries/entities-renderer/src/polyvox_fade.slf @@ -0,0 +1,60 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// polyvox_fade.frag +// fragment shader +// +// Created by Olivier Prat on 2017-06-08 +// 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 model/Material.slh@> +<@include DeferredBufferWrite.slh@> + +<@include Fade.slh@> + +in vec3 _normal; +in vec4 _position; +in vec4 _worldPosition; +in vec4 _worldFadePosition; + +uniform sampler2D xMap; +uniform sampler2D yMap; +uniform sampler2D zMap; +uniform vec3 voxelVolumeSize; + +// Declare after all samplers to prevent sampler location mix up with voxel shading (sampler locations are hardcoded in RenderablePolyVoxEntityItem) +<$declareFadeFragment()$> + +void main(void) { + applyFade(_worldFadePosition.xyz); + + vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); + worldNormal = normalize(worldNormal); + + float inPositionX = (_worldPosition.x - 0.5) / voxelVolumeSize.x; + float inPositionY = (_worldPosition.y - 0.5) / voxelVolumeSize.y; + float inPositionZ = (_worldPosition.z - 0.5) / voxelVolumeSize.z; + + vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY)); + vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ)); + vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY)); + + vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z); + vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y); + vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x); + vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0); + + packDeferredFragment( + _normal, + 1.0, + vec3(diffuse), + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); +} diff --git a/libraries/entities-renderer/src/polyvox_fade.slv b/libraries/entities-renderer/src/polyvox_fade.slv new file mode 100644 index 0000000000..f024957677 --- /dev/null +++ b/libraries/entities-renderer/src/polyvox_fade.slv @@ -0,0 +1,35 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// polyvox_fade.vert +// vertex shader +// +// Created by Seth Alves on 2015-8-3 +// Copyright 2015 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 gpu/Inputs.slh@> + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +<@include Fade.slh@> + +out vec4 _position; +out vec4 _worldPosition; +out vec3 _normal; +out vec4 _worldFadePosition; + +void main(void) { + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldPos(obj, inPosition, _worldFadePosition)$> + _worldPosition = inPosition; +} diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index ceec55c448..f2a799dbc6 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -22,9 +22,13 @@ render::ShapeKey::Builder FadeEffect::getKeyBuilder(render::ShapeKey::Builder bu return builder; } -void FadeEffect::bindPerBatch(gpu::Batch& batch) const -{ - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::FADE_MASK, _fadeMaskMap); +void FadeEffect::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation) const { + batch.setResourceTexture(fadeMaskMapLocation, _fadeMaskMap); +} + +void FadeEffect::bindPerBatch(gpu::Batch& batch, const gpu::PipelinePointer& pipeline) const { + auto slot = pipeline->getProgram()->getTextures().findLocation("fadeMaskMap"); + batch.setResourceTexture(slot, _fadeMaskMap); } float FadeEffect::computeFadePercent(quint64 startTime) const { @@ -37,12 +41,12 @@ float FadeEffect::computeFadePercent(quint64 startTime) const { return fadeAlpha; } -void FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, State state) const { - bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime, state); +bool FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, bool isFading) const { + return bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime, isFading); } -void FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, State state) const { - if (state != Complete || _isDebugEnabled) { +bool FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, bool isFading) const { + if (isFading || _isDebugEnabled) { auto& program = pipeline->getProgram(); auto fadeOffsetLoc = program->getUniforms().findLocation("fadeOffset"); auto fadePercentLoc = program->getUniforms().findLocation("fadePercent"); @@ -60,5 +64,7 @@ void FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, g batch._glUniform1f(fadePercentLoc, percent); batch._glUniform3f(fadeOffsetLoc, offset.x, offset.y, offset.z); } + return true; } + return false; } diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index dea14e5678..5be1288120 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -20,12 +20,6 @@ class FadeEffect : public Dependency { SINGLETON_DEPENDENCY public: - enum State : uint8_t { - WaitingToStart = 0, - InProgress = 1, - Complete = 2, - }; - FadeEffect(); const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; } @@ -38,9 +32,10 @@ public: render::ShapeKey::Builder getKeyBuilder(render::ShapeKey::Builder builder = render::ShapeKey::Builder()) const; - void bindPerBatch(gpu::Batch& batch) const; - void bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, State state = InProgress) const; - void bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, State state = InProgress) const; + void bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation = render::ShapePipeline::Slot::MAP::FADE_MASK) const; + void bindPerBatch(gpu::Batch& batch, const gpu::PipelinePointer& pipeline) const; + bool bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, bool isFading) const; + bool bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, bool isFading) const; float computeFadePercent(quint64 startTime) const; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index a44974cc92..46989eaba7 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -484,7 +484,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { if (wireframe) { builder.withWireframe(); } - if (_fadeState != FadeEffect::Complete) { + if (_fadeState != STATE_COMPLETE) { builder.withFade(); } return builder.build(); @@ -528,13 +528,13 @@ void ModelMeshPartPayload::render(RenderArgs* args) { return; // bail asap } - if (_fadeState == FadeEffect::WaitingToStart) { + if (_fadeState == STATE_WAITING_TO_START) { if (model->isLoaded()) { if (EntityItem::getEntitiesShouldFadeFunction()()) { _fadeStartTime = usecTimestampNow(); - _fadeState = FadeEffect::InProgress; + _fadeState = STATE_IN_PROGRESS; } else { - _fadeState = FadeEffect::Complete; + _fadeState = STATE_COMPLETE; } model->setRenderItemsNeedUpdate(); } else { @@ -567,7 +567,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { bindMaterial(batch, locations, args->_enableTexturing); // Apply fade effect - DependencyManager::get()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState); + DependencyManager::get()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState!=STATE_COMPLETE); args->_details._materialSwitches++; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 6762601738..b68a542bce 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -118,8 +118,14 @@ public: private: + enum State : uint8_t { + STATE_WAITING_TO_START = 0, + STATE_IN_PROGRESS = 1, + STATE_COMPLETE = 2, + }; + mutable quint64 _fadeStartTime { 0 }; - mutable FadeEffect::State _fadeState { FadeEffect::WaitingToStart } ; + mutable State _fadeState { STATE_WAITING_TO_START } ; }; diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 77f7f61801..b521ff12ee 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -70,7 +70,6 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK)); - slotBindings.insert(gpu::Shader::Binding(std::string("fadeBuffer"), Slot::BUFFER::FADE)); gpu::Shader::makeProgram(*program, slotBindings); @@ -90,7 +89,6 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->lightAmbientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer"); locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap"); locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap"); - locations->fadeBufferUnit = program->getUniformBuffers().findLocation("fadeBuffer"); ShapeKey key{filter._flags}; auto gpuPipeline = gpu::Pipeline::create(program, state); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index b8045dfbcc..1c18f2a26e 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -214,7 +214,6 @@ public: LIGHTING_MODEL, LIGHT, LIGHT_AMBIENT_BUFFER, - FADE, }; enum MAP { @@ -245,7 +244,6 @@ public: int lightBufferUnit; int lightAmbientBufferUnit; int lightAmbientMapUnit; - int fadeBufferUnit; int fadeMaskTextureUnit; }; using LocationsPointer = std::shared_ptr; From 7d58c9a741d0eca2b46326847e79170a17ed8652 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 8 Jun 2017 17:09:08 +0200 Subject: [PATCH 13/86] Fixed fade for shadow job --- .../render-utils/src/RenderDeferredTask.cpp | 2 +- .../render-utils/src/RenderShadowTask.cpp | 34 ++++++++++++++++--- .../src/skin_model_normal_map_fade.slv | 2 +- .../render-utils/src/skin_model_shadow.slf | 2 +- .../src/skin_model_shadow_fade.slf | 27 +++++++++++++++ .../src/skin_model_shadow_fade.slv | 2 +- libraries/render/src/render/ShapePipeline.cpp | 2 +- libraries/render/src/render/ShapePipeline.h | 4 +-- 8 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 libraries/render-utils/src/skin_model_shadow_fade.slf diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 8b2a232c87..df27f48271 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -308,7 +308,7 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const const auto& lightingModel = inputs.get1(); RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); + ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index d7ec087174..33d260c2da 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -14,6 +14,7 @@ #include #include +#include "FadeEffect.h" #include #include @@ -28,6 +29,12 @@ #include "model_shadow_frag.h" #include "skin_model_shadow_frag.h" +#include "model_shadow_fade_vert.h" +#include "skin_model_shadow_fade_vert.h" + +#include "model_shadow_fade_frag.h" +#include "skin_model_shadow_fade_frag.h" + using namespace render; void RenderShadowMap::run(const render::RenderContextPointer& renderContext, @@ -46,6 +53,8 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, const auto& fbo = shadow->framebuffer; RenderArgs* args = renderContext->args; + ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -61,8 +70,11 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, batch.setProjectionTransform(shadow->getProjection()); batch.setViewTransform(shadow->getView(), false); - auto shadowPipeline = _shapePlumber->pickPipeline(args, ShapeKey()); - auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, ShapeKey::Builder().withSkinned()); + auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); + auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); + + // Prepare fade effect + DependencyManager::get()->bindPerBatch(batch); std::vector skinnedShapeKeys{}; @@ -103,15 +115,29 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel); shapePlumber->addPipeline( - ShapeKey::Filter::Builder().withoutSkinned(), + ShapeKey::Filter::Builder().withoutSkinned().withoutFade(), modelProgram, state); auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); auto skinPixel = gpu::Shader::createPixel(std::string(skin_model_shadow_frag)); gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, skinPixel); shapePlumber->addPipeline( - ShapeKey::Filter::Builder().withSkinned(), + ShapeKey::Filter::Builder().withSkinned().withoutFade(), skinProgram, state); + + auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_shadow_fade_vert)); + auto modelFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag)); + gpu::ShaderPointer modelFadeProgram = gpu::Shader::createProgram(modelFadeVertex, modelFadePixel); + shapePlumber->addPipeline( + ShapeKey::Filter::Builder().withoutSkinned().withFade(), + modelFadeProgram, state); + + auto skinFadeVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_fade_vert)); + auto skinFadePixel = gpu::Shader::createPixel(std::string(skin_model_shadow_fade_frag)); + gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skinFadeVertex, skinFadePixel); + shapePlumber->addPipeline( + ShapeKey::Filter::Builder().withSkinned().withFade(), + skinFadeProgram, state); } const auto cachedMode = task.addJob("Setup"); diff --git a/libraries/render-utils/src/skin_model_normal_map_fade.slv b/libraries/render-utils/src/skin_model_normal_map_fade.slv index 5169aa5d75..7c88c68537 100644 --- a/libraries/render-utils/src/skin_model_normal_map_fade.slv +++ b/libraries/render-utils/src/skin_model_normal_map_fade.slv @@ -55,7 +55,7 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> - <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> + <$transformModelToFadePos(obj, position, _worldFadePosition)$> <$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> <$transformModelToWorldDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$> diff --git a/libraries/render-utils/src/skin_model_shadow.slf b/libraries/render-utils/src/skin_model_shadow.slf index 178ea7b387..e464d6e6c8 100644 --- a/libraries/render-utils/src/skin_model_shadow.slf +++ b/libraries/render-utils/src/skin_model_shadow.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// model_shadow.frag +// skin_model_shadow.frag // fragment shader // // Created by Andrzej Kapolka on 3/24/14. diff --git a/libraries/render-utils/src/skin_model_shadow_fade.slf b/libraries/render-utils/src/skin_model_shadow_fade.slf new file mode 100644 index 0000000000..7b164f5db1 --- /dev/null +++ b/libraries/render-utils/src/skin_model_shadow_fade.slf @@ -0,0 +1,27 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// skin_model_shadow_fade.frag +// fragment shader +// +// Created by Olivier Prat on 06/08/17. +// 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 Fade.slh@> +<$declareFadeFragment()$> + +in vec4 _worldFadePosition; + +layout(location = 0) out vec4 _fragColor; + +void main(void) { + applyFade(_worldFadePosition.xyz); + + // pass-through to set z-buffer + _fragColor = vec4(1.0, 1.0, 1.0, 0.0); +} diff --git a/libraries/render-utils/src/skin_model_shadow_fade.slv b/libraries/render-utils/src/skin_model_shadow_fade.slv index 84d50ae754..03b060b59b 100644 --- a/libraries/render-utils/src/skin_model_shadow_fade.slv +++ b/libraries/render-utils/src/skin_model_shadow_fade.slv @@ -30,5 +30,5 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, position, gl_Position)$> - <$transformModelToFadePos(obj, inPosition, _worldFadePosition)$> + <$transformModelToFadePos(obj, position, _worldFadePosition)$> } diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index b521ff12ee..6a52f90297 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -103,7 +103,7 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke PerformanceTimer perfTimer("ShapePlumber::pickPipeline"); - const auto& pipelineIterator = _pipelineMap.find(key); + auto pipelineIterator = _pipelineMap.find(key); if (pipelineIterator == _pipelineMap.end()) { // The first time we can't find a pipeline, we should log it if (_missingKeys.find(key) == _missingKeys.end()) { diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 1c18f2a26e..cfcd358287 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -128,8 +128,8 @@ public: Builder& withCullFace() { _flags.reset(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); } Builder& withoutCullFace() { _flags.set(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); } - Builder& withFade() { _flags.reset(FADE); _mask.set(FADE); return (*this); } - Builder& withoutFade() { _flags.set(FADE); _mask.set(FADE); return (*this); } + Builder& withFade() { _flags.set(FADE); _mask.set(FADE); return (*this); } + Builder& withoutFade() { _flags.reset(FADE); _mask.set(FADE); return (*this); } protected: friend class Filter; From f3d252ee6576e4637c603943c78cd3e405ff7d93 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 13 Jun 2017 08:50:50 +0200 Subject: [PATCH 14/86] Switched fade curve to easeInOutQuad --- libraries/render-utils/src/FadeEffect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index f2a799dbc6..dbfcfb780a 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -36,7 +36,7 @@ float FadeEffect::computeFadePercent(quint64 startTime) const { const double INV_FADE_PERIOD = 1.0 / (double)(3 * USECS_PER_SECOND); double fraction = (double)(usecTimestampNow() - startTime) * INV_FADE_PERIOD; if (fraction < 1.0) { - fadeAlpha = Interpolate::simpleNonLinearBlend(fraction); + fadeAlpha = Interpolate::easeInOutQuad(fraction); } return fadeAlpha; } From ace301945c70ecec603ce381e5f4baa023fc2439 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 13 Jun 2017 15:31:04 +0200 Subject: [PATCH 15/86] Added scale and duration debug parameters in debugFade.qml --- libraries/render-utils/src/Fade.slh | 12 ++------- libraries/render-utils/src/FadeEffect.cpp | 27 +++++++++++-------- libraries/render-utils/src/FadeEffect.h | 9 ++++++- .../render-utils/src/RenderDeferredTask.cpp | 12 +++++++-- .../render-utils/src/RenderDeferredTask.h | 4 +++ scripts/developer/utilities/render/fade.qml | 20 +++++++++++++- 6 files changed, 59 insertions(+), 25 deletions(-) diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 38fad9321a..351cbad863 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -20,6 +20,7 @@ uniform vec3 fadeOffset; uniform float fadePercent; +uniform float fadeInvScale; uniform sampler2D fadeMaskMap; vec2 hash2D(vec3 position) { @@ -28,20 +29,11 @@ vec2 hash2D(vec3 position) { float noise3D(vec3 position) { return textureLod(fadeMaskMap, hash2D(position), 0).r; - /*const float ONE_OVER_MAX_POSITIVE_INT = (1.f / 2147483648.f); - int3 iPosition = int3(position); - int position = iPosition.x + (iPosition.y*57) + (iPosition.z*3023); - int bits = (position << 13) ^ position; - int pseudoRandomPositiveInt = (bits * ((bits*bits*15731)+789221)+1376312589) & 0x7fffffff; - float pseudoRandomFloatZeroToOne = ONE_OVER_MAX_POSITIVE_INT * (float)pseudoRandomPositiveInt; - return pseudoRandomFloatZeroToOne;*/ } float evalFadeMask(vec3 position) { - const float FADE_MASK_INV_SCALE = 1.0; - // Do tri-linear interpolation - vec3 noisePosition = position * FADE_MASK_INV_SCALE + fadeOffset; + vec3 noisePosition = position * fadeInvScale + fadeOffset; vec3 noisePositionFloored = floor(noisePosition); vec3 noisePositionFraction = fract(noisePosition); float noiseLowXLowYLowZ = noise3D(noisePositionFloored); diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index dbfcfb780a..71e33549a6 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -7,8 +7,10 @@ #include FadeEffect::FadeEffect() : - _isDebugEnabled{ false }, - _debugFadePercent{ 0.f } + _invScale{ 1.f }, + _duration{ 3.f }, + _debugFadePercent{ 0.f }, + _isDebugEnabled{ false } { auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png"; _fadeMaskMap = DependencyManager::get()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); @@ -27,13 +29,14 @@ void FadeEffect::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation) const } void FadeEffect::bindPerBatch(gpu::Batch& batch, const gpu::PipelinePointer& pipeline) const { - auto slot = pipeline->getProgram()->getTextures().findLocation("fadeMaskMap"); - batch.setResourceTexture(slot, _fadeMaskMap); + auto program = pipeline->getProgram(); + auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap"); + bindPerBatch(batch, maskMapLocation); } float FadeEffect::computeFadePercent(quint64 startTime) const { float fadeAlpha = 1.0f; - const double INV_FADE_PERIOD = 1.0 / (double)(3 * USECS_PER_SECOND); + const double INV_FADE_PERIOD = 1.0 / (double)(_duration * USECS_PER_SECOND); double fraction = (double)(usecTimestampNow() - startTime) * INV_FADE_PERIOD; if (fraction < 1.0) { fadeAlpha = Interpolate::easeInOutQuad(fraction); @@ -47,11 +50,12 @@ bool FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offs bool FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, bool isFading) const { if (isFading || _isDebugEnabled) { - auto& program = pipeline->getProgram(); - auto fadeOffsetLoc = program->getUniforms().findLocation("fadeOffset"); - auto fadePercentLoc = program->getUniforms().findLocation("fadePercent"); + auto& uniforms = pipeline->getProgram()->getUniforms(); + auto fadeScaleLocation = uniforms.findLocation("fadeInvScale"); + auto fadeOffsetLocation = uniforms.findLocation("fadeOffset"); + auto fadePercentLocation = uniforms.findLocation("fadePercent"); - if (fadeOffsetLoc >= 0 && fadePercentLoc >= 0) { + if (fadeScaleLocation >= 0 || fadeOffsetLocation >= 0 || fadePercentLocation>=0) { float percent; // A bit ugly to have the test at every bind... @@ -61,8 +65,9 @@ bool FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, g else { percent = _debugFadePercent; } - batch._glUniform1f(fadePercentLoc, percent); - batch._glUniform3f(fadeOffsetLoc, offset.x, offset.y, offset.z); + batch._glUniform1f(fadeScaleLocation, _invScale); + batch._glUniform1f(fadePercentLocation, percent); + batch._glUniform3f(fadeOffsetLocation, offset.x, offset.y, offset.z); } return true; } diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 5be1288120..80e3b79e2e 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -24,6 +24,12 @@ public: const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; } + void setScale(float value) { assert(value > 0.f); _invScale = 1.f / value; } + float getScale() const { return 1.f / _invScale; } + + void setDuration(float seconds) { assert(seconds > 0.f); _duration = seconds; } + float getDuration() const { return 1.f / _duration; } + void setDebugEnabled(bool isEnabled) { _isDebugEnabled = isEnabled; } bool isDebugEnabled() const { return _isDebugEnabled; } @@ -42,9 +48,10 @@ public: private: gpu::TexturePointer _fadeMaskMap; + float _invScale; + float _duration; float _debugFadePercent; bool _isDebugEnabled; - }; #endif // hifi_FadeEffect_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ae3dbc058f..a752b18da8 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -51,8 +51,16 @@ extern void initDeferredPipelines(render::ShapePlumber& plumber); void RenderDeferredTask::configure(const Config& config) { - DependencyManager::get()->setDebugEnabled(config.debugFade); - DependencyManager::get()->setDebugFadePercent(config.debugFadePercent); + const float SCALE_MIN = 0.01f; + const float SCALE_MAX = 5.f; + + auto fadeEffect = DependencyManager::get(); + float scale = SCALE_MIN + (SCALE_MAX - SCALE_MIN)*config.fadeScale*config.fadeScale*config.fadeScale; + + fadeEffect->setScale(scale); + fadeEffect->setDuration(config.fadeDuration); + fadeEffect->setDebugEnabled(config.debugFade); + fadeEffect->setDebugFadePercent(config.debugFadePercent); } void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index d46f9b53f4..65ae062a9a 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -164,9 +164,13 @@ public: class RenderDeferredTaskConfig : public render::Task::Config { Q_OBJECT + Q_PROPERTY(float fadeScale MEMBER fadeScale NOTIFY dirty) + Q_PROPERTY(float fadeDuration MEMBER fadeDuration NOTIFY dirty) Q_PROPERTY(bool debugFade MEMBER debugFade NOTIFY dirty) Q_PROPERTY(float debugFadePercent MEMBER debugFadePercent NOTIFY dirty) public: + float fadeScale{ 0.5f }; + float fadeDuration{ 3.0f }; float debugFadePercent{ 0.f }; bool debugFade{ false }; diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index 137e45d08d..0a99ca2e7e 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -19,7 +19,7 @@ Row { spacing: 8 CheckBox { - text: "Force Fade" + text: "Manual Fade" checked: taskConfig["debugFade"] onCheckedChanged: { taskConfig["debugFade"] = checked } } @@ -36,6 +36,24 @@ Row { min: 0.0 width: 250 } + ConfigSlider { + label: "Scale" + integral: false + config: taskConfig + property: "fadeScale" + max: 1.0 + min: 0.0 + width: 250 + } + ConfigSlider { + label: "Duration" + integral: false + config: taskConfig + property: "fadeDuration" + max: 10.0 + min: 0.1 + width: 250 + } } } From 5eeff5aa28902033d0ea99de4062f24cb6346a3b Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 14 Jun 2017 10:23:12 +0200 Subject: [PATCH 16/86] Fixed unwanted red tint due to unreset color attrib in ModelMeshPartPayload --- libraries/render-utils/src/MeshPartPayload.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 46989eaba7..bfa4b6770e 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -510,6 +510,11 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { batch.setInputStream(0, _drawMesh->getVertexStream()); } } + + // TODO: Get rid of that extra call + if (!_hasColorAttrib) { + batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + } } void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { From 2e3ffe77217efbba7cc7c379c7868b3858e35344 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 19 Jun 2017 18:19:36 +0200 Subject: [PATCH 17/86] Disabled check on enabled physics when deciding is fade is adequate --- libraries/render-utils/src/FadeEffect.cpp | 3 ++- libraries/render-utils/src/MeshPartPayload.cpp | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 71e33549a6..516fd56478 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -68,8 +68,9 @@ bool FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, g batch._glUniform1f(fadeScaleLocation, _invScale); batch._glUniform1f(fadePercentLocation, percent); batch._glUniform3f(fadeOffsetLocation, offset.x, offset.y, offset.z); + + return percent < 1.f; } - return true; } return false; } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index bfa4b6770e..5365988fbb 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -572,7 +572,10 @@ void ModelMeshPartPayload::render(RenderArgs* args) { bindMaterial(batch, locations, args->_enableTexturing); // Apply fade effect - DependencyManager::get()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState!=STATE_COMPLETE); + if (!DependencyManager::get()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState != STATE_COMPLETE)) { + // TODO : very ugly way to update the fade state. Need to improve this with global fade manager. + _fadeState = STATE_COMPLETE; + } args->_details._materialSwitches++; From b6b1875dd3790f9a53dc3932a73a0dd074fddac5 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 19 Jun 2017 18:19:54 +0200 Subject: [PATCH 18/86] Disabled check on enabled physics when deciding is fade is adequate --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b53807b1cf..cf3cc172e0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1503,7 +1503,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo EntityItem::setEntitiesShouldFadeFunction([this]() { SharedNodePointer entityServerNode = DependencyManager::get()->soloNodeOfType(NodeType::EntityServer); - return entityServerNode && !isPhysicsEnabled(); + return entityServerNode; /*&& !isPhysicsEnabled()*/ // Why shouldn't we fade when physics is enabled??; }); QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav"); From 0211338657ab5d9cd6201aac9fd21fb19eee4c9c Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 19 Jun 2017 20:38:47 +0200 Subject: [PATCH 19/86] Put back test if not physics enabled in entity items should fade function as it gives too many undesired refades --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 10855dfa46..289003a69f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1504,7 +1504,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo EntityItem::setEntitiesShouldFadeFunction([this]() { SharedNodePointer entityServerNode = DependencyManager::get()->soloNodeOfType(NodeType::EntityServer); - return entityServerNode; /*&& !isPhysicsEnabled()*/ // Why shouldn't we fade when physics is enabled??; + return entityServerNode && !isPhysicsEnabled(); }); QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav"); From 8a12d0c106be25a3db8b55aa80579b04b9bb73b0 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 29 Jun 2017 08:54:23 +0200 Subject: [PATCH 20/86] Fade effect working again for basic enter domain but with various Fade jobs --- .../src/RenderablePolyVoxEntityItem.cpp | 16 +- .../src/RenderablePolyVoxEntityItem.h | 2 + .../src/RenderableShapeEntityItem.cpp | 1 - .../entities-renderer/src/polyvox_fade.slf | 5 +- libraries/entities/src/EntityItem.h | 1 + libraries/render-utils/src/Fade.slh | 78 ++++- libraries/render-utils/src/FadeEffect.cpp | 238 +++++++++++--- libraries/render-utils/src/FadeEffect.h | 307 ++++++++++++++++-- libraries/render-utils/src/GeometryCache.cpp | 2 - .../render-utils/src/MeshPartPayload.cpp | 20 +- libraries/render-utils/src/MeshPartPayload.h | 2 + .../render-utils/src/RenderDeferredTask.cpp | 39 +-- .../render-utils/src/RenderShadowTask.cpp | 4 +- libraries/render-utils/src/model_fade.slf | 5 +- .../render-utils/src/model_lightmap_fade.slf | 6 +- .../src/model_lightmap_normal_map_fade.slf | 6 +- ...odel_lightmap_normal_specular_map_fade.slf | 6 +- .../src/model_lightmap_specular_map_fade.slf | 6 +- .../src/model_normal_map_fade.slf | 4 +- .../src/model_normal_specular_map_fade.slf | 6 +- .../render-utils/src/model_shadow_fade.slf | 2 +- .../src/model_specular_map_fade.slf | 6 +- .../src/model_translucent_fade.slf | 6 +- .../src/model_translucent_unlit_fade.slf | 6 +- .../render-utils/src/model_unlit_fade.slf | 6 +- libraries/render-utils/src/simple_fade.slf | 12 +- .../render-utils/src/simple_textured_fade.slf | 8 +- .../src/simple_textured_unlit_fade.slf | 8 +- .../src/simple_transparent_textured_fade.slf | 8 +- ...simple_transparent_textured_unlit_fade.slf | 6 +- .../src/skin_model_shadow_fade.slf | 2 +- libraries/render/src/render/Args.h | 1 + libraries/render/src/render/Item.h | 7 +- .../src/render/RenderFetchCullSortTask.cpp | 3 +- .../src/render/RenderFetchCullSortTask.h | 2 +- libraries/render/src/render/ShapePipeline.cpp | 4 +- libraries/render/src/render/ShapePipeline.h | 2 + libraries/render/src/task/Varying.h | 5 + .../developer/utilities/render/debugFade.js | 2 +- scripts/developer/utilities/render/fade.qml | 237 ++++++++++++-- 40 files changed, 900 insertions(+), 187 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 614af2c64e..32e71389ab 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -740,10 +740,11 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), render::ShapePipeline::Slot::BUFFER::FADE_PARAMETERS)); slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0)); slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2)); - slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), 3)); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), render::ShapePipeline::Slot::MAP::FADE_MASK)); auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); @@ -823,9 +824,9 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { } // Apply fade effect - auto fadeEffect = DependencyManager::get(); - if (fadeEffect->bindPerItem(batch, pipeline.get(), glm::vec3(0, 0, 0), _fadeStartTime, isFading())) { - fadeEffect->bindPerBatch(batch, 3); + if (args->_enableFade) { + FadeRenderJob::bindPerBatch(batch, render::ShapePipeline::Slot::MAP::FADE_MASK, render::ShapePipeline::Slot::BUFFER::FADE_PARAMETERS); + FadeRenderJob::bindPerItem(batch, pipeline.get(), glm::vec3(0, 0, 0), _fadeStartTime); } int voxelVolumeSizeLocation = pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize"); @@ -882,6 +883,13 @@ namespace render { payload->_owner->getRenderableInterface()->render(args); } } + + template <> bool payloadMustFade(const PolyVoxPayload::Pointer& payload) { + if (payload && payload->_owner) { + return payload->_owner->mustFade(); + } + return false; + } } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 73ab0e5937..72871f0439 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -38,6 +38,7 @@ namespace render { template <> const ItemKey payloadGetKey(const PolyVoxPayload::Pointer& payload); template <> const Item::Bound payloadGetBound(const PolyVoxPayload::Pointer& payload); template <> void payloadRender(const PolyVoxPayload::Pointer& payload, RenderArgs* args); + template <> bool payloadMustFade(const PolyVoxPayload::Pointer& payload); } @@ -205,4 +206,5 @@ private: bool inUserBounds(const PolyVox::SimpleVolume* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle, int x, int y, int z); + #endif // hifi_RenderablePolyVoxEntityItem_h diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 917b97dc29..a8ead00771 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -126,7 +126,6 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; // FIXME, support instanced multi-shape rendering using multidraw indirect auto geometryCache = DependencyManager::get(); - auto fadeEffect = DependencyManager::get(); auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); assert(pipeline != nullptr); diff --git a/libraries/entities-renderer/src/polyvox_fade.slf b/libraries/entities-renderer/src/polyvox_fade.slf index ac2d77564b..29bd51200a 100644 --- a/libraries/entities-renderer/src/polyvox_fade.slf +++ b/libraries/entities-renderer/src/polyvox_fade.slf @@ -30,7 +30,8 @@ uniform vec3 voxelVolumeSize; <$declareFadeFragment()$> void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 emissive; + applyFade(_worldFadePosition.xyz, emissive); vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); worldNormal = normalize(worldNormal); @@ -54,7 +55,7 @@ void main(void) { vec3(diffuse), DEFAULT_ROUGHNESS, DEFAULT_METALLIC, - DEFAULT_EMISSIVE, + DEFAULT_EMISSIVE+emissive, DEFAULT_OCCLUSION, DEFAULT_SCATTERING); } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 0318c72991..6cd8e18a27 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -459,6 +459,7 @@ public: bool isFading() const { return _isFading; } float getFadingRatio() const { return (isFading() ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f); } + bool mustFade() const { return _isFading; } virtual void emitScriptEvent(const QVariant& message) {} diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 351cbad863..776343dc53 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -18,9 +18,26 @@ <@func declareFadeFragment()@> -uniform vec3 fadeOffset; -uniform float fadePercent; -uniform float fadeInvScale; +struct FadeParameters +{ + vec4 _baseInvSizeAndLevel; + vec4 _noiseInvSizeAndLevel; + vec3 _innerEdgeColor; + vec3 _outerEdgeColor; + vec2 _edgeWidthInvWidth; + int _invertBase; + float _padding; +}; + +#define EVENT_CATEGORY_COUNT 5 + +uniform fadeParametersBuffer { + FadeParameters fadeParameters[EVENT_CATEGORY_COUNT]; +}; +uniform int fadeCategory; +uniform vec3 fadeNoiseOffset; +uniform vec3 fadeBaseOffset; +uniform float fadeThreshold; uniform sampler2D fadeMaskMap; vec2 hash2D(vec3 position) { @@ -31,9 +48,9 @@ float noise3D(vec3 position) { return textureLod(fadeMaskMap, hash2D(position), 0).r; } -float evalFadeMask(vec3 position) { +float evalFadeNoiseGradient(vec3 position) { // Do tri-linear interpolation - vec3 noisePosition = position * fadeInvScale + fadeOffset; + vec3 noisePosition = position * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.xyz + fadeNoiseOffset; vec3 noisePositionFloored = floor(noisePosition); vec3 noisePositionFraction = fract(noisePosition); float noiseLowXLowYLowZ = noise3D(noisePositionFloored); @@ -49,14 +66,59 @@ float evalFadeMask(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); + return mix(maskY.x, maskY.y, noisePositionFraction.y) * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.w; } -void applyFade(vec3 position) { - if (evalFadeMask(position) > fadePercent) { +float evalFadeBaseGradient(vec3 position) { + float gradient = length((position - fadeBaseOffset) * fadeParameters[fadeCategory]._baseInvSizeAndLevel.xyz); + if (fadeParameters[fadeCategory]._invertBase!=0) { + gradient = 1.0 - gradient; + } + gradient *= fadeParameters[fadeCategory]._baseInvSizeAndLevel.w; + return gradient; +} + +float evalFadeGradient(vec3 position) { + float baseGradient = evalFadeBaseGradient(position); + float noiseGradient = evalFadeNoiseGradient(position); + float gradient = (noiseGradient-0.5*fadeParameters[fadeCategory]._baseInvSizeAndLevel.w); + + // 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); + + return evalFadeGradient(position)-cutoff;*/ + return evalFadeNoiseGradient(position)-fadeThreshold; +} + +void applyFadeClip(vec3 position) { + if (evalFadeAlpha(position) < 0) { discard; } } + +void applyFade(vec3 position, out vec3 emissive) { + float alpha = evalFadeAlpha(position); + if (alpha < 0) { + discard; + } + /* + float edgeMask = alpha * fadeParameters[fadeCategory]._edgeWidthInvWidth.y; + float edgeAlpha = 1.0-clamp(edgeMask, 0, 1); + + edgeMask = step(edgeMask, 1.f); + edgeAlpha *= edgeAlpha; // Square to have a nice ease out + emissive = mix(fadeParameters[fadeCategory]._innerEdgeColor, fadeParameters[fadeCategory]._outerEdgeColor, edgeAlpha); + emissive *= edgeMask; + */ + emissive = vec3(0,0,0); +} <@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 516fd56478..d2bad0d1ef 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -4,73 +4,223 @@ #include #include #include -#include +#include -FadeEffect::FadeEffect() : - _invScale{ 1.f }, - _duration{ 3.f }, - _debugFadePercent{ 0.f }, - _isDebugEnabled{ false } +void FadeSwitchJob::configure(const Config& config) { + _isEditEnabled = config.editFade; +} + +void FadeSwitchJob::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { + auto& normalOutputs = output.edit0(); + auto& fadeOutputs = output.edit1(); + + // Only shapes are affected by fade at this time. + normalOutputs[RenderFetchCullSortTask::LIGHT] = input[RenderFetchCullSortTask::LIGHT]; + normalOutputs[RenderFetchCullSortTask::META] = input[RenderFetchCullSortTask::META]; + normalOutputs[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE] = input[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; + normalOutputs[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE] = input[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; + normalOutputs[RenderFetchCullSortTask::BACKGROUND] = input[RenderFetchCullSortTask::BACKGROUND]; + normalOutputs[RenderFetchCullSortTask::SPATIAL_SELECTION] = input[RenderFetchCullSortTask::SPATIAL_SELECTION]; + + // Now, distribute items that need to be faded accross both outputs + distribute(renderContext, input[RenderFetchCullSortTask::OPAQUE_SHAPE], normalOutputs[RenderFetchCullSortTask::OPAQUE_SHAPE], fadeOutputs[OPAQUE_SHAPE]); + distribute(renderContext, input[RenderFetchCullSortTask::TRANSPARENT_SHAPE], normalOutputs[RenderFetchCullSortTask::TRANSPARENT_SHAPE], fadeOutputs[TRANSPARENT_SHAPE]); +} + +void FadeSwitchJob::distribute(const render::RenderContextPointer& renderContext, const render::Varying& input, + render::Varying& normalOutput, render::Varying& fadeOutput) const { + auto& scene = renderContext->_scene; + assert(_parameters); + const double fadeDuration = double(_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]) * USECS_PER_SECOND; + const auto& inputItems = input.get(); + + // Clear previous values + normalOutput.template edit().clear(); + fadeOutput.template edit().clear(); + + for (const auto& itemBound : inputItems) { + auto& item = scene->getItem(itemBound.id); + + if (!item.mustFade()) { + // No need to fade + normalOutput.template edit().emplace_back(itemBound); + } + else { + fadeOutput.template edit().emplace_back(itemBound); + } + } +/* if (!_isEditEnabled) { + + }*/ +} + +FadeConfigureJob::FadeConfigureJob(FadeCommonParameters::Pointer commonParams) : + _parameters{ commonParams } { auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png"; _fadeMaskMap = DependencyManager::get()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); } -render::ShapeKey::Builder FadeEffect::getKeyBuilder(render::ShapeKey::Builder builder) const { - if (_isDebugEnabled) { - // Force fade for everyone - builder.withFade(); - } - return builder; +void FadeConfigureJob::configure(const Config& config) { + assert(_parameters); + for (auto i = 0; i < FadeJobConfig::EVENT_CATEGORY_COUNT; i++) { + auto& configuration = _configurations[i]; + + _parameters->_durations[i] = config.duration[i]; + configuration._baseInvSizeAndLevel.x = 1.f / config.baseSize[i].x; + configuration._baseInvSizeAndLevel.y = 1.f / config.baseSize[i].y; + configuration._baseInvSizeAndLevel.z = 1.f / config.baseSize[i].z; + configuration._baseInvSizeAndLevel.w = config.baseLevel[i]; + configuration._noiseInvSizeAndLevel.x = 1.f / config.noiseSize[i].x; + configuration._noiseInvSizeAndLevel.y = 1.f / config.noiseSize[i].y; + configuration._noiseInvSizeAndLevel.z = 1.f / config.noiseSize[i].z; + configuration._noiseInvSizeAndLevel.w = config.noiseLevel[i]; + configuration._invertBase = config.baseInverted[i]; + configuration._edgeWidthInvWidth.x = config.edgeWidth[i]; + configuration._edgeWidthInvWidth.y = 1.f / configuration._edgeWidthInvWidth.x; + configuration._innerEdgeColor.r = config.edgeInnerColor[i].r * config.edgeInnerColor[i].a; + configuration._innerEdgeColor.g = config.edgeInnerColor[i].g * config.edgeInnerColor[i].a; + configuration._innerEdgeColor.b = config.edgeInnerColor[i].b * config.edgeInnerColor[i].a; + configuration._outerEdgeColor.r = config.edgeOuterColor[i].r * config.edgeOuterColor[i].a; + configuration._outerEdgeColor.g = config.edgeOuterColor[i].g * config.edgeOuterColor[i].a; + configuration._outerEdgeColor.b = config.edgeOuterColor[i].b * config.edgeOuterColor[i].a; + } + _isBufferDirty = true; } -void FadeEffect::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation) const { - batch.setResourceTexture(fadeMaskMapLocation, _fadeMaskMap); +void FadeConfigureJob::run(const render::RenderContextPointer& renderContext, Output& output) { + if (_isBufferDirty) { + auto& configurations = output.edit1().edit(); + std::copy(_configurations, _configurations + FadeJobConfig::EVENT_CATEGORY_COUNT, configurations.parameters); + _isBufferDirty = false; + } + output.edit0() = _fadeMaskMap; } -void FadeEffect::bindPerBatch(gpu::Batch& batch, const gpu::PipelinePointer& pipeline) const { - auto program = pipeline->getProgram(); - auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap"); - bindPerBatch(batch, maskMapLocation); -} +const FadeRenderJob* FadeRenderJob::_currentInstance{ nullptr }; +gpu::TexturePointer FadeRenderJob::_currentFadeMaskMap; +const gpu::BufferView* FadeRenderJob::_currentFadeBuffer{ nullptr }; -float FadeEffect::computeFadePercent(quint64 startTime) const { +float FadeRenderJob::computeFadePercent(quint64 startTime) { + assert(_currentInstance); float fadeAlpha = 1.0f; - const double INV_FADE_PERIOD = 1.0 / (double)(_duration * USECS_PER_SECOND); - double fraction = (double)(usecTimestampNow() - startTime) * INV_FADE_PERIOD; + const double INV_FADE_PERIOD = 1.0 / (double)(_currentInstance->_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] * USECS_PER_SECOND); + double fraction = (double)(int64_t(usecTimestampNow()) - int64_t(startTime)) * INV_FADE_PERIOD; + fraction = std::max(fraction, 0.0); if (fraction < 1.0) { fadeAlpha = Interpolate::easeInOutQuad(fraction); } return fadeAlpha; } -bool FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, bool isFading) const { - return bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime, isFading); +void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const Input& inputs) { + assert(renderContext->args); + assert(renderContext->args->hasViewFrustum()); + + const auto& inItems = inputs.get0(); + + if (!inItems.empty()) { + const auto& lightingModel = inputs.get1(); + const auto& configuration = inputs.get2(); + const auto& fadeMaskMap = configuration.get0(); + const auto& fadeParamBuffer = configuration.get1(); + + // Very, very ugly hack to keep track of the current fade render job + RenderArgs* args = renderContext->args; + render::ShapeKey::Builder defaultKeyBuilder; + + defaultKeyBuilder.withFade(); + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; + + _currentInstance = this; + _currentFadeMaskMap = fadeMaskMap; + _currentFadeBuffer = &fadeParamBuffer; + + // Setup camera, projection and viewport for all items + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + // Setup lighting model for all items; + batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); + + // From the lighting model define a global shapKey ORED with individiual keys + render::ShapeKey::Builder keyBuilder = defaultKeyBuilder; + if (lightingModel->isWireframeEnabled()) { + keyBuilder.withWireframe(); + } + + // Prepare fade effect + bindPerBatch(batch, fadeMaskMap, render::ShapePipeline::Slot::MAP::FADE_MASK, &fadeParamBuffer, render::ShapePipeline::Slot::BUFFER::FADE_PARAMETERS); + + render::ShapeKey globalKey = keyBuilder.build(); + args->_globalShapeKey = globalKey._flags.to_ulong(); + args->_enableFade = true; + + renderShapes(renderContext, _shapePlumber, inItems, -1, globalKey); + + args->_enableFade = false; + args->_batch = nullptr; + args->_globalShapeKey = 0; + + // Very, very ugly hack to keep track of the current fade render job + _currentInstance = nullptr; + _currentFadeMaskMap.reset(); + _currentFadeBuffer = nullptr; + }); + } } -bool FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, bool isFading) const { - if (isFading || _isDebugEnabled) { - auto& uniforms = pipeline->getProgram()->getUniforms(); - auto fadeScaleLocation = uniforms.findLocation("fadeInvScale"); - auto fadeOffsetLocation = uniforms.findLocation("fadeOffset"); - auto fadePercentLocation = uniforms.findLocation("fadePercent"); +void FadeRenderJob::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation) { + assert(_currentFadeMaskMap); + assert(_currentFadeBuffer!=nullptr); + bindPerBatch(batch, _currentFadeMaskMap, fadeMaskMapLocation, _currentFadeBuffer, fadeBufferLocation); +} - if (fadeScaleLocation >= 0 || fadeOffsetLocation >= 0 || fadePercentLocation>=0) { - float percent; +void FadeRenderJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, int fadeMaskMapLocation, const gpu::BufferView* buffer, int fadeBufferLocation) { + batch.setResourceTexture(fadeMaskMapLocation, texture); + batch.setUniformBuffer(fadeBufferLocation, *buffer); +} - // A bit ugly to have the test at every bind... - if (!_isDebugEnabled) { - percent = computeFadePercent(startTime); - } - else { - percent = _debugFadePercent; - } - batch._glUniform1f(fadeScaleLocation, _invScale); - batch._glUniform1f(fadePercentLocation, percent); - batch._glUniform3f(fadeOffsetLocation, offset.x, offset.y, offset.z); +void FadeRenderJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, const gpu::BufferView* buffer, const gpu::PipelinePointer& pipeline) { + auto program = pipeline->getProgram(); + auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap"); + auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer"); + bindPerBatch(batch, texture, maskMapLocation, buffer, bufferLocation); +} - return percent < 1.f; - } +bool FadeRenderJob::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime) { + return bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime); +} + +bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime) { + auto& uniforms = pipeline->getProgram()->getUniforms(); + auto fadeNoiseOffsetLocation = uniforms.findLocation("fadeNoiseOffset"); + auto fadeBaseOffsetLocation = uniforms.findLocation("fadeBaseOffset"); + auto fadeThresholdLocation = uniforms.findLocation("fadeThreshold"); + auto fadeCategoryLocation = uniforms.findLocation("fadeCategory"); + + if (fadeNoiseOffsetLocation >= 0 || fadeBaseOffsetLocation>=0 || fadeThresholdLocation >= 0 || fadeCategoryLocation>=0) { + float percent; + + percent = computeFadePercent(startTime); + batch._glUniform1i(fadeCategoryLocation, FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN); + batch._glUniform1f(fadeThresholdLocation, 1.f-percent); + // This is really temporary + batch._glUniform3f(fadeNoiseOffsetLocation, offset.x, offset.y, offset.z); + // This is really temporary + batch._glUniform3f(fadeBaseOffsetLocation, offset.x, offset.y, offset.z); + + return percent < 1.f; } return false; } diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 80e3b79e2e..295dbb333a 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -11,47 +11,304 @@ #ifndef hifi_FadeEffect_h #define hifi_FadeEffect_h -#include #include #include +#include + +#include "LightingModel.h" + +class FadeSwitchJobConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty) -// Centralizes fade effect data and functions -class FadeEffect : public Dependency { - SINGLETON_DEPENDENCY public: - FadeEffect(); + bool editFade{ false }; - const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; } +signals: + void dirty(); - void setScale(float value) { assert(value > 0.f); _invScale = 1.f / value; } - float getScale() const { return 1.f / _invScale; } +}; - void setDuration(float seconds) { assert(seconds > 0.f); _duration = seconds; } - float getDuration() const { return 1.f / _duration; } +class FadeJobConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(int editedCategory MEMBER editedCategory WRITE setEditedCategory NOTIFY dirty) + 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 baseInverted READ isBaseInverted WRITE setBaseInverted 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) - void setDebugEnabled(bool isEnabled) { _isDebugEnabled = isEnabled; } - bool isDebugEnabled() const { return _isDebugEnabled; } +public: - void setDebugFadePercent(float value) { assert(value >= 0.f && value <= 1.f); _debugFadePercent = value; } - float getDebugFadePercent() const { return _debugFadePercent; } + enum EventCategory { + ELEMENT_ENTER_LEAVE_DOMAIN = 0, + BUBBLE_ISECT_OWNER, + BUBBLE_ISECT_TRESPASSER, + USER_ENTER_LEAVE_DOMAIN, + AVATAR_CHANGE, - render::ShapeKey::Builder getKeyBuilder(render::ShapeKey::Builder builder = render::ShapeKey::Builder()) const; + // Don't forget to modify Fade.slh to reflect the change in number of categories + EVENT_CATEGORY_COUNT + }; - void bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation = render::ShapePipeline::Slot::MAP::FADE_MASK) const; - void bindPerBatch(gpu::Batch& batch, const gpu::PipelinePointer& pipeline) const; - bool bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, bool isFading) const; - bool bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, bool isFading) const; + void setEditedCategory(int value) { assert(value < EVENT_CATEGORY_COUNT); editedCategory = std::min(EVENT_CATEGORY_COUNT, value); } - float computeFadePercent(quint64 startTime) const; + void setDuration(float value) { duration[editedCategory] = value; } + float getDuration() const { return duration[editedCategory]; } + + void setBaseSizeX(float value) { baseSize[editedCategory].x = value; } + float getBaseSizeX() const { return baseSize[editedCategory].x; } + + void setBaseSizeY(float value) { baseSize[editedCategory].y = value; } + float getBaseSizeY() const { return baseSize[editedCategory].y; } + + void setBaseSizeZ(float value) { baseSize[editedCategory].z = value; } + float getBaseSizeZ() const { return baseSize[editedCategory].z; } + + void setBaseLevel(float value) { baseLevel[editedCategory] = value; } + float getBaseLevel() const { return baseLevel[editedCategory]; } + + void setBaseInverted(bool value) { baseInverted[editedCategory] = value; } + bool isBaseInverted() const { return baseInverted[editedCategory]; } + + void setNoiseSizeX(float value) { noiseSize[editedCategory].x = value; } + float getNoiseSizeX() const { return noiseSize[editedCategory].x; } + + void setNoiseSizeY(float value) { noiseSize[editedCategory].y = value; } + float getNoiseSizeY() const { return noiseSize[editedCategory].y; } + + void setNoiseSizeZ(float value) { noiseSize[editedCategory].z = value; } + float getNoiseSizeZ() const { return noiseSize[editedCategory].z; } + + void setNoiseLevel(float value) { noiseLevel[editedCategory] = value; } + float getNoiseLevel() const { return noiseLevel[editedCategory]; } + + void setEdgeWidth(float value) { edgeWidth[editedCategory] = value; } + float getEdgeWidth() const { return edgeWidth[editedCategory]; } + + void setEdgeInnerColorR(float value) { edgeInnerColor[editedCategory].r = value; } + float getEdgeInnerColorR() const { return edgeInnerColor[editedCategory].r; } + + void setEdgeInnerColorG(float value) { edgeInnerColor[editedCategory].g = value; } + float getEdgeInnerColorG() const { return edgeInnerColor[editedCategory].g; } + + void setEdgeInnerColorB(float value) { edgeInnerColor[editedCategory].b = value; } + float getEdgeInnerColorB() const { return edgeInnerColor[editedCategory].b; } + + void setEdgeInnerIntensity(float value) { edgeInnerColor[editedCategory].a = value; } + float getEdgeInnerIntensity() const { return edgeInnerColor[editedCategory].a; } + + void setEdgeOuterColorR(float value) { edgeOuterColor[editedCategory].r = value; } + float getEdgeOuterColorR() const { return edgeOuterColor[editedCategory].r; } + + void setEdgeOuterColorG(float value) { edgeOuterColor[editedCategory].g = value; } + float getEdgeOuterColorG() const { return edgeOuterColor[editedCategory].g; } + + void setEdgeOuterColorB(float value) { edgeOuterColor[editedCategory].b = value; } + float getEdgeOuterColorB() const { return edgeOuterColor[editedCategory].b; } + + void setEdgeOuterIntensity(float value) { edgeOuterColor[editedCategory].a = value; } + float getEdgeOuterIntensity() const { return edgeOuterColor[editedCategory].a; } + + int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; + glm::vec3 baseSize[EVENT_CATEGORY_COUNT]{ + { 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER + { 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER + { 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN + { 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE + }; + float baseLevel[EVENT_CATEGORY_COUNT]{ + 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN + 1.0f, // BUBBLE_ISECT_OWNER + 1.0f, // BUBBLE_ISECT_TRESPASSER + 1.0f, // USER_ENTER_LEAVE_DOMAIN + 1.0f, // AVATAR_CHANGE + }; + bool baseInverted[EVENT_CATEGORY_COUNT]{ + false, // ELEMENT_ENTER_LEAVE_DOMAIN + false, // BUBBLE_ISECT_OWNER + false, // BUBBLE_ISECT_TRESPASSER + false, // USER_ENTER_LEAVE_DOMAIN + false, // AVATAR_CHANGE + }; + glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]{ + { 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER + { 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER + { 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN + { 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE + }; + float noiseLevel[EVENT_CATEGORY_COUNT]{ + 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN + 1.0f, // BUBBLE_ISECT_OWNER + 1.0f, // BUBBLE_ISECT_TRESPASSER + 1.0f, // USER_ENTER_LEAVE_DOMAIN + 1.0f, // AVATAR_CHANGE + }; + float duration[EVENT_CATEGORY_COUNT]{ + 5.0f, // ELEMENT_ENTER_LEAVE_DOMAIN + 0.0f, // BUBBLE_ISECT_OWNER + 0.0f, // BUBBLE_ISECT_TRESPASSER + 3.0f, // USER_ENTER_LEAVE_DOMAIN + 3.0f, // AVATAR_CHANGE + }; + float edgeWidth[EVENT_CATEGORY_COUNT]{ + 0.1f, // ELEMENT_ENTER_LEAVE_DOMAIN + 0.1f, // BUBBLE_ISECT_OWNER + 0.1f, // BUBBLE_ISECT_TRESPASSER + 0.1f, // USER_ENTER_LEAVE_DOMAIN + 0.1f, // AVATAR_CHANGE + }; + glm::vec4 edgeInnerColor[EVENT_CATEGORY_COUNT]{ + { 1.0f, 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER + { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER + { 1.0f, 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN + { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE + }; + glm::vec4 edgeOuterColor[EVENT_CATEGORY_COUNT]{ + { 1.0f, 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER + { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER + { 1.0f, 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN + { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE + }; + +signals: + void dirty(); + +}; + +struct FadeCommonParameters +{ + using Pointer = std::shared_ptr; + + float _durations[FadeJobConfig::EVENT_CATEGORY_COUNT]{ + 30.0f, // ELEMENT_ENTER_LEAVE_DOMAIN + 0.0f, // BUBBLE_ISECT_OWNER + 0.0f, // BUBBLE_ISECT_TRESPASSER + 3.0f, // USER_ENTER_LEAVE_DOMAIN + 3.0f, // AVATAR_CHANGE + }; +}; + +class FadeSwitchJob { +public: + + enum FadeBuckets { + OPAQUE_SHAPE = 0, + TRANSPARENT_SHAPE, + + NUM_BUCKETS + }; + + using FadeOutput = render::VaryingArray; + + using Input = RenderFetchCullSortTask::Output; + using Output = render::VaryingSet2; + using Config = FadeSwitchJobConfig; + using JobModel = render::Job::ModelIO; + + FadeSwitchJob(FadeCommonParameters::Pointer commonParams) : _parameters{ commonParams } {} + + void configure(const Config& config); + void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); private: - gpu::TexturePointer _fadeMaskMap; - float _invScale; - float _duration; - float _debugFadePercent; - bool _isDebugEnabled; + FadeCommonParameters::Pointer _parameters; + bool _isEditEnabled{ false }; + + void distribute(const render::RenderContextPointer& renderContext, const render::Varying& input, + render::Varying& normalOutput, render::Varying& fadeOutput) const; +}; + +struct FadeParameters +{ + glm::vec4 _baseInvSizeAndLevel; + glm::vec4 _noiseInvSizeAndLevel; + glm::vec3 _innerEdgeColor; + glm::vec3 _outerEdgeColor; + glm::vec2 _edgeWidthInvWidth; + glm::int32 _invertBase; + glm::float32 _padding; +}; + +struct FadeConfiguration +{ + FadeParameters parameters[FadeJobConfig::EVENT_CATEGORY_COUNT]; +}; + +class FadeConfigureJob { + +public: + + using UniformBuffer = gpu::StructBuffer; + using Output = render::VaryingSet2; + using Config = FadeJobConfig; + using JobModel = render::Job::ModelO; + + FadeConfigureJob(FadeCommonParameters::Pointer commonParams); + + const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; } + + void configure(const Config& config); + void run(const render::RenderContextPointer& renderContext, Output& output); + +private: + + FadeCommonParameters::Pointer _parameters; + bool _isBufferDirty{ true }; + gpu::TexturePointer _fadeMaskMap; + FadeParameters _configurations[FadeJobConfig::EVENT_CATEGORY_COUNT]; +}; + +class FadeRenderJob { + +public: + + using Input = render::VaryingSet3; + using JobModel = render::Job::ModelI; + + FadeRenderJob(FadeCommonParameters::Pointer commonParams, render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber }, _parameters{ commonParams } {} + + void run(const render::RenderContextPointer& renderContext, const Input& inputs); + + static void bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation); + static void bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, int fadeMaskMapLocation, const gpu::BufferView* buffer, int fadeBufferLocation); + static void bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, const gpu::BufferView* buffer, const gpu::PipelinePointer& pipeline); + + static bool bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime); + static bool bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime); + + static float computeFadePercent(quint64 startTime); + +private: + + static const FadeRenderJob* _currentInstance; + static gpu::TexturePointer _currentFadeMaskMap; + static const gpu::BufferView* _currentFadeBuffer; + + render::ShapePlumberPointer _shapePlumber; + FadeCommonParameters::Pointer _parameters; + + }; #endif // hifi_FadeEffect_h diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 9179354435..5c1632167e 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -523,12 +523,10 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool } render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading) { - isFading = isFading || DependencyManager::get()->isDebugEnabled(); return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline; } render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) { - isFading = isFading || DependencyManager::get()->isDebugEnabled(); return isFading ? _simpleTransparentFadePipeline : _simpleTransparentPipeline; } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 3e75666fcb..7db75a4df4 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -319,6 +319,11 @@ template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { return payload->render(args); } + +template <> bool payloadMustFade(const ModelMeshPartPayload::Pointer& payload) { + return payload->mustFade(); +} + } ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : @@ -525,6 +530,10 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline: batch.setModelTransform(_transform); } +bool ModelMeshPartPayload::mustFade() const { + return _fadeState != STATE_COMPLETE; +} + void ModelMeshPartPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("ModelMeshPartPayload::render"); @@ -572,11 +581,16 @@ void ModelMeshPartPayload::render(RenderArgs* args) { // apply material properties bindMaterial(batch, locations, args->_enableTexturing); - // Apply fade effect - if (!DependencyManager::get()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState != STATE_COMPLETE)) { + if (args->_enableFade) { + // Apply fade effect + if (!FadeRenderJob::bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime)) { + _fadeState = STATE_COMPLETE; + } + } + /* else { // TODO : very ugly way to update the fade state. Need to improve this with global fade manager. _fadeState = STATE_COMPLETE; - } + }*/ args->_details._materialSwitches++; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index b68a542bce..620976804f 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -97,6 +97,7 @@ public: int getLayer() const; render::ShapeKey getShapeKey() const override; // shape interface void render(RenderArgs* args) override; + bool mustFade() const; // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) override; @@ -135,6 +136,7 @@ namespace render { template <> int payloadGetLayer(const ModelMeshPartPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload); template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args); + template <> bool payloadMustFade(const ModelMeshPartPayload::Pointer& payload); } #endif // hifi_MeshPartPayload_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index c9a67fea3f..a8ead6e76e 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -50,20 +50,15 @@ extern void initDeferredPipelines(render::ShapePlumber& plumber); void RenderDeferredTask::configure(const Config& config) { - const float SCALE_MIN = 0.01f; - const float SCALE_MAX = 5.f; - - auto fadeEffect = DependencyManager::get(); - float scale = SCALE_MIN + (SCALE_MAX - SCALE_MIN)*config.fadeScale*config.fadeScale*config.fadeScale; - - fadeEffect->setScale(scale); - fadeEffect->setDuration(config.fadeDuration); - fadeEffect->setDebugEnabled(config.debugFade); - fadeEffect->setDebugFadePercent(config.debugFadePercent); } void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { - auto items = input.get(); + auto commonFadeParameters = std::make_shared(); + const auto fadeSwitchOutputs = task.addJob("FadeSwitch", input, commonFadeParameters).get(); + const auto fadeConfigureOutputs = task.addJob("FadeConfigure", commonFadeParameters).get(); + + const auto& items = fadeSwitchOutputs.get0(); + const auto& fadeItems = fadeSwitchOutputs.get1(); // Prepare the ShapePipelines ShapePlumberPointer shapePlumber = std::make_shared(); @@ -97,8 +92,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto deferredFramebuffer = prepareDeferredOutputs.getN(0); const auto lightingFramebuffer = prepareDeferredOutputs.getN(1); - DependencyManager::set(); - // draw a stencil mask in hidden regions of the framebuffer. task.addJob("PrepareStencil", primaryFramebuffer); @@ -106,6 +99,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying(); task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber); + const auto fadeOpaques = fadeItems[FadeSwitchJob::OPAQUE_SHAPE]; + const auto fadeOpaqueInputs = FadeRenderJob::Input(fadeOpaques, lightingModel, fadeConfigureOutputs).hasVarying(); + task.addJob("DrawFadeOpaque", fadeOpaqueInputs, commonFadeParameters, shapePlumber); + task.addJob("OpaqueRangeTimer", opaqueRangeTimer); @@ -159,6 +156,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying(); task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); + const auto fadeTransparents = fadeItems[FadeSwitchJob::TRANSPARENT_SHAPE]; + const auto fadeTransparentInputs = FadeRenderJob::Input(fadeTransparents, lightingModel, fadeConfigureOutputs).hasVarying(); + task.addJob("DrawFadeTransparent", fadeTransparentInputs, commonFadeParameters, shapePlumber); + // LIght Cluster Grid Debuging job { const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).hasVarying(); @@ -262,7 +263,6 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& const auto& lightingModel = inputs.get1(); RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -283,14 +283,11 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); // From the lighting model define a global shapKey ORED with individiual keys - ShapeKey::Builder keyBuilder = defaultKeyBuilder; + ShapeKey::Builder keyBuilder; if (lightingModel->isWireframeEnabled()) { keyBuilder.withWireframe(); } - // Prepare fade effect - DependencyManager::get()->bindPerBatch(batch); - ShapeKey globalKey = keyBuilder.build(); args->_globalShapeKey = globalKey._flags.to_ulong(); @@ -313,7 +310,6 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const const auto& lightingModel = inputs.get1(); RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -334,14 +330,11 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); // From the lighting model define a global shapeKey ORED with individiual keys - ShapeKey::Builder keyBuilder = defaultKeyBuilder; + ShapeKey::Builder keyBuilder; if (lightingModel->isWireframeEnabled()) { keyBuilder.withWireframe(); } - // Prepare fade effect - DependencyManager::get()->bindPerBatch(batch); - ShapeKey globalKey = keyBuilder.build(); args->_globalShapeKey = globalKey._flags.to_ulong(); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index a74a814630..c0d7f43516 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -53,7 +53,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, const auto& fbo = shadow->framebuffer; RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder = DependencyManager::get()->getKeyBuilder(); + ShapeKey::Builder defaultKeyBuilder;// TODO: support fade on shadows = DependencyManager::get()->getKeyBuilder(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -75,7 +75,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); // Prepare fade effect - DependencyManager::get()->bindPerBatch(batch); + // TODO: support fade on shadows DependencyManager::get()->bindPerBatch(batch); std::vector skinnedShapeKeys{}; diff --git a/libraries/render-utils/src/model_fade.slf b/libraries/render-utils/src/model_fade.slf index 1526dea7c2..7d145bc76b 100644 --- a/libraries/render-utils/src/model_fade.slf +++ b/libraries/render-utils/src/model_fade.slf @@ -30,7 +30,9 @@ in vec2 _texCoord1; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); @@ -50,6 +52,7 @@ void main(void) { vec3 emissive = getMaterialEmissive(mat); <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + emissive += fadeEmissive; float scattering = getMaterialScattering(mat); diff --git a/libraries/render-utils/src/model_lightmap_fade.slf b/libraries/render-utils/src/model_lightmap_fade.slf index f2055e7ffc..ccad86214a 100644 --- a/libraries/render-utils/src/model_lightmap_fade.slf +++ b/libraries/render-utils/src/model_lightmap_fade.slf @@ -31,7 +31,9 @@ in vec3 _color; in vec4 _worldFadePosition; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); @@ -46,5 +48,5 @@ void main(void) { getMaterialRoughness(mat) * roughness, getMaterialMetallic(mat), getMaterialFresnel(mat), - lightmapVal); + lightmapVal+fadeEmissive); } diff --git a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf index 137e40dd3c..a1dbd398ee 100644 --- a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf @@ -32,7 +32,9 @@ in vec3 _color; in vec4 _worldFadePosition; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); @@ -49,5 +51,5 @@ void main(void) { getMaterialRoughness(mat), getMaterialMetallic(mat), getMaterialFresnel(mat), - lightmapVal); + lightmapVal+fadeEmissive); } diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf index b6cdfbd2a2..d7a8697b7a 100644 --- a/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf +++ b/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf @@ -32,7 +32,9 @@ in vec3 _color; in vec4 _worldFadePosition; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); @@ -49,5 +51,5 @@ void main(void) { getMaterialRoughness(mat) * roughness, getMaterialMetallic(mat) * metallicTex, /*specular, // no use of */ getMaterialFresnel(mat), - lightmapVal); + lightmapVal+fadeEmissive); } diff --git a/libraries/render-utils/src/model_lightmap_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_specular_map_fade.slf index e6d82b778d..c4280ed6d1 100644 --- a/libraries/render-utils/src/model_lightmap_specular_map_fade.slf +++ b/libraries/render-utils/src/model_lightmap_specular_map_fade.slf @@ -31,7 +31,9 @@ in vec3 _color; in vec4 _worldFadePosition; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); @@ -45,5 +47,5 @@ void main(void) { getMaterialRoughness(mat) * roughness, getMaterialMetallic(mat) * metallicTex, /*metallicTex, // no use of */getMaterialFresnel(mat), - lightmapVal); + lightmapVal+fadeEmissive); } diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf index 61314fc834..7c70dabda2 100644 --- a/libraries/render-utils/src/model_normal_map_fade.slf +++ b/libraries/render-utils/src/model_normal_map_fade.slf @@ -31,7 +31,9 @@ in vec3 _tangent; in vec3 _color; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_normal_specular_map_fade.slf b/libraries/render-utils/src/model_normal_specular_map_fade.slf index d9c4288e29..bdf917efea 100644 --- a/libraries/render-utils/src/model_normal_specular_map_fade.slf +++ b/libraries/render-utils/src/model_normal_specular_map_fade.slf @@ -31,7 +31,9 @@ in vec3 _color; in vec4 _worldFadePosition; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); @@ -66,7 +68,7 @@ void main(void) { albedo, roughness, metallic, - emissive, + emissive+fadeEmissive, occlusionTex, scattering); } diff --git a/libraries/render-utils/src/model_shadow_fade.slf b/libraries/render-utils/src/model_shadow_fade.slf index 635917b9f4..76720d6053 100644 --- a/libraries/render-utils/src/model_shadow_fade.slf +++ b/libraries/render-utils/src/model_shadow_fade.slf @@ -20,7 +20,7 @@ layout(location = 0) out vec4 _fragColor; in vec4 _worldFadePosition; void main(void) { - applyFade(_worldFadePosition.xyz); + applyFadeClip(_worldFadePosition.xyz); // pass-through to set z-buffer _fragColor = vec4(1.0, 1.0, 1.0, 0.0); diff --git a/libraries/render-utils/src/model_specular_map_fade.slf b/libraries/render-utils/src/model_specular_map_fade.slf index 3579cf1059..75db1d72a2 100644 --- a/libraries/render-utils/src/model_specular_map_fade.slf +++ b/libraries/render-utils/src/model_specular_map_fade.slf @@ -30,7 +30,9 @@ in vec3 _color; in vec4 _worldFadePosition; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); @@ -62,7 +64,7 @@ void main(void) { albedo, roughness, metallic, - emissive, + emissive+fadeEmissive, occlusionTex, scattering); } diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf index 3bbfdabc7f..9802e863b0 100644 --- a/libraries/render-utils/src/model_translucent_fade.slf +++ b/libraries/render-utils/src/model_translucent_fade.slf @@ -38,7 +38,9 @@ in vec4 _worldFadePosition; out vec4 _fragColor; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); @@ -81,7 +83,7 @@ void main(void) { albedo, fresnel, metallic, - emissive, + emissive+fadeEmissive, roughness, opacity), opacity); } diff --git a/libraries/render-utils/src/model_translucent_unlit_fade.slf b/libraries/render-utils/src/model_translucent_unlit_fade.slf index dd885f66d7..6c6846228e 100644 --- a/libraries/render-utils/src/model_translucent_unlit_fade.slf +++ b/libraries/render-utils/src/model_translucent_unlit_fade.slf @@ -29,7 +29,9 @@ in vec4 _worldFadePosition; out vec4 _fragColor; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); @@ -41,6 +43,6 @@ void main(void) { vec3 albedo = getMaterialAlbedo(mat); <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; albedo *= _color; - + albedo += fadeEmissive; _fragColor = vec4(albedo * isUnlitEnabled(), opacity); } diff --git a/libraries/render-utils/src/model_unlit_fade.slf b/libraries/render-utils/src/model_unlit_fade.slf index be0af7afea..59fdc87bee 100644 --- a/libraries/render-utils/src/model_unlit_fade.slf +++ b/libraries/render-utils/src/model_unlit_fade.slf @@ -29,7 +29,9 @@ in float _alpha; in vec4 _worldFadePosition; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); @@ -42,7 +44,7 @@ void main(void) { vec3 albedo = getMaterialAlbedo(mat); <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; albedo *= _color; - + albedo += fadeEmissive; packDeferredFragmentUnlit( normalize(_normal), opacity, diff --git a/libraries/render-utils/src/simple_fade.slf b/libraries/render-utils/src/simple_fade.slf index c082ea26f3..526b7157d9 100644 --- a/libraries/render-utils/src/simple_fade.slf +++ b/libraries/render-utils/src/simple_fade.slf @@ -33,7 +33,9 @@ in vec4 _worldFadePosition; #line 2030 void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); Material material = getMaterial(); vec3 normal = normalize(_normal.xyz); @@ -61,14 +63,14 @@ void main(void) { packDeferredFragmentTranslucent( normal, _color.a, - specular, + specular+fadeEmissive, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); } else { packDeferredFragmentTranslucent( normal, _color.a, - diffuse, + diffuse+fadeEmissive, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); } @@ -77,7 +79,7 @@ void main(void) { packDeferredFragmentLightmap( normal, 1.0, - diffuse, + diffuse+fadeEmissive, max(0, 1.0 - shininess / 128.0), DEFAULT_METALLIC, specular, @@ -89,7 +91,7 @@ void main(void) { diffuse, max(0, 1.0 - shininess / 128.0), length(specular), - DEFAULT_EMISSIVE, + DEFAULT_EMISSIVE+fadeEmissive, DEFAULT_OCCLUSION, DEFAULT_SCATTERING); } diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf index c939a8d676..5130720277 100644 --- a/libraries/render-utils/src/simple_textured_fade.slf +++ b/libraries/render-utils/src/simple_textured_fade.slf @@ -29,7 +29,9 @@ in vec2 _texCoord0; in vec4 _worldFadePosition; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0); float colorAlpha = _color.a; @@ -43,7 +45,7 @@ void main(void) { packDeferredFragmentTranslucent( normalize(_normal), colorAlpha * texel.a, - _color.rgb * texel.rgb, + _color.rgb * texel.rgb + fadeEmissive, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); } else { @@ -53,7 +55,7 @@ void main(void) { _color.rgb * texel.rgb, DEFAULT_ROUGHNESS, DEFAULT_METALLIC, - DEFAULT_EMISSIVE, + DEFAULT_EMISSIVE + fadeEmissive, DEFAULT_OCCLUSION, DEFAULT_SCATTERING); } diff --git a/libraries/render-utils/src/simple_textured_unlit_fade.slf b/libraries/render-utils/src/simple_textured_unlit_fade.slf index 2db2dfa222..60b6921ae3 100644 --- a/libraries/render-utils/src/simple_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_textured_unlit_fade.slf @@ -28,7 +28,9 @@ in vec2 _texCoord0; in vec4 _worldFadePosition; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0.st); float colorAlpha = _color.a; @@ -42,13 +44,13 @@ void main(void) { packDeferredFragmentTranslucent( normalize(_normal), colorAlpha * texel.a, - _color.rgb * texel.rgb, + _color.rgb * texel.rgb+fadeEmissive, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); } else { packDeferredFragmentUnlit( normalize(_normal), 1.0, - _color.rgb * texel.rgb); + _color.rgb * texel.rgb+fadeEmissive); } } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf index 84cdffeeec..8aa7bf176b 100644 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_fade.slf @@ -35,7 +35,9 @@ in vec2 _texCoord0; in vec4 _worldFadePosition; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0.st); float opacity = _color.a; @@ -59,8 +61,8 @@ void main(void) { fragNormal, albedo, DEFAULT_FRESNEL, - 0.0, - vec3(0.0f), + 0.0f, + fadeEmissive, DEFAULT_ROUGHNESS, opacity), opacity); diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf index 688e1de422..9f74eacc96 100644 --- a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf @@ -29,7 +29,9 @@ in vec4 _worldFadePosition; layout(location = 0) out vec4 _fragColor0; void main(void) { - applyFade(_worldFadePosition.xyz); + vec3 fadeEmissive; + + applyFade(_worldFadePosition.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0.st); float colorAlpha = _color.a; @@ -37,5 +39,5 @@ void main(void) { texel = colorToLinearRGBA(texel); colorAlpha = -_color.a; } - _fragColor0 = vec4(_color.rgb * texel.rgb, colorAlpha * texel.a); + _fragColor0 = vec4(_color.rgb * texel.rgb+fadeEmissive, colorAlpha * texel.a); } \ No newline at end of file diff --git a/libraries/render-utils/src/skin_model_shadow_fade.slf b/libraries/render-utils/src/skin_model_shadow_fade.slf index 7b164f5db1..666525a3ae 100644 --- a/libraries/render-utils/src/skin_model_shadow_fade.slf +++ b/libraries/render-utils/src/skin_model_shadow_fade.slf @@ -20,7 +20,7 @@ in vec4 _worldFadePosition; layout(location = 0) out vec4 _fragColor; void main(void) { - applyFade(_worldFadePosition.xyz); + applyFadeClip(_worldFadePosition.xyz); // pass-through to set z-buffer _fragColor = vec4(1.0, 1.0, 1.0, 0.0); diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index a75488ce7a..6f0bb226ca 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -115,6 +115,7 @@ namespace render { uint32_t _globalShapeKey { 0 }; bool _enableTexturing { true }; + bool _enableFade{ false }; RenderDetails _details; render::ScenePointer _scene; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 007b34395d..4690f0de74 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -316,7 +316,7 @@ public: virtual const ItemKey getKey() const = 0; virtual const Bound getBound() const = 0; virtual int getLayer() const = 0; - + virtual bool mustFade() const = 0; virtual void render(RenderArgs* args) = 0; virtual const ShapeKey getShapeKey() const = 0; @@ -364,6 +364,8 @@ public: // Get the layer where the item belongs. 0 by default meaning NOT LAYERED int getLayer() const { return _payload->getLayer(); } + bool mustFade() const { return _payload->mustFade(); } + // Render call for the item void render(RenderArgs* args) const { _payload->render(args); } @@ -409,6 +411,7 @@ template const ItemKey payloadGetKey(const std::shared_ptr& payload template const Item::Bound payloadGetBound(const std::shared_ptr& payloadData) { return Item::Bound(); } template int payloadGetLayer(const std::shared_ptr& payloadData) { return 0; } template void payloadRender(const std::shared_ptr& payloadData, RenderArgs* args) { } +template bool payloadMustFade(const std::shared_ptr& payloadData) { return false; } // Shape type interface // This allows shapes to characterize their pipeline via a ShapeKey, to be picked with a subclass of Shape. @@ -435,7 +438,7 @@ public: virtual const ItemKey getKey() const override { return payloadGetKey(_data); } virtual const Item::Bound getBound() const override { return payloadGetBound(_data); } virtual int getLayer() const override { return payloadGetLayer(_data); } - + virtual bool mustFade() const override { return payloadMustFade(_data); } virtual void render(RenderArgs* args) override { payloadRender(_data, args); } diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index d735afa52d..6e5d723ce6 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -65,6 +65,5 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const auto overlayTransparents = task.addJob("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET]; - output = Varying(Output{{ - opaques, transparents, lights, metas, overlayOpaques, overlayTransparents, background, spatialSelection }}); + output = Output{opaques, transparents, lights, metas, overlayOpaques, overlayTransparents, background, spatialSelection}; } diff --git a/libraries/render/src/render/RenderFetchCullSortTask.h b/libraries/render/src/render/RenderFetchCullSortTask.h index f32293f001..f3f326aae8 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.h +++ b/libraries/render/src/render/RenderFetchCullSortTask.h @@ -31,7 +31,7 @@ public: NUM_BUCKETS }; - using Output = std::array; + using Output = render::VaryingArray; using JobModel = render::Task::ModelO; RenderFetchCullSortTask() {} diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 6a52f90297..57cfa6342e 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -70,6 +70,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK)); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), Slot::BUFFER::FADE_PARAMETERS)); gpu::Shader::makeProgram(*program, slotBindings); @@ -89,7 +90,8 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->lightAmbientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer"); locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap"); locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap"); - + locations->fadeParameterBufferUnit = program->getUniformBuffers().findLocation("fadeParametersBuffer"); + ShapeKey key{filter._flags}; auto gpuPipeline = gpu::Pipeline::create(program, state); auto shapePipeline = std::make_shared(gpuPipeline, locations, batchSetter); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 06ca1ba15c..5d747a924d 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -215,6 +215,7 @@ public: LIGHTING_MODEL, LIGHT, LIGHT_AMBIENT_BUFFER, + FADE_PARAMETERS, }; enum MAP { @@ -246,6 +247,7 @@ public: int lightAmbientBufferUnit; int lightAmbientMapUnit; int fadeMaskTextureUnit; + int fadeParameterBufferUnit; }; using LocationsPointer = std::shared_ptr; diff --git a/libraries/render/src/task/Varying.h b/libraries/render/src/task/Varying.h index 50f4acd414..d5021383fb 100644 --- a/libraries/render/src/task/Varying.h +++ b/libraries/render/src/task/Varying.h @@ -281,6 +281,11 @@ public: (*this)[i] = Varying(T()); } } + + VaryingArray(std::initializer_list list) { + assert(list.size() == NUM); + std::copy(list.begin(), list.end(), begin()); + } }; } diff --git a/scripts/developer/utilities/render/debugFade.js b/scripts/developer/utilities/render/debugFade.js index 064337dae1..80c2deff73 100644 --- a/scripts/developer/utilities/render/debugFade.js +++ b/scripts/developer/utilities/render/debugFade.js @@ -15,7 +15,7 @@ var window = new OverlayWindow({ title: 'Fade', source: qml, width: 500, - height: 80 + height: 900 }); 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 index 0a99ca2e7e..ba7ed59398 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -12,47 +12,228 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import "configSlider" -Row { - property var taskConfig: Render.getConfig("RenderDeferredTask"); - spacing: 4 - Column { +Column { + property var config: Render.getConfig("RenderDeferredTask"); + spacing: 8 + Row { spacing: 8 CheckBox { - text: "Manual Fade" - checked: taskConfig["debugFade"] - onCheckedChanged: { taskConfig["debugFade"] = checked } + text: "Edit Fade" + checked: config["editFade"] + onCheckedChanged: { config["editFade"] = checked } + } + ComboBox { + width: 400 + model: ["Elements enter/leave domain", "Bubble isect. - Owner POV", "Bubble isect. - Trespasser POV", "Another user leaves/arrives", "Changing an avatar"] + onCurrentIndexChanged: { config["editedCategory"] = currentIndex } } } Column { spacing: 8 - ConfigSlider { - label: "Percent" - integral: false - config: taskConfig - property: "debugFadePercent" - max: 1.0 - min: 0.0 - width: 250 - } - ConfigSlider { - label: "Scale" - integral: false - config: taskConfig - property: "fadeScale" - max: 1.0 - min: 0.0 - width: 250 - } ConfigSlider { label: "Duration" integral: false - config: taskConfig - property: "fadeDuration" + config: config + property: "duration" max: 10.0 min: 0.1 - width: 250 + width: 400 + } + GroupBox { + title: "Base Gradient" + width: 500 + Column { + spacing: 8 + + ConfigSlider { + label: "Size X" + integral: false + config: config + property: "baseSizeX" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Y" + integral: false + config: config + property: "baseSizeY" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Z" + integral: false + config: config + property: "baseSizeZ" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Level" + integral: false + config: config + property: "baseLevel" + max: 1.0 + min: 0.0 + width: 400 + } + CheckBox { + text: "Invert" + checked: config["baseInverted"] + onCheckedChanged: { config["baseInverted"] = checked } + } + } + } + GroupBox { + title: "Noise Gradient" + width: 500 + Column { + spacing: 8 + + ConfigSlider { + label: "Size X" + integral: false + config: config + property: "noiseSizeX" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Y" + integral: false + config: config + property: "noiseSizeY" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Z" + integral: false + config: config + property: "noiseSizeZ" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Level" + integral: false + config: config + property: "noiseLevel" + max: 1.0 + min: 0.0 + width: 400 + } + } + } + GroupBox { + title: "Edge" + width: 500 + Column { + spacing: 8 + + ConfigSlider { + label: "Width" + integral: false + config: config + property: "edgeWidth" + max: 1.0 + min: 0.0 + width: 400 + } + GroupBox { + title: "Inner color" + Column { + spacing: 8 + ConfigSlider { + label: "Color R" + integral: false + config: config + property: "edgeInnerColorR" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color G" + integral: false + config: config + property: "edgeInnerColorG" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color B" + integral: false + config: config + property: "edgeInnerColorB" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color intensity" + integral: false + config: config + property: "edgeInnerIntensity" + max: 5.0 + min: 0.0 + width: 400 + } + } + } + GroupBox { + title: "Outer color" + Column { + spacing: 8 + ConfigSlider { + label: "Color R" + integral: false + config: config + property: "edgeOuterColorR" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color G" + integral: false + config: config + property: "edgeOuterColorG" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color B" + integral: false + config: config + property: "edgeOuterColorB" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color intensity" + integral: false + config: config + property: "edgeOuterIntensity" + max: 5.0 + min: 0.0 + width: 400 + } + } + } + } } } } From 6a31dc2659d1355593a9f9e3a76076173fda1ad7 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 29 Jun 2017 12:13:55 +0200 Subject: [PATCH 21/86] Selection of edited object working --- libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 2 +- libraries/render-utils/src/FadeEffect.cpp | 254 ++++++++++++++++-- libraries/render-utils/src/FadeEffect.h | 52 ++-- .../render-utils/src/RenderDeferredTask.cpp | 2 + libraries/render/src/render/Args.h | 1 + .../developer/utilities/render/debugFade.js | 3 +- scripts/developer/utilities/render/fade.qml | 50 ++-- 7 files changed, 291 insertions(+), 73 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index 3441407f62..960e98d620 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -448,7 +448,7 @@ void GLBackend::do_glUniform1i(const Batch& batch, size_t paramOffset) { } updatePipeline(); - glUniform1f( + glUniform1i( GET_UNIFORM_LOCATION(batch._params[paramOffset + 1]._int), batch._params[paramOffset + 0]._int); (void)CHECK_GL_ERROR(); diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index d2bad0d1ef..a9ac26c891 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -7,7 +7,7 @@ #include void FadeSwitchJob::configure(const Config& config) { - _isEditEnabled = config.editFade; + _parameters->_isEditEnabled = config.editFade; } void FadeSwitchJob::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { @@ -22,13 +22,50 @@ void FadeSwitchJob::run(const render::RenderContextPointer& renderContext, const normalOutputs[RenderFetchCullSortTask::BACKGROUND] = input[RenderFetchCullSortTask::BACKGROUND]; normalOutputs[RenderFetchCullSortTask::SPATIAL_SELECTION] = input[RenderFetchCullSortTask::SPATIAL_SELECTION]; + // Find the nearest item that intersects the view direction + const render::Item* editedItem = nullptr; + if (_parameters->_isEditEnabled) { + float nearestOpaqueDistance = std::numeric_limits::max(); + float nearestTransparentDistance = std::numeric_limits::max(); + const render::Item* nearestItem; + + editedItem = findNearestItem(renderContext, input[RenderFetchCullSortTask::OPAQUE_SHAPE], nearestOpaqueDistance); + nearestItem = findNearestItem(renderContext, input[RenderFetchCullSortTask::TRANSPARENT_SHAPE], nearestTransparentDistance); + if (nearestTransparentDistance < nearestOpaqueDistance) { + editedItem = nearestItem; + } + } + // Now, distribute items that need to be faded accross both outputs - distribute(renderContext, input[RenderFetchCullSortTask::OPAQUE_SHAPE], normalOutputs[RenderFetchCullSortTask::OPAQUE_SHAPE], fadeOutputs[OPAQUE_SHAPE]); - distribute(renderContext, input[RenderFetchCullSortTask::TRANSPARENT_SHAPE], normalOutputs[RenderFetchCullSortTask::TRANSPARENT_SHAPE], fadeOutputs[TRANSPARENT_SHAPE]); + distribute(renderContext, input[RenderFetchCullSortTask::OPAQUE_SHAPE], normalOutputs[RenderFetchCullSortTask::OPAQUE_SHAPE], fadeOutputs[OPAQUE_SHAPE], editedItem); + distribute(renderContext, input[RenderFetchCullSortTask::TRANSPARENT_SHAPE], normalOutputs[RenderFetchCullSortTask::TRANSPARENT_SHAPE], fadeOutputs[TRANSPARENT_SHAPE], editedItem); +} + +const render::Item* FadeSwitchJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const { + const glm::vec3 rayOrigin = renderContext->args->getViewFrustum().getPosition(); + const glm::vec3 rayDirection = renderContext->args->getViewFrustum().getDirection(); + const auto& inputItems = input.get(); + auto& scene = renderContext->_scene; + BoxFace face; + glm::vec3 normal; + float isectDistance; + const render::Item* nearestItem = nullptr; + const float minDistance = 5.f; + + for (const auto& itemBound : inputItems) { + if (itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { + if (isectDistance>minDistance && isectDistance < minIsectDistance) { + auto& item = scene->getItem(itemBound.id); + nearestItem = &item; + minIsectDistance = isectDistance; + } + } + } + return nearestItem; } void FadeSwitchJob::distribute(const render::RenderContextPointer& renderContext, const render::Varying& input, - render::Varying& normalOutput, render::Varying& fadeOutput) const { + render::Varying& normalOutput, render::Varying& fadeOutput, const render::Item* editedItem) const { auto& scene = renderContext->_scene; assert(_parameters); const double fadeDuration = double(_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]) * USECS_PER_SECOND; @@ -41,7 +78,7 @@ void FadeSwitchJob::distribute(const render::RenderContextPointer& renderContext for (const auto& itemBound : inputItems) { auto& item = scene->getItem(itemBound.id); - if (!item.mustFade()) { + if (!item.mustFade() && &item!=editedItem) { // No need to fade normalOutput.template edit().emplace_back(itemBound); } @@ -49,9 +86,107 @@ void FadeSwitchJob::distribute(const render::RenderContextPointer& renderContext fadeOutput.template edit().emplace_back(itemBound); } } -/* if (!_isEditEnabled) { +} - }*/ +void FadeJobConfig::setEditedCategory(int value) { + assert(value < EVENT_CATEGORY_COUNT); + editedCategory = std::min(EVENT_CATEGORY_COUNT, value); + emit dirty(); +} + +void FadeJobConfig::setDuration(float value) { + duration[editedCategory] = value; + emit dirty(); +} + +void FadeJobConfig::setBaseSizeX(float value) { + baseSize[editedCategory].x = value; + emit dirty(); +} + +void FadeJobConfig::setBaseSizeY(float value) { + baseSize[editedCategory].y = value; + emit dirty(); +} + +void FadeJobConfig::setBaseSizeZ(float value) { + baseSize[editedCategory].z = value; + emit dirty(); +} + +void FadeJobConfig::setBaseLevel(float value) { + baseLevel[editedCategory] = value; + emit dirty(); +} + +void FadeJobConfig::setBaseInverted(bool value) { + baseInverted[editedCategory] = value; + emit dirty(); +} + +void FadeJobConfig::setNoiseSizeX(float value) { + noiseSize[editedCategory].x = value; + emit dirty(); +} + +void FadeJobConfig::setNoiseSizeY(float value) { + noiseSize[editedCategory].y = value; + emit dirty(); +} + +void FadeJobConfig::setNoiseSizeZ(float value) { + noiseSize[editedCategory].z = value; + emit dirty(); +} + +void FadeJobConfig::setNoiseLevel(float value) { + noiseLevel[editedCategory] = value; + emit dirty(); +} + +void FadeJobConfig::setEdgeWidth(float value) { + edgeWidth[editedCategory] = value; + emit dirty(); +} + +void FadeJobConfig::setEdgeInnerColorR(float value) { + edgeInnerColor[editedCategory].r = value; + emit dirty(); +} + +void FadeJobConfig::setEdgeInnerColorG(float value) { + edgeInnerColor[editedCategory].g = value; + emit dirty(); +} + +void FadeJobConfig::setEdgeInnerColorB(float value) { + edgeInnerColor[editedCategory].b = value; + emit dirty(); +} + +void FadeJobConfig::setEdgeInnerIntensity(float value) { + edgeInnerColor[editedCategory].a = value; + emit dirty(); +} + +void FadeJobConfig::setEdgeOuterColorR(float value) { + edgeOuterColor[editedCategory].r = value; + emit dirty(); +} + +void FadeJobConfig::setEdgeOuterColorG(float value) { + edgeOuterColor[editedCategory].g = value; + emit dirty(); +} + +void FadeJobConfig::setEdgeOuterColorB(float value) { + edgeOuterColor[editedCategory].b = value; + emit dirty(); +} + +void FadeJobConfig::setEdgeOuterIntensity(float value) { + edgeOuterColor[editedCategory].a = value; + emit dirty(); } FadeConfigureJob::FadeConfigureJob(FadeCommonParameters::Pointer commonParams) : @@ -63,6 +198,7 @@ FadeConfigureJob::FadeConfigureJob(FadeCommonParameters::Pointer commonParams) : void FadeConfigureJob::configure(const Config& config) { assert(_parameters); + _parameters->_editedCategory = config.editedCategory; for (auto i = 0; i < FadeJobConfig::EVENT_CATEGORY_COUNT; i++) { auto& configuration = _configurations[i]; @@ -101,18 +237,6 @@ const FadeRenderJob* FadeRenderJob::_currentInstance{ nullptr }; gpu::TexturePointer FadeRenderJob::_currentFadeMaskMap; const gpu::BufferView* FadeRenderJob::_currentFadeBuffer{ nullptr }; -float FadeRenderJob::computeFadePercent(quint64 startTime) { - assert(_currentInstance); - float fadeAlpha = 1.0f; - const double INV_FADE_PERIOD = 1.0 / (double)(_currentInstance->_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] * USECS_PER_SECOND); - double fraction = (double)(int64_t(usecTimestampNow()) - int64_t(startTime)) * INV_FADE_PERIOD; - fraction = std::max(fraction, 0.0); - if (fraction < 1.0) { - fadeAlpha = Interpolate::easeInOutQuad(fraction); - } - return fadeAlpha; -} - void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const Input& inputs) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); @@ -125,15 +249,23 @@ void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const const auto& fadeMaskMap = configuration.get0(); const auto& fadeParamBuffer = configuration.get1(); - // Very, very ugly hack to keep track of the current fade render job RenderArgs* args = renderContext->args; render::ShapeKey::Builder defaultKeyBuilder; defaultKeyBuilder.withFade(); + // Update interactive edit effect + if (_parameters->_isEditEnabled) { + updateFadeEdit(); + } + else { + _editStartTime = 0; + } + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; + // Very, very ugly hack to keep track of the current fade render job _currentInstance = this; _currentFadeMaskMap = fadeMaskMap; _currentFadeBuffer = &fadeParamBuffer; @@ -180,6 +312,69 @@ void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const } } +float FadeRenderJob::computeElementEnterThreshold(double time) const { + float fadeAlpha = 1.0f; + const double INV_FADE_PERIOD = 1.0 / (double)(_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]); + double fraction = time * INV_FADE_PERIOD; + fraction = std::max(fraction, 0.0); + if (fraction < 1.0) { + fadeAlpha = Interpolate::easeInOutQuad(fraction); + } + return fadeAlpha; +} + +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); +} + +void FadeRenderJob::updateFadeEdit() { + if (_editStartTime == 0) { + _editStartTime = usecTimestampNow(); + } + + const double time = (int64_t(usecTimestampNow()) - int64_t(_editStartTime)) / double(USECS_PER_SECOND); + + switch (_parameters->_editedCategory) { + case FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN: + { + const double waitTime = 0.5; // Wait between fade in and out + const float eventDuration = _parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]; + double cycleTime = fmod(time, (eventDuration+waitTime) * 2.0); + + if (cycleTime < eventDuration) { + _editThreshold = 1.f-computeElementEnterThreshold(cycleTime); + } + else if (cycleTime < (eventDuration + waitTime)) { + _editThreshold = 0.f; + } + else if (cycleTime < (2 * eventDuration + waitTime)) { + _editThreshold = computeElementEnterThreshold(cycleTime- (eventDuration + waitTime)); + } + else { + _editThreshold = 1.f; + } + } + break; + + case FadeJobConfig::BUBBLE_ISECT_OWNER: + break; + + case FadeJobConfig::BUBBLE_ISECT_TRESPASSER: + break; + + case FadeJobConfig::USER_ENTER_LEAVE_DOMAIN: + break; + + case FadeJobConfig::AVATAR_CHANGE: + break; + + default: + assert(false); + } +} + void FadeRenderJob::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation) { assert(_currentFadeMaskMap); assert(_currentFadeBuffer!=nullptr); @@ -210,17 +405,26 @@ bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline auto fadeCategoryLocation = uniforms.findLocation("fadeCategory"); if (fadeNoiseOffsetLocation >= 0 || fadeBaseOffsetLocation>=0 || fadeThresholdLocation >= 0 || fadeCategoryLocation>=0) { - float percent; + float threshold; + int eventCategory = FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN; - percent = computeFadePercent(startTime); - batch._glUniform1i(fadeCategoryLocation, FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN); - batch._glUniform1f(fadeThresholdLocation, 1.f-percent); + threshold = 1.f-computeFadePercent(startTime); + + // Manage interactive edition override + assert(_currentInstance); + if (_currentInstance->_parameters->_isEditEnabled) { + eventCategory = _currentInstance->_parameters->_editedCategory; + threshold = _currentInstance->_editThreshold; + } + + batch._glUniform1i(fadeCategoryLocation, eventCategory); + batch._glUniform1f(fadeThresholdLocation, threshold); // This is really temporary batch._glUniform3f(fadeNoiseOffsetLocation, offset.x, offset.y, offset.z); // This is really temporary batch._glUniform3f(fadeBaseOffsetLocation, offset.x, offset.y, offset.z); - return percent < 1.f; + return threshold > 0.f; } return false; } diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 295dbb333a..2ac9954575 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -66,63 +66,63 @@ public: EVENT_CATEGORY_COUNT }; - void setEditedCategory(int value) { assert(value < EVENT_CATEGORY_COUNT); editedCategory = std::min(EVENT_CATEGORY_COUNT, value); } + void setEditedCategory(int value); - void setDuration(float value) { duration[editedCategory] = value; } + void setDuration(float value); float getDuration() const { return duration[editedCategory]; } - void setBaseSizeX(float value) { baseSize[editedCategory].x = value; } + void setBaseSizeX(float value); float getBaseSizeX() const { return baseSize[editedCategory].x; } - void setBaseSizeY(float value) { baseSize[editedCategory].y = value; } + void setBaseSizeY(float value); float getBaseSizeY() const { return baseSize[editedCategory].y; } - void setBaseSizeZ(float value) { baseSize[editedCategory].z = value; } + void setBaseSizeZ(float value); float getBaseSizeZ() const { return baseSize[editedCategory].z; } - void setBaseLevel(float value) { baseLevel[editedCategory] = value; } + void setBaseLevel(float value); float getBaseLevel() const { return baseLevel[editedCategory]; } - void setBaseInverted(bool value) { baseInverted[editedCategory] = value; } + void setBaseInverted(bool value); bool isBaseInverted() const { return baseInverted[editedCategory]; } - void setNoiseSizeX(float value) { noiseSize[editedCategory].x = value; } + void setNoiseSizeX(float value); float getNoiseSizeX() const { return noiseSize[editedCategory].x; } - void setNoiseSizeY(float value) { noiseSize[editedCategory].y = value; } + void setNoiseSizeY(float value); float getNoiseSizeY() const { return noiseSize[editedCategory].y; } - void setNoiseSizeZ(float value) { noiseSize[editedCategory].z = value; } + void setNoiseSizeZ(float value); float getNoiseSizeZ() const { return noiseSize[editedCategory].z; } - void setNoiseLevel(float value) { noiseLevel[editedCategory] = value; } + void setNoiseLevel(float value); float getNoiseLevel() const { return noiseLevel[editedCategory]; } - void setEdgeWidth(float value) { edgeWidth[editedCategory] = value; } + void setEdgeWidth(float value); float getEdgeWidth() const { return edgeWidth[editedCategory]; } - void setEdgeInnerColorR(float value) { edgeInnerColor[editedCategory].r = value; } + void setEdgeInnerColorR(float value); float getEdgeInnerColorR() const { return edgeInnerColor[editedCategory].r; } - void setEdgeInnerColorG(float value) { edgeInnerColor[editedCategory].g = value; } + void setEdgeInnerColorG(float value); float getEdgeInnerColorG() const { return edgeInnerColor[editedCategory].g; } - void setEdgeInnerColorB(float value) { edgeInnerColor[editedCategory].b = value; } + void setEdgeInnerColorB(float value); float getEdgeInnerColorB() const { return edgeInnerColor[editedCategory].b; } - void setEdgeInnerIntensity(float value) { edgeInnerColor[editedCategory].a = value; } + void setEdgeInnerIntensity(float value); float getEdgeInnerIntensity() const { return edgeInnerColor[editedCategory].a; } - void setEdgeOuterColorR(float value) { edgeOuterColor[editedCategory].r = value; } + void setEdgeOuterColorR(float value); float getEdgeOuterColorR() const { return edgeOuterColor[editedCategory].r; } - void setEdgeOuterColorG(float value) { edgeOuterColor[editedCategory].g = value; } + void setEdgeOuterColorG(float value); float getEdgeOuterColorG() const { return edgeOuterColor[editedCategory].g; } - void setEdgeOuterColorB(float value) { edgeOuterColor[editedCategory].b = value; } + void setEdgeOuterColorB(float value); float getEdgeOuterColorB() const { return edgeOuterColor[editedCategory].b; } - void setEdgeOuterIntensity(float value) { edgeOuterColor[editedCategory].a = value; } + void setEdgeOuterIntensity(float value); float getEdgeOuterIntensity() const { return edgeOuterColor[editedCategory].a; } int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; @@ -199,6 +199,8 @@ struct FadeCommonParameters { using Pointer = std::shared_ptr; + bool _isEditEnabled{ false }; + int _editedCategory{ FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN }; float _durations[FadeJobConfig::EVENT_CATEGORY_COUNT]{ 30.0f, // ELEMENT_ENTER_LEAVE_DOMAIN 0.0f, // BUBBLE_ISECT_OWNER @@ -233,10 +235,10 @@ public: private: FadeCommonParameters::Pointer _parameters; - bool _isEditEnabled{ false }; void distribute(const render::RenderContextPointer& renderContext, const render::Varying& input, - render::Varying& normalOutput, render::Varying& fadeOutput) const; + render::Varying& normalOutput, render::Varying& fadeOutput, const render::Item* editedItem = nullptr) const; + const render::Item* findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const; }; struct FadeParameters @@ -308,7 +310,13 @@ private: render::ShapePlumberPointer _shapePlumber; FadeCommonParameters::Pointer _parameters; + float computeElementEnterThreshold(double time) const; + // Everything needed for interactive edition + uint64_t _editStartTime{ 0 }; + float _editThreshold{ 0.f }; + + void updateFadeEdit(); }; #endif // hifi_FadeEffect_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index a8ead6e76e..ca7f4a10d9 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -103,6 +103,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto fadeOpaqueInputs = FadeRenderJob::Input(fadeOpaques, lightingModel, fadeConfigureOutputs).hasVarying(); task.addJob("DrawFadeOpaque", fadeOpaqueInputs, commonFadeParameters, shapePlumber); + task.addJob("OpaqueRangeTimer", opaqueRangeTimer); @@ -173,6 +174,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("ToneMapping", toneMappingInputs); { // DEbug the bounds of the rendered items, still look at the zbuffer + task.addJob("DrawFadedOpaqueBounds", fadeOpaques); task.addJob("DrawMetaBounds", metas); task.addJob("DrawOpaqueBounds", opaques); task.addJob("DrawTransparentBounds", transparents); diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index 6f0bb226ca..d17e6628d3 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -115,6 +115,7 @@ namespace render { uint32_t _globalShapeKey { 0 }; bool _enableTexturing { true }; + bool _enableFade{ false }; RenderDetails _details; diff --git a/scripts/developer/utilities/render/debugFade.js b/scripts/developer/utilities/render/debugFade.js index 80c2deff73..df18e0370a 100644 --- a/scripts/developer/utilities/render/debugFade.js +++ b/scripts/developer/utilities/render/debugFade.js @@ -18,4 +18,5 @@ var window = new OverlayWindow({ height: 900 }); window.setPosition(50, 50); -window.closed.connect(function() { Script.stop(); }); \ No newline at end of file +window.closed.connect(function() { Script.stop(); }); +Render.getConfig("RenderMainView.DrawFadedOpaqueBounds").enabled = true \ No newline at end of file diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index ba7ed59398..3aff96d7cd 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -13,20 +13,22 @@ import QtQuick.Controls 1.4 import "configSlider" Column { - property var config: Render.getConfig("RenderDeferredTask"); + id: root + property var config: Render.getConfig("RenderMainView.FadeConfigure"); + property var switchConfig: Render.getConfig("RenderMainView.FadeSwitch"); spacing: 8 Row { spacing: 8 CheckBox { text: "Edit Fade" - checked: config["editFade"] - onCheckedChanged: { config["editFade"] = checked } + checked: root.switchConfig["editFade"] + onCheckedChanged: { root.switchConfig["editFade"] = checked } } ComboBox { width: 400 model: ["Elements enter/leave domain", "Bubble isect. - Owner POV", "Bubble isect. - Trespasser POV", "Another user leaves/arrives", "Changing an avatar"] - onCurrentIndexChanged: { config["editedCategory"] = currentIndex } + onCurrentIndexChanged: { root.config["editedCategory"] = currentIndex } } } Column { @@ -35,7 +37,7 @@ Column { ConfigSlider { label: "Duration" integral: false - config: config + config: root.config property: "duration" max: 10.0 min: 0.1 @@ -50,7 +52,7 @@ Column { ConfigSlider { label: "Size X" integral: false - config: config + config: root.config property: "baseSizeX" max: 1.0 min: 0.0 @@ -59,7 +61,7 @@ Column { ConfigSlider { label: "Size Y" integral: false - config: config + config: root.config property: "baseSizeY" max: 1.0 min: 0.0 @@ -68,7 +70,7 @@ Column { ConfigSlider { label: "Size Z" integral: false - config: config + config: root.config property: "baseSizeZ" max: 1.0 min: 0.0 @@ -77,7 +79,7 @@ Column { ConfigSlider { label: "Level" integral: false - config: config + config: root.config property: "baseLevel" max: 1.0 min: 0.0 @@ -85,8 +87,8 @@ Column { } CheckBox { text: "Invert" - checked: config["baseInverted"] - onCheckedChanged: { config["baseInverted"] = checked } + checked: root.config["baseInverted"] + onCheckedChanged: { root.config["baseInverted"] = checked } } } } @@ -99,7 +101,7 @@ Column { ConfigSlider { label: "Size X" integral: false - config: config + config: root.config property: "noiseSizeX" max: 1.0 min: 0.0 @@ -108,7 +110,7 @@ Column { ConfigSlider { label: "Size Y" integral: false - config: config + config: root.config property: "noiseSizeY" max: 1.0 min: 0.0 @@ -117,7 +119,7 @@ Column { ConfigSlider { label: "Size Z" integral: false - config: config + config: root.config property: "noiseSizeZ" max: 1.0 min: 0.0 @@ -126,7 +128,7 @@ Column { ConfigSlider { label: "Level" integral: false - config: config + config: root.config property: "noiseLevel" max: 1.0 min: 0.0 @@ -143,7 +145,7 @@ Column { ConfigSlider { label: "Width" integral: false - config: config + config: root.config property: "edgeWidth" max: 1.0 min: 0.0 @@ -156,7 +158,7 @@ Column { ConfigSlider { label: "Color R" integral: false - config: config + config: root.config property: "edgeInnerColorR" max: 1.0 min: 0.0 @@ -165,7 +167,7 @@ Column { ConfigSlider { label: "Color G" integral: false - config: config + config: root.config property: "edgeInnerColorG" max: 1.0 min: 0.0 @@ -174,7 +176,7 @@ Column { ConfigSlider { label: "Color B" integral: false - config: config + config: root.config property: "edgeInnerColorB" max: 1.0 min: 0.0 @@ -183,7 +185,7 @@ Column { ConfigSlider { label: "Color intensity" integral: false - config: config + config: root.config property: "edgeInnerIntensity" max: 5.0 min: 0.0 @@ -198,7 +200,7 @@ Column { ConfigSlider { label: "Color R" integral: false - config: config + config: root.config property: "edgeOuterColorR" max: 1.0 min: 0.0 @@ -207,7 +209,7 @@ Column { ConfigSlider { label: "Color G" integral: false - config: config + config: root.config property: "edgeOuterColorG" max: 1.0 min: 0.0 @@ -216,7 +218,7 @@ Column { ConfigSlider { label: "Color B" integral: false - config: config + config: root.config property: "edgeOuterColorB" max: 1.0 min: 0.0 @@ -225,7 +227,7 @@ Column { ConfigSlider { label: "Color intensity" integral: false - config: config + config: root.config property: "edgeOuterIntensity" max: 5.0 min: 0.0 From fb33b8d1c1e567d8b72e7601d7c981984d96b7b2 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 29 Jun 2017 12:59:43 +0200 Subject: [PATCH 22/86] Working edition and emissive edge on fade element enter/leave --- libraries/render-utils/src/Fade.slh | 15 ++++---- libraries/render-utils/src/FadeEffect.cpp | 25 +++++++------- libraries/render-utils/src/FadeEffect.h | 42 +++++++++++------------ 3 files changed, 40 insertions(+), 42 deletions(-) diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 776343dc53..5ee7bb2178 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -22,8 +22,8 @@ struct FadeParameters { vec4 _baseInvSizeAndLevel; vec4 _noiseInvSizeAndLevel; - vec3 _innerEdgeColor; - vec3 _outerEdgeColor; + vec4 _innerEdgeColor; + vec4 _outerEdgeColor; vec2 _edgeWidthInvWidth; int _invertBase; float _padding; @@ -108,16 +108,15 @@ void applyFade(vec3 position, out vec3 emissive) { if (alpha < 0) { discard; } - /* + float edgeMask = alpha * fadeParameters[fadeCategory]._edgeWidthInvWidth.y; float edgeAlpha = 1.0-clamp(edgeMask, 0, 1); - edgeMask = step(edgeMask, 1.f); + //edgeMask = step(edgeMask, 1.f); + edgeMask = edgeMask > 1.f ? 0.f : 1.f; edgeAlpha *= edgeAlpha; // Square to have a nice ease out - emissive = mix(fadeParameters[fadeCategory]._innerEdgeColor, fadeParameters[fadeCategory]._outerEdgeColor, edgeAlpha); - emissive *= edgeMask; - */ - emissive = vec3(0,0,0); + vec4 color = mix(fadeParameters[fadeCategory]._innerEdgeColor, fadeParameters[fadeCategory]._outerEdgeColor, edgeAlpha); + emissive = color.rgb * edgeMask * color.a; } <@endfunc@> diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index a9ac26c891..ef15953b2b 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -6,6 +6,9 @@ #include #include +#define FADE_MIN_SCALE 0.001f +#define FADE_MAX_SCALE 100000.f + void FadeSwitchJob::configure(const Config& config) { _parameters->_isEditEnabled = config.editFade; } @@ -100,17 +103,17 @@ void FadeJobConfig::setDuration(float value) { } void FadeJobConfig::setBaseSizeX(float value) { - baseSize[editedCategory].x = value; + baseSize[editedCategory].x = FADE_MIN_SCALE*powf(FADE_MAX_SCALE/ FADE_MIN_SCALE, value); emit dirty(); } void FadeJobConfig::setBaseSizeY(float value) { - baseSize[editedCategory].y = value; + baseSize[editedCategory].y = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); emit dirty(); } void FadeJobConfig::setBaseSizeZ(float value) { - baseSize[editedCategory].z = value; + baseSize[editedCategory].z = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); emit dirty(); } @@ -125,17 +128,17 @@ void FadeJobConfig::setBaseInverted(bool value) { } void FadeJobConfig::setNoiseSizeX(float value) { - noiseSize[editedCategory].x = value; + noiseSize[editedCategory].x = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); emit dirty(); } void FadeJobConfig::setNoiseSizeY(float value) { - noiseSize[editedCategory].y = value; + noiseSize[editedCategory].y = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); emit dirty(); } void FadeJobConfig::setNoiseSizeZ(float value) { - noiseSize[editedCategory].z = value; + noiseSize[editedCategory].z = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); emit dirty(); } @@ -145,7 +148,7 @@ void FadeJobConfig::setNoiseLevel(float value) { } void FadeJobConfig::setEdgeWidth(float value) { - edgeWidth[editedCategory] = value; + edgeWidth[editedCategory] = value * value; emit dirty(); } @@ -214,12 +217,8 @@ void FadeConfigureJob::configure(const Config& config) { configuration._invertBase = config.baseInverted[i]; configuration._edgeWidthInvWidth.x = config.edgeWidth[i]; configuration._edgeWidthInvWidth.y = 1.f / configuration._edgeWidthInvWidth.x; - configuration._innerEdgeColor.r = config.edgeInnerColor[i].r * config.edgeInnerColor[i].a; - configuration._innerEdgeColor.g = config.edgeInnerColor[i].g * config.edgeInnerColor[i].a; - configuration._innerEdgeColor.b = config.edgeInnerColor[i].b * config.edgeInnerColor[i].a; - configuration._outerEdgeColor.r = config.edgeOuterColor[i].r * config.edgeOuterColor[i].a; - configuration._outerEdgeColor.g = config.edgeOuterColor[i].g * config.edgeOuterColor[i].a; - configuration._outerEdgeColor.b = config.edgeOuterColor[i].b * config.edgeOuterColor[i].a; + configuration._innerEdgeColor = config.edgeInnerColor[i]; + configuration._outerEdgeColor = config.edgeOuterColor[i]; } _isBufferDirty = true; } diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 2ac9954575..c3e82c6c5d 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -127,11 +127,11 @@ public: int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; glm::vec3 baseSize[EVENT_CATEGORY_COUNT]{ - { 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER - { 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER - { 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN - { 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE + { 0.35f, 0.35f, 0.35f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 0.35f, 0.35f, 0.35f }, // BUBBLE_ISECT_OWNER + { 0.35f, 0.35f, 0.35f }, // BUBBLE_ISECT_TRESPASSER + { 0.35f, 0.35f, 0.35f }, // USER_ENTER_LEAVE_DOMAIN + { 0.35f, 0.35f, 0.35f }, // AVATAR_CHANGE }; float baseLevel[EVENT_CATEGORY_COUNT]{ 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN @@ -148,11 +148,11 @@ public: false, // AVATAR_CHANGE }; glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]{ - { 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER - { 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER - { 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN - { 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE + { 0.35f, 0.35f, 0.35f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 0.35f, 0.35f, 0.35f }, // BUBBLE_ISECT_OWNER + { 0.35f, 0.35f, 0.35f }, // BUBBLE_ISECT_TRESPASSER + { 0.35f, 0.35f, 0.35f }, // USER_ENTER_LEAVE_DOMAIN + { 0.35f, 0.35f, 0.35f }, // AVATAR_CHANGE }; float noiseLevel[EVENT_CATEGORY_COUNT]{ 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN @@ -169,22 +169,22 @@ public: 3.0f, // AVATAR_CHANGE }; float edgeWidth[EVENT_CATEGORY_COUNT]{ - 0.1f, // ELEMENT_ENTER_LEAVE_DOMAIN - 0.1f, // BUBBLE_ISECT_OWNER - 0.1f, // BUBBLE_ISECT_TRESPASSER - 0.1f, // USER_ENTER_LEAVE_DOMAIN - 0.1f, // AVATAR_CHANGE + 0.05f, // ELEMENT_ENTER_LEAVE_DOMAIN + 0.05f, // BUBBLE_ISECT_OWNER + 0.05f, // BUBBLE_ISECT_TRESPASSER + 0.05f, // USER_ENTER_LEAVE_DOMAIN + 0.05f, // AVATAR_CHANGE }; glm::vec4 edgeInnerColor[EVENT_CATEGORY_COUNT]{ - { 1.0f, 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER + { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER { 1.0f, 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE }; glm::vec4 edgeOuterColor[EVENT_CATEGORY_COUNT]{ - { 1.0f, 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER + { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER { 1.0f, 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE @@ -245,8 +245,8 @@ struct FadeParameters { glm::vec4 _baseInvSizeAndLevel; glm::vec4 _noiseInvSizeAndLevel; - glm::vec3 _innerEdgeColor; - glm::vec3 _outerEdgeColor; + glm::vec4 _innerEdgeColor; + glm::vec4 _outerEdgeColor; glm::vec2 _edgeWidthInvWidth; glm::int32 _invertBase; glm::float32 _padding; From c5ca23f4eae42c7eb2a79febd205ee3e08c58b87 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 29 Jun 2017 17:14:20 +0200 Subject: [PATCH 23/86] Changing edited fade category properly updates widgets in edit window --- libraries/render-utils/src/FadeEffect.cpp | 41 +- libraries/render-utils/src/FadeEffect.h | 55 +-- .../render/configSlider/ConfigSlider.qml | 1 + .../developer/utilities/render/debugFade.js | 3 +- scripts/developer/utilities/render/fade.qml | 418 +++++++++--------- 5 files changed, 290 insertions(+), 228 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index ef15953b2b..7c975ef201 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -94,29 +94,46 @@ void FadeSwitchJob::distribute(const render::RenderContextPointer& renderContext void FadeJobConfig::setEditedCategory(int value) { assert(value < EVENT_CATEGORY_COUNT); editedCategory = std::min(EVENT_CATEGORY_COUNT, value); + emit dirtyCategory(); emit dirty(); } void FadeJobConfig::setDuration(float value) { - duration[editedCategory] = value; + _duration[editedCategory] = value; emit dirty(); } +float FadeJobConfig::getDuration() const { + return _duration[editedCategory]; +} + void FadeJobConfig::setBaseSizeX(float value) { baseSize[editedCategory].x = FADE_MIN_SCALE*powf(FADE_MAX_SCALE/ FADE_MIN_SCALE, value); emit dirty(); } +float FadeJobConfig::getBaseSizeX() const { + return logf(baseSize[editedCategory].x / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); +} + void FadeJobConfig::setBaseSizeY(float value) { baseSize[editedCategory].y = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); emit dirty(); } +float FadeJobConfig::getBaseSizeY() const { + return logf(baseSize[editedCategory].y / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); +} + void FadeJobConfig::setBaseSizeZ(float value) { baseSize[editedCategory].z = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); emit dirty(); } +float FadeJobConfig::getBaseSizeZ() const { + return logf(baseSize[editedCategory].z / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); +} + void FadeJobConfig::setBaseLevel(float value) { baseLevel[editedCategory] = value; emit dirty(); @@ -127,21 +144,37 @@ void FadeJobConfig::setBaseInverted(bool value) { emit dirty(); } +bool FadeJobConfig::isBaseInverted() const { + return baseInverted[editedCategory]; +} + void FadeJobConfig::setNoiseSizeX(float value) { noiseSize[editedCategory].x = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); emit dirty(); } +float FadeJobConfig::getNoiseSizeX() const { + return logf(noiseSize[editedCategory].x / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); +} + void FadeJobConfig::setNoiseSizeY(float value) { noiseSize[editedCategory].y = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); emit dirty(); } +float FadeJobConfig::getNoiseSizeY() const { + return logf(noiseSize[editedCategory].y / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); +} + void FadeJobConfig::setNoiseSizeZ(float value) { noiseSize[editedCategory].z = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); emit dirty(); } +float FadeJobConfig::getNoiseSizeZ() const { + return logf(noiseSize[editedCategory].z / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); +} + void FadeJobConfig::setNoiseLevel(float value) { noiseLevel[editedCategory] = value; emit dirty(); @@ -152,6 +185,10 @@ void FadeJobConfig::setEdgeWidth(float value) { emit dirty(); } +float FadeJobConfig::getEdgeWidth() const { + return sqrtf(edgeWidth[editedCategory]); +} + void FadeJobConfig::setEdgeInnerColorR(float value) { edgeInnerColor[editedCategory].r = value; emit dirty(); @@ -205,7 +242,7 @@ void FadeConfigureJob::configure(const Config& config) { for (auto i = 0; i < FadeJobConfig::EVENT_CATEGORY_COUNT; i++) { auto& configuration = _configurations[i]; - _parameters->_durations[i] = config.duration[i]; + _parameters->_durations[i] = config._duration[i]; configuration._baseInvSizeAndLevel.x = 1.f / config.baseSize[i].x; configuration._baseInvSizeAndLevel.y = 1.f / config.baseSize[i].y; configuration._baseInvSizeAndLevel.z = 1.f / config.baseSize[i].z; diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index c3e82c6c5d..122449e08a 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -32,7 +32,7 @@ signals: class FadeJobConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(int editedCategory MEMBER editedCategory WRITE setEditedCategory NOTIFY dirty) + 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) @@ -69,37 +69,37 @@ public: void setEditedCategory(int value); void setDuration(float value); - float getDuration() const { return duration[editedCategory]; } + float getDuration() const; void setBaseSizeX(float value); - float getBaseSizeX() const { return baseSize[editedCategory].x; } + float getBaseSizeX() const; void setBaseSizeY(float value); - float getBaseSizeY() const { return baseSize[editedCategory].y; } + float getBaseSizeY() const; void setBaseSizeZ(float value); - float getBaseSizeZ() const { return baseSize[editedCategory].z; } + float getBaseSizeZ() const; void setBaseLevel(float value); float getBaseLevel() const { return baseLevel[editedCategory]; } void setBaseInverted(bool value); - bool isBaseInverted() const { return baseInverted[editedCategory]; } + bool isBaseInverted() const; void setNoiseSizeX(float value); - float getNoiseSizeX() const { return noiseSize[editedCategory].x; } + float getNoiseSizeX() const; void setNoiseSizeY(float value); - float getNoiseSizeY() const { return noiseSize[editedCategory].y; } + float getNoiseSizeY() const; void setNoiseSizeZ(float value); - float getNoiseSizeZ() const { return noiseSize[editedCategory].z; } + float getNoiseSizeZ() const; void setNoiseLevel(float value); float getNoiseLevel() const { return noiseLevel[editedCategory]; } void setEdgeWidth(float value); - float getEdgeWidth() const { return edgeWidth[editedCategory]; } + float getEdgeWidth() const; void setEdgeInnerColorR(float value); float getEdgeInnerColorR() const { return edgeInnerColor[editedCategory].r; } @@ -127,11 +127,11 @@ public: int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; glm::vec3 baseSize[EVENT_CATEGORY_COUNT]{ - { 0.35f, 0.35f, 0.35f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 0.35f, 0.35f, 0.35f }, // BUBBLE_ISECT_OWNER - { 0.35f, 0.35f, 0.35f }, // BUBBLE_ISECT_TRESPASSER - { 0.35f, 0.35f, 0.35f }, // USER_ENTER_LEAVE_DOMAIN - { 0.35f, 0.35f, 0.35f }, // AVATAR_CHANGE + { 0.4f, 0.4f, 0.4f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER + { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER + { 0.875f, 0.4f, 0.875f }, // USER_ENTER_LEAVE_DOMAIN + { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE }; float baseLevel[EVENT_CATEGORY_COUNT]{ 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN @@ -144,15 +144,15 @@ public: false, // ELEMENT_ENTER_LEAVE_DOMAIN false, // BUBBLE_ISECT_OWNER false, // BUBBLE_ISECT_TRESPASSER - false, // USER_ENTER_LEAVE_DOMAIN + true, // USER_ENTER_LEAVE_DOMAIN false, // AVATAR_CHANGE }; glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]{ - { 0.35f, 0.35f, 0.35f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 0.35f, 0.35f, 0.35f }, // BUBBLE_ISECT_OWNER - { 0.35f, 0.35f, 0.35f }, // BUBBLE_ISECT_TRESPASSER - { 0.35f, 0.35f, 0.35f }, // USER_ENTER_LEAVE_DOMAIN - { 0.35f, 0.35f, 0.35f }, // AVATAR_CHANGE + { 0.41f, 0.41f, 0.41f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER + { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER + { 0.4f, 0.4f, 0.4f }, // USER_ENTER_LEAVE_DOMAIN + { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE }; float noiseLevel[EVENT_CATEGORY_COUNT]{ 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN @@ -161,18 +161,18 @@ public: 1.0f, // USER_ENTER_LEAVE_DOMAIN 1.0f, // AVATAR_CHANGE }; - float duration[EVENT_CATEGORY_COUNT]{ - 5.0f, // ELEMENT_ENTER_LEAVE_DOMAIN + float _duration[EVENT_CATEGORY_COUNT]{ + 4.0f, // ELEMENT_ENTER_LEAVE_DOMAIN 0.0f, // BUBBLE_ISECT_OWNER 0.0f, // BUBBLE_ISECT_TRESPASSER 3.0f, // USER_ENTER_LEAVE_DOMAIN 3.0f, // AVATAR_CHANGE }; float edgeWidth[EVENT_CATEGORY_COUNT]{ - 0.05f, // ELEMENT_ENTER_LEAVE_DOMAIN - 0.05f, // BUBBLE_ISECT_OWNER - 0.05f, // BUBBLE_ISECT_TRESPASSER - 0.05f, // USER_ENTER_LEAVE_DOMAIN + 0.10f, // ELEMENT_ENTER_LEAVE_DOMAIN + 0.10f, // BUBBLE_ISECT_OWNER + 0.10f, // BUBBLE_ISECT_TRESPASSER + 0.10f, // USER_ENTER_LEAVE_DOMAIN 0.05f, // AVATAR_CHANGE }; glm::vec4 edgeInnerColor[EVENT_CATEGORY_COUNT]{ @@ -192,6 +192,7 @@ public: signals: void dirty(); + void dirtyCategory(); }; diff --git a/scripts/developer/utilities/render/configSlider/ConfigSlider.qml b/scripts/developer/utilities/render/configSlider/ConfigSlider.qml index 996cf4b34c..c1a6d6b7f3 100644 --- a/scripts/developer/utilities/render/configSlider/ConfigSlider.qml +++ b/scripts/developer/utilities/render/configSlider/ConfigSlider.qml @@ -38,6 +38,7 @@ Item { } Label { + id: labelValue text: sliderControl.value.toFixed(root.integral ? 0 : 2) anchors.left: root.left anchors.leftMargin: 200 diff --git a/scripts/developer/utilities/render/debugFade.js b/scripts/developer/utilities/render/debugFade.js index df18e0370a..6632cd8094 100644 --- a/scripts/developer/utilities/render/debugFade.js +++ b/scripts/developer/utilities/render/debugFade.js @@ -15,8 +15,7 @@ var window = new OverlayWindow({ title: 'Fade', source: qml, width: 500, - height: 900 + height: 900, }); window.setPosition(50, 50); window.closed.connect(function() { Script.stop(); }); -Render.getConfig("RenderMainView.DrawFadedOpaqueBounds").enabled = true \ No newline at end of file diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index 3aff96d7cd..9b6ef95837 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -23,220 +23,244 @@ Column { CheckBox { text: "Edit Fade" checked: root.switchConfig["editFade"] - onCheckedChanged: { root.switchConfig["editFade"] = checked } + onCheckedChanged: { + root.switchConfig["editFade"] = checked; + Render.getConfig("RenderMainView.DrawFadedOpaqueBounds").enabled = checked; + } } ComboBox { + id: categoryBox width: 400 model: ["Elements enter/leave domain", "Bubble isect. - Owner POV", "Bubble isect. - Trespasser POV", "Another user leaves/arrives", "Changing an avatar"] - onCurrentIndexChanged: { root.config["editedCategory"] = currentIndex } + Timer { + id: postpone + interval: 100; running: false; repeat: false + onTriggered: { paramWidgetLoader.sourceComponent = paramWidgets } + } + onCurrentIndexChanged: { + root.config["editedCategory"] = currentIndex; + // This is a hack to be sure the widgets below properly reflect the change of category: delete the Component + // by setting the loader source to Null and then recreate it 100ms later + paramWidgetLoader.sourceComponent = undefined; + postpone.start() + } } } - Column { - spacing: 8 - ConfigSlider { - label: "Duration" - integral: false - config: root.config - property: "duration" - max: 10.0 - min: 0.1 - width: 400 - } - GroupBox { - title: "Base Gradient" - width: 500 - Column { - spacing: 8 + Component { + id: paramWidgets - ConfigSlider { - label: "Size X" - integral: false - config: root.config - property: "baseSizeX" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Y" - integral: false - config: root.config - property: "baseSizeY" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Z" - integral: false - config: root.config - property: "baseSizeZ" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Level" - integral: false - config: root.config - property: "baseLevel" - max: 1.0 - min: 0.0 - width: 400 - } - CheckBox { - text: "Invert" - checked: root.config["baseInverted"] - onCheckedChanged: { root.config["baseInverted"] = checked } - } + Column { + spacing: 8 + + ConfigSlider { + label: "Duration" + integral: false + config: root.config + property: "duration" + max: 10.0 + min: 0.1 + width: 400 } - } - GroupBox { - title: "Noise Gradient" - width: 500 - Column { - spacing: 8 + GroupBox { + title: "Base Gradient" + width: 500 + Column { + spacing: 8 - ConfigSlider { - label: "Size X" - integral: false - config: root.config - property: "noiseSizeX" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Y" - integral: false - config: root.config - property: "noiseSizeY" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Z" - integral: false - config: root.config - property: "noiseSizeZ" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Level" - integral: false - config: root.config - property: "noiseLevel" - max: 1.0 - min: 0.0 - width: 400 - } - } - } - GroupBox { - title: "Edge" - width: 500 - Column { - spacing: 8 - - ConfigSlider { - label: "Width" - integral: false - config: root.config - property: "edgeWidth" - max: 1.0 - min: 0.0 - width: 400 - } - GroupBox { - title: "Inner color" - Column { - spacing: 8 - ConfigSlider { - label: "Color R" - integral: false - config: root.config - property: "edgeInnerColorR" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color G" - integral: false - config: root.config - property: "edgeInnerColorG" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color B" - integral: false - config: root.config - property: "edgeInnerColorB" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color intensity" - integral: false - config: root.config - property: "edgeInnerIntensity" - max: 5.0 - min: 0.0 - width: 400 - } + ConfigSlider { + label: "Size X" + integral: false + config: root.config + property: "baseSizeX" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Y" + integral: false + config: root.config + property: "baseSizeY" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Z" + integral: false + config: root.config + property: "baseSizeZ" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Level" + integral: false + config: root.config + property: "baseLevel" + max: 1.0 + min: 0.0 + width: 400 + } + CheckBox { + text: "Invert" + checked: root.config["baseInverted"] + onCheckedChanged: { root.config["baseInverted"] = checked } } } - GroupBox { - title: "Outer color" - Column { - spacing: 8 - ConfigSlider { - label: "Color R" - integral: false - config: root.config - property: "edgeOuterColorR" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color G" - integral: false - config: root.config - property: "edgeOuterColorG" - max: 1.0 - min: 0.0 - width: 400 + } + GroupBox { + title: "Noise Gradient" + width: 500 + Column { + spacing: 8 + + ConfigSlider { + label: "Size X" + integral: false + config: root.config + property: "noiseSizeX" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Y" + integral: false + config: root.config + property: "noiseSizeY" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Z" + integral: false + config: root.config + property: "noiseSizeZ" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Level" + integral: false + config: root.config + property: "noiseLevel" + max: 1.0 + min: 0.0 + width: 400 + } + } + } + GroupBox { + title: "Edge" + width: 500 + Column { + spacing: 8 + + ConfigSlider { + label: "Width" + integral: false + config: root.config + property: "edgeWidth" + max: 1.0 + min: 0.0 + width: 400 + } + GroupBox { + title: "Inner color" + Column { + spacing: 8 + ConfigSlider { + label: "Color R" + integral: false + config: root.config + property: "edgeInnerColorR" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color G" + integral: false + config: root.config + property: "edgeInnerColorG" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color B" + integral: false + config: root.config + property: "edgeInnerColorB" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color intensity" + integral: false + config: root.config + property: "edgeInnerIntensity" + max: 5.0 + min: 0.0 + width: 400 + } } - ConfigSlider { - label: "Color B" - integral: false - config: root.config - property: "edgeOuterColorB" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color intensity" - integral: false - config: root.config - property: "edgeOuterIntensity" - max: 5.0 - min: 0.0 - width: 400 + } + GroupBox { + title: "Outer color" + Column { + spacing: 8 + ConfigSlider { + label: "Color R" + integral: false + config: root.config + property: "edgeOuterColorR" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color G" + integral: false + config: root.config + property: "edgeOuterColorG" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color B" + integral: false + config: root.config + property: "edgeOuterColorB" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color intensity" + integral: false + config: root.config + property: "edgeOuterIntensity" + max: 5.0 + min: 0.0 + width: 400 + } } } } } } } + + Loader { + id: paramWidgetLoader + sourceComponent: paramWidgets + } } - From 87833abd31160a610f2e538916c654ae6b4a25ae Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 30 Jun 2017 16:46:25 +0200 Subject: [PATCH 24/86] Sky working again. --- libraries/render-utils/src/Fade.slh | 5 +- libraries/render-utils/src/FadeEffect.cpp | 138 ++++++++++++------ libraries/render-utils/src/FadeEffect.h | 53 +++---- .../render-utils/src/RenderDeferredTask.cpp | 52 +++---- .../render-utils/src/RenderForwardTask.cpp | 16 +- libraries/render/src/render/FilterTask.cpp | 2 +- .../src/render/RenderFetchCullSortTask.cpp | 2 +- .../src/render/RenderFetchCullSortTask.h | 4 +- libraries/render/src/task/Varying.h | 14 +- 9 files changed, 169 insertions(+), 117 deletions(-) diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 5ee7bb2178..e3a801ff8b 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -90,11 +90,10 @@ float evalFadeGradient(vec3 position) { } float evalFadeAlpha(vec3 position) { -/* float edgeWidth = fadeParameters[fadeCategory]._edgeWidthInvWidth.x; + float edgeWidth = fadeParameters[fadeCategory]._edgeWidthInvWidth.x; float cutoff = mix(-edgeWidth, 1.0+edgeWidth, fadeThreshold); - return evalFadeGradient(position)-cutoff;*/ - return evalFadeNoiseGradient(position)-fadeThreshold; + return evalFadeGradient(position)-cutoff; } void applyFadeClip(vec3 position) { diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 7c975ef201..82dc684d2f 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -6,24 +6,32 @@ #include #include -#define FADE_MIN_SCALE 0.001f -#define FADE_MAX_SCALE 100000.f +#define FADE_MIN_SCALE 0.001 +#define FADE_MAX_SCALE 10000.0 + +inline float parameterToValuePow(float parameter, const double minValue, const double maxOverMinValue) { + return (float)(minValue * pow(maxOverMinValue, parameter)); +} + +inline float valueToParameterPow(float value, const double minValue, const double maxOverMinValue) { + return (float)(log(value / minValue) / log(maxOverMinValue)); +} void FadeSwitchJob::configure(const Config& config) { _parameters->_isEditEnabled = config.editFade; } void FadeSwitchJob::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { - auto& normalOutputs = output.edit0(); + auto& normalOutputs = output.edit0().edit0(); auto& fadeOutputs = output.edit1(); // Only shapes are affected by fade at this time. - normalOutputs[RenderFetchCullSortTask::LIGHT] = input[RenderFetchCullSortTask::LIGHT]; - normalOutputs[RenderFetchCullSortTask::META] = input[RenderFetchCullSortTask::META]; - normalOutputs[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE] = input[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; - normalOutputs[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE] = input[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; - normalOutputs[RenderFetchCullSortTask::BACKGROUND] = input[RenderFetchCullSortTask::BACKGROUND]; - normalOutputs[RenderFetchCullSortTask::SPATIAL_SELECTION] = input[RenderFetchCullSortTask::SPATIAL_SELECTION]; + normalOutputs[RenderFetchCullSortTask::LIGHT].edit() = input.get0()[RenderFetchCullSortTask::LIGHT].get(); + normalOutputs[RenderFetchCullSortTask::META].edit() = input.get0()[RenderFetchCullSortTask::META].get(); + normalOutputs[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE].edit() = input.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE].get(); + normalOutputs[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE].edit() = input.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE].get(); + normalOutputs[RenderFetchCullSortTask::BACKGROUND].edit() = input.get0()[RenderFetchCullSortTask::BACKGROUND].get(); + output.edit0().edit1() = input.get1(); // Find the nearest item that intersects the view direction const render::Item* editedItem = nullptr; @@ -32,16 +40,20 @@ void FadeSwitchJob::run(const render::RenderContextPointer& renderContext, const float nearestTransparentDistance = std::numeric_limits::max(); const render::Item* nearestItem; - editedItem = findNearestItem(renderContext, input[RenderFetchCullSortTask::OPAQUE_SHAPE], nearestOpaqueDistance); - nearestItem = findNearestItem(renderContext, input[RenderFetchCullSortTask::TRANSPARENT_SHAPE], nearestTransparentDistance); + editedItem = findNearestItem(renderContext, input.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE], nearestOpaqueDistance); + nearestItem = findNearestItem(renderContext, input.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE], nearestTransparentDistance); if (nearestTransparentDistance < nearestOpaqueDistance) { editedItem = nearestItem; } + + if (editedItem) { + output.edit2() = editedItem->getBound(); + } } // Now, distribute items that need to be faded accross both outputs - distribute(renderContext, input[RenderFetchCullSortTask::OPAQUE_SHAPE], normalOutputs[RenderFetchCullSortTask::OPAQUE_SHAPE], fadeOutputs[OPAQUE_SHAPE], editedItem); - distribute(renderContext, input[RenderFetchCullSortTask::TRANSPARENT_SHAPE], normalOutputs[RenderFetchCullSortTask::TRANSPARENT_SHAPE], fadeOutputs[TRANSPARENT_SHAPE], editedItem); + distribute(renderContext, input.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE], normalOutputs[RenderFetchCullSortTask::OPAQUE_SHAPE], fadeOutputs[OPAQUE_SHAPE], editedItem); + distribute(renderContext, input.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE], normalOutputs[RenderFetchCullSortTask::TRANSPARENT_SHAPE], fadeOutputs[TRANSPARENT_SHAPE], editedItem); } const render::Item* FadeSwitchJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const { @@ -71,22 +83,21 @@ void FadeSwitchJob::distribute(const render::RenderContextPointer& renderContext render::Varying& normalOutput, render::Varying& fadeOutput, const render::Item* editedItem) const { auto& scene = renderContext->_scene; assert(_parameters); - const double fadeDuration = double(_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]) * USECS_PER_SECOND; const auto& inputItems = input.get(); // Clear previous values - normalOutput.template edit().clear(); - fadeOutput.template edit().clear(); + normalOutput.edit().clear(); + fadeOutput.edit().clear(); for (const auto& itemBound : inputItems) { auto& item = scene->getItem(itemBound.id); if (!item.mustFade() && &item!=editedItem) { // No need to fade - normalOutput.template edit().emplace_back(itemBound); + normalOutput.edit().emplace_back(itemBound); } else { - fadeOutput.template edit().emplace_back(itemBound); + fadeOutput.edit().emplace_back(itemBound); } } } @@ -108,30 +119,30 @@ float FadeJobConfig::getDuration() const { } void FadeJobConfig::setBaseSizeX(float value) { - baseSize[editedCategory].x = FADE_MIN_SCALE*powf(FADE_MAX_SCALE/ FADE_MIN_SCALE, value); + baseSize[editedCategory].x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE/ FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getBaseSizeX() const { - return logf(baseSize[editedCategory].x / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(baseSize[editedCategory].x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setBaseSizeY(float value) { - baseSize[editedCategory].y = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); + baseSize[editedCategory].y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getBaseSizeY() const { - return logf(baseSize[editedCategory].y / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(baseSize[editedCategory].y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setBaseSizeZ(float value) { - baseSize[editedCategory].z = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); + baseSize[editedCategory].z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getBaseSizeZ() const { - return logf(baseSize[editedCategory].z / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(baseSize[editedCategory].z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setBaseLevel(float value) { @@ -149,30 +160,30 @@ bool FadeJobConfig::isBaseInverted() const { } void FadeJobConfig::setNoiseSizeX(float value) { - noiseSize[editedCategory].x = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); + noiseSize[editedCategory].x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getNoiseSizeX() const { - return logf(noiseSize[editedCategory].x / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(noiseSize[editedCategory].x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setNoiseSizeY(float value) { - noiseSize[editedCategory].y = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); + noiseSize[editedCategory].y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getNoiseSizeY() const { - return logf(noiseSize[editedCategory].y / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(noiseSize[editedCategory].y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setNoiseSizeZ(float value) { - noiseSize[editedCategory].z = FADE_MIN_SCALE*powf(FADE_MAX_SCALE / FADE_MIN_SCALE, value); + noiseSize[editedCategory].z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getNoiseSizeZ() const { - return logf(noiseSize[editedCategory].z / FADE_MIN_SCALE) / logf(FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(noiseSize[editedCategory].z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setNoiseLevel(float value) { @@ -251,7 +262,7 @@ void FadeConfigureJob::configure(const Config& config) { configuration._noiseInvSizeAndLevel.y = 1.f / config.noiseSize[i].y; configuration._noiseInvSizeAndLevel.z = 1.f / config.noiseSize[i].z; configuration._noiseInvSizeAndLevel.w = config.noiseLevel[i]; - configuration._invertBase = config.baseInverted[i]; + configuration._invertBase = config.baseInverted[i] & 1; configuration._edgeWidthInvWidth.x = config.edgeWidth[i]; configuration._edgeWidthInvWidth.y = 1.f / configuration._edgeWidthInvWidth.x; configuration._innerEdgeColor = config.edgeInnerColor[i]; @@ -260,10 +271,13 @@ void FadeConfigureJob::configure(const Config& config) { _isBufferDirty = true; } -void FadeConfigureJob::run(const render::RenderContextPointer& renderContext, Output& output) { - if (_isBufferDirty) { +void FadeConfigureJob::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { + if (_isBufferDirty || _parameters->_isEditEnabled) { 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; + } _isBufferDirty = false; } output.edit0() = _fadeMaskMap; @@ -290,14 +304,6 @@ void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const defaultKeyBuilder.withFade(); - // Update interactive edit effect - if (_parameters->_isEditEnabled) { - updateFadeEdit(); - } - else { - _editStartTime = 0; - } - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -306,6 +312,14 @@ void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const _currentFadeMaskMap = fadeMaskMap; _currentFadeBuffer = &fadeParamBuffer; + // Update interactive edit effect + if (_parameters->_isEditEnabled) { + updateFadeEdit(inItems.front()); + } + else { + _editStartTime = 0; + } + // Setup camera, projection and viewport for all items batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); @@ -365,18 +379,18 @@ float FadeRenderJob::computeFadePercent(quint64 startTime) { return _currentInstance->computeElementEnterThreshold(time); } -void FadeRenderJob::updateFadeEdit() { +void FadeRenderJob::updateFadeEdit(const render::ItemBound& itemBounds) { if (_editStartTime == 0) { _editStartTime = usecTimestampNow(); } const double time = (int64_t(usecTimestampNow()) - int64_t(_editStartTime)) / double(USECS_PER_SECOND); + const float eventDuration = _parameters->_durations[_parameters->_editedCategory]; switch (_parameters->_editedCategory) { case FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN: { const double waitTime = 0.5; // Wait between fade in and out - const float eventDuration = _parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]; double cycleTime = fmod(time, (eventDuration+waitTime) * 2.0); if (cycleTime < eventDuration) { @@ -401,7 +415,35 @@ void FadeRenderJob::updateFadeEdit() { break; case FadeJobConfig::USER_ENTER_LEAVE_DOMAIN: - break; + { + 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.y = 0.f; + _editNoiseOffset.z = time*0.75; + + _editBaseOffset.x = 0.f; + _editBaseOffset.y = -itemBounds.bound.getDimensions().y; + _editBaseOffset.z = 0.f; + { + + } + + if (cycleTime < eventDuration) { + _editThreshold = 1.f - computeElementEnterThreshold(cycleTime); + } + else if (cycleTime < (eventDuration + waitTime)) { + _editThreshold = 0.f; + } + else if (cycleTime < (2 * eventDuration + waitTime)) { + _editThreshold = computeElementEnterThreshold(cycleTime - (eventDuration + waitTime)); + } + else { + _editThreshold = 1.f; + } + } + break; case FadeJobConfig::AVATAR_CHANGE: break; @@ -443,6 +485,8 @@ bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline if (fadeNoiseOffsetLocation >= 0 || fadeBaseOffsetLocation>=0 || fadeThresholdLocation >= 0 || fadeCategoryLocation>=0) { float threshold; int eventCategory = FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN; + glm::vec3 noiseOffset = offset; + glm::vec3 baseOffset = offset; threshold = 1.f-computeFadePercent(startTime); @@ -451,14 +495,16 @@ bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline if (_currentInstance->_parameters->_isEditEnabled) { eventCategory = _currentInstance->_parameters->_editedCategory; threshold = _currentInstance->_editThreshold; + noiseOffset += _currentInstance->_editNoiseOffset; + baseOffset += _currentInstance->_editBaseOffset; } batch._glUniform1i(fadeCategoryLocation, eventCategory); batch._glUniform1f(fadeThresholdLocation, threshold); // This is really temporary - batch._glUniform3f(fadeNoiseOffsetLocation, offset.x, offset.y, offset.z); + batch._glUniform3f(fadeNoiseOffsetLocation, noiseOffset.x, noiseOffset.y, noiseOffset.z); // This is really temporary - batch._glUniform3f(fadeBaseOffsetLocation, offset.x, offset.y, offset.z); + batch._glUniform3f(fadeBaseOffsetLocation, baseOffset.x, baseOffset.y, baseOffset.z); return threshold > 0.f; } diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 122449e08a..dce5687151 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -126,15 +126,29 @@ public: float getEdgeOuterIntensity() const { return edgeOuterColor[editedCategory].a; } int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; - glm::vec3 baseSize[EVENT_CATEGORY_COUNT]{ - { 0.4f, 0.4f, 0.4f }, // ELEMENT_ENTER_LEAVE_DOMAIN + glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]{ + { 1.f, 1.f, 1.f }, // ELEMENT_ENTER_LEAVE_DOMAIN { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER - { 0.875f, 0.4f, 0.875f }, // USER_ENTER_LEAVE_DOMAIN + { 10.f, 0.01f, 10.0f }, // USER_ENTER_LEAVE_DOMAIN + { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE + }; + float noiseLevel[EVENT_CATEGORY_COUNT]{ + 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN + 1.0f, // BUBBLE_ISECT_OWNER + 1.0f, // BUBBLE_ISECT_TRESPASSER + 0.70f, // USER_ENTER_LEAVE_DOMAIN + 1.0f, // AVATAR_CHANGE + }; + glm::vec3 baseSize[EVENT_CATEGORY_COUNT]{ + { 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER + { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER + { 10000.f, 1.0f, 10000.0f }, // USER_ENTER_LEAVE_DOMAIN { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE }; float baseLevel[EVENT_CATEGORY_COUNT]{ - 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN + 0.0f, // ELEMENT_ENTER_LEAVE_DOMAIN 1.0f, // BUBBLE_ISECT_OWNER 1.0f, // BUBBLE_ISECT_TRESPASSER 1.0f, // USER_ENTER_LEAVE_DOMAIN @@ -147,20 +161,6 @@ public: true, // USER_ENTER_LEAVE_DOMAIN false, // AVATAR_CHANGE }; - glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]{ - { 0.41f, 0.41f, 0.41f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER - { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER - { 0.4f, 0.4f, 0.4f }, // USER_ENTER_LEAVE_DOMAIN - { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE - }; - float noiseLevel[EVENT_CATEGORY_COUNT]{ - 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN - 1.0f, // BUBBLE_ISECT_OWNER - 1.0f, // BUBBLE_ISECT_TRESPASSER - 1.0f, // USER_ENTER_LEAVE_DOMAIN - 1.0f, // AVATAR_CHANGE - }; float _duration[EVENT_CATEGORY_COUNT]{ 4.0f, // ELEMENT_ENTER_LEAVE_DOMAIN 0.0f, // BUBBLE_ISECT_OWNER @@ -172,21 +172,21 @@ public: 0.10f, // ELEMENT_ENTER_LEAVE_DOMAIN 0.10f, // BUBBLE_ISECT_OWNER 0.10f, // BUBBLE_ISECT_TRESPASSER - 0.10f, // USER_ENTER_LEAVE_DOMAIN + 0.529f, // USER_ENTER_LEAVE_DOMAIN 0.05f, // AVATAR_CHANGE }; glm::vec4 edgeInnerColor[EVENT_CATEGORY_COUNT]{ { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER - { 1.0f, 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN + { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }, // USER_ENTER_LEAVE_DOMAIN { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE }; glm::vec4 edgeOuterColor[EVENT_CATEGORY_COUNT]{ { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER - { 1.0f, 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN + { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE }; @@ -224,7 +224,7 @@ public: using FadeOutput = render::VaryingArray; using Input = RenderFetchCullSortTask::Output; - using Output = render::VaryingSet2; + using Output = render::VaryingSet3 < RenderFetchCullSortTask::Output, FadeOutput, render::Item::Bound > ; using Config = FadeSwitchJobConfig; using JobModel = render::Job::ModelIO; @@ -263,16 +263,17 @@ class FadeConfigureJob { public: using UniformBuffer = gpu::StructBuffer; + using Input = render::Item::Bound ; using Output = render::VaryingSet2; using Config = FadeJobConfig; - using JobModel = render::Job::ModelO; + using JobModel = render::Job::ModelIO; FadeConfigureJob(FadeCommonParameters::Pointer commonParams); const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; } void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext, Output& output); + void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); private: @@ -316,8 +317,10 @@ private: // Everything needed for interactive edition uint64_t _editStartTime{ 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(); + void updateFadeEdit(const render::ItemBound& itemBounds); }; #endif // hifi_FadeEffect_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ca7f4a10d9..aa62038bb6 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -55,24 +55,26 @@ void RenderDeferredTask::configure(const Config& config) void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { auto commonFadeParameters = std::make_shared(); const auto fadeSwitchOutputs = task.addJob("FadeSwitch", input, commonFadeParameters).get(); - const auto fadeConfigureOutputs = task.addJob("FadeConfigure", commonFadeParameters).get(); const auto& items = fadeSwitchOutputs.get0(); const auto& fadeItems = fadeSwitchOutputs.get1(); + const auto& fadeEditedItem = fadeSwitchOutputs[2]; + + const auto fadeConfigureOutputs = task.addJob("FadeConfigure", fadeEditedItem, commonFadeParameters).get(); // Prepare the ShapePipelines ShapePlumberPointer shapePlumber = std::make_shared(); initDeferredPipelines(*shapePlumber); // Extract opaques / transparents / lights / metas / overlays / background - const auto opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE]; - const auto transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; - const auto lights = items[RenderFetchCullSortTask::LIGHT]; - const auto metas = items[RenderFetchCullSortTask::META]; - const auto overlayOpaques = items[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; - const auto overlayTransparents = items[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; - const auto background = items[RenderFetchCullSortTask::BACKGROUND]; - const auto spatialSelection = items[RenderFetchCullSortTask::SPATIAL_SELECTION]; + const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE]; + const auto& transparents = items.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; + const auto& lights = items.get0()[RenderFetchCullSortTask::LIGHT]; + const auto& metas = items.get0()[RenderFetchCullSortTask::META]; + const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; + const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; + const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND]; + const auto& spatialSelection = items[1]; // Filter the non antialiaased overlays const int LAYER_NO_AA = 3; @@ -87,7 +89,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto opaqueRangeTimer = task.addJob("BeginOpaqueRangeTimer", "DrawOpaques"); - const auto prepareDeferredInputs = PrepareDeferred::Inputs(primaryFramebuffer, lightingModel).hasVarying(); + const auto prepareDeferredInputs = PrepareDeferred::Inputs(primaryFramebuffer, lightingModel).asVarying(); const auto prepareDeferredOutputs = task.addJob("PrepareDeferred", prepareDeferredInputs); const auto deferredFramebuffer = prepareDeferredOutputs.getN(0); const auto lightingFramebuffer = prepareDeferredOutputs.getN(1); @@ -96,11 +98,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("PrepareStencil", primaryFramebuffer); // Render opaque objects in DeferredBuffer - const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying(); + const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).asVarying(); task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber); const auto fadeOpaques = fadeItems[FadeSwitchJob::OPAQUE_SHAPE]; - const auto fadeOpaqueInputs = FadeRenderJob::Input(fadeOpaques, lightingModel, fadeConfigureOutputs).hasVarying(); + const auto fadeOpaqueInputs = FadeRenderJob::Input(fadeOpaques, lightingModel, fadeConfigureOutputs).asVarying(); task.addJob("DrawFadeOpaque", fadeOpaqueInputs, commonFadeParameters, shapePlumber); @@ -110,12 +112,12 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Opaque all rendered // Linear Depth Pass - const auto linearDepthPassInputs = LinearDepthPass::Inputs(deferredFrameTransform, deferredFramebuffer).hasVarying(); + const auto linearDepthPassInputs = LinearDepthPass::Inputs(deferredFrameTransform, deferredFramebuffer).asVarying(); const auto linearDepthPassOutputs = task.addJob("LinearDepth", linearDepthPassInputs); const auto linearDepthTarget = linearDepthPassOutputs.getN(0); // Curvature pass - const auto surfaceGeometryPassInputs = SurfaceGeometryPass::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget).hasVarying(); + const auto surfaceGeometryPassInputs = SurfaceGeometryPass::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget).asVarying(); const auto surfaceGeometryPassOutputs = task.addJob("SurfaceGeometry", surfaceGeometryPassInputs); const auto surfaceGeometryFramebuffer = surfaceGeometryPassOutputs.getN(0); const auto curvatureFramebuffer = surfaceGeometryPassOutputs.getN(1); @@ -126,7 +128,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto scatteringResource = task.addJob("Scattering"); // AO job - const auto ambientOcclusionInputs = AmbientOcclusionEffect::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget).hasVarying(); + const auto ambientOcclusionInputs = AmbientOcclusionEffect::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget).asVarying(); const auto ambientOcclusionOutputs = task.addJob("AmbientOcclusion", ambientOcclusionInputs); const auto ambientOcclusionFramebuffer = ambientOcclusionOutputs.getN(0); const auto ambientOcclusionUniforms = ambientOcclusionOutputs.getN(1); @@ -140,13 +142,13 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Light Clustering // Create the cluster grid of lights, cpu job for now - const auto lightClusteringPassInputs = LightClusteringPass::Inputs(deferredFrameTransform, lightingModel, linearDepthTarget).hasVarying(); + const auto lightClusteringPassInputs = LightClusteringPass::Inputs(deferredFrameTransform, lightingModel, linearDepthTarget).asVarying(); const auto lightClusters = task.addJob("LightClustering", lightClusteringPassInputs); // DeferredBuffer is complete, now let's shade it into the LightingBuffer const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, - surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters).hasVarying(); + surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters).asVarying(); task.addJob("RenderDeferred", deferredLightingInputs); @@ -154,16 +156,16 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawBackgroundDeferred", lightingModel); // Render transparent objects forward in LightingBuffer - const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying(); + const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).asVarying(); task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); const auto fadeTransparents = fadeItems[FadeSwitchJob::TRANSPARENT_SHAPE]; - const auto fadeTransparentInputs = FadeRenderJob::Input(fadeTransparents, lightingModel, fadeConfigureOutputs).hasVarying(); + const auto fadeTransparentInputs = FadeRenderJob::Input(fadeTransparents, lightingModel, fadeConfigureOutputs).asVarying(); task.addJob("DrawFadeTransparent", fadeTransparentInputs, commonFadeParameters, shapePlumber); // LIght Cluster Grid Debuging job { - const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).hasVarying(); + const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).asVarying(); task.addJob("DebugLightClusters", debugLightClustersInputs); } @@ -184,8 +186,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren } // Overlays - const auto overlayOpaquesInputs = DrawOverlay3D::Inputs(overlayOpaques, lightingModel).hasVarying(); - const auto overlayTransparentsInputs = DrawOverlay3D::Inputs(overlayTransparents, lightingModel).hasVarying(); + const auto overlayOpaquesInputs = DrawOverlay3D::Inputs(overlayOpaques, lightingModel).asVarying(); + const auto overlayTransparentsInputs = DrawOverlay3D::Inputs(overlayTransparents, lightingModel).asVarying(); task.addJob("DrawOverlay3DOpaque", overlayOpaquesInputs, true); task.addJob("DrawOverlay3DTransparent", overlayTransparentsInputs, false); @@ -201,10 +203,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DebugDeferredBuffer", debugFramebuffers); const auto debugSubsurfaceScatteringInputs = DebugSubsurfaceScattering::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, - surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource).hasVarying(); + surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource).asVarying(); task.addJob("DebugScattering", debugSubsurfaceScatteringInputs); - const auto debugAmbientOcclusionInputs = DebugAmbientOcclusion::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget, ambientOcclusionUniforms).hasVarying(); + const auto debugAmbientOcclusionInputs = DebugAmbientOcclusion::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget, ambientOcclusionUniforms).asVarying(); task.addJob("DebugAmbientOcclusion", debugAmbientOcclusionInputs); // Scene Octree Debugging job @@ -229,7 +231,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("Antialiasing", primaryFramebuffer); // Draw 2DWeb non AA - const auto nonAAOverlaysInputs = DrawOverlay3D::Inputs(nonAAOverlays, lightingModel).hasVarying(); + const auto nonAAOverlaysInputs = DrawOverlay3D::Inputs(nonAAOverlays, lightingModel).asVarying(); task.addJob("Draw2DWebSurfaces", nonAAOverlaysInputs, false); task.addJob("ToneAndPostRangeTimer", toneAndPostRangeTimer); diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index a77d741aa5..ef9cfe8613 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -36,14 +36,14 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend initForwardPipelines(*shapePlumber); // Extract opaques / transparents / lights / metas / overlays / background - const auto opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE]; - const auto transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; - const auto lights = items[RenderFetchCullSortTask::LIGHT]; - const auto metas = items[RenderFetchCullSortTask::META]; - const auto overlayOpaques = items[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; - const auto overlayTransparents = items[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; - const auto background = items[RenderFetchCullSortTask::BACKGROUND]; - const auto spatialSelection = items[RenderFetchCullSortTask::SPATIAL_SELECTION]; + const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE]; + const auto& transparents = items.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; + const auto& lights = items.get0()[RenderFetchCullSortTask::LIGHT]; + const auto& metas = items.get0()[RenderFetchCullSortTask::META]; + const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; + const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; + const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND]; + const auto& spatialSelection = items[1]; const auto framebuffer = task.addJob("PrepareFramebuffer"); diff --git a/libraries/render/src/render/FilterTask.cpp b/libraries/render/src/render/FilterTask.cpp index f6b765cd9d..19953f3399 100644 --- a/libraries/render/src/render/FilterTask.cpp +++ b/libraries/render/src/render/FilterTask.cpp @@ -28,7 +28,7 @@ void FilterLayeredItems::run(const RenderContextPointer& renderContext, const It outItems.clear(); // For each item, filter it into one bucket - for (auto itemBound : inItems) { + for (auto& itemBound : inItems) { auto& item = scene->getItem(itemBound.id); if (item.getLayer() == _keepLayer) { outItems.emplace_back(itemBound); diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index 6e5d723ce6..b9f65f48a0 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -65,5 +65,5 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const auto overlayTransparents = task.addJob("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET]; - output = Output{opaques, transparents, lights, metas, overlayOpaques, overlayTransparents, background, spatialSelection}; + output = Output(BucketList{ opaques, transparents, lights, metas, overlayOpaques, overlayTransparents, background }, spatialSelection); } diff --git a/libraries/render/src/render/RenderFetchCullSortTask.h b/libraries/render/src/render/RenderFetchCullSortTask.h index f3f326aae8..b25480ae3a 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.h +++ b/libraries/render/src/render/RenderFetchCullSortTask.h @@ -26,12 +26,12 @@ public: OVERLAY_OPAQUE_SHAPE, OVERLAY_TRANSPARENT_SHAPE, BACKGROUND, - SPATIAL_SELECTION, NUM_BUCKETS }; - using Output = render::VaryingArray; + using BucketList = render::VaryingArray; + using Output = render::VaryingSet2; using JobModel = render::Task::ModelO; RenderFetchCullSortTask() {} diff --git a/libraries/render/src/task/Varying.h b/libraries/render/src/task/Varying.h index d5021383fb..c9eb78fd71 100644 --- a/libraries/render/src/task/Varying.h +++ b/libraries/render/src/task/Varying.h @@ -40,6 +40,8 @@ public: template Varying getN (uint8_t index) const { return get()[index]; } template Varying editN (uint8_t index) { return edit()[index]; } + bool isNull() const { return _concept == nullptr; } + protected: class Concept { public: @@ -93,7 +95,7 @@ public: } virtual uint8_t length() const { return 2; } - Varying hasVarying() const { return Varying((*this)); } + Varying asVarying() const { return Varying((*this)); } }; @@ -126,7 +128,7 @@ public: } virtual uint8_t length() const { return 3; } - Varying hasVarying() const { return Varying((*this)); } + Varying asVarying() const { return Varying((*this)); } }; template @@ -163,7 +165,7 @@ public: } virtual uint8_t length() const { return 4; } - Varying hasVarying() const { return Varying((*this)); } + Varying asVarying() const { return Varying((*this)); } }; @@ -206,7 +208,7 @@ public: } virtual uint8_t length() const { return 5; } - Varying hasVarying() const { return Varying((*this)); } + Varying asVarying() const { return Varying((*this)); } }; template @@ -236,7 +238,7 @@ public: const T5& get5() const { return std::get<5>((*this)).template get(); } T5& edit5() { return std::get<5>((*this)).template edit(); } - Varying hasVarying() const { return Varying((*this)); } + Varying asVarying() const { return Varying((*this)); } }; template @@ -269,7 +271,7 @@ public: const T6& get6() const { return std::get<6>((*this)).template get(); } T6& edit6() { return std::get<6>((*this)).template edit(); } - Varying hasVarying() const { return Varying((*this)); } + Varying asVarying() const { return Varying((*this)); } }; From af7957491b21507b11c8914b70d2ce5f3f0a595e Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 3 Jul 2017 12:40:58 +0200 Subject: [PATCH 25/86] 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 From 3fddac9f6e6b4b4f3d715f5463f7661c48f8d260 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 3 Jul 2017 16:12:23 +0200 Subject: [PATCH 26/86] Fixed compilation errors with array initializations --- libraries/render-utils/src/FadeEffect.cpp | 80 +++++++++++++++++++++ libraries/render-utils/src/FadeEffect.h | 84 ++++------------------- 2 files changed, 94 insertions(+), 70 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 64c2fedfc6..ab104bc531 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -102,6 +102,86 @@ void FadeSwitchJob::distribute(const render::RenderContextPointer& renderContext } } +FadeCommonParameters::FadeCommonParameters() : + _durations{ + 30.0f, // ELEMENT_ENTER_LEAVE_DOMAIN + 0.0f, // BUBBLE_ISECT_OWNER + 0.0f, // BUBBLE_ISECT_TRESPASSER + 3.0f, // USER_ENTER_LEAVE_DOMAIN + 3.0f, // AVATAR_CHANGE + } +{ + +} + +FadeJobConfig::FadeJobConfig() : + noiseSize{ + { 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 + { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE + }, + noiseLevel{ + 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN + 1.0f, // BUBBLE_ISECT_OWNER + 1.0f, // BUBBLE_ISECT_TRESPASSER + 0.70f, // USER_ENTER_LEAVE_DOMAIN + 1.0f, // AVATAR_CHANGE + }, + baseSize{ + { 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER + { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER + { 10000.f, 1.0f, 10000.0f }, // USER_ENTER_LEAVE_DOMAIN + { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE + }, + baseLevel{ + 0.0f, // ELEMENT_ENTER_LEAVE_DOMAIN + 1.0f, // BUBBLE_ISECT_OWNER + 1.0f, // BUBBLE_ISECT_TRESPASSER + 1.0f, // USER_ENTER_LEAVE_DOMAIN + 1.0f, // AVATAR_CHANGE + }, + baseInverted{ + false, // ELEMENT_ENTER_LEAVE_DOMAIN + false, // BUBBLE_ISECT_OWNER + false, // BUBBLE_ISECT_TRESPASSER + true, // USER_ENTER_LEAVE_DOMAIN + false, // AVATAR_CHANGE + }, + _duration{ + 4.0f, // ELEMENT_ENTER_LEAVE_DOMAIN + 0.0f, // BUBBLE_ISECT_OWNER + 0.0f, // BUBBLE_ISECT_TRESPASSER + 3.0f, // USER_ENTER_LEAVE_DOMAIN + 3.0f, // AVATAR_CHANGE + }, + edgeWidth{ + 0.10f, // ELEMENT_ENTER_LEAVE_DOMAIN + 0.10f, // BUBBLE_ISECT_OWNER + 0.10f, // BUBBLE_ISECT_TRESPASSER + 0.529f, // USER_ENTER_LEAVE_DOMAIN + 0.05f, // AVATAR_CHANGE + }, + edgeInnerColor{ + { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER + { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER + { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }, // USER_ENTER_LEAVE_DOMAIN + { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE + }, + edgeOuterColor{ + { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN + { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER + { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER + { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN + { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE + } +{ + +} + void FadeJobConfig::setEditedCategory(int value) { assert(value < EVENT_CATEGORY_COUNT); editedCategory = std::min(EVENT_CATEGORY_COUNT, value); diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index a441ce831d..c3a41187e1 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -68,6 +68,8 @@ public: EVENT_CATEGORY_COUNT }; + FadeJobConfig(); + void setEditedCategory(int value); void setDuration(float value); @@ -130,69 +132,15 @@ public: bool manualFade{ false }; float manualThreshold{ 0.f }; int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; - glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]{ - { 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 - { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE - }; - float noiseLevel[EVENT_CATEGORY_COUNT]{ - 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN - 1.0f, // BUBBLE_ISECT_OWNER - 1.0f, // BUBBLE_ISECT_TRESPASSER - 0.70f, // USER_ENTER_LEAVE_DOMAIN - 1.0f, // AVATAR_CHANGE - }; - glm::vec3 baseSize[EVENT_CATEGORY_COUNT]{ - { 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER - { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER - { 10000.f, 1.0f, 10000.0f }, // USER_ENTER_LEAVE_DOMAIN - { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE - }; - float baseLevel[EVENT_CATEGORY_COUNT]{ - 0.0f, // ELEMENT_ENTER_LEAVE_DOMAIN - 1.0f, // BUBBLE_ISECT_OWNER - 1.0f, // BUBBLE_ISECT_TRESPASSER - 1.0f, // USER_ENTER_LEAVE_DOMAIN - 1.0f, // AVATAR_CHANGE - }; - bool baseInverted[EVENT_CATEGORY_COUNT]{ - false, // ELEMENT_ENTER_LEAVE_DOMAIN - false, // BUBBLE_ISECT_OWNER - false, // BUBBLE_ISECT_TRESPASSER - true, // USER_ENTER_LEAVE_DOMAIN - false, // AVATAR_CHANGE - }; - float _duration[EVENT_CATEGORY_COUNT]{ - 4.0f, // ELEMENT_ENTER_LEAVE_DOMAIN - 0.0f, // BUBBLE_ISECT_OWNER - 0.0f, // BUBBLE_ISECT_TRESPASSER - 3.0f, // USER_ENTER_LEAVE_DOMAIN - 3.0f, // AVATAR_CHANGE - }; - float edgeWidth[EVENT_CATEGORY_COUNT]{ - 0.10f, // ELEMENT_ENTER_LEAVE_DOMAIN - 0.10f, // BUBBLE_ISECT_OWNER - 0.10f, // BUBBLE_ISECT_TRESPASSER - 0.529f, // USER_ENTER_LEAVE_DOMAIN - 0.05f, // AVATAR_CHANGE - }; - glm::vec4 edgeInnerColor[EVENT_CATEGORY_COUNT]{ - { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER - { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER - { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }, // USER_ENTER_LEAVE_DOMAIN - { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE - }; - glm::vec4 edgeOuterColor[EVENT_CATEGORY_COUNT]{ - { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER - { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER - { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN - { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE - }; + glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]; + float noiseLevel[EVENT_CATEGORY_COUNT]; + glm::vec3 baseSize[EVENT_CATEGORY_COUNT]; + float baseLevel[EVENT_CATEGORY_COUNT]; + bool baseInverted[EVENT_CATEGORY_COUNT]; + float _duration[EVENT_CATEGORY_COUNT]; + float edgeWidth[EVENT_CATEGORY_COUNT]; + glm::vec4 edgeInnerColor[EVENT_CATEGORY_COUNT]; + glm::vec4 edgeOuterColor[EVENT_CATEGORY_COUNT]; signals: void dirty(); @@ -204,18 +152,14 @@ struct FadeCommonParameters { using Pointer = std::shared_ptr; + FadeCommonParameters(); + 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 - 0.0f, // BUBBLE_ISECT_OWNER - 0.0f, // BUBBLE_ISECT_TRESPASSER - 3.0f, // USER_ENTER_LEAVE_DOMAIN - 3.0f, // AVATAR_CHANGE - }; + float _durations[FadeJobConfig::EVENT_CATEGORY_COUNT]; }; class FadeSwitchJob { From 0d1d262db45be23f3d0888d5a8913eeb54e79442 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 3 Jul 2017 16:28:00 +0200 Subject: [PATCH 27/86] Working on bubble intersections --- libraries/render-utils/src/Fade.slh | 2 +- libraries/render-utils/src/FadeEffect.cpp | 80 +++++++++++------------ 2 files changed, 39 insertions(+), 43 deletions(-) diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index cc79c26f07..f539d90217 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -73,7 +73,7 @@ float evalFadeNoiseGradient(vec3 position) { float evalFadeBaseGradient(vec3 position) { float gradient = length((position - fadeBaseOffset) * fadeParameters[fadeCategory]._baseInvSizeAndLevel.xyz); - gradient = mod(gradient, 1.0)-0.5; // Center on value 0.5 + gradient = gradient-0.5; // Center on value 0.5 gradient *= fadeParameters[fadeCategory]._baseInvSizeAndLevel.w; return gradient; } diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index ab104bc531..5e95297644 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -65,10 +65,10 @@ const render::Item* FadeSwitchJob::findNearestItem(const render::RenderContextPo glm::vec3 normal; float isectDistance; const render::Item* nearestItem = nullptr; - const float minDistance = 5.f; + const float minDistance = 2.f; for (const auto& itemBound : inputItems) { - if (itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { + if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { if (isectDistance>minDistance && isectDistance < minIsectDistance) { auto& item = scene->getItem(itemBound.id); nearestItem = &item; @@ -117,7 +117,7 @@ FadeCommonParameters::FadeCommonParameters() : FadeJobConfig::FadeJobConfig() : noiseSize{ { 0.75f, 0.75f, 0.75f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER + { 1.0f, 1.0f/15.f, 1.0f }, // BUBBLE_ISECT_OWNER { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER { 10.f, 0.01f, 10.0f }, // USER_ENTER_LEAVE_DOMAIN { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE @@ -131,8 +131,8 @@ FadeJobConfig::FadeJobConfig() : }, baseSize{ { 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER - { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER + { 2.0f, 2.0f, 2.0f }, // BUBBLE_ISECT_OWNER + { 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER { 10000.f, 1.0f, 10000.0f }, // USER_ENTER_LEAVE_DOMAIN { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE }, @@ -159,22 +159,22 @@ FadeJobConfig::FadeJobConfig() : }, edgeWidth{ 0.10f, // ELEMENT_ENTER_LEAVE_DOMAIN - 0.10f, // BUBBLE_ISECT_OWNER - 0.10f, // BUBBLE_ISECT_TRESPASSER + 0.08f, // BUBBLE_ISECT_OWNER + 0.08f, // BUBBLE_ISECT_TRESPASSER 0.529f, // USER_ENTER_LEAVE_DOMAIN 0.05f, // AVATAR_CHANGE }, edgeInnerColor{ { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER - { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER + { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_TRESPASSER { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }, // USER_ENTER_LEAVE_DOMAIN { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE }, edgeOuterColor{ { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER - { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER + { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }, // BUBBLE_ISECT_OWNER + { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }, // BUBBLE_ISECT_TRESPASSER { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE } @@ -479,51 +479,47 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon _editTime += deltaTime; _editPreviousTime = now; + if (cycleTime < eventDuration) { + _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), eventDuration); + } + else { + _editThreshold = 1.f; + } + switch (_parameters->_editedCategory) { case FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN: - { - if (cycleTime < eventDuration) { - _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), eventDuration); - } - else { - _editThreshold = 1.f; - } - } - break; + break; case FadeJobConfig::BUBBLE_ISECT_OWNER: - break; + { + const glm::vec3 cameraPos = renderContext->args->getViewFrustum().getPosition(); + const glm::vec3 delta = itemBounds.bound.calcCenter() - cameraPos; + + _editNoiseOffset.x = _editTime*0.1f; + _editNoiseOffset.y = _editTime*2.5f; + _editNoiseOffset.z = _editTime*0.1f; + + _editBaseOffset = cameraPos + delta*_editThreshold; + _editThreshold = 0.33f; + } + break; case FadeJobConfig::BUBBLE_ISECT_TRESPASSER: break; case FadeJobConfig::USER_ENTER_LEAVE_DOMAIN: { - _editNoiseOffset.x = _editTime*0.5; + _editNoiseOffset.x = _editTime*0.5f; _editNoiseOffset.y = 0.f; - _editNoiseOffset.z = _editTime*0.75; + _editNoiseOffset.z = _editTime*0.75f; _editBaseOffset = itemBounds.bound.calcCenter(); - _editBaseOffset.y -= itemBounds.bound.getDimensions().y/2.f; - - if (cycleTime < eventDuration) { - _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), eventDuration); - } - else { - _editThreshold = 1.f; - } } break; From ec1cf9dc5068e22918db26e23e8deb73e4bfeac5 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 3 Jul 2017 16:42:27 +0200 Subject: [PATCH 28/86] Changed array initialization to old style C --- libraries/render-utils/src/FadeEffect.cpp | 132 ++++++++++------------ 1 file changed, 59 insertions(+), 73 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index ab104bc531..836c56079c 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -102,84 +102,70 @@ void FadeSwitchJob::distribute(const render::RenderContextPointer& renderContext } } -FadeCommonParameters::FadeCommonParameters() : - _durations{ - 30.0f, // ELEMENT_ENTER_LEAVE_DOMAIN - 0.0f, // BUBBLE_ISECT_OWNER - 0.0f, // BUBBLE_ISECT_TRESPASSER - 3.0f, // USER_ENTER_LEAVE_DOMAIN - 3.0f, // AVATAR_CHANGE - } +FadeCommonParameters::FadeCommonParameters() { - + _durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 0.f; + _durations[FadeJobConfig::BUBBLE_ISECT_OWNER] = 0.f; + _durations[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 0.f; + _durations[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 0.f; + _durations[FadeJobConfig::AVATAR_CHANGE] = 0.f; } -FadeJobConfig::FadeJobConfig() : - noiseSize{ - { 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 - { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE - }, - noiseLevel{ - 1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN - 1.0f, // BUBBLE_ISECT_OWNER - 1.0f, // BUBBLE_ISECT_TRESPASSER - 0.70f, // USER_ENTER_LEAVE_DOMAIN - 1.0f, // AVATAR_CHANGE - }, - baseSize{ - { 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER - { 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER - { 10000.f, 1.0f, 10000.0f }, // USER_ENTER_LEAVE_DOMAIN - { 0.4f, 0.4f, 0.4f }, // AVATAR_CHANGE - }, - baseLevel{ - 0.0f, // ELEMENT_ENTER_LEAVE_DOMAIN - 1.0f, // BUBBLE_ISECT_OWNER - 1.0f, // BUBBLE_ISECT_TRESPASSER - 1.0f, // USER_ENTER_LEAVE_DOMAIN - 1.0f, // AVATAR_CHANGE - }, - baseInverted{ - false, // ELEMENT_ENTER_LEAVE_DOMAIN - false, // BUBBLE_ISECT_OWNER - false, // BUBBLE_ISECT_TRESPASSER - true, // USER_ENTER_LEAVE_DOMAIN - false, // AVATAR_CHANGE - }, - _duration{ - 4.0f, // ELEMENT_ENTER_LEAVE_DOMAIN - 0.0f, // BUBBLE_ISECT_OWNER - 0.0f, // BUBBLE_ISECT_TRESPASSER - 3.0f, // USER_ENTER_LEAVE_DOMAIN - 3.0f, // AVATAR_CHANGE - }, - edgeWidth{ - 0.10f, // ELEMENT_ENTER_LEAVE_DOMAIN - 0.10f, // BUBBLE_ISECT_OWNER - 0.10f, // BUBBLE_ISECT_TRESPASSER - 0.529f, // USER_ENTER_LEAVE_DOMAIN - 0.05f, // AVATAR_CHANGE - }, - edgeInnerColor{ - { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER - { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER - { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }, // USER_ENTER_LEAVE_DOMAIN - { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE - }, - edgeOuterColor{ - { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN - { 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }, // BUBBLE_ISECT_OWNER - { 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER - { 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN - { 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE - } +FadeJobConfig::FadeJobConfig() { + noiseSize[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec3{ 0.75f, 0.75f, 0.75f }; + noiseSize[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec3{ 0.4f, 0.4f, 0.4f }; + noiseSize[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec3{ 0.4f, 0.4f, 0.4f }; + noiseSize[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec3{ 10.f, 0.01f, 10.0f }; + noiseSize[FadeJobConfig::AVATAR_CHANGE] = glm::vec3{ 0.4f, 0.4f, 0.4f }; + noiseLevel[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 1.f; + noiseLevel[FadeJobConfig::BUBBLE_ISECT_OWNER] = 1.f; + noiseLevel[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 1.f; + noiseLevel[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 0.7f; + noiseLevel[FadeJobConfig::AVATAR_CHANGE] = 1.f; + + baseSize[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec3{ 1.0f, 1.0f, 1.0f }; + baseSize[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec3{ 2.0f, 2.0f, 2.0f }; + baseSize[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec3{ 2.0f, 2.0f, 2.0f }; + baseSize[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec3{ 10000.f, 1.0f, 10000.0f }; + baseSize[FadeJobConfig::AVATAR_CHANGE] = glm::vec3{ 0.4f, 0.4f, 0.4f }; + + baseLevel[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 0.f; + baseLevel[FadeJobConfig::BUBBLE_ISECT_OWNER] = 1.f; + baseLevel[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 1.f; + baseLevel[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 1.f; + baseLevel[FadeJobConfig::AVATAR_CHANGE] = 1.f; + + baseInverted[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = false; + baseInverted[FadeJobConfig::BUBBLE_ISECT_OWNER] = false; + baseInverted[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = false; + baseInverted[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = true; + baseInverted[FadeJobConfig::AVATAR_CHANGE] = false; + + _duration[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 4.f; + _duration[FadeJobConfig::BUBBLE_ISECT_OWNER] = 0.f; + _duration[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 0.f; + _duration[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 3.f; + _duration[FadeJobConfig::AVATAR_CHANGE] = 3.f; + + edgeWidth[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 0.1f; + edgeWidth[FadeJobConfig::BUBBLE_ISECT_OWNER] = 0.08f; + edgeWidth[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 0.08f; + edgeWidth[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 0.329f; + edgeWidth[FadeJobConfig::AVATAR_CHANGE] = 0.05f; + + edgeInnerColor[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }; + edgeInnerColor[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; + edgeInnerColor[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; + edgeInnerColor[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }; + edgeInnerColor[FadeJobConfig::AVATAR_CHANGE] = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; + + edgeOuterColor[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; + edgeOuterColor[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }; + edgeOuterColor[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }; + edgeOuterColor[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; + edgeOuterColor[FadeJobConfig::AVATAR_CHANGE] = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; } void FadeJobConfig::setEditedCategory(int value) { From 972db8f54c04312eceee9cbe778c654b1358fbff Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 3 Jul 2017 17:17:37 +0200 Subject: [PATCH 29/86] Fixed compilation error on Mac and Linux --- libraries/render/src/task/Varying.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render/src/task/Varying.h b/libraries/render/src/task/Varying.h index c9eb78fd71..0144801701 100644 --- a/libraries/render/src/task/Varying.h +++ b/libraries/render/src/task/Varying.h @@ -286,7 +286,7 @@ public: VaryingArray(std::initializer_list list) { assert(list.size() == NUM); - std::copy(list.begin(), list.end(), begin()); + std::copy(list.begin(), list.end(), std::array::begin()); } }; } From 57b2bdf7090ec12604095a176c5124704c8ae641 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 4 Jul 2017 09:14:08 +0200 Subject: [PATCH 30/86] Working bubble isect owner POV --- libraries/render-utils/src/FadeEffect.cpp | 53 +++++++++++-------- .../render-utils/src/RenderDeferredTask.cpp | 2 +- .../render-utils/src/RenderForwardTask.cpp | 12 ++--- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index dd59e729a3..20931e3a67 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -10,11 +10,11 @@ #define FADE_MAX_SCALE 10000.0 inline float parameterToValuePow(float parameter, const double minValue, const double maxOverMinValue) { - return (float)(minValue * pow(maxOverMinValue, parameter)); + return (float)(minValue * pow(maxOverMinValue, double(parameter))); } inline float valueToParameterPow(float value, const double minValue, const double maxOverMinValue) { - return (float)(log(value / minValue) / log(maxOverMinValue)); + return (float)(log(double(value) / minValue) / log(maxOverMinValue)); } void FadeSwitchJob::configure(const Config& config) { @@ -71,8 +71,11 @@ const render::Item* FadeSwitchJob::findNearestItem(const render::RenderContextPo if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { if (isectDistance>minDistance && isectDistance < minIsectDistance) { auto& item = scene->getItem(itemBound.id); - nearestItem = &item; - minIsectDistance = isectDistance; + + if (item.getKey().isShape() && !item.getKey().isMeta()) { + nearestItem = &item; + minIsectDistance = isectDistance; + } } } } @@ -114,13 +117,13 @@ FadeCommonParameters::FadeCommonParameters() FadeJobConfig::FadeJobConfig() { noiseSize[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec3{ 0.75f, 0.75f, 0.75f }; - noiseSize[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec3{ 0.4f, 0.4f, 0.4f }; + noiseSize[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec3{ 1.0f, 1.0f/15.f, 1.0f }; noiseSize[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec3{ 0.4f, 0.4f, 0.4f }; noiseSize[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec3{ 10.f, 0.01f, 10.0f }; noiseSize[FadeJobConfig::AVATAR_CHANGE] = glm::vec3{ 0.4f, 0.4f, 0.4f }; noiseLevel[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 1.f; - noiseLevel[FadeJobConfig::BUBBLE_ISECT_OWNER] = 1.f; + noiseLevel[FadeJobConfig::BUBBLE_ISECT_OWNER] = 0.37f; noiseLevel[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 1.f; noiseLevel[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 0.7f; noiseLevel[FadeJobConfig::AVATAR_CHANGE] = 1.f; @@ -144,8 +147,8 @@ FadeJobConfig::FadeJobConfig() baseInverted[FadeJobConfig::AVATAR_CHANGE] = false; _duration[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 4.f; - _duration[FadeJobConfig::BUBBLE_ISECT_OWNER] = 0.f; - _duration[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 0.f; + _duration[FadeJobConfig::BUBBLE_ISECT_OWNER] = 4.f; + _duration[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 4.f; _duration[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 3.f; _duration[FadeJobConfig::AVATAR_CHANGE] = 3.f; @@ -458,24 +461,29 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon 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 eventDuration = (double)_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; - if (cycleTime < eventDuration) { - _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), eventDuration); + if (_parameters->_isManualThresholdEnabled) { + _editThreshold = _parameters->_manualThreshold; } else { - _editThreshold = 1.f; + if (cycleTime < eventDuration) { + _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), eventDuration); + } + else { + _editThreshold = 1.f; + } } switch (_parameters->_editedCategory) { @@ -485,8 +493,10 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon case FadeJobConfig::BUBBLE_ISECT_OWNER: { const glm::vec3 cameraPos = renderContext->args->getViewFrustum().getPosition(); - const glm::vec3 delta = itemBounds.bound.calcCenter() - cameraPos; + glm::vec3 delta = itemBounds.bound.calcCenter() - cameraPos; + float distance = glm::length(delta); + delta = glm::normalize(delta) * std::max(0.f, distance - 0.5f); _editNoiseOffset.x = _editTime*0.1f; _editNoiseOffset.y = _editTime*2.5f; _editNoiseOffset.z = _editTime*0.1f; @@ -506,6 +516,7 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon _editNoiseOffset.z = _editTime*0.75f; _editBaseOffset = itemBounds.bound.calcCenter(); + _editBaseOffset.y -= itemBounds.bound.getDimensions().y / 2.f; } break; @@ -515,10 +526,6 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon default: assert(false); } - - if (_parameters->_isManualThresholdEnabled) { - _editThreshold = _parameters->_manualThreshold; - } } void FadeRenderJob::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation) { diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index d717d45b76..92f23751f4 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -73,7 +73,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto& metas = items.get0()[RenderFetchCullSortTask::META]; const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; - const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND]; + //const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND]; const auto& spatialSelection = items[1]; // Filter the non antialiaased overlays diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index ef9cfe8613..296eea1da8 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -37,13 +37,13 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend // Extract opaques / transparents / lights / metas / overlays / background const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE]; - const auto& transparents = items.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; - const auto& lights = items.get0()[RenderFetchCullSortTask::LIGHT]; - const auto& metas = items.get0()[RenderFetchCullSortTask::META]; - const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; - const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; +// const auto& transparents = items.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; +// const auto& lights = items.get0()[RenderFetchCullSortTask::LIGHT]; +// const auto& metas = items.get0()[RenderFetchCullSortTask::META]; +// const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; +// const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND]; - const auto& spatialSelection = items[1]; +// const auto& spatialSelection = items[1]; const auto framebuffer = task.addJob("PrepareFramebuffer"); From 0244dd6325b2c5306086a2223e56b1cede969edd Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 4 Jul 2017 09:47:23 +0200 Subject: [PATCH 31/86] Working bubble isect trespasser POV --- libraries/render-utils/src/FadeEffect.cpp | 33 +++++++++++++++-------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 20931e3a67..faca326171 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -117,8 +117,8 @@ FadeCommonParameters::FadeCommonParameters() FadeJobConfig::FadeJobConfig() { noiseSize[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec3{ 0.75f, 0.75f, 0.75f }; - noiseSize[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec3{ 1.0f, 1.0f/15.f, 1.0f }; - noiseSize[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec3{ 0.4f, 0.4f, 0.4f }; + noiseSize[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec3{ 1.5f, 1.0f/25.f, 0.5f }; + noiseSize[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec3{ 0.5f, 1.0f / 25.f, 0.5f }; noiseSize[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec3{ 10.f, 0.01f, 10.0f }; noiseSize[FadeJobConfig::AVATAR_CHANGE] = glm::vec3{ 0.4f, 0.4f, 0.4f }; @@ -136,7 +136,7 @@ FadeJobConfig::FadeJobConfig() baseLevel[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 0.f; baseLevel[FadeJobConfig::BUBBLE_ISECT_OWNER] = 1.f; - baseLevel[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 1.f; + baseLevel[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 0.f; baseLevel[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 1.f; baseLevel[FadeJobConfig::AVATAR_CHANGE] = 1.f; @@ -153,14 +153,14 @@ FadeJobConfig::FadeJobConfig() _duration[FadeJobConfig::AVATAR_CHANGE] = 3.f; edgeWidth[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 0.1f; - edgeWidth[FadeJobConfig::BUBBLE_ISECT_OWNER] = 0.08f; - edgeWidth[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 0.08f; + edgeWidth[FadeJobConfig::BUBBLE_ISECT_OWNER] = 0.02f; + edgeWidth[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 0.025f; edgeWidth[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 0.329f; edgeWidth[FadeJobConfig::AVATAR_CHANGE] = 0.05f; edgeInnerColor[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }; edgeInnerColor[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; - edgeInnerColor[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; + edgeInnerColor[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; edgeInnerColor[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }; edgeInnerColor[FadeJobConfig::AVATAR_CHANGE] = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; @@ -497,9 +497,9 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon float distance = glm::length(delta); delta = glm::normalize(delta) * std::max(0.f, distance - 0.5f); - _editNoiseOffset.x = _editTime*0.1f; - _editNoiseOffset.y = _editTime*2.5f; - _editNoiseOffset.z = _editTime*0.1f; + _editNoiseOffset.x = _editTime*2.1f; + _editNoiseOffset.y = _editTime*1.0f; + _editNoiseOffset.z = _editTime*2.1f; _editBaseOffset = cameraPos + delta*_editThreshold; _editThreshold = 0.33f; @@ -507,6 +507,13 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon break; case FadeJobConfig::BUBBLE_ISECT_TRESPASSER: + { + _editNoiseOffset.x = _editTime*2.1f; + _editNoiseOffset.y = _editTime*1.0f; + _editNoiseOffset.z = _editTime*2.1f; + + _editBaseOffset = glm::vec3{ 0.f, 0.f, 0.f }; + } break; case FadeJobConfig::USER_ENTER_LEAVE_DOMAIN: @@ -572,10 +579,14 @@ bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline threshold = _currentInstance->_editThreshold; noiseOffset += _currentInstance->_editNoiseOffset; // This works supposing offset is the world position of the object that is fading. - baseOffset = _currentInstance->_editBaseOffset - offset; + if (eventCategory != FadeJobConfig::BUBBLE_ISECT_TRESPASSER) { + baseOffset = _currentInstance->_editBaseOffset - offset; + } } - threshold = (threshold-0.5f)*_currentInstance->_parameters->_thresholdScale[eventCategory] + 0.5f; + if (eventCategory != FadeJobConfig::BUBBLE_ISECT_OWNER) { + threshold = (threshold - 0.5f)*_currentInstance->_parameters->_thresholdScale[eventCategory] + 0.5f; + } batch._glUniform1i(fadeCategoryLocation, eventCategory); batch._glUniform1f(fadeThresholdLocation, threshold); From 7d851c1cbdd9c66d0db30dd37f33fd0ee4c20fb5 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 4 Jul 2017 12:01:28 +0200 Subject: [PATCH 32/86] Added timing parameters and visual debug of threshold --- libraries/render-utils/src/Fade.slh | 4 +- libraries/render-utils/src/FadeEffect.cpp | 115 +++-- libraries/render-utils/src/FadeEffect.h | 59 ++- .../render/configSlider/ConfigSlider.qml | 4 +- .../developer/utilities/render/debugFade.js | 4 +- scripts/developer/utilities/render/fade.qml | 468 ++++++++++-------- 6 files changed, 418 insertions(+), 236 deletions(-) diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index f539d90217..5828c815e7 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -25,7 +25,7 @@ struct FadeParameters vec4 _innerEdgeColor; vec4 _outerEdgeColor; vec2 _edgeWidthInvWidth; - int _invertBase; + int _isInverted; float _padding; }; @@ -102,7 +102,7 @@ void applyFadeClip(vec3 position) { void applyFade(vec3 position, out vec3 emissive) { float alpha = evalFadeAlpha(position); - if (fadeParameters[fadeCategory]._invertBase!=0) { + if (fadeParameters[fadeCategory]._isInverted!=0) { alpha = -alpha; } diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index faca326171..b4f66e36ce 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -8,6 +8,7 @@ #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))); @@ -128,6 +129,18 @@ FadeJobConfig::FadeJobConfig() noiseLevel[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 0.7f; noiseLevel[FadeJobConfig::AVATAR_CHANGE] = 1.f; + noiseSpeed[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec3{ 0.0f, 0.0f, 0.0f }; + noiseSpeed[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec3{ 1.0f, 0.2f, 1.0f }; + noiseSpeed[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec3{ 1.0f, 0.2f, 1.0f }; + noiseSpeed[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec3{ 0.0f, -0.5f, 0.0f }; + noiseSpeed[FadeJobConfig::AVATAR_CHANGE] = glm::vec3{ 0.0f, 0.0f, 0.0f }; + + timing[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = FadeJobConfig::LINEAR; + timing[FadeJobConfig::BUBBLE_ISECT_OWNER] = FadeJobConfig::LINEAR; + timing[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = FadeJobConfig::LINEAR; + timing[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = FadeJobConfig::LINEAR; + timing[FadeJobConfig::AVATAR_CHANGE] = FadeJobConfig::LINEAR; + baseSize[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec3{ 1.0f, 1.0f, 1.0f }; baseSize[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec3{ 2.0f, 2.0f, 2.0f }; baseSize[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec3{ 2.0f, 2.0f, 2.0f }; @@ -140,11 +153,11 @@ FadeJobConfig::FadeJobConfig() baseLevel[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 1.f; baseLevel[FadeJobConfig::AVATAR_CHANGE] = 1.f; - baseInverted[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = false; - baseInverted[FadeJobConfig::BUBBLE_ISECT_OWNER] = false; - baseInverted[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = false; - baseInverted[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = true; - baseInverted[FadeJobConfig::AVATAR_CHANGE] = false; + _isInverted[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = false; + _isInverted[FadeJobConfig::BUBBLE_ISECT_OWNER] = false; + _isInverted[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = false; + _isInverted[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = true; + _isInverted[FadeJobConfig::AVATAR_CHANGE] = false; _duration[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 4.f; _duration[FadeJobConfig::BUBBLE_ISECT_OWNER] = 4.f; @@ -219,13 +232,13 @@ void FadeJobConfig::setBaseLevel(float value) { emit dirty(); } -void FadeJobConfig::setBaseInverted(bool value) { - baseInverted[editedCategory] = value; +void FadeJobConfig::setInverted(bool value) { + _isInverted[editedCategory] = value; emit dirty(); } -bool FadeJobConfig::isBaseInverted() const { - return baseInverted[editedCategory]; +bool FadeJobConfig::isInverted() const { + return _isInverted[editedCategory]; } void FadeJobConfig::setNoiseSizeX(float value) { @@ -260,6 +273,33 @@ void FadeJobConfig::setNoiseLevel(float value) { emit dirty(); } +void FadeJobConfig::setNoiseSpeedX(float value) { + noiseSpeed[editedCategory].x = powf(value, 3.f)*FADE_MAX_SPEED; + emit dirty(); +} + +float FadeJobConfig::getNoiseSpeedX() const { + return powf(noiseSpeed[editedCategory].x / FADE_MAX_SPEED, 1.f/3.f); +} + +void FadeJobConfig::setNoiseSpeedY(float value) { + noiseSpeed[editedCategory].y = powf(value, 3.f)*FADE_MAX_SPEED; + emit dirty(); +} + +float FadeJobConfig::getNoiseSpeedY() const { + return powf(noiseSpeed[editedCategory].y / FADE_MAX_SPEED, 1.f / 3.f); +} + +void FadeJobConfig::setNoiseSpeedZ(float value) { + noiseSpeed[editedCategory].z = powf(value, 3.f)*FADE_MAX_SPEED; + emit dirty(); +} + +float FadeJobConfig::getNoiseSpeedZ() const { + return powf(noiseSpeed[editedCategory].z / FADE_MAX_SPEED, 1.f / 3.f); +} + void FadeJobConfig::setEdgeWidth(float value) { edgeWidth[editedCategory] = value * value; emit dirty(); @@ -309,6 +349,12 @@ void FadeJobConfig::setEdgeOuterIntensity(float value) { emit dirty(); } +void FadeJobConfig::setTiming(int value) { + assert(value < TIMING_COUNT); + timing[editedCategory] = value; + emit dirty(); +} + FadeConfigureJob::FadeConfigureJob(FadeCommonParameters::Pointer commonParams) : _parameters{ commonParams } { @@ -334,12 +380,14 @@ void FadeConfigureJob::configure(const Config& config) { configuration._noiseInvSizeAndLevel.y = 1.f / config.noiseSize[i].y; configuration._noiseInvSizeAndLevel.z = 1.f / config.noiseSize[i].z; configuration._noiseInvSizeAndLevel.w = config.noiseLevel[i]; - configuration._invertBase = config.baseInverted[i] & 1; + configuration._isInverted = config._isInverted[i] & 1; configuration._edgeWidthInvWidth.x = config.edgeWidth[i]; 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)); + _parameters->_noiseSpeed[i] = config.noiseSpeed[i]; + _parameters->_timing[i] = (FadeJobConfig::Timing) config.timing[i]; } _isBufferDirty = true; } @@ -435,14 +483,28 @@ void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const } } -float FadeRenderJob::computeElementEnterThreshold(double time, const double period) const { +float FadeRenderJob::computeElementEnterThreshold(double time, const double period, FadeJobConfig::Timing timing) const { 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) { - fadeAlpha = Interpolate::easeInOutQuad(fraction); + switch (timing) { + default: + fadeAlpha = fraction; + break; + case FadeJobConfig::EASE_IN: + fadeAlpha = fraction*fraction; + break; + case FadeJobConfig::EASE_OUT: + fadeAlpha = 1.f - fraction; + fadeAlpha = 1.f- fadeAlpha*fadeAlpha; + break; + case FadeJobConfig::EASE_IN_OUT: + fadeAlpha = fraction*fraction*(3 - 2 * fraction); + break; + } } return fadeAlpha; } @@ -450,7 +512,9 @@ float FadeRenderJob::computeElementEnterThreshold(double time, const double peri 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, _currentInstance->_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]); + return _currentInstance->computeElementEnterThreshold(time, + _currentInstance->_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN], + _currentInstance->_parameters->_timing[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]); } void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderContext, const render::ItemBound& itemBounds) { @@ -461,7 +525,9 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon uint64_t now = usecTimestampNow(); const double deltaTime = (int64_t(now) - int64_t(_editPreviousTime)) / double(USECS_PER_SECOND); - const double eventDuration = (double)_parameters->_durations[_parameters->_editedCategory]; + const int editedCategory = _parameters->_editedCategory; + const double eventDuration = (double)_parameters->_durations[editedCategory]; + const FadeJobConfig::Timing timing = _parameters->_timing[editedCategory]; const double waitTime = 0.5; // Wait between fade in and out double cycleTime = fmod(_editTime, (eventDuration + waitTime) * 2.0); @@ -473,20 +539,24 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon } else { if (cycleTime < eventDuration) { - _editThreshold = 1.f - computeElementEnterThreshold(cycleTime, eventDuration); + _editThreshold = 1.f - computeElementEnterThreshold(cycleTime, eventDuration, timing); } else if (cycleTime < (eventDuration + waitTime)) { _editThreshold = 0.f; } else if (cycleTime < (2 * eventDuration + waitTime)) { - _editThreshold = computeElementEnterThreshold(cycleTime - (eventDuration + waitTime), eventDuration); + _editThreshold = computeElementEnterThreshold(cycleTime - (eventDuration + waitTime), eventDuration, timing); } else { _editThreshold = 1.f; } } - switch (_parameters->_editedCategory) { + renderContext->jobConfig->setProperty("threshold", _editThreshold); + + _editNoiseOffset = _parameters->_noiseSpeed[editedCategory] * (float)_editTime; + + switch (editedCategory) { case FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN: break; @@ -497,9 +567,6 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon float distance = glm::length(delta); delta = glm::normalize(delta) * std::max(0.f, distance - 0.5f); - _editNoiseOffset.x = _editTime*2.1f; - _editNoiseOffset.y = _editTime*1.0f; - _editNoiseOffset.z = _editTime*2.1f; _editBaseOffset = cameraPos + delta*_editThreshold; _editThreshold = 0.33f; @@ -508,20 +575,12 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon case FadeJobConfig::BUBBLE_ISECT_TRESPASSER: { - _editNoiseOffset.x = _editTime*2.1f; - _editNoiseOffset.y = _editTime*1.0f; - _editNoiseOffset.z = _editTime*2.1f; - _editBaseOffset = glm::vec3{ 0.f, 0.f, 0.f }; } break; case FadeJobConfig::USER_ENTER_LEAVE_DOMAIN: { - _editNoiseOffset.x = _editTime*0.5f; - _editNoiseOffset.y = 0.f; - _editNoiseOffset.z = _editTime*0.75f; - _editBaseOffset = itemBounds.bound.calcCenter(); _editBaseOffset.y -= itemBounds.bound.getDimensions().y / 2.f; } diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index c3a41187e1..b29495cea0 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -38,7 +38,7 @@ class FadeJobConfig : public render::Job::Config { 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 baseInverted READ isBaseInverted WRITE setBaseInverted 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) @@ -54,6 +54,10 @@ class FadeJobConfig : public render::Job::Config { Q_PROPERTY(float edgeOuterIntensity READ getEdgeOuterIntensity WRITE setEdgeOuterIntensity NOTIFY dirty) Q_PROPERTY(bool manualFade MEMBER manualFade NOTIFY dirty) Q_PROPERTY(float manualThreshold MEMBER manualThreshold NOTIFY dirty) + Q_PROPERTY(int timing READ getTiming WRITE setTiming NOTIFY dirty) + Q_PROPERTY(float noiseSpeedX READ getNoiseSpeedX WRITE setNoiseSpeedX NOTIFY dirty) + Q_PROPERTY(float noiseSpeedY READ getNoiseSpeedY WRITE setNoiseSpeedY NOTIFY dirty) + Q_PROPERTY(float noiseSpeedZ READ getNoiseSpeedZ WRITE setNoiseSpeedZ NOTIFY dirty) public: @@ -68,6 +72,15 @@ public: EVENT_CATEGORY_COUNT }; + enum Timing { + LINEAR, + EASE_IN, + EASE_OUT, + EASE_IN_OUT, + + TIMING_COUNT + }; + FadeJobConfig(); void setEditedCategory(int value); @@ -87,8 +100,8 @@ public: void setBaseLevel(float value); float getBaseLevel() const { return baseLevel[editedCategory]; } - void setBaseInverted(bool value); - bool isBaseInverted() const; + void setInverted(bool value); + bool isInverted() const; void setNoiseSizeX(float value); float getNoiseSizeX() const; @@ -102,6 +115,15 @@ public: void setNoiseLevel(float value); float getNoiseLevel() const { return noiseLevel[editedCategory]; } + 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; @@ -128,19 +150,24 @@ public: void setEdgeOuterIntensity(float value); float getEdgeOuterIntensity() const { return edgeOuterColor[editedCategory].a; } + + void setTiming(int value); + int getTiming() const { return timing[editedCategory]; } bool manualFade{ false }; float manualThreshold{ 0.f }; int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]; + glm::vec3 noiseSpeed[EVENT_CATEGORY_COUNT]; float noiseLevel[EVENT_CATEGORY_COUNT]; glm::vec3 baseSize[EVENT_CATEGORY_COUNT]; float baseLevel[EVENT_CATEGORY_COUNT]; - bool baseInverted[EVENT_CATEGORY_COUNT]; + bool _isInverted[EVENT_CATEGORY_COUNT]; float _duration[EVENT_CATEGORY_COUNT]; float edgeWidth[EVENT_CATEGORY_COUNT]; glm::vec4 edgeInnerColor[EVENT_CATEGORY_COUNT]; glm::vec4 edgeOuterColor[EVENT_CATEGORY_COUNT]; + int timing[EVENT_CATEGORY_COUNT]; signals: void dirty(); @@ -160,6 +187,8 @@ struct FadeCommonParameters float _thresholdScale[FadeJobConfig::EVENT_CATEGORY_COUNT]; int _editedCategory{ FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN }; float _durations[FadeJobConfig::EVENT_CATEGORY_COUNT]; + glm::vec3 _noiseSpeed[FadeJobConfig::EVENT_CATEGORY_COUNT]; + FadeJobConfig::Timing _timing[FadeJobConfig::EVENT_CATEGORY_COUNT]; }; class FadeSwitchJob { @@ -200,7 +229,7 @@ struct FadeParameters glm::vec4 _innerEdgeColor; glm::vec4 _outerEdgeColor; glm::vec2 _edgeWidthInvWidth; - glm::int32 _invertBase; + glm::int32 _isInverted; glm::float32 _padding; }; @@ -234,15 +263,31 @@ private: FadeParameters _configurations[FadeJobConfig::EVENT_CATEGORY_COUNT]; }; + +class FadeRenderJobConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty) + +public: + + float threshold{ 0.f }; + +signals: + void dirty(); + +}; + class FadeRenderJob { public: + using Config = FadeRenderJobConfig; using Input = render::VaryingSet3; - using JobModel = render::Job::ModelI; + using JobModel = render::Job::ModelI; FadeRenderJob(FadeCommonParameters::Pointer commonParams, render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber }, _parameters{ commonParams } {} + void configure(const Config& config) {} void run(const render::RenderContextPointer& renderContext, const Input& inputs); static void bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation); @@ -263,7 +308,7 @@ private: render::ShapePlumberPointer _shapePlumber; FadeCommonParameters::Pointer _parameters; - float computeElementEnterThreshold(double time, const double period) const; + float computeElementEnterThreshold(double time, const double period, FadeJobConfig::Timing timing) const; // Everything needed for interactive edition uint64_t _editPreviousTime{ 0 }; diff --git a/scripts/developer/utilities/render/configSlider/ConfigSlider.qml b/scripts/developer/utilities/render/configSlider/ConfigSlider.qml index c1a6d6b7f3..021365686a 100644 --- a/scripts/developer/utilities/render/configSlider/ConfigSlider.qml +++ b/scripts/developer/utilities/render/configSlider/ConfigSlider.qml @@ -43,7 +43,7 @@ Item { anchors.left: root.left anchors.leftMargin: 200 anchors.top: root.top - anchors.topMargin: 7 + anchors.topMargin: 15 } Binding { @@ -57,7 +57,7 @@ Item { Slider { id: sliderControl stepSize: root.integral ? 1.0 : 0.0 - width: 150 + width: root.width-130 height: 20 anchors.right: root.right anchors.rightMargin: 8 diff --git a/scripts/developer/utilities/render/debugFade.js b/scripts/developer/utilities/render/debugFade.js index 6632cd8094..b01c4b5e1f 100644 --- a/scripts/developer/utilities/render/debugFade.js +++ b/scripts/developer/utilities/render/debugFade.js @@ -14,8 +14,8 @@ var qml = Script.resolvePath('fade.qml'); var window = new OverlayWindow({ title: 'Fade', source: qml, - width: 500, - height: 900, + width: 910, + height: 610, }); window.setPosition(50, 50); window.closed.connect(function() { Script.stop(); }); diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index 8b3885d230..da180aaefe 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -11,6 +11,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import "configSlider" +import "../lib/plotperf" Column { id: root @@ -47,6 +48,8 @@ Column { } } Row { + spacing: 8 + CheckBox { text: "Manual" checked: root.config["manualFade"] @@ -72,209 +75,284 @@ Column { Column { spacing: 8 - ConfigSlider { - label: "Duration" - integral: false - config: root.config - property: "duration" - max: 10.0 - min: 0.1 - width: 400 + CheckBox { + text: "Invert" + checked: root.config["isInverted"] + onCheckedChanged: { root.config["isInverted"] = checked } } - GroupBox { - title: "Base Gradient" - width: 500 - Column { - spacing: 8 + Row { + spacing: 8 + + GroupBox { + title: "Base Gradient" + width: 450 + Column { + spacing: 8 - ConfigSlider { - label: "Size X" - integral: false - config: root.config - property: "baseSizeX" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Y" - integral: false - config: root.config - property: "baseSizeY" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Z" - integral: false - config: root.config - property: "baseSizeZ" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Level" - integral: false - config: root.config - property: "baseLevel" - max: 1.0 - min: 0.0 - width: 400 - } - CheckBox { - text: "Invert" - checked: root.config["baseInverted"] - onCheckedChanged: { root.config["baseInverted"] = checked } - } - } - } - GroupBox { - title: "Noise Gradient" - width: 500 - Column { - spacing: 8 - - ConfigSlider { - label: "Size X" - integral: false - config: root.config - property: "noiseSizeX" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Y" - integral: false - config: root.config - property: "noiseSizeY" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Z" - integral: false - config: root.config - property: "noiseSizeZ" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Level" - integral: false - config: root.config - property: "noiseLevel" - max: 1.0 - min: 0.0 - width: 400 - } - } - } - GroupBox { - title: "Edge" - width: 500 - Column { - spacing: 8 - - ConfigSlider { - label: "Width" - integral: false - config: root.config - property: "edgeWidth" - max: 1.0 - min: 0.0 - width: 400 - } - GroupBox { - title: "Inner color" - Column { - spacing: 8 - ConfigSlider { - label: "Color R" - integral: false - config: root.config - property: "edgeInnerColorR" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color G" - integral: false - config: root.config - property: "edgeInnerColorG" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color B" - integral: false - config: root.config - property: "edgeInnerColorB" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color intensity" - integral: false - config: root.config - property: "edgeInnerIntensity" - max: 5.0 - min: 0.0 - width: 400 - } + ConfigSlider { + label: "Size X" + integral: false + config: root.config + property: "baseSizeX" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Y" + integral: false + config: root.config + property: "baseSizeY" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Z" + integral: false + config: root.config + property: "baseSizeZ" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Level" + integral: false + config: root.config + property: "baseLevel" + max: 1.0 + min: 0.0 + width: 400 } } - GroupBox { - title: "Outer color" - Column { - spacing: 8 - ConfigSlider { - label: "Color R" - integral: false - config: root.config - property: "edgeOuterColorR" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color G" - integral: false - config: root.config - property: "edgeOuterColorG" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color B" - integral: false - config: root.config - property: "edgeOuterColorB" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color intensity" - integral: false - config: root.config - property: "edgeOuterIntensity" - max: 5.0 - min: 0.0 - width: 400 - } + } + GroupBox { + title: "Noise Gradient" + width: 450 + Column { + spacing: 8 + + ConfigSlider { + label: "Size X" + integral: false + config: root.config + property: "noiseSizeX" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Y" + integral: false + config: root.config + property: "noiseSizeY" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Z" + integral: false + config: root.config + property: "noiseSizeZ" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Level" + integral: false + config: root.config + property: "noiseLevel" + max: 1.0 + min: 0.0 + width: 400 } } } } + Row { + spacing: 8 + + GroupBox { + title: "Edge" + width: 450 + Column { + spacing: 8 + + ConfigSlider { + label: "Width" + integral: false + config: root.config + property: "edgeWidth" + max: 1.0 + min: 0.0 + width: 400 + } + GroupBox { + title: "Inner color" + Column { + spacing: 8 + ConfigSlider { + label: "Color R" + integral: false + config: root.config + property: "edgeInnerColorR" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color G" + integral: false + config: root.config + property: "edgeInnerColorG" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color B" + integral: false + config: root.config + property: "edgeInnerColorB" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color intensity" + integral: false + config: root.config + property: "edgeInnerIntensity" + max: 5.0 + min: 0.0 + width: 400 + } + } + } + GroupBox { + title: "Outer color" + Column { + spacing: 8 + ConfigSlider { + label: "Color R" + integral: false + config: root.config + property: "edgeOuterColorR" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color G" + integral: false + config: root.config + property: "edgeOuterColorG" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color B" + integral: false + config: root.config + property: "edgeOuterColorB" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color intensity" + integral: false + config: root.config + property: "edgeOuterIntensity" + max: 5.0 + min: 0.0 + width: 400 + } + } + } + } + } + + GroupBox { + title: "Timing" + width: 450 + Column { + spacing: 8 + + ConfigSlider { + label: "Duration" + integral: false + config: root.config + property: "duration" + max: 10.0 + min: 0.1 + width: 400 + } + ComboBox { + width: 400 + model: ["Linear", "Ease In", "Ease Out", "Ease In / Out"] + onCurrentIndexChanged: { + root.config["timing"] = currentIndex; + } + } + GroupBox { + title: "Noise Animation" + Column { + spacing: 8 + ConfigSlider { + label: "Speed X" + integral: false + config: root.config + property: "noiseSpeedX" + max: 1.0 + min: -1.0 + width: 400 + } + ConfigSlider { + label: "Speed Y" + integral: false + config: root.config + property: "noiseSpeedY" + max: 1.0 + min: -1.0 + width: 400 + } + ConfigSlider { + label: "Speed Z" + integral: false + config: root.config + property: "noiseSpeedZ" + max: 1.0 + min: -1.0 + width: 400 + } + } + } + + PlotPerf { + title: "Threshold" + height: parent.evalEvenHeight() + object: Render.getConfig("RenderMainView.DrawFadeOpaque") + valueUnit: "%" + valueScale: 0.01 + valueNumDigits: "1" + plots: [ + { + prop: "threshold", + label: "Threshold", + color: "#FFBB77" + } + ] + } + + } + } + + } } } From 98d915cf0f12a37ac4bb09cf83a36e6694d9355f Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 4 Jul 2017 14:35:43 +0200 Subject: [PATCH 33/86] Smoother ease in / out functions --- libraries/render-utils/src/Fade.slh | 5 ++--- libraries/render-utils/src/FadeEffect.cpp | 14 +++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 5828c815e7..d3ab532650 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -45,7 +45,8 @@ vec2 hash2D(vec3 position) { } float noise3D(vec3 position) { - return textureLod(fadeMaskMap, hash2D(position), 0).r; + float n = textureLod(fadeMaskMap, hash2D(position), 0).r; + return pow(n, 1.0/2.2); // Need to fix this later directly in the texture } float evalFadeNoiseGradient(vec3 position) { @@ -87,8 +88,6 @@ float evalFadeGradient(vec3 position) { } float evalFadeAlpha(vec3 position) { - //float edgeWidth = fadeParameters[fadeCategory]._edgeWidthInvWidth.x; - //float cutoff = mix(-edgeWidth, 1.0+edgeWidth, fadeThreshold); float cutoff = fadeThreshold; return evalFadeGradient(position)-cutoff; diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index b4f66e36ce..6152bc213b 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -385,7 +385,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)); + _parameters->_thresholdScale[i] = 1.f + (configuration._edgeWidthInvWidth.x + std::max(0.f, (config.noiseLevel[i] + config.baseLevel[i])*0.5f-0.5f)); _parameters->_noiseSpeed[i] = config.noiseSpeed[i]; _parameters->_timing[i] = (FadeJobConfig::Timing) config.timing[i]; } @@ -495,14 +495,14 @@ float FadeRenderJob::computeElementEnterThreshold(double time, const double peri fadeAlpha = fraction; break; case FadeJobConfig::EASE_IN: - fadeAlpha = fraction*fraction; + fadeAlpha = fraction*fraction*fraction; break; case FadeJobConfig::EASE_OUT: fadeAlpha = 1.f - fraction; - fadeAlpha = 1.f- fadeAlpha*fadeAlpha; + fadeAlpha = 1.f- fadeAlpha*fadeAlpha*fadeAlpha; break; case FadeJobConfig::EASE_IN_OUT: - fadeAlpha = fraction*fraction*(3 - 2 * fraction); + fadeAlpha = fraction*fraction*fraction*(fraction*(fraction * 6 - 15) + 10); break; } } @@ -552,7 +552,11 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon } } - renderContext->jobConfig->setProperty("threshold", _editThreshold); + float threshold = _editThreshold; + if (editedCategory != FadeJobConfig::BUBBLE_ISECT_OWNER) { + threshold = (threshold - 0.5f)*_parameters->_thresholdScale[editedCategory] + 0.5f; + } + renderContext->jobConfig->setProperty("threshold", threshold); _editNoiseOffset = _parameters->_noiseSpeed[editedCategory] * (float)_editTime; From 2525fe5869716b240146f3770def4dc12a867841 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 4 Jul 2017 17:31:24 +0200 Subject: [PATCH 34/86] Working save and load --- libraries/render-utils/src/FadeEffect.cpp | 431 +++++++++++++++----- libraries/render-utils/src/FadeEffect.h | 54 ++- scripts/developer/utilities/render/fade.qml | 168 +++++--- 3 files changed, 452 insertions(+), 201 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 6152bc213b..dec67dac85 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -6,6 +6,8 @@ #include #include +#include + #define FADE_MIN_SCALE 0.001 #define FADE_MAX_SCALE 10000.0 #define FADE_MAX_SPEED 50.f @@ -117,71 +119,65 @@ FadeCommonParameters::FadeCommonParameters() FadeJobConfig::FadeJobConfig() { - noiseSize[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec3{ 0.75f, 0.75f, 0.75f }; - noiseSize[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec3{ 1.5f, 1.0f/25.f, 0.5f }; - noiseSize[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec3{ 0.5f, 1.0f / 25.f, 0.5f }; - noiseSize[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec3{ 10.f, 0.01f, 10.0f }; - noiseSize[FadeJobConfig::AVATAR_CHANGE] = glm::vec3{ 0.4f, 0.4f, 0.4f }; + events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 0.75f, 0.75f, 0.75f }; + events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].noiseLevel = 1.f; + events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f }; + events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].timing = FadeJobConfig::LINEAR; + events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 1.0f, 1.0f, 1.0f }; + events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].baseLevel = 0.f; + events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]._isInverted = false; + events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]._duration = 4.f; + events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].edgeWidth = 0.1f; + events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }; + events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; - noiseLevel[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 1.f; - noiseLevel[FadeJobConfig::BUBBLE_ISECT_OWNER] = 0.37f; - noiseLevel[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 1.f; - noiseLevel[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 0.7f; - noiseLevel[FadeJobConfig::AVATAR_CHANGE] = 1.f; + events[FadeJobConfig::BUBBLE_ISECT_OWNER].noiseSize = glm::vec3{ 1.5f, 1.0f/25.f, 0.5f }; + events[FadeJobConfig::BUBBLE_ISECT_OWNER].noiseLevel = 0.37f; + events[FadeJobConfig::BUBBLE_ISECT_OWNER].noiseSpeed = glm::vec3{ 1.0f, 0.2f, 1.0f }; + events[FadeJobConfig::BUBBLE_ISECT_OWNER].timing = FadeJobConfig::LINEAR; + events[FadeJobConfig::BUBBLE_ISECT_OWNER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f }; + events[FadeJobConfig::BUBBLE_ISECT_OWNER].baseLevel = 1.f; + events[FadeJobConfig::BUBBLE_ISECT_OWNER]._isInverted = false; + events[FadeJobConfig::BUBBLE_ISECT_OWNER]._duration = 4.f; + events[FadeJobConfig::BUBBLE_ISECT_OWNER].edgeWidth = 0.02f; + events[FadeJobConfig::BUBBLE_ISECT_OWNER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; + events[FadeJobConfig::BUBBLE_ISECT_OWNER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }; - noiseSpeed[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec3{ 0.0f, 0.0f, 0.0f }; - noiseSpeed[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec3{ 1.0f, 0.2f, 1.0f }; - noiseSpeed[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec3{ 1.0f, 0.2f, 1.0f }; - noiseSpeed[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec3{ 0.0f, -0.5f, 0.0f }; - noiseSpeed[FadeJobConfig::AVATAR_CHANGE] = glm::vec3{ 0.0f, 0.0f, 0.0f }; + events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].noiseSize = glm::vec3{ 0.5f, 1.0f / 25.f, 0.5f }; + events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].noiseLevel = 1.f; + events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].noiseSpeed = glm::vec3{ 1.0f, 0.2f, 1.0f }; + events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].timing = FadeJobConfig::LINEAR; + events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f }; + events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].baseLevel = 0.f; + events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER]._isInverted = false; + events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER]._duration = 4.f; + events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].edgeWidth = 0.025f; + events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; + events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }; - timing[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = FadeJobConfig::LINEAR; - timing[FadeJobConfig::BUBBLE_ISECT_OWNER] = FadeJobConfig::LINEAR; - timing[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = FadeJobConfig::LINEAR; - timing[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = FadeJobConfig::LINEAR; - timing[FadeJobConfig::AVATAR_CHANGE] = FadeJobConfig::LINEAR; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 10.f, 0.01f, 10.0f }; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].noiseLevel = 0.7f; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 1.0f, -0.5f, 50.0f }; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].timing = FadeJobConfig::LINEAR; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 10000.f, 1.0f, 10000.0f }; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].baseLevel = 1.f; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN]._isInverted = true; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN]._duration = 3.f; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].edgeWidth = 0.329f; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; - baseSize[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec3{ 1.0f, 1.0f, 1.0f }; - baseSize[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec3{ 2.0f, 2.0f, 2.0f }; - baseSize[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec3{ 2.0f, 2.0f, 2.0f }; - baseSize[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec3{ 10000.f, 1.0f, 10000.0f }; - baseSize[FadeJobConfig::AVATAR_CHANGE] = glm::vec3{ 0.4f, 0.4f, 0.4f }; - - baseLevel[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 0.f; - baseLevel[FadeJobConfig::BUBBLE_ISECT_OWNER] = 1.f; - baseLevel[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 0.f; - baseLevel[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 1.f; - baseLevel[FadeJobConfig::AVATAR_CHANGE] = 1.f; - - _isInverted[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = false; - _isInverted[FadeJobConfig::BUBBLE_ISECT_OWNER] = false; - _isInverted[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = false; - _isInverted[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = true; - _isInverted[FadeJobConfig::AVATAR_CHANGE] = false; - - _duration[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 4.f; - _duration[FadeJobConfig::BUBBLE_ISECT_OWNER] = 4.f; - _duration[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 4.f; - _duration[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 3.f; - _duration[FadeJobConfig::AVATAR_CHANGE] = 3.f; - - edgeWidth[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 0.1f; - edgeWidth[FadeJobConfig::BUBBLE_ISECT_OWNER] = 0.02f; - edgeWidth[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 0.025f; - edgeWidth[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 0.329f; - edgeWidth[FadeJobConfig::AVATAR_CHANGE] = 0.05f; - - edgeInnerColor[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }; - edgeInnerColor[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; - edgeInnerColor[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; - edgeInnerColor[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }; - edgeInnerColor[FadeJobConfig::AVATAR_CHANGE] = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; - - edgeOuterColor[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; - edgeOuterColor[FadeJobConfig::BUBBLE_ISECT_OWNER] = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }; - edgeOuterColor[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }; - edgeOuterColor[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; - edgeOuterColor[FadeJobConfig::AVATAR_CHANGE] = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; + events[FadeJobConfig::AVATAR_CHANGE].noiseSize = glm::vec3{ 0.4f, 0.4f, 0.4f }; + events[FadeJobConfig::AVATAR_CHANGE].noiseLevel = 1.f; + events[FadeJobConfig::AVATAR_CHANGE].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f }; + events[FadeJobConfig::AVATAR_CHANGE].timing = FadeJobConfig::LINEAR; + events[FadeJobConfig::AVATAR_CHANGE].baseSize = glm::vec3{ 0.4f, 0.4f, 0.4f }; + events[FadeJobConfig::AVATAR_CHANGE].baseLevel = 1.f; + events[FadeJobConfig::AVATAR_CHANGE]._isInverted = false; + events[FadeJobConfig::AVATAR_CHANGE]._duration = 3.f; + events[FadeJobConfig::AVATAR_CHANGE].edgeWidth = 0.05f; + events[FadeJobConfig::AVATAR_CHANGE].edgeInnerColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; + events[FadeJobConfig::AVATAR_CHANGE].edgeOuterColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; } void FadeJobConfig::setEditedCategory(int value) { @@ -192,169 +188,373 @@ void FadeJobConfig::setEditedCategory(int value) { } void FadeJobConfig::setDuration(float value) { - _duration[editedCategory] = value; + events[editedCategory]._duration = value; emit dirty(); } float FadeJobConfig::getDuration() const { - return _duration[editedCategory]; + return events[editedCategory]._duration; } void FadeJobConfig::setBaseSizeX(float value) { - baseSize[editedCategory].x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE/ FADE_MIN_SCALE); + events[editedCategory].baseSize.x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE/ FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getBaseSizeX() const { - return valueToParameterPow(baseSize[editedCategory].x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(events[editedCategory].baseSize.x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setBaseSizeY(float value) { - baseSize[editedCategory].y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); + events[editedCategory].baseSize.y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getBaseSizeY() const { - return valueToParameterPow(baseSize[editedCategory].y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(events[editedCategory].baseSize.y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setBaseSizeZ(float value) { - baseSize[editedCategory].z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); + events[editedCategory].baseSize.z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getBaseSizeZ() const { - return valueToParameterPow(baseSize[editedCategory].z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(events[editedCategory].baseSize.z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setBaseLevel(float value) { - baseLevel[editedCategory] = value; + events[editedCategory].baseLevel = value; emit dirty(); } void FadeJobConfig::setInverted(bool value) { - _isInverted[editedCategory] = value; + events[editedCategory]._isInverted = value; emit dirty(); } bool FadeJobConfig::isInverted() const { - return _isInverted[editedCategory]; + return events[editedCategory]._isInverted; } void FadeJobConfig::setNoiseSizeX(float value) { - noiseSize[editedCategory].x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); + events[editedCategory].noiseSize.x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getNoiseSizeX() const { - return valueToParameterPow(noiseSize[editedCategory].x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(events[editedCategory].noiseSize.x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setNoiseSizeY(float value) { - noiseSize[editedCategory].y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); + events[editedCategory].noiseSize.y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getNoiseSizeY() const { - return valueToParameterPow(noiseSize[editedCategory].y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(events[editedCategory].noiseSize.y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setNoiseSizeZ(float value) { - noiseSize[editedCategory].z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); + events[editedCategory].noiseSize.z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } float FadeJobConfig::getNoiseSizeZ() const { - return valueToParameterPow(noiseSize[editedCategory].z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); + return valueToParameterPow(events[editedCategory].noiseSize.z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } void FadeJobConfig::setNoiseLevel(float value) { - noiseLevel[editedCategory] = value; + events[editedCategory].noiseLevel = value; emit dirty(); } void FadeJobConfig::setNoiseSpeedX(float value) { - noiseSpeed[editedCategory].x = powf(value, 3.f)*FADE_MAX_SPEED; + events[editedCategory].noiseSpeed.x = powf(value, 3.f)*FADE_MAX_SPEED; emit dirty(); } float FadeJobConfig::getNoiseSpeedX() const { - return powf(noiseSpeed[editedCategory].x / FADE_MAX_SPEED, 1.f/3.f); + return powf(events[editedCategory].noiseSpeed.x / FADE_MAX_SPEED, 1.f / 3.f); } void FadeJobConfig::setNoiseSpeedY(float value) { - noiseSpeed[editedCategory].y = powf(value, 3.f)*FADE_MAX_SPEED; + events[editedCategory].noiseSpeed.y = powf(value, 3.f)*FADE_MAX_SPEED; emit dirty(); } float FadeJobConfig::getNoiseSpeedY() const { - return powf(noiseSpeed[editedCategory].y / FADE_MAX_SPEED, 1.f / 3.f); + return powf(events[editedCategory].noiseSpeed.y / FADE_MAX_SPEED, 1.f / 3.f); } void FadeJobConfig::setNoiseSpeedZ(float value) { - noiseSpeed[editedCategory].z = powf(value, 3.f)*FADE_MAX_SPEED; + events[editedCategory].noiseSpeed.z = powf(value, 3.f)*FADE_MAX_SPEED; emit dirty(); } float FadeJobConfig::getNoiseSpeedZ() const { - return powf(noiseSpeed[editedCategory].z / FADE_MAX_SPEED, 1.f / 3.f); + return powf(events[editedCategory].noiseSpeed.z / FADE_MAX_SPEED, 1.f / 3.f); } void FadeJobConfig::setEdgeWidth(float value) { - edgeWidth[editedCategory] = value * value; + events[editedCategory].edgeWidth = value * value; emit dirty(); } float FadeJobConfig::getEdgeWidth() const { - return sqrtf(edgeWidth[editedCategory]); + return sqrtf(events[editedCategory].edgeWidth); } void FadeJobConfig::setEdgeInnerColorR(float value) { - edgeInnerColor[editedCategory].r = value; + events[editedCategory].edgeInnerColor.r = value; emit dirty(); } void FadeJobConfig::setEdgeInnerColorG(float value) { - edgeInnerColor[editedCategory].g = value; + events[editedCategory].edgeInnerColor.g = value; emit dirty(); } void FadeJobConfig::setEdgeInnerColorB(float value) { - edgeInnerColor[editedCategory].b = value; + events[editedCategory].edgeInnerColor.b = value; emit dirty(); } void FadeJobConfig::setEdgeInnerIntensity(float value) { - edgeInnerColor[editedCategory].a = value; + events[editedCategory].edgeInnerColor.a = value; emit dirty(); } void FadeJobConfig::setEdgeOuterColorR(float value) { - edgeOuterColor[editedCategory].r = value; + events[editedCategory].edgeOuterColor.r = value; emit dirty(); } void FadeJobConfig::setEdgeOuterColorG(float value) { - edgeOuterColor[editedCategory].g = value; + events[editedCategory].edgeOuterColor.g = value; emit dirty(); } void FadeJobConfig::setEdgeOuterColorB(float value) { - edgeOuterColor[editedCategory].b = value; + events[editedCategory].edgeOuterColor.b = value; emit dirty(); } void FadeJobConfig::setEdgeOuterIntensity(float value) { - edgeOuterColor[editedCategory].a = value; + events[editedCategory].edgeOuterColor.a = value; emit dirty(); } void FadeJobConfig::setTiming(int value) { assert(value < TIMING_COUNT); - timing[editedCategory] = value; + events[editedCategory].timing = value; emit dirty(); } +QString FadeJobConfig::eventNames[EVENT_CATEGORY_COUNT] = { + "element_enter_leave_domain", + "bubble_isect_owner", + "bubble_isect_trespasser", + "user_enter_leave_domain", + "avatar_change", +}; + +void FadeJobConfig::save() const { + assert(category < EVENT_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 FadeJobConfig::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; + } + } +} + FadeConfigureJob::FadeConfigureJob(FadeCommonParameters::Pointer commonParams) : _parameters{ commonParams } { @@ -370,24 +570,25 @@ void FadeConfigureJob::configure(const Config& config) { for (auto i = 0; i < FadeJobConfig::EVENT_CATEGORY_COUNT; i++) { auto& configuration = _configurations[i]; + const auto& eventConfig = config.events[i]; - _parameters->_durations[i] = config._duration[i]; - configuration._baseInvSizeAndLevel.x = 1.f / config.baseSize[i].x; - configuration._baseInvSizeAndLevel.y = 1.f / config.baseSize[i].y; - configuration._baseInvSizeAndLevel.z = 1.f / config.baseSize[i].z; - configuration._baseInvSizeAndLevel.w = config.baseLevel[i]; - configuration._noiseInvSizeAndLevel.x = 1.f / config.noiseSize[i].x; - configuration._noiseInvSizeAndLevel.y = 1.f / config.noiseSize[i].y; - configuration._noiseInvSizeAndLevel.z = 1.f / config.noiseSize[i].z; - configuration._noiseInvSizeAndLevel.w = config.noiseLevel[i]; - configuration._isInverted = config._isInverted[i] & 1; - configuration._edgeWidthInvWidth.x = config.edgeWidth[i]; + _parameters->_durations[i] = eventConfig._duration; + configuration._baseInvSizeAndLevel.x = 1.f / eventConfig.baseSize.x; + configuration._baseInvSizeAndLevel.y = 1.f / eventConfig.baseSize.y; + configuration._baseInvSizeAndLevel.z = 1.f / eventConfig.baseSize.z; + configuration._baseInvSizeAndLevel.w = eventConfig.baseLevel; + configuration._noiseInvSizeAndLevel.x = 1.f / eventConfig.noiseSize.x; + configuration._noiseInvSizeAndLevel.y = 1.f / eventConfig.noiseSize.y; + configuration._noiseInvSizeAndLevel.z = 1.f / eventConfig.noiseSize.z; + configuration._noiseInvSizeAndLevel.w = eventConfig.noiseLevel; + configuration._isInverted = eventConfig._isInverted & 1; + configuration._edgeWidthInvWidth.x = eventConfig.edgeWidth; configuration._edgeWidthInvWidth.y = 1.f / configuration._edgeWidthInvWidth.x; - configuration._innerEdgeColor = config.edgeInnerColor[i]; - configuration._outerEdgeColor = config.edgeOuterColor[i]; - _parameters->_thresholdScale[i] = 1.f + (configuration._edgeWidthInvWidth.x + std::max(0.f, (config.noiseLevel[i] + config.baseLevel[i])*0.5f-0.5f)); - _parameters->_noiseSpeed[i] = config.noiseSpeed[i]; - _parameters->_timing[i] = (FadeJobConfig::Timing) config.timing[i]; + configuration._innerEdgeColor = eventConfig.edgeInnerColor; + configuration._outerEdgeColor = eventConfig.edgeOuterColor; + _parameters->_thresholdScale[i] = 1.f + (configuration._edgeWidthInvWidth.x + std::max(0.f, (eventConfig.noiseLevel + eventConfig.baseLevel)*0.5f-0.5f)); + _parameters->_noiseSpeed[i] = eventConfig.noiseSpeed; + _parameters->_timing[i] = (FadeJobConfig::Timing) eventConfig.timing; } _isBufferDirty = true; } @@ -530,6 +731,7 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon const FadeJobConfig::Timing timing = _parameters->_timing[editedCategory]; const double waitTime = 0.5; // Wait between fade in and out double cycleTime = fmod(_editTime, (eventDuration + waitTime) * 2.0); + bool inverseTime = false; _editTime += deltaTime; _editPreviousTime = now; @@ -546,9 +748,11 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon } else if (cycleTime < (2 * eventDuration + waitTime)) { _editThreshold = computeElementEnterThreshold(cycleTime - (eventDuration + waitTime), eventDuration, timing); + inverseTime = true; } else { _editThreshold = 1.f; + inverseTime = true; } } @@ -559,6 +763,9 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon renderContext->jobConfig->setProperty("threshold", threshold); _editNoiseOffset = _parameters->_noiseSpeed[editedCategory] * (float)_editTime; + if (inverseTime) { + _editNoiseOffset = -_editNoiseOffset; + } switch (editedCategory) { case FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN: diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index b29495cea0..157b4aebac 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -98,7 +98,7 @@ public: float getBaseSizeZ() const; void setBaseLevel(float value); - float getBaseLevel() const { return baseLevel[editedCategory]; } + float getBaseLevel() const { return events[editedCategory].baseLevel; } void setInverted(bool value); bool isInverted() const; @@ -113,7 +113,7 @@ public: float getNoiseSizeZ() const; void setNoiseLevel(float value); - float getNoiseLevel() const { return noiseLevel[editedCategory]; } + float getNoiseLevel() const { return events[editedCategory].noiseLevel; } void setNoiseSpeedX(float value); float getNoiseSpeedX() const; @@ -128,46 +128,56 @@ public: float getEdgeWidth() const; void setEdgeInnerColorR(float value); - float getEdgeInnerColorR() const { return edgeInnerColor[editedCategory].r; } + float getEdgeInnerColorR() const { return events[editedCategory].edgeInnerColor.r; } void setEdgeInnerColorG(float value); - float getEdgeInnerColorG() const { return edgeInnerColor[editedCategory].g; } + float getEdgeInnerColorG() const { return events[editedCategory].edgeInnerColor.g; } void setEdgeInnerColorB(float value); - float getEdgeInnerColorB() const { return edgeInnerColor[editedCategory].b; } + float getEdgeInnerColorB() const { return events[editedCategory].edgeInnerColor.b; } void setEdgeInnerIntensity(float value); - float getEdgeInnerIntensity() const { return edgeInnerColor[editedCategory].a; } + float getEdgeInnerIntensity() const { return events[editedCategory].edgeInnerColor.a; } void setEdgeOuterColorR(float value); - float getEdgeOuterColorR() const { return edgeOuterColor[editedCategory].r; } + float getEdgeOuterColorR() const { return events[editedCategory].edgeOuterColor.r; } void setEdgeOuterColorG(float value); - float getEdgeOuterColorG() const { return edgeOuterColor[editedCategory].g; } + float getEdgeOuterColorG() const { return events[editedCategory].edgeOuterColor.g; } void setEdgeOuterColorB(float value); - float getEdgeOuterColorB() const { return edgeOuterColor[editedCategory].b; } + float getEdgeOuterColorB() const { return events[editedCategory].edgeOuterColor.b; } void setEdgeOuterIntensity(float value); - float getEdgeOuterIntensity() const { return edgeOuterColor[editedCategory].a; } + float getEdgeOuterIntensity() const { return events[editedCategory].edgeOuterColor.a; } void setTiming(int value); - int getTiming() const { return timing[editedCategory]; } + int getTiming() const { return events[editedCategory].timing; } bool manualFade{ false }; float manualThreshold{ 0.f }; int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; - glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]; - glm::vec3 noiseSpeed[EVENT_CATEGORY_COUNT]; - float noiseLevel[EVENT_CATEGORY_COUNT]; - glm::vec3 baseSize[EVENT_CATEGORY_COUNT]; - float baseLevel[EVENT_CATEGORY_COUNT]; - bool _isInverted[EVENT_CATEGORY_COUNT]; - float _duration[EVENT_CATEGORY_COUNT]; - float edgeWidth[EVENT_CATEGORY_COUNT]; - glm::vec4 edgeInnerColor[EVENT_CATEGORY_COUNT]; - glm::vec4 edgeOuterColor[EVENT_CATEGORY_COUNT]; - int timing[EVENT_CATEGORY_COUNT]; + + 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[EVENT_CATEGORY_COUNT]; + + Q_INVOKABLE void save() const; + Q_INVOKABLE void load(); + + static QString eventNames[EVENT_CATEGORY_COUNT]; signals: void dirty(); diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index da180aaefe..698b2384da 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -18,6 +18,7 @@ Column { property var config: Render.getConfig("RenderMainView.FadeConfigure"); property var switchConfig: Render.getConfig("RenderMainView.FadeSwitch"); spacing: 8 + Row { spacing: 8 @@ -43,6 +44,7 @@ Column { // This is a hack to be sure the widgets below properly reflect the change of category: delete the Component // by setting the loader source to Null and then recreate it 100ms later paramWidgetLoader.sourceComponent = undefined; + postpone.interval = 100 postpone.start() } } @@ -68,6 +70,25 @@ Column { } } + Action { + id: saveAction + text: "Save" + onTriggered: { + root.config.save() + } + } + Action { + id: loadAction + text: "Load" + onTriggered: { + root.config.load() + // This is a hack to be sure the widgets below properly reflect the change of category: delete the Component + // by setting the loader source to Null and then recreate it 500ms later + paramWidgetLoader.sourceComponent = undefined; + postpone.interval = 500 + postpone.start() + } + } Component { id: paramWidgets @@ -277,81 +298,94 @@ Column { } } - GroupBox { - title: "Timing" - width: 450 - Column { - spacing: 8 + Column { + GroupBox { + title: "Timing" + width: 450 + Column { + spacing: 8 - ConfigSlider { - label: "Duration" - integral: false - config: root.config - property: "duration" - max: 10.0 - min: 0.1 - width: 400 - } - ComboBox { - width: 400 - model: ["Linear", "Ease In", "Ease Out", "Ease In / Out"] - onCurrentIndexChanged: { - root.config["timing"] = currentIndex; + ConfigSlider { + label: "Duration" + integral: false + config: root.config + property: "duration" + max: 10.0 + min: 0.1 + width: 400 } - } - GroupBox { - title: "Noise Animation" - Column { - spacing: 8 - ConfigSlider { - label: "Speed X" - integral: false - config: root.config - property: "noiseSpeedX" - max: 1.0 - min: -1.0 - width: 400 - } - ConfigSlider { - label: "Speed Y" - integral: false - config: root.config - property: "noiseSpeedY" - max: 1.0 - min: -1.0 - width: 400 - } - ConfigSlider { - label: "Speed Z" - integral: false - config: root.config - property: "noiseSpeedZ" - max: 1.0 - min: -1.0 - width: 400 + ComboBox { + width: 400 + model: ["Linear", "Ease In", "Ease Out", "Ease In / Out"] + currentIndex: root.config["timing"] + onCurrentIndexChanged: { + root.config["timing"] = currentIndex; } } - } - - PlotPerf { - title: "Threshold" - height: parent.evalEvenHeight() - object: Render.getConfig("RenderMainView.DrawFadeOpaque") - valueUnit: "%" - valueScale: 0.01 - valueNumDigits: "1" - plots: [ - { - prop: "threshold", - label: "Threshold", - color: "#FFBB77" + GroupBox { + title: "Noise Animation" + Column { + spacing: 8 + ConfigSlider { + label: "Speed X" + integral: false + config: root.config + property: "noiseSpeedX" + max: 1.0 + min: -1.0 + width: 400 + } + ConfigSlider { + label: "Speed Y" + integral: false + config: root.config + property: "noiseSpeedY" + max: 1.0 + min: -1.0 + width: 400 + } + ConfigSlider { + label: "Speed Z" + integral: false + config: root.config + property: "noiseSpeedZ" + max: 1.0 + min: -1.0 + width: 400 + } } - ] - } + } + PlotPerf { + title: "Threshold" + height: parent.evalEvenHeight() + object: Render.getConfig("RenderMainView.DrawFadeOpaque") + valueUnit: "%" + valueScale: 0.01 + valueNumDigits: "1" + plots: [ + { + prop: "threshold", + label: "Threshold", + color: "#FFBB77" + } + ] + } + + } } - } + Row { + spacing: 8 + Button { + action: saveAction + } + Button { + action: loadAction + } + } + + } } } } From 704effc0a6a75b3873c693d22ec826aeba8654d5 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 4 Jul 2017 17:38:45 +0200 Subject: [PATCH 35/86] Added cubic interpolation in noise for rounder effect --- libraries/render-utils/src/Fade.slh | 3 +++ libraries/render-utils/src/FadeEffect.cpp | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index d3ab532650..28fe718942 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -54,6 +54,9 @@ float evalFadeNoiseGradient(vec3 position) { vec3 noisePosition = position * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.xyz + fadeNoiseOffset; vec3 noisePositionFloored = floor(noisePosition); vec3 noisePositionFraction = fract(noisePosition); + + noisePositionFraction = noisePositionFraction*noisePositionFraction*(3 - 2*noisePositionFraction); + float noiseLowXLowYLowZ = noise3D(noisePositionFloored); float noiseLowXHighYLowZ = noise3D(noisePositionFloored+vec3(0,1,0)); float noiseHighXLowYLowZ = noise3D(noisePositionFloored+vec3(1,0,0)); diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index dec67dac85..f1abca434a 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -157,13 +157,13 @@ FadeJobConfig::FadeJobConfig() events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 10.f, 0.01f, 10.0f }; events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].noiseLevel = 0.7f; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 1.0f, -0.5f, 50.0f }; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, -0.5f, 0.0f }; events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].timing = FadeJobConfig::LINEAR; events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 10000.f, 1.0f, 10000.0f }; events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].baseLevel = 1.f; events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN]._isInverted = true; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN]._duration = 3.f; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].edgeWidth = 0.329f; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN]._duration = 5.f; + events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].edgeWidth = 0.229f; events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }; events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; From 45342a00fd248d26573b78e5967624071508e562 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 4 Jul 2017 17:45:32 +0200 Subject: [PATCH 36/86] Forced faded objects to double sided (without correct lighting for the moment) --- libraries/render-utils/src/FadeEffect.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index f1abca434a..bb5e5799f6 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -625,6 +625,7 @@ void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const render::ShapeKey::Builder defaultKeyBuilder; defaultKeyBuilder.withFade(); + defaultKeyBuilder.withoutCullFace(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; From 23bfc2c13d9b87848c056f5e41de474d061840bf Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 4 Jul 2017 18:36:54 +0200 Subject: [PATCH 37/86] Fixed compilation on mac and linux --- libraries/render-utils/src/FadeEffect.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index bb5e5799f6..fcc6a52b8c 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -1,5 +1,6 @@ #include "FadeEffect.h" #include "TextureCache.h" +#include "Logging.h" #include #include @@ -694,17 +695,17 @@ float FadeRenderJob::computeElementEnterThreshold(double time, const double peri if (fraction < 1.0) { switch (timing) { default: - fadeAlpha = fraction; + fadeAlpha = (float)fraction; break; case FadeJobConfig::EASE_IN: - fadeAlpha = fraction*fraction*fraction; + fadeAlpha = (float)(fraction*fraction*fraction); break; case FadeJobConfig::EASE_OUT: - fadeAlpha = 1.f - fraction; + fadeAlpha = 1.f - (float)fraction; fadeAlpha = 1.f- fadeAlpha*fadeAlpha*fadeAlpha; break; case FadeJobConfig::EASE_IN_OUT: - fadeAlpha = fraction*fraction*fraction*(fraction*(fraction * 6 - 15) + 10); + fadeAlpha = (float)(fraction*fraction*fraction*(fraction*(fraction * 6 - 15) + 10)); break; } } From b1b11ec756ccdc75b6bfde884de66394f24c110c Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 5 Jul 2017 09:08:51 +0200 Subject: [PATCH 38/86] Correct fix for mac and linux due to multiple Logging.h files --- libraries/render-utils/src/FadeEffect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index fcc6a52b8c..3ffb54f2a2 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -1,6 +1,6 @@ #include "FadeEffect.h" #include "TextureCache.h" -#include "Logging.h" +#include "render/Logging.h" #include #include From e178e369632eac2aca3bfe9a1188bf5d8d3a436c Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 6 Jul 2017 17:29:14 +0200 Subject: [PATCH 39/86] Fixed compilation error --- libraries/render/src/render/ShapePipeline.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 10774bc1e7..7bb73c1e1e 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -256,7 +256,7 @@ public: using ItemSetter = std::function; - ShapePipeline(gpu::PipelinePointer pipeline, LocationsPointer locations, BatchSetter batchSetter, ItemSetter itemSetter) : + ShapePipeline(gpu::PipelinePointer pipeline, LocationsPointer locations, BatchSetter batchSetter = nullptr, ItemSetter itemSetter = nullptr) : pipeline(pipeline), locations(locations), _batchSetter(batchSetter), From 69a7ec42fd325b68911fddee76cd824cca74f494 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 7 Jul 2017 09:16:54 +0200 Subject: [PATCH 40/86] Added fade state in render::Item --- .../src/RenderablePolyVoxEntityItem.cpp | 7 ----- .../src/RenderablePolyVoxEntityItem.h | 1 - libraries/entities/src/EntityItem.h | 1 - libraries/render-utils/src/FadeEffect.cpp | 6 ++-- .../render-utils/src/MeshPartPayload.cpp | 27 ++++++++--------- libraries/render-utils/src/MeshPartPayload.h | 16 +++++----- libraries/render/src/render/Item.h | 29 +++++++++++++++---- 7 files changed, 50 insertions(+), 37 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index fcadb9e439..74b36ed4d4 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -888,13 +888,6 @@ namespace render { payload->_owner->getRenderableInterface()->render(args); } } - - template <> bool payloadMustFade(const PolyVoxPayload::Pointer& payload) { - if (payload && payload->_owner) { - return payload->_owner->mustFade(); - } - return false; - } } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 57f61038f0..8f71e3fbc6 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -40,7 +40,6 @@ namespace render { template <> const ItemKey payloadGetKey(const PolyVoxPayload::Pointer& payload); template <> const Item::Bound payloadGetBound(const PolyVoxPayload::Pointer& payload); template <> void payloadRender(const PolyVoxPayload::Pointer& payload, RenderArgs* args); - template <> bool payloadMustFade(const PolyVoxPayload::Pointer& payload); } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 8132111a8c..92c83651aa 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -455,7 +455,6 @@ public: bool isFading() const { return _isFading; } float getFadingRatio() const { return (isFading() ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f); } - bool mustFade() const { return _isFading; } virtual void emitScriptEvent(const QVariant& message) {} diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 3ffb54f2a2..f6d4a5739b 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -99,13 +99,13 @@ void FadeSwitchJob::distribute(const render::RenderContextPointer& renderContext for (const auto& itemBound : inputItems) { auto& item = scene->getItem(itemBound.id); - if (!item.mustFade() && &item!=editedItem) { +// if (!item.mustFade() && &item!=editedItem) { // No need to fade normalOutput.edit().emplace_back(itemBound); - } +/* } else { fadeOutput.edit().emplace_back(itemBound); - } + }*/ } } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 7db75a4df4..42cc3eb36b 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -320,8 +320,12 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren return payload->render(args); } -template <> bool payloadMustFade(const ModelMeshPartPayload::Pointer& payload) { - return payload->mustFade(); +template <> const Item::FadeState* payloadGetFadeState(const ModelMeshPartPayload::Pointer& payload) { + return &payload->getFadeState(); +} + +template <> Item::FadeState* const payloadEditFadeState(ModelMeshPartPayload::Pointer& payload) { + return &payload->editFadeState(); } } @@ -489,9 +493,9 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { if (wireframe) { builder.withWireframe(); } - if (_fadeState != STATE_COMPLETE) { +/* if (_fadeState != STATE_COMPLETE) { builder.withFade(); - } + }*/ return builder.build(); } @@ -530,10 +534,6 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline: batch.setModelTransform(_transform); } -bool ModelMeshPartPayload::mustFade() const { - return _fadeState != STATE_COMPLETE; -} - void ModelMeshPartPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("ModelMeshPartPayload::render"); @@ -542,15 +542,16 @@ void ModelMeshPartPayload::render(RenderArgs* args) { return; // bail asap } - if (_fadeState == STATE_WAITING_TO_START) { + if (_state == WAITING_TO_START) { if (model->isLoaded()) { - // FIXME as far as I can tell this is the ONLY reason render-util depends on entities. + /* // FIXME as far as I can tell this is the ONLY reason render-util depends on entities. if (EntityItem::getEntitiesShouldFadeFunction()()) { _fadeStartTime = usecTimestampNow(); _fadeState = STATE_IN_PROGRESS; } else { _fadeState = STATE_COMPLETE; - } + }*/ + _state = STARTED; model->setRenderItemsNeedUpdate(); } else { return; @@ -581,12 +582,12 @@ void ModelMeshPartPayload::render(RenderArgs* args) { // apply material properties bindMaterial(batch, locations, args->_enableTexturing); - if (args->_enableFade) { + /* if (args->_enableFade) { // Apply fade effect if (!FadeRenderJob::bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime)) { _fadeState = STATE_COMPLETE; } - } + }*/ /* else { // TODO : very ugly way to update the fade state. Need to improve this with global fade manager. _fadeState = STATE_COMPLETE; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 620976804f..6fa49e7aa4 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -97,7 +97,9 @@ public: int getLayer() const; render::ShapeKey getShapeKey() const override; // shape interface void render(RenderArgs* args) override; - bool mustFade() const; + + const render::Item::FadeState& getFadeState() const { return _fadeState; } + render::Item::FadeState& editFadeState() { return _fadeState; } // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) override; @@ -120,14 +122,13 @@ public: private: enum State : uint8_t { - STATE_WAITING_TO_START = 0, - STATE_IN_PROGRESS = 1, - STATE_COMPLETE = 2, + WAITING_TO_START = 0, + STARTED = 1, }; - mutable quint64 _fadeStartTime { 0 }; - mutable State _fadeState { STATE_WAITING_TO_START } ; + mutable State _state { WAITING_TO_START } ; + render::Item::FadeState _fadeState; }; namespace render { @@ -136,7 +137,8 @@ namespace render { template <> int payloadGetLayer(const ModelMeshPartPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload); template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args); - template <> bool payloadMustFade(const ModelMeshPartPayload::Pointer& payload); + template <> const Item::FadeState* payloadGetFadeState(const ModelMeshPartPayload::Pointer& payload); + template <> Item::FadeState* const payloadEditFadeState(ModelMeshPartPayload::Pointer& payload); } #endif // hifi_MeshPartPayload_h diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 4690f0de74..39f8661d74 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -310,19 +310,34 @@ public: }; typedef std::shared_ptr UpdateFunctorPointer; + // This holds the current state for all fade event types applied to this item + class FadeState { + public: + + uint64_t startTime{ 0 }; + glm::vec3 noiseOffset{ 0.f, 0.f, 0.f }; + glm::vec3 baseOffset{ 0.f, 0.f, 0.f }; + glm::vec3 baseSize{ 1.f, 1.f, 1.f }; + float threshold{ 0.f }; + uint8_t eventType{ (uint8_t)-1 }; + + }; + // Payload is whatever is in this Item and implement the Payload Interface class PayloadInterface { public: virtual const ItemKey getKey() const = 0; virtual const Bound getBound() const = 0; virtual int getLayer() const = 0; - virtual bool mustFade() const = 0; virtual void render(RenderArgs* args) = 0; virtual const ShapeKey getShapeKey() const = 0; virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const = 0; + virtual const FadeState* getFadeState() const = 0; + virtual FadeState* const editFadeState() = 0; + ~PayloadInterface() {} // Status interface is local to the base class @@ -364,8 +379,6 @@ public: // Get the layer where the item belongs. 0 by default meaning NOT LAYERED int getLayer() const { return _payload->getLayer(); } - bool mustFade() const { return _payload->mustFade(); } - // Render call for the item void render(RenderArgs* args) const { _payload->render(args); } @@ -378,6 +391,9 @@ public: // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } + const FadeState* getFadeState() const { return _payload->getFadeState(); } + FadeState* const editFadeState() { return _payload->editFadeState(); } + protected: PayloadPointer _payload; ItemKey _key; @@ -411,7 +427,8 @@ template const ItemKey payloadGetKey(const std::shared_ptr& payload template const Item::Bound payloadGetBound(const std::shared_ptr& payloadData) { return Item::Bound(); } template int payloadGetLayer(const std::shared_ptr& payloadData) { return 0; } template void payloadRender(const std::shared_ptr& payloadData, RenderArgs* args) { } -template bool payloadMustFade(const std::shared_ptr& payloadData) { return false; } +template const Item::FadeState* payloadGetFadeState(const std::shared_ptr& payloadData) { return nullptr; } +template Item::FadeState* const payloadEditFadeState(std::shared_ptr& payloadData) { return nullptr; } // Shape type interface // This allows shapes to characterize their pipeline via a ShapeKey, to be picked with a subclass of Shape. @@ -438,7 +455,9 @@ public: virtual const ItemKey getKey() const override { return payloadGetKey(_data); } virtual const Item::Bound getBound() const override { return payloadGetBound(_data); } virtual int getLayer() const override { return payloadGetLayer(_data); } - virtual bool mustFade() const override { return payloadMustFade(_data); } + + virtual const Item::FadeState* getFadeState() const { return payloadGetFadeState(_data); } + virtual Item::FadeState* const editFadeState() { return payloadEditFadeState(_data); } virtual void render(RenderArgs* args) override { payloadRender(_data, args); } From 5ab093dc387cdc6fd8d27643b64c08ae94a5c877 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 7 Jul 2017 11:01:47 +0200 Subject: [PATCH 41/86] Preparing to introducte TransitionStage --- .../src/RenderablePolyVoxEntityItem.cpp | 4 +- libraries/render-utils/src/FadeEffect.cpp | 297 +++++------------- libraries/render-utils/src/FadeEffect.h | 133 ++------ .../render-utils/src/RenderDeferredTask.cpp | 21 +- libraries/render/src/render/Item.h | 6 +- 5 files changed, 101 insertions(+), 360 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 74b36ed4d4..c10e5c7a27 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -829,10 +829,10 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { } // Apply fade effect - if (args->_enableFade) { +/* if (args->_enableFade) { FadeRenderJob::bindPerBatch(batch, render::ShapePipeline::Slot::MAP::FADE_MASK, render::ShapePipeline::Slot::BUFFER::FADE_PARAMETERS); FadeRenderJob::bindPerItem(batch, pipeline.get(), glm::vec3(0, 0, 0), _fadeStartTime); - } + }*/ int voxelVolumeSizeLocation = pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize"); batch._glUniform3f(voxelVolumeSizeLocation, voxelVolumeSize.x, voxelVolumeSize.y, voxelVolumeSize.z); diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index f6d4a5739b..cc17aada8e 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -21,103 +21,6 @@ inline float valueToParameterPow(float value, const double minValue, const doubl return (float)(log(double(value) / minValue) / log(maxOverMinValue)); } -void FadeSwitchJob::configure(const Config& config) { - _parameters->_isEditEnabled = config.editFade; -} - -void FadeSwitchJob::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { - auto& normalOutputs = output.edit0().edit0(); - auto& fadeOutputs = output.edit1(); - - // Only shapes are affected by fade at this time. - normalOutputs[RenderFetchCullSortTask::LIGHT].edit() = input.get0()[RenderFetchCullSortTask::LIGHT].get(); - normalOutputs[RenderFetchCullSortTask::META].edit() = input.get0()[RenderFetchCullSortTask::META].get(); - normalOutputs[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE].edit() = input.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE].get(); - normalOutputs[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE].edit() = input.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE].get(); - normalOutputs[RenderFetchCullSortTask::BACKGROUND].edit() = input.get0()[RenderFetchCullSortTask::BACKGROUND].get(); - output.edit0().edit1() = input.get1(); - - // Find the nearest item that intersects the view direction - const render::Item* editedItem = nullptr; - if (_parameters->_isEditEnabled) { - float nearestOpaqueDistance = std::numeric_limits::max(); - float nearestTransparentDistance = std::numeric_limits::max(); - const render::Item* nearestItem; - - editedItem = findNearestItem(renderContext, input.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE], nearestOpaqueDistance); - nearestItem = findNearestItem(renderContext, input.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE], nearestTransparentDistance); - if (nearestTransparentDistance < nearestOpaqueDistance) { - editedItem = nearestItem; - } - - if (editedItem) { - output.edit2() = editedItem->getBound(); - } - } - - // Now, distribute items that need to be faded accross both outputs - distribute(renderContext, input.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE], normalOutputs[RenderFetchCullSortTask::OPAQUE_SHAPE], fadeOutputs[OPAQUE_SHAPE], editedItem); - distribute(renderContext, input.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE], normalOutputs[RenderFetchCullSortTask::TRANSPARENT_SHAPE], fadeOutputs[TRANSPARENT_SHAPE], editedItem); -} - -const render::Item* FadeSwitchJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const { - const glm::vec3 rayOrigin = renderContext->args->getViewFrustum().getPosition(); - const glm::vec3 rayDirection = renderContext->args->getViewFrustum().getDirection(); - const auto& inputItems = input.get(); - auto& scene = renderContext->_scene; - BoxFace face; - glm::vec3 normal; - float isectDistance; - const render::Item* nearestItem = nullptr; - const float minDistance = 2.f; - - for (const auto& itemBound : inputItems) { - if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { - if (isectDistance>minDistance && isectDistance < minIsectDistance) { - auto& item = scene->getItem(itemBound.id); - - if (item.getKey().isShape() && !item.getKey().isMeta()) { - nearestItem = &item; - minIsectDistance = isectDistance; - } - } - } - } - return nearestItem; -} - -void FadeSwitchJob::distribute(const render::RenderContextPointer& renderContext, const render::Varying& input, - render::Varying& normalOutput, render::Varying& fadeOutput, const render::Item* editedItem) const { - auto& scene = renderContext->_scene; - assert(_parameters); - const auto& inputItems = input.get(); - - // Clear previous values - normalOutput.edit().clear(); - fadeOutput.edit().clear(); - - for (const auto& itemBound : inputItems) { - auto& item = scene->getItem(itemBound.id); - -// if (!item.mustFade() && &item!=editedItem) { - // No need to fade - normalOutput.edit().emplace_back(itemBound); -/* } - else { - fadeOutput.edit().emplace_back(itemBound); - }*/ - } -} - -FadeCommonParameters::FadeCommonParameters() -{ - _durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] = 0.f; - _durations[FadeJobConfig::BUBBLE_ISECT_OWNER] = 0.f; - _durations[FadeJobConfig::BUBBLE_ISECT_TRESPASSER] = 0.f; - _durations[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN] = 0.f; - _durations[FadeJobConfig::AVATAR_CHANGE] = 0.f; -} - FadeJobConfig::FadeJobConfig() { events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 0.75f, 0.75f, 0.75f }; @@ -556,137 +459,54 @@ void FadeJobConfig::load() { } } -FadeConfigureJob::FadeConfigureJob(FadeCommonParameters::Pointer commonParams) : - _parameters{ commonParams } +FadeJob::FadeJob() { auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png"; _fadeMaskMap = DependencyManager::get()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); } -void FadeConfigureJob::configure(const Config& config) { - assert(_parameters); - _parameters->_editedCategory = config.editedCategory; - _parameters->_isManualThresholdEnabled = config.manualFade; - _parameters->_manualThreshold = config.manualThreshold; +void FadeJob::configure(const Config& config) { + auto& configurations = _configurations.edit(); for (auto i = 0; i < FadeJobConfig::EVENT_CATEGORY_COUNT; i++) { - auto& configuration = _configurations[i]; + auto& eventParameters = configurations.parameters[i]; const auto& eventConfig = config.events[i]; - _parameters->_durations[i] = eventConfig._duration; - configuration._baseInvSizeAndLevel.x = 1.f / eventConfig.baseSize.x; - configuration._baseInvSizeAndLevel.y = 1.f / eventConfig.baseSize.y; - configuration._baseInvSizeAndLevel.z = 1.f / eventConfig.baseSize.z; - configuration._baseInvSizeAndLevel.w = eventConfig.baseLevel; - configuration._noiseInvSizeAndLevel.x = 1.f / eventConfig.noiseSize.x; - configuration._noiseInvSizeAndLevel.y = 1.f / eventConfig.noiseSize.y; - configuration._noiseInvSizeAndLevel.z = 1.f / eventConfig.noiseSize.z; - configuration._noiseInvSizeAndLevel.w = eventConfig.noiseLevel; - configuration._isInverted = eventConfig._isInverted & 1; - configuration._edgeWidthInvWidth.x = eventConfig.edgeWidth; - configuration._edgeWidthInvWidth.y = 1.f / configuration._edgeWidthInvWidth.x; - configuration._innerEdgeColor = eventConfig.edgeInnerColor; - configuration._outerEdgeColor = eventConfig.edgeOuterColor; - _parameters->_thresholdScale[i] = 1.f + (configuration._edgeWidthInvWidth.x + std::max(0.f, (eventConfig.noiseLevel + eventConfig.baseLevel)*0.5f-0.5f)); - _parameters->_noiseSpeed[i] = eventConfig.noiseSpeed; - _parameters->_timing[i] = (FadeJobConfig::Timing) eventConfig.timing; + 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)); } - _isBufferDirty = true; } -void FadeConfigureJob::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { - if (_isBufferDirty || _parameters->_isEditEnabled) { - 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 = 1.0f / input.getDimensions().y; +const FadeJob* FadeJob::_currentInstance{ nullptr }; +gpu::TexturePointer FadeJob::_currentFadeMaskMap; +const gpu::BufferView* FadeJob::_currentFadeBuffer{ nullptr }; + +void FadeJob::run(const render::RenderContextPointer& renderContext, const Input& input) { + const Config* jobConfig = static_cast(renderContext->jobConfig.get()); + auto scene = renderContext->args->_scene; + + // And now update fade effect on all visible items + for (auto i = 0; i < RenderFetchCullSortTask::NUM_BUCKETS; i++) { + auto& bucket = input[i].get(); + + for (const auto& itemBound : bucket) { + auto& item = scene->getItem(itemBound.id); + + //updateFadeOnItem(item); } - _isBufferDirty = false; - } - output.edit0() = _fadeMaskMap; -} - -const FadeRenderJob* FadeRenderJob::_currentInstance{ nullptr }; -gpu::TexturePointer FadeRenderJob::_currentFadeMaskMap; -const gpu::BufferView* FadeRenderJob::_currentFadeBuffer{ nullptr }; - -void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const Input& inputs) { - assert(renderContext->args); - assert(renderContext->args->hasViewFrustum()); - - const auto& inItems = inputs.get0(); - - if (!inItems.empty()) { - const auto& lightingModel = inputs.get1(); - const auto& configuration = inputs.get2(); - const auto& fadeMaskMap = configuration.get0(); - const auto& fadeParamBuffer = configuration.get1(); - - RenderArgs* args = renderContext->args; - render::ShapeKey::Builder defaultKeyBuilder; - - defaultKeyBuilder.withFade(); - defaultKeyBuilder.withoutCullFace(); - - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - args->_batch = &batch; - - // Very, very ugly hack to keep track of the current fade render job - _currentInstance = this; - _currentFadeMaskMap = fadeMaskMap; - _currentFadeBuffer = &fadeParamBuffer; - - // Update interactive edit effect - if (_parameters->_isEditEnabled) { - updateFadeEdit(renderContext, inItems.front()); - } - else { - _editPreviousTime = 0; - } - - // Setup camera, projection and viewport for all items - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - - glm::mat4 projMat; - Transform viewMat; - args->getViewFrustum().evalProjectionMatrix(projMat); - args->getViewFrustum().evalViewTransform(viewMat); - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - - // Setup lighting model for all items; - batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); - - // From the lighting model define a global shapKey ORED with individiual keys - render::ShapeKey::Builder keyBuilder = defaultKeyBuilder; - if (lightingModel->isWireframeEnabled()) { - keyBuilder.withWireframe(); - } - - // Prepare fade effect - bindPerBatch(batch, fadeMaskMap, render::ShapePipeline::Slot::MAP::FADE_MASK, &fadeParamBuffer, render::ShapePipeline::Slot::BUFFER::FADE_PARAMETERS); - - render::ShapeKey globalKey = keyBuilder.build(); - args->_globalShapeKey = globalKey._flags.to_ulong(); - args->_enableFade = true; - - renderShapes(renderContext, _shapePlumber, inItems, -1, globalKey); - - args->_enableFade = false; - args->_batch = nullptr; - args->_globalShapeKey = 0; - - // Very, very ugly hack to keep track of the current fade render job - _currentInstance = nullptr; - _currentFadeMaskMap.reset(); - _currentFadeBuffer = nullptr; - }); } } -float FadeRenderJob::computeElementEnterThreshold(double time, const double period, FadeJobConfig::Timing timing) const { +float FadeJob::computeElementEnterThreshold(double time, const double period, FadeJobConfig::Timing timing) const { assert(period > 0.0); float fadeAlpha = 1.0f; const double INV_FADE_PERIOD = 1.0 / period; @@ -712,16 +532,17 @@ float FadeRenderJob::computeElementEnterThreshold(double time, const double peri return fadeAlpha; } -float FadeRenderJob::computeFadePercent(quint64 startTime) { +float FadeJob::computeFadePercent(quint64 startTime) { const double time = (double)(int64_t(usecTimestampNow()) - int64_t(startTime)) / (double)(USECS_PER_SECOND); - assert(_currentInstance); +/* assert(_currentInstance); return _currentInstance->computeElementEnterThreshold(time, _currentInstance->_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN], - _currentInstance->_parameters->_timing[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]); + _currentInstance->_parameters->_timing[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]);*/ + return (float)time; } -void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderContext, const render::ItemBound& itemBounds) { - if (_editPreviousTime == 0) { +void FadeJob::updateFadeEdit(const render::RenderContextPointer& renderContext, const render::ItemBound& itemBounds) { +/* if (_editPreviousTime == 0) { _editPreviousTime = usecTimestampNow(); _editTime = 0.0; } @@ -804,32 +625,32 @@ void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderCon default: assert(false); - } + }*/ } -void FadeRenderJob::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation) { +void FadeJob::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation) { assert(_currentFadeMaskMap); assert(_currentFadeBuffer!=nullptr); bindPerBatch(batch, _currentFadeMaskMap, fadeMaskMapLocation, _currentFadeBuffer, fadeBufferLocation); } -void FadeRenderJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, int fadeMaskMapLocation, const gpu::BufferView* buffer, int fadeBufferLocation) { +void FadeJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, int fadeMaskMapLocation, const gpu::BufferView* buffer, int fadeBufferLocation) { batch.setResourceTexture(fadeMaskMapLocation, texture); batch.setUniformBuffer(fadeBufferLocation, *buffer); } -void FadeRenderJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, const gpu::BufferView* buffer, const gpu::PipelinePointer& pipeline) { +void FadeJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, const gpu::BufferView* buffer, const gpu::PipelinePointer& pipeline) { auto program = pipeline->getProgram(); auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap"); auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer"); bindPerBatch(batch, texture, maskMapLocation, buffer, bufferLocation); } -bool FadeRenderJob::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime) { +bool FadeJob::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime) { return bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime); } -bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime) { +bool FadeJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime) { auto& uniforms = pipeline->getProgram()->getUniforms(); auto fadeNoiseOffsetLocation = uniforms.findLocation("fadeNoiseOffset"); auto fadeBaseOffsetLocation = uniforms.findLocation("fadeBaseOffset"); @@ -845,7 +666,7 @@ bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline threshold = 1.f-computeFadePercent(startTime); // Manage interactive edition override - assert(_currentInstance); +/* assert(_currentInstance); if (_currentInstance->_parameters->_isEditEnabled) { eventCategory = _currentInstance->_parameters->_editedCategory; threshold = _currentInstance->_editThreshold; @@ -859,7 +680,7 @@ bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline if (eventCategory != FadeJobConfig::BUBBLE_ISECT_OWNER) { threshold = (threshold - 0.5f)*_currentInstance->_parameters->_thresholdScale[eventCategory] + 0.5f; } - + */ batch._glUniform1i(fadeCategoryLocation, eventCategory); batch._glUniform1f(fadeThresholdLocation, threshold); // This is really temporary @@ -871,3 +692,29 @@ bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline } return false; } + +const render::Item* FadeJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const { + const glm::vec3 rayOrigin = renderContext->args->getViewFrustum().getPosition(); + const glm::vec3 rayDirection = renderContext->args->getViewFrustum().getDirection(); + const auto& inputItems = input.get(); + auto& scene = renderContext->_scene; + BoxFace face; + glm::vec3 normal; + float isectDistance; + const render::Item* nearestItem = nullptr; + const float minDistance = 2.f; + + for (const auto& itemBound : inputItems) { + if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { + if (isectDistance>minDistance && isectDistance < minIsectDistance) { + auto& item = scene->getItem(itemBound.id); + + if (item.getKey().isShape() && !item.getKey().isMeta()) { + nearestItem = &item; + minIsectDistance = isectDistance; + } + } + } + } + return nearestItem; +} diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 157b4aebac..ede3d1843f 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -15,21 +15,6 @@ #include #include -#include "LightingModel.h" - -class FadeSwitchJobConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty) - -public: - - bool editFade{ false }; - -signals: - void dirty(); - -}; - class FadeJobConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int editedCategory MEMBER editedCategory WRITE setEditedCategory NOTIFY dirtyCategory) @@ -58,6 +43,8 @@ class FadeJobConfig : public render::Job::Config { Q_PROPERTY(float noiseSpeedX READ getNoiseSpeedX WRITE setNoiseSpeedX NOTIFY dirty) Q_PROPERTY(float noiseSpeedY READ getNoiseSpeedY WRITE setNoiseSpeedY NOTIFY dirty) Q_PROPERTY(float noiseSpeedZ READ getNoiseSpeedZ WRITE setNoiseSpeedZ NOTIFY dirty) + Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty) + Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty) public: @@ -153,10 +140,6 @@ public: void setTiming(int value); int getTiming() const { return events[editedCategory].timing; } - - bool manualFade{ false }; - float manualThreshold{ 0.f }; - int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; struct Event { glm::vec4 edgeInnerColor; @@ -173,6 +156,11 @@ public: }; Event events[EVENT_CATEGORY_COUNT]; + float threshold{ 0.f }; + float manualThreshold{ 0.f }; + int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; + bool editFade{ false }; + bool manualFade{ false }; Q_INVOKABLE void save() const; Q_INVOKABLE void load(); @@ -180,67 +168,20 @@ public: static QString eventNames[EVENT_CATEGORY_COUNT]; signals: + void dirty(); void dirtyCategory(); }; -struct FadeCommonParameters -{ - using Pointer = std::shared_ptr; - - FadeCommonParameters(); - - 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]; - glm::vec3 _noiseSpeed[FadeJobConfig::EVENT_CATEGORY_COUNT]; - FadeJobConfig::Timing _timing[FadeJobConfig::EVENT_CATEGORY_COUNT]; -}; - -class FadeSwitchJob { -public: - - enum FadeBuckets { - OPAQUE_SHAPE = 0, - TRANSPARENT_SHAPE, - - NUM_BUCKETS - }; - - using FadeOutput = render::VaryingArray; - - using Input = RenderFetchCullSortTask::Output; - using Output = render::VaryingSet3 < RenderFetchCullSortTask::Output, FadeOutput, render::Item::Bound > ; - using Config = FadeSwitchJobConfig; - using JobModel = render::Job::ModelIO; - - FadeSwitchJob(FadeCommonParameters::Pointer commonParams) : _parameters{ commonParams } {} - - void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); - -private: - - FadeCommonParameters::Pointer _parameters; - - void distribute(const render::RenderContextPointer& renderContext, const render::Varying& input, - render::Varying& normalOutput, render::Varying& fadeOutput, const render::Item* editedItem = nullptr) const; - const render::Item* findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const; -}; - struct FadeParameters { - glm::vec4 _baseInvSizeAndLevel; glm::vec4 _noiseInvSizeAndLevel; glm::vec4 _innerEdgeColor; glm::vec4 _outerEdgeColor; glm::vec2 _edgeWidthInvWidth; + glm::float32 _baseLevel; glm::int32 _isInverted; - glm::float32 _padding; }; struct FadeConfiguration @@ -248,56 +189,17 @@ struct FadeConfiguration FadeParameters parameters[FadeJobConfig::EVENT_CATEGORY_COUNT]; }; -class FadeConfigureJob { +class FadeJob { public: - using UniformBuffer = gpu::StructBuffer; - using Input = render::Item::Bound ; - using Output = render::VaryingSet2; using Config = FadeJobConfig; - using JobModel = render::Job::ModelIO; + using Input = RenderFetchCullSortTask::BucketList; + using JobModel = render::Job::ModelI; - FadeConfigureJob(FadeCommonParameters::Pointer commonParams); - - const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; } + FadeJob(); void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); - -private: - - FadeCommonParameters::Pointer _parameters; - bool _isBufferDirty{ true }; - gpu::TexturePointer _fadeMaskMap; - FadeParameters _configurations[FadeJobConfig::EVENT_CATEGORY_COUNT]; -}; - - -class FadeRenderJobConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty) - -public: - - float threshold{ 0.f }; - -signals: - void dirty(); - -}; - -class FadeRenderJob { - -public: - - using Config = FadeRenderJobConfig; - using Input = render::VaryingSet3; - using JobModel = render::Job::ModelI; - - FadeRenderJob(FadeCommonParameters::Pointer commonParams, render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber }, _parameters{ commonParams } {} - - void configure(const Config& config) {} void run(const render::RenderContextPointer& renderContext, const Input& inputs); static void bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation); @@ -311,15 +213,17 @@ public: private: - static const FadeRenderJob* _currentInstance; + static const FadeJob* _currentInstance; static gpu::TexturePointer _currentFadeMaskMap; static const gpu::BufferView* _currentFadeBuffer; - render::ShapePlumberPointer _shapePlumber; - FadeCommonParameters::Pointer _parameters; + gpu::StructBuffer _configurations; + gpu::TexturePointer _fadeMaskMap; + float _thresholdScale[FadeJobConfig::EVENT_CATEGORY_COUNT]; float computeElementEnterThreshold(double time, const double period, FadeJobConfig::Timing timing) const; + // Everything needed for interactive edition uint64_t _editPreviousTime{ 0 }; double _editTime{ 0.0 }; @@ -328,6 +232,7 @@ private: glm::vec3 _editBaseOffset{ 0.f, 0.f, 0.f }; void updateFadeEdit(const render::RenderContextPointer& renderContext, const render::ItemBound& itemBounds); + const render::Item* findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const; }; #endif // hifi_FadeEffect_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 92f23751f4..abd7be0093 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -53,14 +53,9 @@ void RenderDeferredTask::configure(const Config& config) } void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { - auto commonFadeParameters = std::make_shared(); - const auto fadeSwitchOutputs = task.addJob("FadeSwitch", input, commonFadeParameters).get(); - - const auto& items = fadeSwitchOutputs.get0(); - const auto& fadeItems = fadeSwitchOutputs.get1(); - const auto& fadeEditedItem = fadeSwitchOutputs[2]; - - const auto fadeConfigureOutputs = task.addJob("FadeConfigure", fadeEditedItem, commonFadeParameters).get(); + const auto& items = input.get(); + +// task.addJob("Fade", fadeEditedItem, commonFadeParameters).get(); // Prepare the ShapePipelines ShapePlumberPointer shapePlumber = std::make_shared(); @@ -101,11 +96,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).asVarying(); task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber); - const auto fadeOpaques = fadeItems[FadeSwitchJob::OPAQUE_SHAPE]; - const auto fadeOpaqueInputs = FadeRenderJob::Input(fadeOpaques, lightingModel, fadeConfigureOutputs).asVarying(); - task.addJob("DrawFadeOpaque", fadeOpaqueInputs, commonFadeParameters, shapePlumber); - - task.addJob("OpaqueRangeTimer", opaqueRangeTimer); @@ -159,10 +149,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).asVarying(); task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); - const auto fadeTransparents = fadeItems[FadeSwitchJob::TRANSPARENT_SHAPE]; - const auto fadeTransparentInputs = FadeRenderJob::Input(fadeTransparents, lightingModel, fadeConfigureOutputs).asVarying(); - task.addJob("DrawFadeTransparent", fadeTransparentInputs, commonFadeParameters, shapePlumber); - // LIght Cluster Grid Debuging job { const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).asVarying(); @@ -176,7 +162,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("ToneMapping", toneMappingInputs); { // DEbug the bounds of the rendered items, still look at the zbuffer - task.addJob("DrawFadedOpaqueBounds", fadeOpaques); task.addJob("DrawMetaBounds", metas); task.addJob("DrawOpaqueBounds", opaques); task.addJob("DrawTransparentBounds", transparents); diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 39f8661d74..543a130427 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -314,12 +314,16 @@ public: class FadeState { public: + enum { + INACTIVE = (uint8_t)-1 + }; + + uint8_t eventType{ INACTIVE }; uint64_t startTime{ 0 }; glm::vec3 noiseOffset{ 0.f, 0.f, 0.f }; glm::vec3 baseOffset{ 0.f, 0.f, 0.f }; glm::vec3 baseSize{ 1.f, 1.f, 1.f }; float threshold{ 0.f }; - uint8_t eventType{ (uint8_t)-1 }; }; From 4256a1f2a78c8fc1682661b4561aa386542588c7 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 7 Jul 2017 15:16:20 +0200 Subject: [PATCH 42/86] Preparing for merge with stage. DOESN'T COMPILE! --- .../src/RenderablePolyVoxEntityItem.cpp | 2 - .../src/RenderableShapeEntityItem.cpp | 1 - libraries/render-utils/src/Fade.slh | 16 +- libraries/render-utils/src/FadeEffect.cpp | 393 ++++++++++-------- libraries/render-utils/src/FadeEffect.h | 91 ++-- libraries/render-utils/src/Fade_shared.slh | 22 + libraries/render-utils/src/GeometryCache.cpp | 1 - .../render-utils/src/MeshPartPayload.cpp | 9 - libraries/render-utils/src/MeshPartPayload.h | 8 - .../render-utils/src/RenderDeferredTask.cpp | 7 +- .../render-utils/src/RenderPipelines.cpp | 62 +-- .../render-utils/src/RenderShadowTask.cpp | 6 +- libraries/render/src/render/Item.cpp | 8 + libraries/render/src/render/Item.h | 34 +- libraries/render/src/render/Transition.h | 46 ++ .../render/src/render/TransitionStage.cpp | 25 ++ libraries/render/src/render/TransitionStage.h | 53 +++ libraries/render/src/task/Task.h | 6 + tests/gpu-test/src/TestWindow.cpp | 2 +- 19 files changed, 446 insertions(+), 346 deletions(-) create mode 100644 libraries/render-utils/src/Fade_shared.slh create mode 100644 libraries/render/src/render/Transition.h create mode 100644 libraries/render/src/render/TransitionStage.cpp create mode 100644 libraries/render/src/render/TransitionStage.h diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index c10e5c7a27..085cd69352 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -63,8 +63,6 @@ #include "EntityEditPacketSender.h" #include "PhysicalEntitySimulation.h" -#include "FadeEffect.h" - gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipelines[2] = { nullptr, nullptr }; gpu::PipelinePointer RenderablePolyVoxEntityItem::_wireframePipelines[2] = { nullptr, nullptr }; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index a8ead00771..dd5487ff45 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 28fe718942..0d3c397812 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -18,16 +18,7 @@ <@func declareFadeFragment()@> -struct FadeParameters -{ - vec4 _baseInvSizeAndLevel; - vec4 _noiseInvSizeAndLevel; - vec4 _innerEdgeColor; - vec4 _outerEdgeColor; - vec2 _edgeWidthInvWidth; - int _isInverted; - float _padding; -}; +<@include Fade_shared.slh@> #define EVENT_CATEGORY_COUNT 5 @@ -37,6 +28,7 @@ uniform fadeParametersBuffer { uniform int fadeCategory; uniform vec3 fadeNoiseOffset; uniform vec3 fadeBaseOffset; +uniform vec3 fadeBaseInvSize; uniform float fadeThreshold; uniform sampler2D fadeMaskMap; @@ -76,9 +68,9 @@ float evalFadeNoiseGradient(vec3 position) { } float evalFadeBaseGradient(vec3 position) { - float gradient = length((position - fadeBaseOffset) * fadeParameters[fadeCategory]._baseInvSizeAndLevel.xyz); + float gradient = length((position - fadeBaseOffset) * fadeBaseInvSize.xyz); gradient = gradient-0.5; // Center on value 0.5 - gradient *= fadeParameters[fadeCategory]._baseInvSizeAndLevel.w; + gradient *= fadeParameters[fadeCategory]._baseLevel; return gradient; } diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index cc17aada8e..948f3f8f2b 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -21,241 +21,241 @@ inline float valueToParameterPow(float value, const double minValue, const doubl return (float)(log(double(value) / minValue) / log(maxOverMinValue)); } -FadeJobConfig::FadeJobConfig() +FadeConfig::FadeConfig() { - events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 0.75f, 0.75f, 0.75f }; - events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].noiseLevel = 1.f; - events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f }; - events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].timing = FadeJobConfig::LINEAR; - events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 1.0f, 1.0f, 1.0f }; - events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].baseLevel = 0.f; - events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]._isInverted = false; - events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]._duration = 4.f; - events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].edgeWidth = 0.1f; - events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }; - events[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; + events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 0.75f, 0.75f, 0.75f }; + events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].noiseLevel = 1.f; + events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f }; + events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].timing = FadeConfig::LINEAR; + events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 1.0f, 1.0f, 1.0f }; + events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].baseLevel = 0.f; + events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN]._isInverted = false; + events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN]._duration = 4.f; + events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].edgeWidth = 0.1f; + events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }; + events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; - events[FadeJobConfig::BUBBLE_ISECT_OWNER].noiseSize = glm::vec3{ 1.5f, 1.0f/25.f, 0.5f }; - events[FadeJobConfig::BUBBLE_ISECT_OWNER].noiseLevel = 0.37f; - events[FadeJobConfig::BUBBLE_ISECT_OWNER].noiseSpeed = glm::vec3{ 1.0f, 0.2f, 1.0f }; - events[FadeJobConfig::BUBBLE_ISECT_OWNER].timing = FadeJobConfig::LINEAR; - events[FadeJobConfig::BUBBLE_ISECT_OWNER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f }; - events[FadeJobConfig::BUBBLE_ISECT_OWNER].baseLevel = 1.f; - events[FadeJobConfig::BUBBLE_ISECT_OWNER]._isInverted = false; - events[FadeJobConfig::BUBBLE_ISECT_OWNER]._duration = 4.f; - events[FadeJobConfig::BUBBLE_ISECT_OWNER].edgeWidth = 0.02f; - events[FadeJobConfig::BUBBLE_ISECT_OWNER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; - events[FadeJobConfig::BUBBLE_ISECT_OWNER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }; + events[render::Transition::BUBBLE_ISECT_OWNER].noiseSize = glm::vec3{ 1.5f, 1.0f/25.f, 0.5f }; + events[render::Transition::BUBBLE_ISECT_OWNER].noiseLevel = 0.37f; + events[render::Transition::BUBBLE_ISECT_OWNER].noiseSpeed = glm::vec3{ 1.0f, 0.2f, 1.0f }; + events[render::Transition::BUBBLE_ISECT_OWNER].timing = FadeConfig::LINEAR; + events[render::Transition::BUBBLE_ISECT_OWNER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f }; + events[render::Transition::BUBBLE_ISECT_OWNER].baseLevel = 1.f; + events[render::Transition::BUBBLE_ISECT_OWNER]._isInverted = false; + events[render::Transition::BUBBLE_ISECT_OWNER]._duration = 4.f; + events[render::Transition::BUBBLE_ISECT_OWNER].edgeWidth = 0.02f; + events[render::Transition::BUBBLE_ISECT_OWNER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; + events[render::Transition::BUBBLE_ISECT_OWNER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }; - events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].noiseSize = glm::vec3{ 0.5f, 1.0f / 25.f, 0.5f }; - events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].noiseLevel = 1.f; - events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].noiseSpeed = glm::vec3{ 1.0f, 0.2f, 1.0f }; - events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].timing = FadeJobConfig::LINEAR; - events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f }; - events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].baseLevel = 0.f; - events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER]._isInverted = false; - events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER]._duration = 4.f; - events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].edgeWidth = 0.025f; - events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; - events[FadeJobConfig::BUBBLE_ISECT_TRESPASSER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }; + events[render::Transition::BUBBLE_ISECT_TRESPASSER].noiseSize = glm::vec3{ 0.5f, 1.0f / 25.f, 0.5f }; + events[render::Transition::BUBBLE_ISECT_TRESPASSER].noiseLevel = 1.f; + events[render::Transition::BUBBLE_ISECT_TRESPASSER].noiseSpeed = glm::vec3{ 1.0f, 0.2f, 1.0f }; + events[render::Transition::BUBBLE_ISECT_TRESPASSER].timing = FadeConfig::LINEAR; + events[render::Transition::BUBBLE_ISECT_TRESPASSER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f }; + events[render::Transition::BUBBLE_ISECT_TRESPASSER].baseLevel = 0.f; + events[render::Transition::BUBBLE_ISECT_TRESPASSER]._isInverted = false; + events[render::Transition::BUBBLE_ISECT_TRESPASSER]._duration = 4.f; + events[render::Transition::BUBBLE_ISECT_TRESPASSER].edgeWidth = 0.025f; + events[render::Transition::BUBBLE_ISECT_TRESPASSER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; + events[render::Transition::BUBBLE_ISECT_TRESPASSER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.0f }; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 10.f, 0.01f, 10.0f }; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].noiseLevel = 0.7f; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, -0.5f, 0.0f }; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].timing = FadeJobConfig::LINEAR; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 10000.f, 1.0f, 10000.0f }; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].baseLevel = 1.f; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN]._isInverted = true; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN]._duration = 5.f; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].edgeWidth = 0.229f; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }; - events[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; + events[render::Transition::USER_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 10.f, 0.01f, 10.0f }; + events[render::Transition::USER_ENTER_LEAVE_DOMAIN].noiseLevel = 0.7f; + events[render::Transition::USER_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, -0.5f, 0.0f }; + events[render::Transition::USER_ENTER_LEAVE_DOMAIN].timing = FadeConfig::LINEAR; + events[render::Transition::USER_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 10000.f, 1.0f, 10000.0f }; + events[render::Transition::USER_ENTER_LEAVE_DOMAIN].baseLevel = 1.f; + events[render::Transition::USER_ENTER_LEAVE_DOMAIN]._isInverted = true; + events[render::Transition::USER_ENTER_LEAVE_DOMAIN]._duration = 5.f; + events[render::Transition::USER_ENTER_LEAVE_DOMAIN].edgeWidth = 0.229f; + events[render::Transition::USER_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }; + events[render::Transition::USER_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; - events[FadeJobConfig::AVATAR_CHANGE].noiseSize = glm::vec3{ 0.4f, 0.4f, 0.4f }; - events[FadeJobConfig::AVATAR_CHANGE].noiseLevel = 1.f; - events[FadeJobConfig::AVATAR_CHANGE].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f }; - events[FadeJobConfig::AVATAR_CHANGE].timing = FadeJobConfig::LINEAR; - events[FadeJobConfig::AVATAR_CHANGE].baseSize = glm::vec3{ 0.4f, 0.4f, 0.4f }; - events[FadeJobConfig::AVATAR_CHANGE].baseLevel = 1.f; - events[FadeJobConfig::AVATAR_CHANGE]._isInverted = false; - events[FadeJobConfig::AVATAR_CHANGE]._duration = 3.f; - events[FadeJobConfig::AVATAR_CHANGE].edgeWidth = 0.05f; - events[FadeJobConfig::AVATAR_CHANGE].edgeInnerColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; - events[FadeJobConfig::AVATAR_CHANGE].edgeOuterColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; + events[render::Transition::AVATAR_CHANGE].noiseSize = glm::vec3{ 0.4f, 0.4f, 0.4f }; + events[render::Transition::AVATAR_CHANGE].noiseLevel = 1.f; + events[render::Transition::AVATAR_CHANGE].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f }; + events[render::Transition::AVATAR_CHANGE].timing = FadeConfig::LINEAR; + events[render::Transition::AVATAR_CHANGE].baseSize = glm::vec3{ 0.4f, 0.4f, 0.4f }; + events[render::Transition::AVATAR_CHANGE].baseLevel = 1.f; + events[render::Transition::AVATAR_CHANGE]._isInverted = false; + events[render::Transition::AVATAR_CHANGE]._duration = 3.f; + events[render::Transition::AVATAR_CHANGE].edgeWidth = 0.05f; + events[render::Transition::AVATAR_CHANGE].edgeInnerColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; + events[render::Transition::AVATAR_CHANGE].edgeOuterColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; } -void FadeJobConfig::setEditedCategory(int value) { +void FadeConfig::setEditedCategory(int value) { assert(value < EVENT_CATEGORY_COUNT); - editedCategory = std::min(EVENT_CATEGORY_COUNT, value); + editedCategory = std::min(render::Transition::EVENT_CATEGORY_COUNT, value); emit dirtyCategory(); emit dirty(); } -void FadeJobConfig::setDuration(float value) { +void FadeConfig::setDuration(float value) { events[editedCategory]._duration = value; emit dirty(); } -float FadeJobConfig::getDuration() const { +float FadeConfig::getDuration() const { return events[editedCategory]._duration; } -void FadeJobConfig::setBaseSizeX(float value) { +void FadeConfig::setBaseSizeX(float value) { events[editedCategory].baseSize.x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE/ FADE_MIN_SCALE); emit dirty(); } -float FadeJobConfig::getBaseSizeX() const { +float FadeConfig::getBaseSizeX() const { return valueToParameterPow(events[editedCategory].baseSize.x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } -void FadeJobConfig::setBaseSizeY(float value) { +void FadeConfig::setBaseSizeY(float value) { events[editedCategory].baseSize.y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } -float FadeJobConfig::getBaseSizeY() const { +float FadeConfig::getBaseSizeY() const { return valueToParameterPow(events[editedCategory].baseSize.y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } -void FadeJobConfig::setBaseSizeZ(float value) { +void FadeConfig::setBaseSizeZ(float value) { events[editedCategory].baseSize.z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } -float FadeJobConfig::getBaseSizeZ() const { +float FadeConfig::getBaseSizeZ() const { return valueToParameterPow(events[editedCategory].baseSize.z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } -void FadeJobConfig::setBaseLevel(float value) { +void FadeConfig::setBaseLevel(float value) { events[editedCategory].baseLevel = value; emit dirty(); } -void FadeJobConfig::setInverted(bool value) { +void FadeConfig::setInverted(bool value) { events[editedCategory]._isInverted = value; emit dirty(); } -bool FadeJobConfig::isInverted() const { +bool FadeConfig::isInverted() const { return events[editedCategory]._isInverted; } -void FadeJobConfig::setNoiseSizeX(float value) { +void FadeConfig::setNoiseSizeX(float value) { events[editedCategory].noiseSize.x = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } -float FadeJobConfig::getNoiseSizeX() const { +float FadeConfig::getNoiseSizeX() const { return valueToParameterPow(events[editedCategory].noiseSize.x, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } -void FadeJobConfig::setNoiseSizeY(float value) { +void FadeConfig::setNoiseSizeY(float value) { events[editedCategory].noiseSize.y = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } -float FadeJobConfig::getNoiseSizeY() const { +float FadeConfig::getNoiseSizeY() const { return valueToParameterPow(events[editedCategory].noiseSize.y, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } -void FadeJobConfig::setNoiseSizeZ(float value) { +void FadeConfig::setNoiseSizeZ(float value) { events[editedCategory].noiseSize.z = parameterToValuePow(value, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); emit dirty(); } -float FadeJobConfig::getNoiseSizeZ() const { +float FadeConfig::getNoiseSizeZ() const { return valueToParameterPow(events[editedCategory].noiseSize.z, FADE_MIN_SCALE, FADE_MAX_SCALE / FADE_MIN_SCALE); } -void FadeJobConfig::setNoiseLevel(float value) { +void FadeConfig::setNoiseLevel(float value) { events[editedCategory].noiseLevel = value; emit dirty(); } -void FadeJobConfig::setNoiseSpeedX(float value) { +void FadeConfig::setNoiseSpeedX(float value) { events[editedCategory].noiseSpeed.x = powf(value, 3.f)*FADE_MAX_SPEED; emit dirty(); } -float FadeJobConfig::getNoiseSpeedX() const { +float FadeConfig::getNoiseSpeedX() const { return powf(events[editedCategory].noiseSpeed.x / FADE_MAX_SPEED, 1.f / 3.f); } -void FadeJobConfig::setNoiseSpeedY(float value) { +void FadeConfig::setNoiseSpeedY(float value) { events[editedCategory].noiseSpeed.y = powf(value, 3.f)*FADE_MAX_SPEED; emit dirty(); } -float FadeJobConfig::getNoiseSpeedY() const { +float FadeConfig::getNoiseSpeedY() const { return powf(events[editedCategory].noiseSpeed.y / FADE_MAX_SPEED, 1.f / 3.f); } -void FadeJobConfig::setNoiseSpeedZ(float value) { +void FadeConfig::setNoiseSpeedZ(float value) { events[editedCategory].noiseSpeed.z = powf(value, 3.f)*FADE_MAX_SPEED; emit dirty(); } -float FadeJobConfig::getNoiseSpeedZ() const { +float FadeConfig::getNoiseSpeedZ() const { return powf(events[editedCategory].noiseSpeed.z / FADE_MAX_SPEED, 1.f / 3.f); } -void FadeJobConfig::setEdgeWidth(float value) { +void FadeConfig::setEdgeWidth(float value) { events[editedCategory].edgeWidth = value * value; emit dirty(); } -float FadeJobConfig::getEdgeWidth() const { +float FadeConfig::getEdgeWidth() const { return sqrtf(events[editedCategory].edgeWidth); } -void FadeJobConfig::setEdgeInnerColorR(float value) { +void FadeConfig::setEdgeInnerColorR(float value) { events[editedCategory].edgeInnerColor.r = value; emit dirty(); } -void FadeJobConfig::setEdgeInnerColorG(float value) { +void FadeConfig::setEdgeInnerColorG(float value) { events[editedCategory].edgeInnerColor.g = value; emit dirty(); } -void FadeJobConfig::setEdgeInnerColorB(float value) { +void FadeConfig::setEdgeInnerColorB(float value) { events[editedCategory].edgeInnerColor.b = value; emit dirty(); } -void FadeJobConfig::setEdgeInnerIntensity(float value) { +void FadeConfig::setEdgeInnerIntensity(float value) { events[editedCategory].edgeInnerColor.a = value; emit dirty(); } -void FadeJobConfig::setEdgeOuterColorR(float value) { +void FadeConfig::setEdgeOuterColorR(float value) { events[editedCategory].edgeOuterColor.r = value; emit dirty(); } -void FadeJobConfig::setEdgeOuterColorG(float value) { +void FadeConfig::setEdgeOuterColorG(float value) { events[editedCategory].edgeOuterColor.g = value; emit dirty(); } -void FadeJobConfig::setEdgeOuterColorB(float value) { +void FadeConfig::setEdgeOuterColorB(float value) { events[editedCategory].edgeOuterColor.b = value; emit dirty(); } -void FadeJobConfig::setEdgeOuterIntensity(float value) { +void FadeConfig::setEdgeOuterIntensity(float value) { events[editedCategory].edgeOuterColor.a = value; emit dirty(); } -void FadeJobConfig::setTiming(int value) { +void FadeConfig::setTiming(int value) { assert(value < TIMING_COUNT); events[editedCategory].timing = value; emit dirty(); } -QString FadeJobConfig::eventNames[EVENT_CATEGORY_COUNT] = { +QString FadeConfig::eventNames[render::Transition::EVENT_CATEGORY_COUNT] = { "element_enter_leave_domain", "bubble_isect_owner", "bubble_isect_trespasser", @@ -263,7 +263,7 @@ QString FadeJobConfig::eventNames[EVENT_CATEGORY_COUNT] = { "avatar_change", }; -void FadeJobConfig::save() const { +void FadeConfig::save() const { assert(category < EVENT_CATEGORY_COUNT); QJsonObject lProperties; const QString configFile = "config/" + eventNames[editedCategory] + ".json"; @@ -292,7 +292,7 @@ void FadeJobConfig::save() const { } } -void FadeJobConfig::load() { +void FadeConfig::load() { const QString configFile = "config/" + eventNames[editedCategory] + ".json"; QUrl path(PathUtils::resourcesPath() + configFile); @@ -468,7 +468,7 @@ FadeJob::FadeJob() void FadeJob::configure(const Config& config) { auto& configurations = _configurations.edit(); - for (auto i = 0; i < FadeJobConfig::EVENT_CATEGORY_COUNT; i++) { + for (auto i = 0; i < render::Transition::EVENT_CATEGORY_COUNT; i++) { auto& eventParameters = configurations.parameters[i]; const auto& eventConfig = config.events[i]; @@ -477,7 +477,7 @@ void FadeJob::configure(const Config& config) { 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._isInverted = eventConfig.isInverted & 1; eventParameters._edgeWidthInvWidth.x = eventConfig.edgeWidth; eventParameters._edgeWidthInvWidth.y = 1.f / eventParameters._edgeWidthInvWidth.x; eventParameters._innerEdgeColor = eventConfig.edgeInnerColor; @@ -486,27 +486,80 @@ void FadeJob::configure(const Config& config) { } } -const FadeJob* FadeJob::_currentInstance{ nullptr }; -gpu::TexturePointer FadeJob::_currentFadeMaskMap; -const gpu::BufferView* FadeJob::_currentFadeBuffer{ nullptr }; - -void FadeJob::run(const render::RenderContextPointer& renderContext, const Input& input) { +void FadeJob::run(const render::RenderContextPointer& renderContext) { const Config* jobConfig = static_cast(renderContext->jobConfig.get()); auto scene = renderContext->args->_scene; + render::TransitionStage* transitionStage; // TODO: get transition stage + uint64_t now = usecTimestampNow(); + const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND); - // And now update fade effect on all visible items - for (auto i = 0; i < RenderFetchCullSortTask::NUM_BUCKETS; i++) { - auto& bucket = input[i].get(); - - for (const auto& itemBound : bucket) { - auto& item = scene->getItem(itemBound.id); - - //updateFadeOnItem(item); - } + // And now update fade effect + for (auto transitionId : *transitionStage) { + auto& state = transitionStage->editTransition(transitionId); + update(*jobConfig, scene, state, deltaTime); } } -float FadeJob::computeElementEnterThreshold(double time, const double period, FadeJobConfig::Timing timing) const { +void FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const { + auto& eventConfig = config.events[transition.eventType]; + auto& item = scene->getItem(transition.itemId); + auto& aabb = item.getBound(); + auto& dimensions = aabb.getDimensions(); + const double eventDuration = (double)eventConfig.duration; + const FadeConfig::Timing timing = (FadeConfig::Timing) eventConfig.timing; + + assert(timing < render::Transition::EVENT_CATEGORY_COUNT); + + switch (transition.eventType) { + case render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN: + transition.threshold = 1.f - computeElementEnterThreshold(transition.time, eventConfig.duration, timing); + transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[transition.eventType] + 0.5f; + transition.noiseOffset = aabb.calcCenter(); + transition.baseOffset = transition.noiseOffset - dimensions.y; + transition.baseInvSize.x = 1.f / dimensions.x; + transition.baseInvSize.y = 1.f / dimensions.y; + transition.baseInvSize.z = 1.f / dimensions.z; + break; + + case render::Transition::BUBBLE_ISECT_OWNER: + { + /* const glm::vec3 cameraPos = renderContext->args->getViewFrustum().getPosition(); + glm::vec3 delta = itemBounds.bound.calcCenter() - cameraPos; + float distance = glm::length(delta); + + delta = glm::normalize(delta) * std::max(0.f, distance - 0.5f); + + _editBaseOffset = cameraPos + delta*_editThreshold; + _editThreshold = 0.33f;*/ + } + break; + + case render::Transition::BUBBLE_ISECT_TRESPASSER: + { + // _editBaseOffset = glm::vec3{ 0.f, 0.f, 0.f }; + } + break; + + case render::Transition::USER_ENTER_LEAVE_DOMAIN: + { +/* _editBaseOffset = itemBounds.bound.calcCenter(); + _editBaseOffset.y -= itemBounds.bound.getDimensions().y / 2.f;*/ + } + break; + + case render::Transition::AVATAR_CHANGE: + break; + + default: + assert(false); + } + + transition.time += deltaTime; + +// renderContext->jobConfig->setProperty("threshold", threshold); +} + +float FadeJob::computeElementEnterThreshold(double time, const double period, FadeConfig::Timing timing) const { assert(period > 0.0); float fadeAlpha = 1.0f; const double INV_FADE_PERIOD = 1.0 / period; @@ -517,14 +570,14 @@ float FadeJob::computeElementEnterThreshold(double time, const double period, Fa default: fadeAlpha = (float)fraction; break; - case FadeJobConfig::EASE_IN: + case FadeConfig::EASE_IN: fadeAlpha = (float)(fraction*fraction*fraction); break; - case FadeJobConfig::EASE_OUT: + case FadeConfig::EASE_OUT: fadeAlpha = 1.f - (float)fraction; fadeAlpha = 1.f- fadeAlpha*fadeAlpha*fadeAlpha; break; - case FadeJobConfig::EASE_IN_OUT: + case FadeConfig::EASE_IN_OUT: fadeAlpha = (float)(fraction*fraction*fraction*(fraction*(fraction * 6 - 15) + 10)); break; } @@ -536,8 +589,8 @@ float FadeJob::computeFadePercent(quint64 startTime) { const double time = (double)(int64_t(usecTimestampNow()) - int64_t(startTime)) / (double)(USECS_PER_SECOND); /* assert(_currentInstance); return _currentInstance->computeElementEnterThreshold(time, - _currentInstance->_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN], - _currentInstance->_parameters->_timing[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]);*/ + _currentInstance->_parameters->_durations[FadeConfig::ELEMENT_ENTER_LEAVE_DOMAIN], + _currentInstance->_parameters->_timing[FadeConfig::ELEMENT_ENTER_LEAVE_DOMAIN]);*/ return (float)time; } @@ -551,7 +604,7 @@ void FadeJob::updateFadeEdit(const render::RenderContextPointer& renderContext, const double deltaTime = (int64_t(now) - int64_t(_editPreviousTime)) / double(USECS_PER_SECOND); const int editedCategory = _parameters->_editedCategory; const double eventDuration = (double)_parameters->_durations[editedCategory]; - const FadeJobConfig::Timing timing = _parameters->_timing[editedCategory]; + const FadeConfig::Timing timing = _parameters->_timing[editedCategory]; const double waitTime = 0.5; // Wait between fade in and out double cycleTime = fmod(_editTime, (eventDuration + waitTime) * 2.0); bool inverseTime = false; @@ -580,7 +633,7 @@ void FadeJob::updateFadeEdit(const render::RenderContextPointer& renderContext, } float threshold = _editThreshold; - if (editedCategory != FadeJobConfig::BUBBLE_ISECT_OWNER) { + if (editedCategory != FadeConfig::BUBBLE_ISECT_OWNER) { threshold = (threshold - 0.5f)*_parameters->_thresholdScale[editedCategory] + 0.5f; } renderContext->jobConfig->setProperty("threshold", threshold); @@ -591,10 +644,10 @@ void FadeJob::updateFadeEdit(const render::RenderContextPointer& renderContext, } switch (editedCategory) { - case FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN: + case FadeConfig::ELEMENT_ENTER_LEAVE_DOMAIN: break; - case FadeJobConfig::BUBBLE_ISECT_OWNER: + case FadeConfig::BUBBLE_ISECT_OWNER: { const glm::vec3 cameraPos = renderContext->args->getViewFrustum().getPosition(); glm::vec3 delta = itemBounds.bound.calcCenter() - cameraPos; @@ -607,20 +660,20 @@ void FadeJob::updateFadeEdit(const render::RenderContextPointer& renderContext, } break; - case FadeJobConfig::BUBBLE_ISECT_TRESPASSER: + case FadeConfig::BUBBLE_ISECT_TRESPASSER: { _editBaseOffset = glm::vec3{ 0.f, 0.f, 0.f }; } break; - case FadeJobConfig::USER_ENTER_LEAVE_DOMAIN: + case FadeConfig::USER_ENTER_LEAVE_DOMAIN: { _editBaseOffset = itemBounds.bound.calcCenter(); _editBaseOffset.y -= itemBounds.bound.getDimensions().y / 2.f; } break; - case FadeJobConfig::AVATAR_CHANGE: + case FadeConfig::AVATAR_CHANGE: break; default: @@ -628,69 +681,45 @@ void FadeJob::updateFadeEdit(const render::RenderContextPointer& renderContext, }*/ } -void FadeJob::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation) { - assert(_currentFadeMaskMap); - assert(_currentFadeBuffer!=nullptr); - bindPerBatch(batch, _currentFadeMaskMap, fadeMaskMapLocation, _currentFadeBuffer, fadeBufferLocation); +render::ShapePipeline::BatchSetter FadeJob::getBatchSetter() const { + return [this](const render::ShapePipeline& shapePipeline, gpu::Batch& batch) { + auto program = shapePipeline.pipeline->getProgram(); + auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap"); + auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer"); + batch.setResourceTexture(maskMapLocation, _fadeMaskMap); + batch.setUniformBuffer(bufferLocation, _configurations); + }; } -void FadeJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, int fadeMaskMapLocation, const gpu::BufferView* buffer, int fadeBufferLocation) { - batch.setResourceTexture(fadeMaskMapLocation, texture); - batch.setUniformBuffer(fadeBufferLocation, *buffer); -} +render::ShapePipeline::ItemSetter FadeJob::getItemSetter() const { + return [this](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; + render::Transition transitionState; // TODO : get the transition state + render::ShapeKey shapeKey(args->_globalShapeKey); -void FadeJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, const gpu::BufferView* buffer, const gpu::PipelinePointer& pipeline) { - auto program = pipeline->getProgram(); - auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap"); - auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer"); - bindPerBatch(batch, texture, maskMapLocation, buffer, bufferLocation); -} + // 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(); + auto& uniforms = program->getUniforms(); + auto fadeNoiseOffsetLocation = uniforms.findLocation("fadeNoiseOffset"); + auto fadeBaseOffsetLocation = uniforms.findLocation("fadeBaseOffset"); + auto fadeBaseInvSizeLocation = uniforms.findLocation("fadeBaseInvSize"); + auto fadeThresholdLocation = uniforms.findLocation("fadeThreshold"); + auto fadeCategoryLocation = uniforms.findLocation("fadeCategory"); -bool FadeJob::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime) { - return bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime); -} - -bool FadeJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime) { - auto& uniforms = pipeline->getProgram()->getUniforms(); - auto fadeNoiseOffsetLocation = uniforms.findLocation("fadeNoiseOffset"); - auto fadeBaseOffsetLocation = uniforms.findLocation("fadeBaseOffset"); - auto fadeThresholdLocation = uniforms.findLocation("fadeThreshold"); - auto fadeCategoryLocation = uniforms.findLocation("fadeCategory"); - - if (fadeNoiseOffsetLocation >= 0 || fadeBaseOffsetLocation>=0 || fadeThresholdLocation >= 0 || fadeCategoryLocation>=0) { - float threshold; - int eventCategory = FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN; - glm::vec3 noiseOffset = offset; - glm::vec3 baseOffset = offset; - - threshold = 1.f-computeFadePercent(startTime); - - // Manage interactive edition override -/* assert(_currentInstance); - if (_currentInstance->_parameters->_isEditEnabled) { - eventCategory = _currentInstance->_parameters->_editedCategory; - threshold = _currentInstance->_editThreshold; - noiseOffset += _currentInstance->_editNoiseOffset; - // This works supposing offset is the world position of the object that is fading. - if (eventCategory != FadeJobConfig::BUBBLE_ISECT_TRESPASSER) { - baseOffset = _currentInstance->_editBaseOffset - offset; + if (fadeNoiseOffsetLocation >= 0 || fadeBaseInvSizeLocation >= 0 || fadeBaseOffsetLocation >= 0 || fadeThresholdLocation >= 0 || fadeCategoryLocation >= 0) { + batch->_glUniform1i(fadeCategoryLocation, transitionState.eventType); + batch->_glUniform1f(fadeThresholdLocation, transitionState.threshold); + batch->_glUniform3f(fadeNoiseOffsetLocation, transitionState.noiseOffset.x, transitionState.noiseOffset.y, transitionState.noiseOffset.z); + batch->_glUniform3f(fadeBaseOffsetLocation, transitionState.baseOffset.x, transitionState.baseOffset.y, transitionState.baseOffset.z); + batch->_glUniform3f(fadeBaseInvSizeLocation, transitionState.baseInvSize.x, transitionState.baseInvSize.y, transitionState.baseInvSize.z); + } } } - - if (eventCategory != FadeJobConfig::BUBBLE_ISECT_OWNER) { - threshold = (threshold - 0.5f)*_currentInstance->_parameters->_thresholdScale[eventCategory] + 0.5f; - } - */ - batch._glUniform1i(fadeCategoryLocation, eventCategory); - batch._glUniform1f(fadeThresholdLocation, threshold); - // This is really temporary - batch._glUniform3f(fadeNoiseOffsetLocation, noiseOffset.x, noiseOffset.y, noiseOffset.z); - // This is really temporary - batch._glUniform3f(fadeBaseOffsetLocation, baseOffset.x, baseOffset.y, baseOffset.z); - - return threshold > 0.f; - } - return false; + }; } const render::Item* FadeJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const { diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index ede3d1843f..4d0b51ffe2 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -1,21 +1,22 @@ // // FadeEffect.h -// libraries/render-utils/src/ -// -// Created by Olivier Prat on 06/06/17. + +// 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_FadeEffect_h -#define hifi_FadeEffect_h + +#ifndef hifi_render_utils_FadeEffect_h +#define hifi_render_utils_FadeEffect_h #include #include #include +#include -class FadeJobConfig : public render::Job::Config { +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) @@ -48,17 +49,6 @@ class FadeJobConfig : public render::Job::Config { public: - enum EventCategory { - 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 - EVENT_CATEGORY_COUNT - }; - enum Timing { LINEAR, EASE_IN, @@ -68,7 +58,7 @@ public: TIMING_COUNT }; - FadeJobConfig(); + FadeConfig(); void setEditedCategory(int value); @@ -149,23 +139,23 @@ public: glm::vec3 baseSize; float noiseLevel; float baseLevel; - float _duration; + float duration; float edgeWidth; int timing; - bool _isInverted; + bool isInverted; }; - Event events[EVENT_CATEGORY_COUNT]; + Event events[render::Transition::EVENT_CATEGORY_COUNT]; float threshold{ 0.f }; float manualThreshold{ 0.f }; - int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; + int editedCategory{ render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN }; bool editFade{ false }; bool manualFade{ false }; Q_INVOKABLE void save() const; Q_INVOKABLE void load(); - static QString eventNames[EVENT_CATEGORY_COUNT]; + static QString eventNames[render::Transition::EVENT_CATEGORY_COUNT]; signals: @@ -174,65 +164,42 @@ signals: }; -struct FadeParameters -{ - glm::vec4 _noiseInvSizeAndLevel; - glm::vec4 _innerEdgeColor; - glm::vec4 _outerEdgeColor; - glm::vec2 _edgeWidthInvWidth; - glm::float32 _baseLevel; - glm::int32 _isInverted; -}; - -struct FadeConfiguration -{ - FadeParameters parameters[FadeJobConfig::EVENT_CATEGORY_COUNT]; -}; - class FadeJob { public: - using Config = FadeJobConfig; - using Input = RenderFetchCullSortTask::BucketList; - using JobModel = render::Job::ModelI; + using Config = FadeConfig; + using JobModel = render::Job::Model; FadeJob(); void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext, const Input& inputs); + void run(const render::RenderContextPointer& renderContext); - static void bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation); - static void bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, int fadeMaskMapLocation, const gpu::BufferView* buffer, int fadeBufferLocation); - static void bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, const gpu::BufferView* buffer, const gpu::PipelinePointer& pipeline); - - static bool bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime); - static bool bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime); + render::ShapePipeline::BatchSetter getBatchSetter() const; + render::ShapePipeline::ItemSetter getItemSetter() const; static float computeFadePercent(quint64 startTime); private: - static const FadeJob* _currentInstance; - static gpu::TexturePointer _currentFadeMaskMap; - static const gpu::BufferView* _currentFadeBuffer; +#include "Fade_shared.slh" + + struct FadeConfiguration + { + FadeParameters parameters[render::Transition::EVENT_CATEGORY_COUNT]; + }; gpu::StructBuffer _configurations; gpu::TexturePointer _fadeMaskMap; - float _thresholdScale[FadeJobConfig::EVENT_CATEGORY_COUNT]; + float _thresholdScale[render::Transition::EVENT_CATEGORY_COUNT]; + uint64_t _previousTime{ 0 }; - float computeElementEnterThreshold(double time, const double period, FadeJobConfig::Timing timing) const; - - - // Everything needed for interactive edition - 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 update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const; + float computeElementEnterThreshold(double time, const double period, FadeConfig::Timing timing) const; void updateFadeEdit(const render::RenderContextPointer& renderContext, const render::ItemBound& itemBounds); const render::Item* findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const; }; -#endif // hifi_FadeEffect_h +#endif // hifi_render_utils_FadeEffect_h diff --git a/libraries/render-utils/src/Fade_shared.slh b/libraries/render-utils/src/Fade_shared.slh new file mode 100644 index 0000000000..669156abac --- /dev/null +++ b/libraries/render-utils/src/Fade_shared.slh @@ -0,0 +1,22 @@ +// glsl / C++ compatible source as interface for FadeEffect +#ifdef __cplusplus +# define VEC4 glm::vec4 +# define VEC2 glm::vec2 +# define FLOAT32 glm::float32 +# define INT32 glm::int32 +#else +# define VEC4 vec4 +# define VEC2 vec2 +# define FLOAT32 float +# define INT32 int +#endif + +struct FadeParameters +{ + VEC4 _noiseInvSizeAndLevel; + VEC4 _innerEdgeColor; + VEC4 _outerEdgeColor; + VEC2 _edgeWidthInvWidth; + FLOAT32 _baseLevel; + INT32 _isInverted; +}; \ No newline at end of file diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 5c1632167e..a610e551a0 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -24,7 +24,6 @@ #include "TextureCache.h" #include "RenderUtilsLogging.h" -#include "FadeEffect.h" #include "StencilMaskPass.h" #include "gpu/StandardShaderLib.h" diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 42cc3eb36b..8b0ff4f549 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -15,7 +15,6 @@ #include "DeferredLightingEffect.h" #include "EntityItem.h" -#include "FadeEffect.h" using namespace render; @@ -320,14 +319,6 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren return payload->render(args); } -template <> const Item::FadeState* payloadGetFadeState(const ModelMeshPartPayload::Pointer& payload) { - return &payload->getFadeState(); -} - -template <> Item::FadeState* const payloadEditFadeState(ModelMeshPartPayload::Pointer& payload) { - return &payload->editFadeState(); -} - } ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 6fa49e7aa4..99c14510b5 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -22,7 +22,6 @@ #include #include "Model.h" -#include "FadeEffect.h" class Model; @@ -98,9 +97,6 @@ public: render::ShapeKey getShapeKey() const override; // shape interface void render(RenderArgs* args) override; - const render::Item::FadeState& getFadeState() const { return _fadeState; } - render::Item::FadeState& editFadeState() { return _fadeState; } - // 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; @@ -127,8 +123,6 @@ private: }; mutable State _state { WAITING_TO_START } ; - - render::Item::FadeState _fadeState; }; namespace render { @@ -137,8 +131,6 @@ namespace render { template <> int payloadGetLayer(const ModelMeshPartPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload); template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args); - template <> const Item::FadeState* payloadGetFadeState(const ModelMeshPartPayload::Pointer& payload); - template <> Item::FadeState* const payloadEditFadeState(ModelMeshPartPayload::Pointer& payload); } #endif // hifi_MeshPartPayload_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index abd7be0093..2bb1f50774 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -46,7 +46,7 @@ using namespace render; extern void initOverlay3DPipelines(render::ShapePlumber& plumber); -extern void initDeferredPipelines(render::ShapePlumber& plumber); +extern void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter); void RenderDeferredTask::configure(const Config& config) { @@ -55,11 +55,12 @@ void RenderDeferredTask::configure(const Config& config) void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { const auto& items = input.get(); -// task.addJob("Fade", fadeEditedItem, commonFadeParameters).get(); + task.addJob("Fade"); + auto& fadeJob = task._jobs.back().get(); // Prepare the ShapePipelines ShapePlumberPointer shapePlumber = std::make_shared(); - initDeferredPipelines(*shapePlumber); + initDeferredPipelines(*shapePlumber, fadeJob.getBatchSetter(), fadeJob.getItemSetter()); // Extract opaques / transparents / lights / metas / overlays / background const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE]; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index d6a6cf4ff4..fdccb7e0be 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -100,7 +100,7 @@ using namespace render; using namespace std::placeholders; void initOverlay3DPipelines(ShapePlumber& plumber); -void initDeferredPipelines(ShapePlumber& plumber); +void initDeferredPipelines(ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter); void initForwardPipelines(ShapePlumber& plumber); void addPlumberPipeline(ShapePlumber& plumber, @@ -170,7 +170,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { } } -void initDeferredPipelines(render::ShapePlumber& plumber) { +void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter) { // Vertex shaders auto simpleVertex = gpu::Shader::createVertex(std::string(simple_vert)); auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); @@ -255,25 +255,25 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withFade(), - modelFadeVertex, modelFadePixel); + modelFadeVertex, modelFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withFade(), - simpleFadeVertex, simpleFadePixel); + simpleFadeVertex, simpleFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withUnlit().withFade(), - modelFadeVertex, modelUnlitFadePixel); + modelFadeVertex, modelUnlitFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withUnlit().withFade(), - simpleFadeVertex, simpleUnlitFadePixel); + simpleFadeVertex, simpleUnlitFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTangents().withFade(), - modelNormalMapFadeVertex, modelNormalMapFadePixel); + modelNormalMapFadeVertex, modelNormalMapFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSpecular().withFade(), - modelFadeVertex, modelSpecularMapFadePixel); + modelFadeVertex, modelSpecularMapFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTangents().withSpecular().withFade(), - modelNormalMapFadeVertex, modelNormalSpecularMapFadePixel); + modelNormalMapFadeVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter); // Translucents addPipeline( @@ -304,29 +304,29 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withTranslucent().withFade(), - modelFadeVertex, modelTranslucentFadePixel); + modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withTranslucent().withFade(), - simpleFadeVertex, simpleTranslucentFadePixel); + simpleFadeVertex, simpleTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withUnlit().withFade(), - modelFadeVertex, modelTranslucentUnlitFadePixel); + modelFadeVertex, modelTranslucentUnlitFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withTranslucent().withUnlit().withFade(), - simpleFadeVertex, simpleTranslucentUnlitFadePixel); + simpleFadeVertex, simpleTranslucentUnlitFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withFade(), - modelNormalMapFadeVertex, modelTranslucentFadePixel); + modelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withSpecular().withFade(), - modelFadeVertex, modelTranslucentFadePixel); + modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular().withFade(), - modelNormalMapFadeVertex, modelTranslucentFadePixel); + modelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(), - modelFadeVertex, modelTranslucentFadePixel); + modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); // Lightmapped addPipeline( @@ -344,16 +344,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withLightmap().withFade(), - modelLightmapFadeVertex, modelLightmapFadePixel); + modelLightmapFadeVertex, modelLightmapFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withLightmap().withTangents().withFade(), - modelLightmapNormalMapFadeVertex, modelLightmapNormalMapFadePixel); + modelLightmapNormalMapFadeVertex, modelLightmapNormalMapFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withLightmap().withSpecular().withFade(), - modelLightmapFadeVertex, modelLightmapSpecularMapFadePixel); + modelLightmapFadeVertex, modelLightmapSpecularMapFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withLightmap().withTangents().withSpecular().withFade(), - modelLightmapNormalMapFadeVertex, modelLightmapNormalSpecularMapFadePixel); + modelLightmapNormalMapFadeVertex, modelLightmapNormalSpecularMapFadePixel, batchSetter, itemSetter); // Skinned addPipeline( @@ -371,16 +371,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withFade(), - skinModelFadeVertex, modelFadePixel); + skinModelFadeVertex, modelFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTangents().withFade(), - skinModelNormalMapFadeVertex, modelNormalMapFadePixel); + skinModelNormalMapFadeVertex, modelNormalMapFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withSpecular().withFade(), - skinModelFadeVertex, modelSpecularMapFadePixel); + skinModelFadeVertex, modelSpecularMapFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTangents().withSpecular().withFade(), - skinModelNormalMapFadeVertex, modelNormalSpecularMapFadePixel); + skinModelNormalMapFadeVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter); // Skinned and Translucent addPipeline( @@ -398,16 +398,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(), - skinModelFadeVertex, modelTranslucentFadePixel); + skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withFade(), - skinModelNormalMapFadeVertex, modelTranslucentFadePixel); + skinModelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular().withFade(), - skinModelFadeVertex, modelTranslucentFadePixel); + skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular().withFade(), - skinModelNormalMapFadeVertex, modelTranslucentFadePixel); + skinModelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); // Depth-only addPipeline( @@ -419,10 +419,10 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // Same thing but with Fade on addPipeline( Key::Builder().withDepthOnly().withFade(), - modelShadowFadeVertex, modelShadowFadePixel); + modelShadowFadeVertex, modelShadowFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withSkinned().withDepthOnly().withFade(), - skinModelShadowFadeVertex, modelShadowFadePixel); + skinModelShadowFadeVertex, modelShadowFadePixel, batchSetter, itemSetter); } void initForwardPipelines(render::ShapePlumber& plumber) { diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index c0d7f43516..717d87310b 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -14,7 +14,6 @@ #include #include -#include "FadeEffect.h" #include #include @@ -53,7 +52,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, const auto& fbo = shadow->framebuffer; RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder;// TODO: support fade on shadows = DependencyManager::get()->getKeyBuilder(); + ShapeKey::Builder defaultKeyBuilder; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -74,9 +73,6 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); - // Prepare fade effect - // TODO: support fade on shadows DependencyManager::get()->bindPerBatch(batch); - std::vector skinnedShapeKeys{}; // Iterate through all inShapes and render the unskinned diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index f80563bf73..cc679588e2 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -78,3 +78,11 @@ void Item::resetPayload(const PayloadPointer& payload) { _key = _payload->getKey(); } } + +const ShapeKey Item::getShapeKey() const { + auto shapeKey = _payload->getShapeKey(); + if (_transitionId != TransitionStage::INVALID_INDEX) { + return ShapeKey::Builder(shapeKey).withFade(); + } + return shapeKey; +} \ No newline at end of file diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 543a130427..6ee382b1e2 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -27,7 +27,7 @@ #include "model/Material.h" #include "ShapePipeline.h" - +#include "TransitionStage.h" namespace render { @@ -310,23 +310,6 @@ public: }; typedef std::shared_ptr UpdateFunctorPointer; - // This holds the current state for all fade event types applied to this item - class FadeState { - public: - - enum { - INACTIVE = (uint8_t)-1 - }; - - uint8_t eventType{ INACTIVE }; - uint64_t startTime{ 0 }; - glm::vec3 noiseOffset{ 0.f, 0.f, 0.f }; - glm::vec3 baseOffset{ 0.f, 0.f, 0.f }; - glm::vec3 baseSize{ 1.f, 1.f, 1.f }; - float threshold{ 0.f }; - - }; - // Payload is whatever is in this Item and implement the Payload Interface class PayloadInterface { public: @@ -339,9 +322,6 @@ public: virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const = 0; - virtual const FadeState* getFadeState() const = 0; - virtual FadeState* const editFadeState() = 0; - ~PayloadInterface() {} // Status interface is local to the base class @@ -387,7 +367,7 @@ public: void render(RenderArgs* args) const { _payload->render(args); } // Shape Type Interface - const ShapeKey getShapeKey() const { return _payload->getShapeKey(); } + const ShapeKey getShapeKey() const; // Meta Type Interface uint32_t fetchMetaSubItems(ItemIDs& subItems) const { return _payload->fetchMetaSubItems(subItems); } @@ -395,13 +375,14 @@ public: // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } - const FadeState* getFadeState() const { return _payload->getFadeState(); } - FadeState* const editFadeState() { return _payload->editFadeState(); } + void setTransitionId(TransitionStage::Index id) { _transitionId = id; } + TransitionStage::Index getTransitionId() const { return _transitionId; } protected: PayloadPointer _payload; ItemKey _key; ItemCell _cell{ INVALID_CELL }; + TransitionStage::Index _transitionId{ TransitionStage::INVALID_INDEX }; friend class Scene; }; @@ -431,8 +412,6 @@ template const ItemKey payloadGetKey(const std::shared_ptr& payload template const Item::Bound payloadGetBound(const std::shared_ptr& payloadData) { return Item::Bound(); } template int payloadGetLayer(const std::shared_ptr& payloadData) { return 0; } template void payloadRender(const std::shared_ptr& payloadData, RenderArgs* args) { } -template const Item::FadeState* payloadGetFadeState(const std::shared_ptr& payloadData) { return nullptr; } -template Item::FadeState* const payloadEditFadeState(std::shared_ptr& payloadData) { return nullptr; } // Shape type interface // This allows shapes to characterize their pipeline via a ShapeKey, to be picked with a subclass of Shape. @@ -460,9 +439,6 @@ public: virtual const Item::Bound getBound() const override { return payloadGetBound(_data); } virtual int getLayer() const override { return payloadGetLayer(_data); } - virtual const Item::FadeState* getFadeState() const { return payloadGetFadeState(_data); } - virtual Item::FadeState* const editFadeState() { return payloadEditFadeState(_data); } - virtual void render(RenderArgs* args) override { payloadRender(_data, args); } // Shape Type interface diff --git a/libraries/render/src/render/Transition.h b/libraries/render/src/render/Transition.h new file mode 100644 index 0000000000..40fe10c9e5 --- /dev/null +++ b/libraries/render/src/render/Transition.h @@ -0,0 +1,46 @@ +// +// Transition.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_Transition_h +#define hifi_render_utils_Transition_h + +#include "Item.h" + +namespace render { + + // This holds the current state for all transition event types applied to a render item + class Transition { + public: + + enum Type { + 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 + EVENT_CATEGORY_COUNT + }; + + Type eventType{ ELEMENT_ENTER_LEAVE_DOMAIN }; + ItemID itemId{ Item::INVALID_ITEM_ID }; + double time{ 0.0 }; + glm::vec3 noiseOffset{ 0.f, 0.f, 0.f }; + glm::vec3 baseOffset{ 0.f, 0.f, 0.f }; + glm::vec3 baseInvSize{ 1.f, 1.f, 1.f }; + float threshold{ 0.f }; + + }; + + typedef std::shared_ptr TransitionPointer; +} + +#endif \ No newline at end of file diff --git a/libraries/render/src/render/TransitionStage.cpp b/libraries/render/src/render/TransitionStage.cpp new file mode 100644 index 0000000000..2ffb4e26fa --- /dev/null +++ b/libraries/render/src/render/TransitionStage.cpp @@ -0,0 +1,25 @@ +#include "TransitionStage.h" + +#include + +using namespace render; + +TransitionStage::Index TransitionStage::addTransition(ItemID itemId, Transition::Type type) { + Transition transition; + Index id; + + transition.eventType = type; + transition.itemId = itemId; + id = _transitions.newElement(transition); + _activeTransitionIds.push_back(id); + + return id; +} + +void TransitionStage::removeTransition(Index index) { + TransitionIdList::iterator idIterator = std::find(_activeTransitionIds.begin(), _activeTransitionIds.end(), index); + if (idIterator != _activeTransitionIds.end()) { + _activeTransitionIds.erase(idIterator); + } + _transitions.freeElement(index); +} diff --git a/libraries/render/src/render/TransitionStage.h b/libraries/render/src/render/TransitionStage.h new file mode 100644 index 0000000000..d7727c4d72 --- /dev/null +++ b/libraries/render/src/render/TransitionStage.h @@ -0,0 +1,53 @@ +// +// TransitionStage.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_TransitionStage_h +#define hifi_render_TransitionStage_h + +#include +#include "IndexedContainer.h" + +#include "Transition.h" + +namespace render { + + // Transition stage to set up Transition-related effects + class TransitionStage { + public: + using Index = indexed_container::Index; + static const Index INVALID_INDEX{ indexed_container::INVALID_INDEX }; + using TransitionIdList = indexed_container::Indices; + + static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } + + bool checkTransitionId(Index index) const { return _transitions.checkIndex(index); } + + const Transition& getTransition(Index TransitionId) const { return _transitions.get(TransitionId); } + + Transition& editTransition(Index TransitionId) { return _transitions.edit(TransitionId); } + + Index addTransition(ItemID itemId, Transition::Type type); + void removeTransition(Index index); + + TransitionIdList::iterator begin() { return _activeTransitionIds.begin(); } + TransitionIdList::iterator end() { return _activeTransitionIds.end(); } + + private: + + using Transitions = indexed_container::IndexedVector; + + Transitions _transitions; + TransitionIdList _activeTransitionIds; + }; + using TransitionStagePointer = std::shared_ptr; + +} + +#endif // hifi_render_TransitionStage_h diff --git a/libraries/render/src/task/Task.h b/libraries/render/src/task/Task.h index f76ba92546..e99b33305c 100644 --- a/libraries/render/src/task/Task.h +++ b/libraries/render/src/task/Task.h @@ -155,6 +155,12 @@ public: return concept->_data; } + template const T& get() const { + auto concept = std::static_pointer_cast(_concept); + assert(concept); + return concept->_data; + } + virtual void run(const ContextPointer& renderContext) { PerformanceTimer perfTimer(_name.c_str()); PROFILE_RANGE(render, _name.c_str()); diff --git a/tests/gpu-test/src/TestWindow.cpp b/tests/gpu-test/src/TestWindow.cpp index 6436ff1ef4..d0dda3d8ee 100644 --- a/tests/gpu-test/src/TestWindow.cpp +++ b/tests/gpu-test/src/TestWindow.cpp @@ -24,7 +24,7 @@ #include #ifdef DEFERRED_LIGHTING -extern void initDeferredPipelines(render::ShapePlumber& plumber); +extern void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter); extern void initStencilPipeline(gpu::PipelinePointer& pipeline); #endif From 267531cc1a43e0a7cf29182a4a2525d24066fd8c Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 10 Jul 2017 15:27:09 +0200 Subject: [PATCH 43/86] First working fade --- .../src/avatars-renderer/Avatar.cpp | 2 +- .../src/RenderableModelEntityItem.cpp | 17 ++- .../src/RenderableModelEntityItem.h | 11 +- libraries/render-utils/src/FadeEffect.cpp | 104 ++++++++++-------- libraries/render-utils/src/FadeEffect.h | 4 +- .../render-utils/src/RenderPipelines.cpp | 82 ++++++++------ libraries/render/src/render/Scene.cpp | 72 ++++++++++++ libraries/render/src/render/Scene.h | 12 +- libraries/render/src/render/Transition.h | 4 +- 9 files changed, 221 insertions(+), 87 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 9fa40fc60e..44a005194b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -61,7 +61,7 @@ namespace render { template <> uint32_t metaFetchMetaSubItems(const AvatarSharedPointer& avatar, ItemIDs& subItems) { auto avatarPtr = static_pointer_cast(avatar); if (avatarPtr->getSkeletonModel()) { - auto metaSubItems = avatarPtr->getSkeletonModel()->fetchRenderItemIDs(); + auto& metaSubItems = avatarPtr->getSkeletonModel()->fetchRenderItemIDs(); subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end()); return (uint32_t) metaSubItems.size(); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 0b6271a6b1..95a8812550 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -217,8 +217,9 @@ namespace render { } template <> uint32_t metaFetchMetaSubItems(const RenderableModelEntityItemMeta::Pointer& payload, ItemIDs& subItems) { auto modelEntity = std::static_pointer_cast(payload->entity); - if (modelEntity->hasModel()) { - auto metaSubItems = modelEntity->getModelNotSafe()->fetchRenderItemIDs(); + auto model = modelEntity->getModelNotSafe(); + if (modelEntity->hasModel() && model) { + auto& metaSubItems = model->fetchRenderItemIDs(); subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end()); return (uint32_t) metaSubItems.size(); } @@ -489,6 +490,17 @@ ModelPointer RenderableModelEntityItem::getModelNotSafe() { return _model; } +void RenderableModelEntityItem::setModelURLFinished(bool success) { + if (success) { + const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene(); + render::Transaction transaction; + + const auto& item = scene->getItem(_myMetaItem); + transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN); + scene->enqueueTransaction(transaction); + } +} + ModelPointer RenderableModelEntityItem::getModel() { // make sure our renderer is setup if (!_myRenderer) { @@ -506,6 +518,7 @@ ModelPointer RenderableModelEntityItem::getModel() { // If we don't have a model, allocate one *immediately* if (!_model) { _model = _myRenderer->allocateModel(getModelURL(), _myRenderer->getEntityLoadingPriority(*this), this); + QObject::connect(_model.get(), &Model::setURLFinished, this, &RenderableModelEntityItem::setModelURLFinished); _needsInitialSimulation = true; // If we need to change URLs, update it *after rendering* (to avoid access violations) } else if (QUrl(getModelURL()) != _model->getURL()) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 2d240c01a6..6586678906 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -12,16 +12,21 @@ #ifndef hifi_RenderableModelEntityItem_h #define hifi_RenderableModelEntityItem_h +#include #include #include #include #include +#include + +#include "RenderableEntityItem.h" class Model; class EntityTreeRenderer; -class RenderableModelEntityItem : public ModelEntityItem, RenderableEntityInterface { +class RenderableModelEntityItem : public QObject, public ModelEntityItem, RenderableEntityInterface { + Q_OBJECT public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); @@ -116,6 +121,10 @@ public: return _animation; } +public slots: + + void setModelURLFinished(bool success); + private: QVariantMap parseTexturesToMap(QString textures); void remapTextures(); diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index ac087dc1c0..c8a9167ed4 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -464,6 +464,7 @@ FadeJob::FadeJob() { auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png"; _fadeMaskMap = DependencyManager::get()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); + _previousTime = usecTimestampNow(); } void FadeJob::configure(const Config& config) { @@ -493,76 +494,91 @@ void FadeJob::run(const render::RenderContextPointer& renderContext) { auto transitionStage = scene->getStage(render::TransitionStage::getName()); uint64_t now = usecTimestampNow(); const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND); + render::Transaction transaction; + bool hasTransactions = false; // And now update fade effect for (auto transitionId : *transitionStage) { auto& state = transitionStage->editTransition(transitionId); - update(*jobConfig, scene, state, deltaTime); + if (!update(*jobConfig, scene, state, deltaTime)) { + // Remove transition for this item + transaction.transitionItem(state.itemId, render::Transition::NONE); + hasTransactions = true; + } } + if (hasTransactions) { + scene->enqueueTransaction(transaction); + } _previousTime = now; } -void FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const { +bool FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const { auto& eventConfig = config.events[transition.eventType]; auto& item = scene->getItem(transition.itemId); - auto& aabb = item.getBound(); - auto& dimensions = aabb.getDimensions(); const double eventDuration = (double)eventConfig.duration; const FadeConfig::Timing timing = (FadeConfig::Timing) eventConfig.timing; + bool continueTransition = true; - assert(timing < render::Transition::EVENT_CATEGORY_COUNT); + if (item.exist()) { + auto& aabb = item.getBound(); + auto& dimensions = aabb.getDimensions(); - switch (transition.eventType) { - case render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN: - transition.threshold = 1.f - computeElementEnterThreshold(transition.time, eventConfig.duration, timing); - transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[transition.eventType] + 0.5f; - transition.noiseOffset = aabb.calcCenter(); - transition.baseOffset = transition.noiseOffset - dimensions.y; - transition.baseInvSize.x = 1.f / dimensions.x; - transition.baseInvSize.y = 1.f / dimensions.y; - transition.baseInvSize.z = 1.f / dimensions.z; + assert(timing < render::Transition::EVENT_CATEGORY_COUNT); + + switch (transition.eventType) { + case render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN: + transition.threshold = 1.f - computeElementEnterRatio(transition.time, eventConfig.duration, timing); + transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[transition.eventType] + 0.5f; + transition.noiseOffset = aabb.calcCenter(); + transition.baseOffset = transition.noiseOffset - dimensions.y; + transition.baseInvSize.x = 1.f / dimensions.x; + transition.baseInvSize.y = 1.f / dimensions.y; + transition.baseInvSize.z = 1.f / dimensions.z; + continueTransition = transition.threshold > 0.f; + break; + + case render::Transition::BUBBLE_ISECT_OWNER: + { + /* const glm::vec3 cameraPos = renderContext->args->getViewFrustum().getPosition(); + glm::vec3 delta = itemBounds.bound.calcCenter() - cameraPos; + float distance = glm::length(delta); + + delta = glm::normalize(delta) * std::max(0.f, distance - 0.5f); + + _editBaseOffset = cameraPos + delta*_editThreshold; + _editThreshold = 0.33f;*/ + } break; - case render::Transition::BUBBLE_ISECT_OWNER: - { - /* const glm::vec3 cameraPos = renderContext->args->getViewFrustum().getPosition(); - glm::vec3 delta = itemBounds.bound.calcCenter() - cameraPos; - float distance = glm::length(delta); - - delta = glm::normalize(delta) * std::max(0.f, distance - 0.5f); - - _editBaseOffset = cameraPos + delta*_editThreshold; - _editThreshold = 0.33f;*/ - } - break; - - case render::Transition::BUBBLE_ISECT_TRESPASSER: - { - // _editBaseOffset = glm::vec3{ 0.f, 0.f, 0.f }; - } - break; - - case render::Transition::USER_ENTER_LEAVE_DOMAIN: - { -/* _editBaseOffset = itemBounds.bound.calcCenter(); - _editBaseOffset.y -= itemBounds.bound.getDimensions().y / 2.f;*/ - } - break; - - case render::Transition::AVATAR_CHANGE: + case render::Transition::BUBBLE_ISECT_TRESPASSER: + { + // _editBaseOffset = glm::vec3{ 0.f, 0.f, 0.f }; + } break; - default: - assert(false); + case render::Transition::USER_ENTER_LEAVE_DOMAIN: + { + /* _editBaseOffset = itemBounds.bound.calcCenter(); + _editBaseOffset.y -= itemBounds.bound.getDimensions().y / 2.f;*/ + } + break; + + case render::Transition::AVATAR_CHANGE: + break; + + default: + assert(false); + } } transition.time += deltaTime; // renderContext->jobConfig->setProperty("threshold", threshold); + return continueTransition; } -float FadeJob::computeElementEnterThreshold(double time, const double period, FadeConfig::Timing timing) const { +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; diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 14f5ef1deb..413d4124ce 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -193,8 +193,8 @@ private: float _thresholdScale[render::Transition::EVENT_CATEGORY_COUNT]; uint64_t _previousTime{ 0 }; - void update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const; - float computeElementEnterThreshold(double time, const double period, FadeConfig::Timing timing) const; + bool 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; }; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 12c19bc06e..c5949cb336 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -104,7 +104,8 @@ void initDeferredPipelines(ShapePlumber& plumber, const render::ShapePipeline::B void initForwardPipelines(ShapePlumber& plumber); void addPlumberPipeline(ShapePlumber& plumber, - const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel); + const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel, + const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter); void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args); void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args); @@ -228,30 +229,30 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto simpleTranslucentUnlitFadePixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_unlit_fade_frag)); using Key = render::ShapeKey; - auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3); + auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4, _5); // TODO: Refactor this to use a filter // Opaques addPipeline( Key::Builder().withMaterial(), - modelVertex, modelPixel); + modelVertex, modelPixel, nullptr, nullptr); addPipeline( Key::Builder(), - simpleVertex, simplePixel); + simpleVertex, simplePixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withUnlit(), - modelVertex, modelUnlitPixel); + modelVertex, modelUnlitPixel, nullptr, nullptr); addPipeline( Key::Builder().withUnlit(), - simpleVertex, simpleUnlitPixel); + simpleVertex, simpleUnlitPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTangents(), - modelNormalMapVertex, modelNormalMapPixel); + modelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSpecular(), - modelVertex, modelSpecularMapPixel); + modelVertex, modelSpecularMapPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTangents().withSpecular(), - modelNormalMapVertex, modelNormalSpecularMapPixel); + modelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withFade(), @@ -278,29 +279,29 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip // Translucents addPipeline( Key::Builder().withMaterial().withTranslucent(), - modelVertex, modelTranslucentPixel); + modelVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withTranslucent(), - simpleVertex, simpleTranslucentPixel); + simpleVertex, simpleTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withUnlit(), - modelVertex, modelTranslucentUnlitPixel); + modelVertex, modelTranslucentUnlitPixel, nullptr, nullptr); addPipeline( Key::Builder().withTranslucent().withUnlit(), - simpleVertex, simpleTranslucentUnlitPixel); + simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents(), - modelNormalMapVertex, modelTranslucentPixel); + modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withSpecular(), - modelVertex, modelTranslucentPixel); + modelVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(), - modelNormalMapVertex, modelTranslucentPixel); + modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap(), - modelVertex, modelTranslucentPixel); + modelVertex, modelTranslucentPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withTranslucent().withFade(), @@ -331,16 +332,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip // Lightmapped addPipeline( Key::Builder().withMaterial().withLightmap(), - modelLightmapVertex, modelLightmapPixel); + modelLightmapVertex, modelLightmapPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withLightmap().withTangents(), - modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); + modelLightmapNormalMapVertex, modelLightmapNormalMapPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withLightmap().withSpecular(), - modelLightmapVertex, modelLightmapSpecularMapPixel); + modelLightmapVertex, modelLightmapSpecularMapPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withLightmap().withTangents().withSpecular(), - modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); + modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withLightmap().withFade(), @@ -358,16 +359,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip // Skinned addPipeline( Key::Builder().withMaterial().withSkinned(), - skinModelVertex, modelPixel); + skinModelVertex, modelPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTangents(), - skinModelNormalMapVertex, modelNormalMapPixel); + skinModelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withSpecular(), - skinModelVertex, modelSpecularMapPixel); + skinModelVertex, modelSpecularMapPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(), - skinModelNormalMapVertex, modelNormalSpecularMapPixel); + skinModelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withFade(), @@ -385,16 +386,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip // Skinned and Translucent addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent(), - skinModelVertex, modelTranslucentPixel); + skinModelVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), - skinModelNormalMapVertex, modelTranslucentPixel); + skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(), - skinModelVertex, modelTranslucentPixel); + skinModelVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(), - skinModelNormalMapVertex, modelTranslucentPixel); + skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(), @@ -412,10 +413,10 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip // Depth-only addPipeline( Key::Builder().withDepthOnly(), - modelShadowVertex, modelShadowPixel); + modelShadowVertex, modelShadowPixel, nullptr, nullptr); addPipeline( Key::Builder().withSkinned().withDepthOnly(), - skinModelShadowVertex, modelShadowPixel); + skinModelShadowVertex, modelShadowPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withDepthOnly().withFade(), @@ -440,7 +441,7 @@ void initForwardPipelines(render::ShapePlumber& plumber) { auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(forward_model_normal_specular_map_frag)); using Key = render::ShapeKey; - auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3); + auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, nullptr, nullptr); // Opaques addPipeline( Key::Builder().withMaterial(), @@ -473,7 +474,8 @@ void initForwardPipelines(render::ShapePlumber& plumber) { } void addPlumberPipeline(ShapePlumber& plumber, - const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel) { + const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel, + const render::ShapePipeline::BatchSetter& extraBatchSetter, const render::ShapePipeline::ItemSetter& itemSetter) { // These key-values' pipelines are added by this functor in addition to the key passed assert(!key.isWireframe()); assert(!key.isDepthBiased()); @@ -510,8 +512,18 @@ void addPlumberPipeline(ShapePlumber& plumber, state->setDepthBiasSlopeScale(1.0f); } - plumber.addPipeline(builder.build(), program, state, - key.isTranslucent() ? &lightBatchSetter : &batchSetter); + auto baseBatchSetter = key.isTranslucent() ? &lightBatchSetter : &batchSetter; + render::ShapePipeline::BatchSetter finalBatchSetter; + if (extraBatchSetter) { + finalBatchSetter = [baseBatchSetter, extraBatchSetter](const ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) { + baseBatchSetter(pipeline, batch, args); + extraBatchSetter(pipeline, batch, args); + }; + } + else { + finalBatchSetter = baseBatchSetter; + } + plumber.addPipeline(builder.build(), program, state, finalBatchSetter, itemSetter); } } diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index b8f93c52c3..12a04eef7b 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -13,6 +13,7 @@ #include #include #include "Logging.h" +#include "TransitionStage.h" using namespace render; @@ -30,6 +31,11 @@ void Transaction::removeItem(ItemID id) { _removedItems.emplace_back(id); } +void Transaction::transitionItem(ItemID id, Transition::Type transition) { + _transitioningItems.emplace_back(id); + _transitionTypes.emplace_back(transition); +} + void Transaction::updateItem(ItemID id, const UpdateFunctorPointer& functor) { _updatedItems.emplace_back(id); _updateFunctors.emplace_back(functor); @@ -46,6 +52,8 @@ void Transaction::merge(const Transaction& transaction) { _updatedItems.insert(_updatedItems.end(), transaction._updatedItems.begin(), transaction._updatedItems.end()); _updateFunctors.insert(_updateFunctors.end(), transaction._updateFunctors.begin(), transaction._updateFunctors.end()); _resetSelections.insert(_resetSelections.end(), transaction._resetSelections.begin(), transaction._resetSelections.end()); + _transitioningItems.insert(_transitioningItems.end(), transaction._transitioningItems.begin(), transaction._transitioningItems.end()); + _transitionTypes.insert(_transitionTypes.end(), transaction._transitionTypes.begin(), transaction._transitionTypes.end()); } @@ -115,6 +123,9 @@ void Scene::processTransactionQueue() { // removes removeItems(consolidatedTransaction._removedItems); + // Transitions + transitionItems(consolidatedTransaction._transitioningItems, consolidatedTransaction._transitionTypes); + // Update the numItemsAtomic counter AFTER the pending changes went through _numAllocatedItems.exchange(maxID); } @@ -216,6 +227,67 @@ void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) { } } +void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types) { + auto transitionType = types.begin(); + auto transitionStage = getStage(TransitionStage::getName()); + + for (auto itemId : ids) { + auto transitionId = INVALID_INDEX; + + if (*transitionType != Transition::NONE) { + transitionId = transitionStage->addTransition(itemId, *transitionType); + } + + setItemTransition(itemId, transitionId); + // next loop + transitionType++; + } +} + +void Scene::collectSubItems(ItemID parentId, ItemIDs& subItems) const { + // Access the true item + auto& item = _items[parentId]; + + if (item.exist()) { + // Recursivelly collect the subitems + auto subItemBeginIndex = subItems.size(); + auto subItemCount = item.fetchMetaSubItems(subItems); + for (auto i = subItemBeginIndex; i < (subItemBeginIndex + subItemCount); i++) { + collectSubItems(subItems[i], subItems); + } + } +} + +void Scene::setItemTransition(ItemID itemId, Index transitionId) { + // Access the true item + auto& item = _items[itemId]; + + if (item.exist()) { + ItemIDs subItems; + + item.setTransitionId(transitionId); + + // Sub-items share the same transition Id + collectSubItems(itemId, subItems); + for (auto subItemId : subItems) { + auto& subItem = _items[subItemId]; + subItem.setTransitionId(transitionId); + } + } + else { + qWarning() << "Collecting sub items on item without payload"; + } +} + +void Scene::resetItemTransition(ItemID itemId) { + // Access the true item + auto& item = _items[itemId]; + auto transitionStage = getStage(TransitionStage::getName()); + + transitionStage->removeTransition(item.getTransitionId()); + setItemTransition(itemId, Transition::NONE); +} + // THis fucntion is thread safe Selection Scene::getSelection(const Selection::Name& name) const { std::unique_lock lock(_selectionsMutex); diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 199d9ce224..90255033ce 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -16,6 +16,7 @@ #include "SpatialTree.h" #include "Stage.h" #include "Selection.h" +#include "Transition.h" namespace render { @@ -39,6 +40,8 @@ public: void resetItem(ItemID id, const PayloadPointer& payload); void removeItem(ItemID id); + void transitionItem(ItemID id, Transition::Type transition); + template void updateItem(ItemID id, std::function func) { updateItem(id, std::make_shared>(func)); } @@ -54,10 +57,12 @@ public: // Checkers if there is work to do when processing the transaction bool touchTransactions() const { return !_resetSelections.empty(); } - ItemIDs _resetItems; + ItemIDs _resetItems; Payloads _resetPayloads; ItemIDs _removedItems; ItemIDs _updatedItems; + ItemIDs _transitioningItems; + TransitionTypes _transitionTypes; UpdateFunctors _updateFunctors; Selections _resetSelections; @@ -123,6 +128,8 @@ public: } void resetStage(const Stage::Name& name, const StagePointer& stage); + void setItemTransition(ItemID id, Index transitionId); + void resetItemTransition(ItemID id); protected: // Thread safe elements that can be accessed from anywhere @@ -141,6 +148,9 @@ protected: void resetItems(const ItemIDs& ids, Payloads& payloads); void removeItems(const ItemIDs& ids); void updateItems(const ItemIDs& ids, UpdateFunctors& functors); + void transitionItems(const ItemIDs& ids, const TransitionTypes& types); + + void collectSubItems(ItemID parentId, ItemIDs& subItems) const; // The Selection map mutable std::mutex _selectionsMutex; // mutable so it can be used in the thread safe getSelection const method diff --git a/libraries/render/src/render/Transition.h b/libraries/render/src/render/Transition.h index 240c5fe339..4e52693efd 100644 --- a/libraries/render/src/render/Transition.h +++ b/libraries/render/src/render/Transition.h @@ -27,7 +27,8 @@ namespace render { AVATAR_CHANGE, // Don't forget to modify Fade.slh to reflect the change in number of categories - EVENT_CATEGORY_COUNT + EVENT_CATEGORY_COUNT, + NONE = EVENT_CATEGORY_COUNT }; Type eventType{ ELEMENT_ENTER_LEAVE_DOMAIN }; @@ -41,6 +42,7 @@ namespace render { }; typedef std::shared_ptr TransitionPointer; + typedef std::vector TransitionTypes; } #endif // hifi_render_Transition_h \ No newline at end of file From 66d09a4c3ceca00c7574668c646ea2423d2d3b27 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 10 Jul 2017 16:02:12 +0200 Subject: [PATCH 44/86] Some objects fade and fixed crash due to invalid meta item id --- .../src/RenderableModelEntityItem.cpp | 14 ++++++++++---- libraries/render-utils/src/FadeEffect.cpp | 2 +- libraries/render/src/render/IndexedContainer.h | 4 ++++ libraries/render/src/render/Scene.cpp | 10 ++++++++++ libraries/render/src/render/TransitionStage.cpp | 4 +++- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 95a8812550..b65c8ee49c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -493,11 +493,17 @@ ModelPointer RenderableModelEntityItem::getModelNotSafe() { void RenderableModelEntityItem::setModelURLFinished(bool success) { if (success) { const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene(); - render::Transaction transaction; - const auto& item = scene->getItem(_myMetaItem); - transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN); - scene->enqueueTransaction(transaction); + if (scene->isAllocatedID(_myMetaItem)) { + render::Transaction transaction; + + const auto& item = scene->getItem(_myMetaItem); + if (!item.exist()) { + qWarning() << "Starting transition on item without payload"; + } + transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN); + scene->enqueueTransaction(transaction); + } } } diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index c8a9167ed4..9067f4ff09 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -620,7 +620,7 @@ render::ShapePipeline::ItemSetter FadeJob::getItemSetter() const { auto scene = args->_scene; auto batch = args->_batch; auto transitionStage = scene->getStage(render::TransitionStage::getName()); - render::Transition transitionState = transitionStage->getTransition(item.getTransitionId()); + auto& transitionState = transitionStage->getTransition(item.getTransitionId()); render::ShapeKey shapeKey(args->_globalShapeKey); // TODO test various cases: polyvox... etc diff --git a/libraries/render/src/render/IndexedContainer.h b/libraries/render/src/render/IndexedContainer.h index 4429ea22db..5aca12f83e 100644 --- a/libraries/render/src/render/IndexedContainer.h +++ b/libraries/render/src/render/IndexedContainer.h @@ -98,6 +98,10 @@ namespace indexed_container { return _elements[index]; } + bool isElementFreed(Index index) const { + return std::find(_allocator._freeIndices.begin(), _allocator._freeIndices.end(), index) != _allocator._freeIndices.end(); + } + const Element& get(Index index) const { return _elements[index]; } diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 12a04eef7b..2c55658657 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -178,6 +178,12 @@ void Scene::removeItems(const ItemIDs& ids) { _masterNonspatialSet.erase(removedID); } + // If there is a transition on this item, remove it + if (item.getTransitionId() != render::TransitionStage::INVALID_INDEX) { + auto transitionStage = getStage(TransitionStage::getName()); + transitionStage->removeTransition(item.getTransitionId()); + } + // Kill it item.kill(); } @@ -237,6 +243,10 @@ void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types) { if (*transitionType != Transition::NONE) { transitionId = transitionStage->addTransition(itemId, *transitionType); } + else { + const auto& item = _items[itemId]; + transitionStage->removeTransition(item.getTransitionId()); + } setItemTransition(itemId, transitionId); // next loop diff --git a/libraries/render/src/render/TransitionStage.cpp b/libraries/render/src/render/TransitionStage.cpp index 76943d3409..ad2fbbe9cc 100644 --- a/libraries/render/src/render/TransitionStage.cpp +++ b/libraries/render/src/render/TransitionStage.cpp @@ -23,7 +23,9 @@ void TransitionStage::removeTransition(Index index) { if (idIterator != _activeTransitionIds.end()) { _activeTransitionIds.erase(idIterator); } - _transitions.freeElement(index); + if (!_transitions.isElementFreed(index)) { + _transitions.freeElement(index); + } } TransitionStageSetup::TransitionStageSetup() { From cc4e1683697d9545337eace26a3c1e0054c023ed Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 10 Jul 2017 16:45:13 +0200 Subject: [PATCH 45/86] Working fade again --- .../src/RenderableModelEntityItem.cpp | 22 ++++-------------- .../src/RenderableModelEntityItem.h | 8 +------ libraries/render/src/render/Scene.cpp | 23 ++++++++++++------- 3 files changed, 20 insertions(+), 33 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index b65c8ee49c..320ff1342d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -242,6 +242,8 @@ bool RenderableModelEntityItem::addToScene(const EntityItemPointer& self, const // note: we don't mind if the model fails to add, we'll retry (in render()) until it succeeds _model->addToScene(scene, transaction, statusGetters); + + transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN); } // we've successfully added _myMetaItem so we always return true @@ -475,6 +477,8 @@ void RenderableModelEntityItem::render(RenderArgs* args) { makeEntityItemStatusGetters(getThisPointer(), statusGetters); _model->addToScene(scene, transaction, statusGetters); + transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN); + scene->enqueueTransaction(transaction); } @@ -490,23 +494,6 @@ ModelPointer RenderableModelEntityItem::getModelNotSafe() { return _model; } -void RenderableModelEntityItem::setModelURLFinished(bool success) { - if (success) { - const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene(); - - if (scene->isAllocatedID(_myMetaItem)) { - render::Transaction transaction; - - const auto& item = scene->getItem(_myMetaItem); - if (!item.exist()) { - qWarning() << "Starting transition on item without payload"; - } - transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN); - scene->enqueueTransaction(transaction); - } - } -} - ModelPointer RenderableModelEntityItem::getModel() { // make sure our renderer is setup if (!_myRenderer) { @@ -524,7 +511,6 @@ ModelPointer RenderableModelEntityItem::getModel() { // If we don't have a model, allocate one *immediately* if (!_model) { _model = _myRenderer->allocateModel(getModelURL(), _myRenderer->getEntityLoadingPriority(*this), this); - QObject::connect(_model.get(), &Model::setURLFinished, this, &RenderableModelEntityItem::setModelURLFinished); _needsInitialSimulation = true; // If we need to change URLs, update it *after rendering* (to avoid access violations) } else if (QUrl(getModelURL()) != _model->getURL()) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 6586678906..37d08a044a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -12,7 +12,6 @@ #ifndef hifi_RenderableModelEntityItem_h #define hifi_RenderableModelEntityItem_h -#include #include #include @@ -25,8 +24,7 @@ class Model; class EntityTreeRenderer; -class RenderableModelEntityItem : public QObject, public ModelEntityItem, RenderableEntityInterface { - Q_OBJECT +class RenderableModelEntityItem : public ModelEntityItem, RenderableEntityInterface { public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); @@ -121,10 +119,6 @@ public: return _animation; } -public slots: - - void setModelURLFinished(bool success); - private: QVariantMap parseTexturesToMap(QString textures); void remapTextures(); diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 2c55658657..d6606bcd68 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -238,17 +238,24 @@ void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types) { auto transitionStage = getStage(TransitionStage::getName()); for (auto itemId : ids) { - auto transitionId = INVALID_INDEX; - - if (*transitionType != Transition::NONE) { - transitionId = transitionStage->addTransition(itemId, *transitionType); - } - else { + // Access the true item + const auto& item = _items[itemId]; + if (item.exist()) { + auto transitionId = INVALID_INDEX; const auto& item = _items[itemId]; - transitionStage->removeTransition(item.getTransitionId()); + + // Remove pre-existing transition, if need be + if (item.getTransitionId() == render::TransitionStage::INVALID_INDEX) { + transitionStage->removeTransition(item.getTransitionId()); + } + // Add a new one. + if (*transitionType != Transition::NONE) { + transitionId = transitionStage->addTransition(itemId, *transitionType); + } + + setItemTransition(itemId, transitionId); } - setItemTransition(itemId, transitionId); // next loop transitionType++; } From 9758a6ded00d16df49acaa57995b7ed213408f23 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 10 Jul 2017 17:57:02 +0200 Subject: [PATCH 46/86] Edition picking again (but without bounding box highlighting) --- libraries/render-utils/src/FadeEffect.cpp | 81 ++++++++++++------- libraries/render-utils/src/FadeEffect.h | 48 ++++++++--- .../render-utils/src/RenderDeferredTask.cpp | 5 +- libraries/render/src/render/Item.cpp | 2 +- libraries/render/src/render/Scene.cpp | 2 +- scripts/developer/utilities/render/fade.qml | 16 ++-- 6 files changed, 105 insertions(+), 49 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 9067f4ff09..2fc3d8bb02 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -22,6 +22,52 @@ inline float valueToParameterPow(float value, const double minValue, const doubl return (float)(log(double(value) / minValue) / log(maxOverMinValue)); } +void FadeEditJob::run(const render::RenderContextPointer& renderContext, const Input& inputs) { + auto jobConfig = static_cast(renderContext->jobConfig.get()); + auto& itemBounds = inputs.get0(); + + if (jobConfig->editFade) { + float minIsectDistance = std::numeric_limits::max(); + auto itemId = findNearestItem(renderContext, itemBounds, minIsectDistance); + + if (itemId != render::Item::INVALID_ITEM_ID) { + const auto& item = renderContext->_scene->getItem(itemId); + + if (item.getTransitionId() == render::TransitionStage::INVALID_INDEX) { + // Relaunch transition + render::Transaction transaction; + transaction.transitionItem(itemId, inputs.get1()); + renderContext->_scene->enqueueTransaction(transaction); + } + } + } +} + +render::ItemID FadeEditJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const { + const glm::vec3 rayOrigin = renderContext->args->getViewFrustum().getPosition(); + const glm::vec3 rayDirection = renderContext->args->getViewFrustum().getDirection(); + auto& scene = renderContext->_scene; + BoxFace face; + glm::vec3 normal; + float isectDistance; + render::ItemID nearestItem = render::Item::INVALID_ITEM_ID; + const float minDistance = 2.f; + + for (const auto& itemBound : inputs) { + if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { + if (isectDistance>minDistance && isectDistance < minIsectDistance) { + auto& item = scene->getItem(itemBound.id); + + if (item.getKey().isShape() && !item.getKey().isMeta()) { + nearestItem = itemBound.id; + minIsectDistance = isectDistance; + } + } + } + } + return nearestItem; +} + FadeConfig::FadeConfig() { events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 0.75f, 0.75f, 0.75f }; @@ -488,14 +534,16 @@ void FadeJob::configure(const Config& config) { } } -void FadeJob::run(const render::RenderContextPointer& renderContext) { - const Config* jobConfig = static_cast(renderContext->jobConfig.get()); +void FadeJob::run(const render::RenderContextPointer& renderContext, Output& output) { + Config* jobConfig = static_cast(renderContext->jobConfig.get()); auto scene = renderContext->args->_scene; auto transitionStage = scene->getStage(render::TransitionStage::getName()); uint64_t now = usecTimestampNow(); const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND); render::Transaction transaction; bool hasTransactions = false; + + output = (render::Transition::Type) jobConfig->editedCategory; // And now update fade effect for (auto transitionId : *transitionStage) { @@ -505,6 +553,8 @@ void FadeJob::run(const render::RenderContextPointer& renderContext) { transaction.transitionItem(state.itemId, render::Transition::NONE); hasTransactions = true; } + + jobConfig->setProperty("threshold", state.threshold); } if (hasTransactions) { @@ -574,7 +624,6 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re transition.time += deltaTime; -// renderContext->jobConfig->setProperty("threshold", threshold); return continueTransition; } @@ -645,29 +694,3 @@ render::ShapePipeline::ItemSetter FadeJob::getItemSetter() const { } }; } - -const render::Item* FadeJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const { - const glm::vec3 rayOrigin = renderContext->args->getViewFrustum().getPosition(); - const glm::vec3 rayDirection = renderContext->args->getViewFrustum().getDirection(); - const auto& inputItems = input.get(); - auto& scene = renderContext->_scene; - BoxFace face; - glm::vec3 normal; - float isectDistance; - const render::Item* nearestItem = nullptr; - const float minDistance = 2.f; - - for (const auto& itemBound : inputItems) { - if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { - if (isectDistance>minDistance && isectDistance < minIsectDistance) { - auto& item = scene->getItem(itemBound.id); - - if (item.getKey().isShape() && !item.getKey().isMeta()) { - nearestItem = &item; - minIsectDistance = isectDistance; - } - } - } - } - return nearestItem; -} diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 413d4124ce..b0f7577c6a 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -16,6 +16,41 @@ #include #include +class FadeEditConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(bool manualFade MEMBER manualFade NOTIFY dirty) + Q_PROPERTY(float manualThreshold MEMBER manualThreshold NOTIFY dirty) + Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty) + +public: + + float manualThreshold{ 0.f }; + bool editFade{ false }; + bool manualFade{ false }; + +signals: + + void dirty(); +}; + +class FadeEditJob { + +public: + + using Config = FadeEditConfig; + using Input = render::VaryingSet2; + using JobModel = render::Job::ModelI; + + FadeEditJob() {} + + void configure(const Config& config) {} + void run(const render::RenderContextPointer& renderContext, const Input& inputs); + +private: + + render::ItemID findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const; +}; + class FadeConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int editedCategory MEMBER editedCategory WRITE setEditedCategory NOTIFY dirtyCategory) @@ -38,14 +73,11 @@ class FadeConfig : public render::Job::Config { Q_PROPERTY(float edgeOuterColorG READ getEdgeOuterColorG WRITE setEdgeOuterColorG NOTIFY dirty) Q_PROPERTY(float edgeOuterColorB READ getEdgeOuterColorB WRITE setEdgeOuterColorB NOTIFY dirty) Q_PROPERTY(float edgeOuterIntensity READ getEdgeOuterIntensity WRITE setEdgeOuterIntensity NOTIFY dirty) - Q_PROPERTY(bool manualFade MEMBER manualFade NOTIFY dirty) - Q_PROPERTY(float manualThreshold MEMBER manualThreshold NOTIFY dirty) Q_PROPERTY(int timing READ getTiming WRITE setTiming NOTIFY dirty) Q_PROPERTY(float noiseSpeedX READ getNoiseSpeedX WRITE setNoiseSpeedX NOTIFY dirty) Q_PROPERTY(float noiseSpeedY READ getNoiseSpeedY WRITE setNoiseSpeedY NOTIFY dirty) Q_PROPERTY(float noiseSpeedZ READ getNoiseSpeedZ WRITE setNoiseSpeedZ NOTIFY dirty) Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty) - Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty) public: @@ -146,11 +178,8 @@ public: }; Event events[render::Transition::EVENT_CATEGORY_COUNT]; - float threshold{ 0.f }; - float manualThreshold{ 0.f }; int editedCategory{ render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN }; - bool editFade{ false }; - bool manualFade{ false }; + float threshold{ 0.f }; Q_INVOKABLE void save() const; Q_INVOKABLE void load(); @@ -169,12 +198,13 @@ class FadeJob { public: using Config = FadeConfig; - using JobModel = render::Job::Model; + using Output = render::Transition::Type; + using JobModel = render::Job::ModelO; FadeJob(); void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext); + void run(const render::RenderContextPointer& renderContext, Output& output); render::ShapePipeline::BatchSetter getBatchSetter() const; render::ShapePipeline::ItemSetter getItemSetter() const; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 2bb1f50774..de6460b9ff 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -55,7 +55,7 @@ void RenderDeferredTask::configure(const Config& config) void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { const auto& items = input.get(); - task.addJob("Fade"); + auto editedTransitionType = task.addJob("Fade"); auto& fadeJob = task._jobs.back().get(); // Prepare the ShapePipelines @@ -72,6 +72,9 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren //const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND]; const auto& spatialSelection = items[1]; + const auto fadeEditInput = FadeEditJob::Input(opaques, editedTransitionType).asVarying(); + task.addJob("FadeEdit", fadeEditInput); + // Filter the non antialiaased overlays const int LAYER_NO_AA = 3; const auto nonAAOverlays = task.addJob("Filter2DWebOverlays", overlayOpaques, LAYER_NO_AA); diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 0e2adca3f4..3657b9611b 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -84,7 +84,7 @@ void Item::resetPayload(const PayloadPointer& payload) { const ShapeKey Item::getShapeKey() const { auto shapeKey = _payload->getShapeKey(); if (_transitionId != TransitionStage::INVALID_INDEX) { - return ShapeKey::Builder(shapeKey).withFade(); + return ShapeKey::Builder(shapeKey).withFade().withoutCullFace(); } return shapeKey; } \ No newline at end of file diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index d6606bcd68..1b5ba129b3 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -245,7 +245,7 @@ void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types) { const auto& item = _items[itemId]; // Remove pre-existing transition, if need be - if (item.getTransitionId() == render::TransitionStage::INVALID_INDEX) { + if (item.getTransitionId() != render::TransitionStage::INVALID_INDEX) { transitionStage->removeTransition(item.getTransitionId()); } // Add a new one. diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index 698b2384da..cc25cdfde6 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -15,8 +15,8 @@ import "../lib/plotperf" Column { id: root - property var config: Render.getConfig("RenderMainView.FadeConfigure"); - property var switchConfig: Render.getConfig("RenderMainView.FadeSwitch"); + property var config: Render.getConfig("RenderMainView.Fade"); + property var configEdit: Render.getConfig("RenderMainView.FadeEdit"); spacing: 8 Row { @@ -24,9 +24,9 @@ Column { CheckBox { text: "Edit Fade" - checked: root.switchConfig["editFade"] + checked: root.configEdit["editFade"] onCheckedChanged: { - root.switchConfig["editFade"] = checked; + root.configEdit["editFade"] = checked; Render.getConfig("RenderMainView.DrawFadedOpaqueBounds").enabled = checked; } } @@ -54,15 +54,15 @@ Column { CheckBox { text: "Manual" - checked: root.config["manualFade"] + checked: root.configEdit["manualFade"] onCheckedChanged: { - root.config["manualFade"] = checked; + root.configEdit["manualFade"] = checked; } } ConfigSlider { label: "Threshold" integral: false - config: root.config + config: root.configEdit property: "manualThreshold" max: 1.0 min: 0.0 @@ -359,7 +359,7 @@ Column { PlotPerf { title: "Threshold" height: parent.evalEvenHeight() - object: Render.getConfig("RenderMainView.DrawFadeOpaque") + object: config valueUnit: "%" valueScale: 0.01 valueNumDigits: "1" From aba8be595ea8d388526099d21ec241e61cb2f93d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 11 Jul 2017 11:37:24 +0200 Subject: [PATCH 47/86] Separated fade categories from transition event types --- .../src/RenderableModelEntityItem.cpp | 11 +- .../src/RenderableModelEntityItem.h | 1 + libraries/render-utils/src/Fade.slh | 6 +- libraries/render-utils/src/FadeEffect.cpp | 194 +++++++++++------- libraries/render-utils/src/FadeEffect.h | 63 +++--- .../render-utils/src/MeshPartPayload.cpp | 5 +- libraries/render-utils/src/Model.h | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 4 +- libraries/render/src/render/Transition.h | 12 +- 9 files changed, 179 insertions(+), 119 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 320ff1342d..8fd3b5f470 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -243,7 +243,10 @@ bool RenderableModelEntityItem::addToScene(const EntityItemPointer& self, const // note: we don't mind if the model fails to add, we'll retry (in render()) until it succeeds _model->addToScene(scene, transaction, statusGetters); - transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN); + if (!_hasTransitioned) { + transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); + _hasTransitioned = true; + } } // we've successfully added _myMetaItem so we always return true @@ -366,6 +369,7 @@ void RenderableModelEntityItem::updateModelBounds() { // the per frame simulation/update that might be required if the models properties changed. void RenderableModelEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RMEIrender"); + assert(getType() == EntityTypes::Model); // When the individual mesh parts of a model finish fading, they will mark their Model as needing updating @@ -477,7 +481,10 @@ void RenderableModelEntityItem::render(RenderArgs* args) { makeEntityItemStatusGetters(getThisPointer(), statusGetters); _model->addToScene(scene, transaction, statusGetters); - transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN); + if (!_hasTransitioned) { + transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); + _hasTransitioned = true; + } scene->enqueueTransaction(transaction); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 37d08a044a..bfe64c04d9 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -134,6 +134,7 @@ private: QVariantMap _originalTextures; bool _originalTexturesRead = false; bool _dimensionsInitialized = true; + bool _hasTransitioned{ false }; AnimationPropertyGroup _renderAnimationProperties; diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 1e15568ead..9d403da7b6 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -11,7 +11,7 @@ <@func transformModelToFadePos(objectTransform, objectPosition, fadePosition)@> { - vec4 objectVector = vec4(<$objectPosition$>.xyz, 0.f); + vec4 objectVector = vec4(<$objectPosition$>.xyz, 1.f); <$transformModelToWorldPos($objectTransform$, objectVector, $fadePosition$)$> } <@endfunc@> @@ -19,12 +19,12 @@ <@func declareFadeFragment()@> -#define EVENT_CATEGORY_COUNT 5 +#define CATEGORY_COUNT 5 <@include Fade_shared.slh@> uniform fadeParametersBuffer { - FadeParameters fadeParameters[EVENT_CATEGORY_COUNT]; + FadeParameters fadeParameters[CATEGORY_COUNT]; }; uniform int fadeCategory; uniform vec3 fadeNoiseOffset; diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 2fc3d8bb02..ae54c25cad 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -22,7 +22,7 @@ inline float valueToParameterPow(float value, const double minValue, const doubl return (float)(log(double(value) / minValue) / log(maxOverMinValue)); } -void FadeEditJob::run(const render::RenderContextPointer& renderContext, const Input& inputs) { +void FadeEditJob::run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& inputs) { auto jobConfig = static_cast(renderContext->jobConfig.get()); auto& itemBounds = inputs.get0(); @@ -34,9 +34,17 @@ void FadeEditJob::run(const render::RenderContextPointer& renderContext, const I const auto& item = renderContext->_scene->getItem(itemId); if (item.getTransitionId() == render::TransitionStage::INVALID_INDEX) { + 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 + }; + // Relaunch transition render::Transaction transaction; - transaction.transitionItem(itemId, inputs.get1()); + transaction.transitionItem(itemId, categoryToTransition[inputs.get1()]); renderContext->_scene->enqueueTransaction(transaction); } } @@ -70,70 +78,70 @@ render::ItemID FadeEditJob::findNearestItem(const render::RenderContextPointer& FadeConfig::FadeConfig() { - events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 0.75f, 0.75f, 0.75f }; - events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].noiseLevel = 1.f; - events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f }; - events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].timing = FadeConfig::LINEAR; - events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 1.0f, 1.0f, 1.0f }; - events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].baseLevel = 0.f; - events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].isInverted = false; - events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].duration = 4.f; - events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].edgeWidth = 0.1f; - events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.0f }; - events[render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; + 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[render::Transition::BUBBLE_ISECT_OWNER].noiseSize = glm::vec3{ 1.5f, 1.0f/25.f, 0.5f }; - events[render::Transition::BUBBLE_ISECT_OWNER].noiseLevel = 0.37f; - events[render::Transition::BUBBLE_ISECT_OWNER].noiseSpeed = glm::vec3{ 1.0f, 0.2f, 1.0f }; - events[render::Transition::BUBBLE_ISECT_OWNER].timing = FadeConfig::LINEAR; - events[render::Transition::BUBBLE_ISECT_OWNER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f }; - events[render::Transition::BUBBLE_ISECT_OWNER].baseLevel = 1.f; - events[render::Transition::BUBBLE_ISECT_OWNER].isInverted = false; - events[render::Transition::BUBBLE_ISECT_OWNER].duration = 4.f; - events[render::Transition::BUBBLE_ISECT_OWNER].edgeWidth = 0.02f; - events[render::Transition::BUBBLE_ISECT_OWNER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; - events[render::Transition::BUBBLE_ISECT_OWNER].edgeOuterColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 2.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[render::Transition::BUBBLE_ISECT_TRESPASSER].noiseSize = glm::vec3{ 0.5f, 1.0f / 25.f, 0.5f }; - events[render::Transition::BUBBLE_ISECT_TRESPASSER].noiseLevel = 1.f; - events[render::Transition::BUBBLE_ISECT_TRESPASSER].noiseSpeed = glm::vec3{ 1.0f, 0.2f, 1.0f }; - events[render::Transition::BUBBLE_ISECT_TRESPASSER].timing = FadeConfig::LINEAR; - events[render::Transition::BUBBLE_ISECT_TRESPASSER].baseSize = glm::vec3{ 2.0f, 2.0f, 2.0f }; - events[render::Transition::BUBBLE_ISECT_TRESPASSER].baseLevel = 0.f; - events[render::Transition::BUBBLE_ISECT_TRESPASSER].isInverted = false; - events[render::Transition::BUBBLE_ISECT_TRESPASSER].duration = 4.f; - events[render::Transition::BUBBLE_ISECT_TRESPASSER].edgeWidth = 0.025f; - events[render::Transition::BUBBLE_ISECT_TRESPASSER].edgeInnerColor = glm::vec4{ 31.f / 255.f, 198.f / 255.f, 166.f / 255.f, 1.0f }; - events[render::Transition::BUBBLE_ISECT_TRESPASSER].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, 0.2f, 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[render::Transition::USER_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 10.f, 0.01f, 10.0f }; - events[render::Transition::USER_ENTER_LEAVE_DOMAIN].noiseLevel = 0.7f; - events[render::Transition::USER_ENTER_LEAVE_DOMAIN].noiseSpeed = glm::vec3{ 0.0f, -0.5f, 0.0f }; - events[render::Transition::USER_ENTER_LEAVE_DOMAIN].timing = FadeConfig::LINEAR; - events[render::Transition::USER_ENTER_LEAVE_DOMAIN].baseSize = glm::vec3{ 10000.f, 1.0f, 10000.0f }; - events[render::Transition::USER_ENTER_LEAVE_DOMAIN].baseLevel = 1.f; - events[render::Transition::USER_ENTER_LEAVE_DOMAIN].isInverted = true; - events[render::Transition::USER_ENTER_LEAVE_DOMAIN].duration = 5.f; - events[render::Transition::USER_ENTER_LEAVE_DOMAIN].edgeWidth = 0.229f; - events[render::Transition::USER_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }; - events[render::Transition::USER_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 1.0f }; + events[USER_ENTER_LEAVE_DOMAIN].noiseSize = glm::vec3{ 10.f, 0.01f, 10.0f }; + events[USER_ENTER_LEAVE_DOMAIN].noiseLevel = 0.7f; + 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 = 5.f; + events[USER_ENTER_LEAVE_DOMAIN].edgeWidth = 0.229f; + events[USER_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }; + events[USER_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 1.f, 1.f, 1.f, 1.0f }; - events[render::Transition::AVATAR_CHANGE].noiseSize = glm::vec3{ 0.4f, 0.4f, 0.4f }; - events[render::Transition::AVATAR_CHANGE].noiseLevel = 1.f; - events[render::Transition::AVATAR_CHANGE].noiseSpeed = glm::vec3{ 0.0f, 0.0f, 0.0f }; - events[render::Transition::AVATAR_CHANGE].timing = FadeConfig::LINEAR; - events[render::Transition::AVATAR_CHANGE].baseSize = glm::vec3{ 0.4f, 0.4f, 0.4f }; - events[render::Transition::AVATAR_CHANGE].baseLevel = 1.f; - events[render::Transition::AVATAR_CHANGE].isInverted = false; - events[render::Transition::AVATAR_CHANGE].duration = 3.f; - events[render::Transition::AVATAR_CHANGE].edgeWidth = 0.05f; - events[render::Transition::AVATAR_CHANGE].edgeInnerColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f }; - events[render::Transition::AVATAR_CHANGE].edgeOuterColor = glm::vec4{ 1.0f, 1.0f, 1.0f, 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 < render::Transition::EVENT_CATEGORY_COUNT); - editedCategory = std::min(render::Transition::EVENT_CATEGORY_COUNT, value); + assert(value < CATEGORY_COUNT); + editedCategory = std::min(CATEGORY_COUNT, value); emit dirtyCategory(); emit dirty(); } @@ -302,7 +310,7 @@ void FadeConfig::setTiming(int value) { emit dirty(); } -QString FadeConfig::eventNames[render::Transition::EVENT_CATEGORY_COUNT] = { +QString FadeConfig::eventNames[FadeConfig::CATEGORY_COUNT] = { "element_enter_leave_domain", "bubble_isect_owner", "bubble_isect_trespasser", @@ -311,7 +319,7 @@ QString FadeConfig::eventNames[render::Transition::EVENT_CATEGORY_COUNT] = { }; void FadeConfig::save() const { - assert(editedCategory < render::Transition::EVENT_CATEGORY_COUNT); + assert(editedCategory < FadeConfig::CATEGORY_COUNT); QJsonObject lProperties; const QString configFile = "config/" + eventNames[editedCategory] + ".json"; QUrl path(PathUtils::resourcesPath() + configFile); @@ -516,7 +524,7 @@ FadeJob::FadeJob() void FadeJob::configure(const Config& config) { auto& configurations = _configurations.edit(); - for (auto i = 0; i < render::Transition::EVENT_CATEGORY_COUNT; i++) { + for (auto i = 0; i < FadeConfig::CATEGORY_COUNT; i++) { auto& eventParameters = configurations.parameters[i]; const auto& eventConfig = config.events[i]; @@ -534,7 +542,7 @@ void FadeJob::configure(const Config& config) { } } -void FadeJob::run(const render::RenderContextPointer& renderContext, Output& output) { +void FadeJob::run(const render::RenderContextPointer& renderContext, FadeJob::Output& output) { Config* jobConfig = static_cast(renderContext->jobConfig.get()); auto scene = renderContext->args->_scene; auto transitionStage = scene->getStage(render::TransitionStage::getName()); @@ -542,8 +550,9 @@ void FadeJob::run(const render::RenderContextPointer& renderContext, Output& out const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND); render::Transaction transaction; bool hasTransactions = false; + bool isFirstItem = true; - output = (render::Transition::Type) jobConfig->editedCategory; + output = (FadeConfig::Category) jobConfig->editedCategory; // And now update fade effect for (auto transitionId : *transitionStage) { @@ -554,7 +563,10 @@ void FadeJob::run(const render::RenderContextPointer& renderContext, Output& out hasTransactions = true; } - jobConfig->setProperty("threshold", state.threshold); + if (isFirstItem) { + jobConfig->setProperty("threshold", state.threshold); + isFirstItem = false; + } } if (hasTransactions) { @@ -563,8 +575,19 @@ void FadeJob::run(const render::RenderContextPointer& renderContext, Output& out _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 +}; + bool FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const { - auto& eventConfig = config.events[transition.eventType]; + 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; @@ -574,19 +597,24 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re auto& aabb = item.getBound(); auto& dimensions = aabb.getDimensions(); - assert(timing < render::Transition::EVENT_CATEGORY_COUNT); + assert(timing < FadeConfig::TIMING_COUNT); switch (transition.eventType) { - case render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN: - transition.threshold = 1.f - computeElementEnterRatio(transition.time, eventConfig.duration, timing); - transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[transition.eventType] + 0.5f; + case render::Transition::ELEMENT_ENTER_DOMAIN: + case render::Transition::ELEMENT_LEAVE_DOMAIN: + { + transition.threshold = computeElementEnterRatio(transition.time, eventConfig.duration, timing); transition.noiseOffset = aabb.calcCenter(); - transition.baseOffset = transition.noiseOffset - dimensions.y; + 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; - continueTransition = transition.threshold > 0.f; - break; + continueTransition = transition.threshold < 1.f; + if (transition.eventType == render::Transition::ELEMENT_ENTER_DOMAIN) { + transition.threshold = 1.f - transition.threshold; + } + } + break; case render::Transition::BUBBLE_ISECT_OWNER: { @@ -607,10 +635,19 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re } break; - case render::Transition::USER_ENTER_LEAVE_DOMAIN: + case render::Transition::USER_ENTER_DOMAIN: + case render::Transition::USER_LEAVE_DOMAIN: { - /* _editBaseOffset = itemBounds.bound.calcCenter(); - _editBaseOffset.y -= itemBounds.bound.getDimensions().y / 2.f;*/ + transition.threshold = computeElementEnterRatio(transition.time, eventConfig.duration, timing); + transition.noiseOffset = aabb.calcCenter(); + transition.baseOffset = transition.noiseOffset - dimensions.y / 2.f; + transition.baseInvSize.x = 1.f / eventConfig.baseSize.x; + transition.baseInvSize.y = 1.f / dimensions.y; + transition.baseInvSize.z = 1.f / eventConfig.baseSize.z; + continueTransition = transition.threshold < 1.f; + if (transition.eventType == render::Transition::USER_ENTER_DOMAIN) { + transition.threshold = 1.f - transition.threshold; + } } break; @@ -622,6 +659,7 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re } } + transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[fadeCategory] + 0.5f; transition.time += deltaTime; return continueTransition; @@ -684,7 +722,9 @@ render::ShapePipeline::ItemSetter FadeJob::getItemSetter() const { auto fadeCategoryLocation = uniforms.findLocation("fadeCategory"); if (fadeNoiseOffsetLocation >= 0 || fadeBaseInvSizeLocation >= 0 || fadeBaseOffsetLocation >= 0 || fadeThresholdLocation >= 0 || fadeCategoryLocation >= 0) { - batch->_glUniform1i(fadeCategoryLocation, transitionState.eventType); + const auto fadeCategory = transitionToCategory[transitionState.eventType]; + + batch->_glUniform1i(fadeCategoryLocation, fadeCategory); batch->_glUniform1f(fadeThresholdLocation, transitionState.threshold); batch->_glUniform3f(fadeNoiseOffsetLocation, transitionState.noiseOffset.x, transitionState.noiseOffset.y, transitionState.noiseOffset.z); batch->_glUniform3f(fadeBaseOffsetLocation, transitionState.baseOffset.x, transitionState.baseOffset.y, transitionState.baseOffset.z); diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index b0f7577c6a..242e05ef72 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -33,24 +33,6 @@ signals: void dirty(); }; -class FadeEditJob { - -public: - - using Config = FadeEditConfig; - using Input = render::VaryingSet2; - using JobModel = render::Job::ModelI; - - FadeEditJob() {} - - void configure(const Config& config) {} - void run(const render::RenderContextPointer& renderContext, const Input& inputs); - -private: - - render::ItemID findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const; -}; - class FadeConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int editedCategory MEMBER editedCategory WRITE setEditedCategory NOTIFY dirtyCategory) @@ -81,6 +63,17 @@ class FadeConfig : public render::Job::Config { 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, @@ -177,14 +170,14 @@ public: bool isInverted; }; - Event events[render::Transition::EVENT_CATEGORY_COUNT]; - int editedCategory{ render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN }; + Event events[CATEGORY_COUNT]; + int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN }; float threshold{ 0.f }; Q_INVOKABLE void save() const; Q_INVOKABLE void load(); - static QString eventNames[render::Transition::EVENT_CATEGORY_COUNT]; + static QString eventNames[CATEGORY_COUNT]; signals: @@ -193,34 +186,54 @@ signals: }; +class FadeEditJob { + +public: + + using Config = FadeEditConfig; + using Input = render::VaryingSet2; + using JobModel = render::Job::ModelI; + + FadeEditJob() {} + + void configure(const Config& config) {} + void run(const render::RenderContextPointer& renderContext, const FadeEditJob::Input& inputs); + +private: + + render::ItemID findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const; +}; + class FadeJob { public: using Config = FadeConfig; - using Output = render::Transition::Type; + using Output = FadeConfig::Category; using JobModel = render::Job::ModelO; FadeJob(); void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext, Output& output); + void run(const render::RenderContextPointer& renderContext, FadeJob::Output& output); render::ShapePipeline::BatchSetter getBatchSetter() const; render::ShapePipeline::ItemSetter getItemSetter() const; private: + static const FadeConfig::Category transitionToCategory[render::Transition::TYPE_COUNT]; + #include "Fade_shared.slh" struct FadeConfiguration { - FadeParameters parameters[render::Transition::EVENT_CATEGORY_COUNT]; + FadeParameters parameters[FadeConfig::CATEGORY_COUNT]; }; gpu::StructBuffer _configurations; gpu::TexturePointer _fadeMaskMap; - float _thresholdScale[render::Transition::EVENT_CATEGORY_COUNT]; + float _thresholdScale[FadeConfig::CATEGORY_COUNT]; uint64_t _previousTime{ 0 }; bool update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 8b0ff4f549..159abfa0aa 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -484,9 +484,6 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { if (wireframe) { builder.withWireframe(); } -/* if (_fadeState != STATE_COMPLETE) { - builder.withFade(); - }*/ return builder.build(); } @@ -529,7 +526,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("ModelMeshPartPayload::render"); ModelPointer model = _model.lock(); - if (!model || !model->addedToScene() || !model->isVisible()) { + if (!model || !model->isAddedToScene() || !model->isVisible()) { return; // bail asap } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 3eb796b763..5a135ab4a4 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -116,6 +116,7 @@ public: const QVector& vertices, const QVector& normals); bool isLoaded() const { return (bool)_renderGeometry && _renderGeometry->isGeometryLoaded(); } + bool isAddedToScene() const { return _addedToScene; } void setIsWireframe(bool isWireframe) { _isWireframe = isWireframe; } bool isWireframe() const { return _isWireframe; } @@ -265,7 +266,6 @@ signals: void setCollisionModelURLFinished(bool success); protected: - bool addedToScene() const { return _addedToScene; } void setBlendshapeCoefficients(const QVector& coefficients) { _blendshapeCoefficients = coefficients; } const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index de6460b9ff..f6a715efa3 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -55,7 +55,7 @@ void RenderDeferredTask::configure(const Config& config) void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { const auto& items = input.get(); - auto editedTransitionType = task.addJob("Fade"); + auto editedFadeCategory = task.addJob("Fade"); auto& fadeJob = task._jobs.back().get(); // Prepare the ShapePipelines @@ -72,7 +72,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, editedTransitionType).asVarying(); + const auto fadeEditInput = FadeEditJob::Input(opaques, editedFadeCategory).asVarying(); task.addJob("FadeEdit", fadeEditInput); // Filter the non antialiaased overlays diff --git a/libraries/render/src/render/Transition.h b/libraries/render/src/render/Transition.h index 4e52693efd..3252a9f568 100644 --- a/libraries/render/src/render/Transition.h +++ b/libraries/render/src/render/Transition.h @@ -20,18 +20,20 @@ namespace render { public: enum Type { - ELEMENT_ENTER_LEAVE_DOMAIN = 0, + ELEMENT_ENTER_DOMAIN = 0, + ELEMENT_LEAVE_DOMAIN, BUBBLE_ISECT_OWNER, BUBBLE_ISECT_TRESPASSER, - USER_ENTER_LEAVE_DOMAIN, + USER_ENTER_DOMAIN, + USER_LEAVE_DOMAIN, AVATAR_CHANGE, // Don't forget to modify Fade.slh to reflect the change in number of categories - EVENT_CATEGORY_COUNT, - NONE = EVENT_CATEGORY_COUNT + TYPE_COUNT, + NONE = TYPE_COUNT }; - Type eventType{ ELEMENT_ENTER_LEAVE_DOMAIN }; + Type eventType{ ELEMENT_ENTER_DOMAIN }; ItemID itemId{ Item::INVALID_ITEM_ID }; double time{ 0.0 }; glm::vec3 noiseOffset{ 0.f, 0.f, 0.f }; From 381e0c64a8354ddab8118e70321556e04cfa60a3 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 11 Jul 2017 16:43:27 +0200 Subject: [PATCH 48/86] Working avatar fade in / fade out except that it is also triggered on bubble collisions --- interface/src/avatar/AvatarManager.cpp | 14 ++--- .../src/avatars-renderer/Avatar.cpp | 51 +++++++++++++++++++ .../src/avatars-renderer/Avatar.h | 8 +++ libraries/render-utils/src/FadeEffect.cpp | 10 +++- libraries/render/src/render/Scene.cpp | 13 +++-- libraries/render/src/render/Scene.h | 5 +- libraries/render/src/render/Transition.h | 1 + .../render/src/render/TransitionStage.cpp | 3 +- libraries/render/src/render/TransitionStage.h | 2 +- 9 files changed, 90 insertions(+), 17 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index c46d61cf68..1184bc8311 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -274,19 +274,20 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { return; } - const float SHRINK_RATE = 0.15f; - const float MIN_FADE_SCALE = MIN_AVATAR_SCALE; + //const float SHRINK_RATE = 0.15f; + //const float MIN_FADE_SCALE = MIN_AVATAR_SCALE; QReadLocker locker(&_hashLock); QVector::iterator avatarItr = _avatarsToFade.begin(); + const render::ScenePointer& scene = qApp->getMain3DScene(); while (avatarItr != _avatarsToFade.end()) { auto avatar = std::static_pointer_cast(*avatarItr); - avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE); - avatar->animateScaleChanges(deltaTime); - if (avatar->getTargetScale() <= MIN_FADE_SCALE) { + // TEMP OP avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE); + // TEMP OP avatar->animateScaleChanges(deltaTime); + // TEMP OP if (avatar->getTargetScale() <= MIN_FADE_SCALE) { + if (!avatar->isFading(scene)) { // fading to zero is such a rare event we push a unique transaction for each if (avatar->isInScene()) { - const render::ScenePointer& scene = qApp->getMain3DScene(); render::Transaction transaction; avatar->removeFromScene(*avatarItr, scene, transaction); scene->enqueueTransaction(transaction); @@ -329,6 +330,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar DependencyManager::get()->avatarDisconnected(avatar->getSessionUUID()); } _avatarsToFade.push_back(removedAvatar); + avatar->fadeOut(qApp->getMain3DScene()); } void AvatarManager::clearOtherAvatars() { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 44a005194b..647d6ee58a 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "Logging.h" @@ -493,6 +494,39 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc for (auto& attachmentModel : _attachmentModels) { attachmentModel->addToScene(scene, transaction); } + + _mustFadeIn = true; +} + +bool Avatar::isFading(render::ScenePointer scene) const { + if (isInScene()) { + const auto& item = scene->getItem(_renderItemID); + auto transitionId = item.getTransitionId(); + return _isWaitingForFade || transitionId!= render::TransitionStage::INVALID_INDEX; + } + return _isWaitingForFade; +} + +void Avatar::fadeIn(render::ScenePointer scene) { + render::Transaction transaction; + fade(transaction, render::Transition::USER_ENTER_DOMAIN); + scene->enqueueTransaction(transaction); +} + +void Avatar::fadeOut(render::ScenePointer scene) { + render::Transaction transaction; + fade(transaction, render::Transition::USER_LEAVE_DOMAIN); + scene->enqueueTransaction(transaction); +} + +void Avatar::fade(render::Transaction& transaction, render::Transition::Type type) { + transaction.transitionItem(_renderItemID, type); + for (auto& attachmentModel : _attachmentModels) { + for (auto itemId : attachmentModel->fetchRenderItemIDs()) { + transaction.transitionItem(itemId, type, _renderItemID); + } + } + _isWaitingForFade = true; } void Avatar::removeFromScene(AvatarSharedPointer self, const render::ScenePointer& scene, render::Transaction& transaction) { @@ -645,6 +679,8 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { } void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { + bool canTryFade{ false }; + _attachmentsToDelete.clear(); // check to see if when we added our models to the scene they were ready, if they were not ready, then @@ -653,6 +689,7 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) { _skeletonModel->removeFromScene(scene, transaction); _skeletonModel->addToScene(scene, transaction); + canTryFade = true; } for (auto attachmentModel : _attachmentModels) { if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) { @@ -661,6 +698,20 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { } } + if (_mustFadeIn && canTryFade) { + // Do it now to be sure all the sub items are ready and the fade is sent to them too + fade(transaction, render::Transition::USER_ENTER_DOMAIN); + _mustFadeIn = false; + } + + if (isInScene()) { + const auto& item = scene->getItem(_renderItemID); + auto transitionId = item.getTransitionId(); + if (_isWaitingForFade && transitionId != render::TransitionStage::INVALID_INDEX) { + _isWaitingForFade = false; + } + } + for (auto attachmentModelToRemove : _attachmentsToRemove) { attachmentModelToRemove->removeFromScene(scene, transaction); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 1724d42510..dccf23a20c 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -250,6 +250,10 @@ public: void addPhysicsFlags(uint32_t flags); bool isInPhysicsSimulation() const { return _physicsCallback != nullptr; } + void fadeIn(render::ScenePointer scene); + void fadeOut(render::ScenePointer scene); + bool isFading(render::ScenePointer scene) const; + public slots: // FIXME - these should be migrated to use Pose data instead @@ -294,6 +298,8 @@ protected: // protected methods... bool isLookingAtMe(AvatarSharedPointer avatar) const; + void fade(render::Transaction& transaction, render::Transition::Type type); + glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; } glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const; @@ -342,6 +348,8 @@ private: bool _initialized { false }; bool _isLookAtTarget { false }; bool _isAnimatingScale { false }; + bool _mustFadeIn{ false }; + bool _isWaitingForFade{ false }; static int _jointConesID; diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index ae54c25cad..c3eea52eea 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -594,7 +594,13 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re bool continueTransition = true; if (item.exist()) { - auto& aabb = item.getBound(); + 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); @@ -645,7 +651,7 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re transition.baseInvSize.y = 1.f / dimensions.y; transition.baseInvSize.z = 1.f / eventConfig.baseSize.z; continueTransition = transition.threshold < 1.f; - if (transition.eventType == render::Transition::USER_ENTER_DOMAIN) { + if (transition.eventType == render::Transition::USER_LEAVE_DOMAIN) { transition.threshold = 1.f - transition.threshold; } } diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 1b5ba129b3..40c46203a0 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -31,8 +31,9 @@ void Transaction::removeItem(ItemID id) { _removedItems.emplace_back(id); } -void Transaction::transitionItem(ItemID id, Transition::Type transition) { +void Transaction::transitionItem(ItemID id, Transition::Type transition, ItemID boundId) { _transitioningItems.emplace_back(id); + _transitioningItemBounds.emplace_back(boundId); _transitionTypes.emplace_back(transition); } @@ -53,6 +54,7 @@ void Transaction::merge(const Transaction& transaction) { _updateFunctors.insert(_updateFunctors.end(), transaction._updateFunctors.begin(), transaction._updateFunctors.end()); _resetSelections.insert(_resetSelections.end(), transaction._resetSelections.begin(), transaction._resetSelections.end()); _transitioningItems.insert(_transitioningItems.end(), transaction._transitioningItems.begin(), transaction._transitioningItems.end()); + _transitioningItemBounds.insert(_transitioningItemBounds.end(), transaction._transitioningItemBounds.begin(), transaction._transitioningItemBounds.end()); _transitionTypes.insert(_transitionTypes.end(), transaction._transitionTypes.begin(), transaction._transitionTypes.end()); } @@ -124,7 +126,7 @@ void Scene::processTransactionQueue() { removeItems(consolidatedTransaction._removedItems); // Transitions - transitionItems(consolidatedTransaction._transitioningItems, consolidatedTransaction._transitionTypes); + transitionItems(consolidatedTransaction._transitioningItems, consolidatedTransaction._transitionTypes, consolidatedTransaction._transitioningItemBounds); // Update the numItemsAtomic counter AFTER the pending changes went through _numAllocatedItems.exchange(maxID); @@ -233,8 +235,9 @@ void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) { } } -void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types) { +void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types, const ItemIDs& boundIds) { auto transitionType = types.begin(); + auto boundId = boundIds.begin(); auto transitionStage = getStage(TransitionStage::getName()); for (auto itemId : ids) { @@ -242,7 +245,6 @@ void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types) { const auto& item = _items[itemId]; if (item.exist()) { auto transitionId = INVALID_INDEX; - const auto& item = _items[itemId]; // Remove pre-existing transition, if need be if (item.getTransitionId() != render::TransitionStage::INVALID_INDEX) { @@ -250,7 +252,7 @@ void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types) { } // Add a new one. if (*transitionType != Transition::NONE) { - transitionId = transitionStage->addTransition(itemId, *transitionType); + transitionId = transitionStage->addTransition(itemId, *transitionType, *boundId); } setItemTransition(itemId, transitionId); @@ -258,6 +260,7 @@ void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types) { // next loop transitionType++; + boundId++; } } diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 90255033ce..3be31c10a6 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -40,7 +40,7 @@ public: void resetItem(ItemID id, const PayloadPointer& payload); void removeItem(ItemID id); - void transitionItem(ItemID id, Transition::Type transition); + void transitionItem(ItemID id, Transition::Type transition, ItemID boundId = render::Item::INVALID_ITEM_ID); template void updateItem(ItemID id, std::function func) { updateItem(id, std::make_shared>(func)); @@ -62,6 +62,7 @@ public: ItemIDs _removedItems; ItemIDs _updatedItems; ItemIDs _transitioningItems; + ItemIDs _transitioningItemBounds; TransitionTypes _transitionTypes; UpdateFunctors _updateFunctors; @@ -148,7 +149,7 @@ protected: void resetItems(const ItemIDs& ids, Payloads& payloads); void removeItems(const ItemIDs& ids); void updateItems(const ItemIDs& ids, UpdateFunctors& functors); - void transitionItems(const ItemIDs& ids, const TransitionTypes& types); + void transitionItems(const ItemIDs& ids, const TransitionTypes& types, const ItemIDs& boundIds); void collectSubItems(ItemID parentId, ItemIDs& subItems) const; diff --git a/libraries/render/src/render/Transition.h b/libraries/render/src/render/Transition.h index 3252a9f568..20efe524cf 100644 --- a/libraries/render/src/render/Transition.h +++ b/libraries/render/src/render/Transition.h @@ -35,6 +35,7 @@ namespace render { Type eventType{ ELEMENT_ENTER_DOMAIN }; ItemID itemId{ Item::INVALID_ITEM_ID }; + ItemID boundItemId{ Item::INVALID_ITEM_ID }; double time{ 0.0 }; glm::vec3 noiseOffset{ 0.f, 0.f, 0.f }; glm::vec3 baseOffset{ 0.f, 0.f, 0.f }; diff --git a/libraries/render/src/render/TransitionStage.cpp b/libraries/render/src/render/TransitionStage.cpp index ad2fbbe9cc..33ef829c64 100644 --- a/libraries/render/src/render/TransitionStage.cpp +++ b/libraries/render/src/render/TransitionStage.cpp @@ -6,12 +6,13 @@ using namespace render; std::string TransitionStage::_name("Transition"); -TransitionStage::Index TransitionStage::addTransition(ItemID itemId, Transition::Type type) { +TransitionStage::Index TransitionStage::addTransition(ItemID itemId, Transition::Type type, ItemID boundId) { Transition transition; Index id; transition.eventType = type; transition.itemId = itemId; + transition.boundItemId = boundId; id = _transitions.newElement(transition); _activeTransitionIds.push_back(id); diff --git a/libraries/render/src/render/TransitionStage.h b/libraries/render/src/render/TransitionStage.h index 0d2a5a41ff..8dfef1b78e 100644 --- a/libraries/render/src/render/TransitionStage.h +++ b/libraries/render/src/render/TransitionStage.h @@ -36,7 +36,7 @@ namespace render { Transition& editTransition(Index TransitionId) { return _transitions.edit(TransitionId); } - Index addTransition(ItemID itemId, Transition::Type type); + Index addTransition(ItemID itemId, Transition::Type type, ItemID boundId); void removeTransition(Index index); TransitionIdList::iterator begin() { return _activeTransitionIds.begin(); } From 7552cca316c5da0c16a13b6b176aa21027d56702 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 11 Jul 2017 19:26:15 +0200 Subject: [PATCH 49/86] First alpha version of bubble collision fade events. Missing a lot of information. --- interface/src/avatar/AvatarManager.cpp | 2 +- .../src/avatars-renderer/Avatar.cpp | 16 +++++++++---- .../src/avatars-renderer/Avatar.h | 2 +- libraries/avatars/src/AvatarHashMap.cpp | 9 ++++++- .../src/RenderableModelEntityItem.cpp | 4 ++-- libraries/render-utils/src/FadeEffect.cpp | 24 ++++++++++++------- libraries/render/src/render/Scene.cpp | 8 ++++++- libraries/render/src/render/Scene.h | 3 ++- 8 files changed, 48 insertions(+), 20 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 1184bc8311..7aa2f4b78d 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -330,7 +330,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar DependencyManager::get()->avatarDisconnected(avatar->getSessionUUID()); } _avatarsToFade.push_back(removedAvatar); - avatar->fadeOut(qApp->getMain3DScene()); + avatar->fadeOut(qApp->getMain3DScene(), removalReason); } void AvatarManager::clearOtherAvatars() { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 647d6ee58a..192f5e6969 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -513,17 +513,25 @@ void Avatar::fadeIn(render::ScenePointer scene) { scene->enqueueTransaction(transaction); } -void Avatar::fadeOut(render::ScenePointer scene) { +void Avatar::fadeOut(render::ScenePointer scene, KillAvatarReason reason) { + render::Transition::Type transitionType = render::Transition::USER_LEAVE_DOMAIN; render::Transaction transaction; - fade(transaction, render::Transition::USER_LEAVE_DOMAIN); + + if (reason == KillAvatarReason::YourAvatarEnteredTheirBubble) { + transitionType = render::Transition::BUBBLE_ISECT_TRESPASSER; + } + else if (reason == KillAvatarReason::TheirAvatarEnteredYourBubble) { + transitionType = render::Transition::BUBBLE_ISECT_OWNER; + } + fade(transaction, transitionType); scene->enqueueTransaction(transaction); } void Avatar::fade(render::Transaction& transaction, render::Transition::Type type) { - transaction.transitionItem(_renderItemID, type); + transaction.addTransitionToItem(_renderItemID, type); for (auto& attachmentModel : _attachmentModels) { for (auto itemId : attachmentModel->fetchRenderItemIDs()) { - transaction.transitionItem(itemId, type, _renderItemID); + transaction.addTransitionToItem(itemId, type, _renderItemID); } } _isWaitingForFade = true; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index dccf23a20c..aec328d798 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -251,7 +251,7 @@ public: bool isInPhysicsSimulation() const { return _physicsCallback != nullptr; } void fadeIn(render::ScenePointer scene); - void fadeOut(render::ScenePointer scene); + void fadeOut(render::ScenePointer scene, KillAvatarReason reason); bool isFading(render::ScenePointer scene) const; public slots: diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index e8c37bdaa8..38601dcd8d 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -180,7 +180,14 @@ void AvatarHashMap::processExitingSpaceBubble(QSharedPointer me void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) { QWriteLocker locker(&_hashLock); - auto removedAvatar = _avatarHash.take(sessionUUID); + AvatarSharedPointer removedAvatar; + + if (removalReason != KillAvatarReason::TheirAvatarEnteredYourBubble && removalReason != KillAvatarReason::YourAvatarEnteredTheirBubble) { + removedAvatar = _avatarHash.take(sessionUUID); + } + else { + removedAvatar = _avatarHash[sessionUUID]; + } if (removedAvatar) { handleRemovedAvatar(removedAvatar, removalReason); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 8fd3b5f470..03d22e8598 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -244,7 +244,7 @@ bool RenderableModelEntityItem::addToScene(const EntityItemPointer& self, const _model->addToScene(scene, transaction, statusGetters); if (!_hasTransitioned) { - transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); + transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); _hasTransitioned = true; } } @@ -482,7 +482,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { _model->addToScene(scene, transaction, statusGetters); if (!_hasTransitioned) { - transaction.transitionItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); + transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); _hasTransitioned = true; } diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index c3eea52eea..3131944c90 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -44,7 +44,7 @@ void FadeEditJob::run(const render::RenderContextPointer& renderContext, const F // Relaunch transition render::Transaction transaction; - transaction.transitionItem(itemId, categoryToTransition[inputs.get1()]); + transaction.addTransitionToItem(itemId, categoryToTransition[inputs.get1()]); renderContext->_scene->enqueueTransaction(transaction); } } @@ -115,13 +115,13 @@ FadeConfig::FadeConfig() 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.7f; + 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 = 5.f; + events[USER_ENTER_LEAVE_DOMAIN].duration = 2.f; events[USER_ENTER_LEAVE_DOMAIN].edgeWidth = 0.229f; events[USER_ENTER_LEAVE_DOMAIN].edgeInnerColor = glm::vec4{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }; events[USER_ENTER_LEAVE_DOMAIN].edgeOuterColor = glm::vec4{ 1.f, 1.f, 1.f, 1.0f }; @@ -559,7 +559,7 @@ void FadeJob::run(const render::RenderContextPointer& renderContext, FadeJob::Ou auto& state = transitionStage->editTransition(transitionId); if (!update(*jobConfig, scene, state, deltaTime)) { // Remove transition for this item - transaction.transitionItem(state.itemId, render::Transition::NONE); + transaction.addTransitionToItem(state.itemId, render::Transition::NONE); hasTransactions = true; } @@ -605,12 +605,16 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re 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, eventConfig.duration, timing); - transition.noiseOffset = aabb.calcCenter(); transition.baseOffset = transition.noiseOffset; transition.baseInvSize.x = 1.f / dimensions.x; transition.baseInvSize.y = 1.f / dimensions.y; @@ -624,6 +628,9 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re case render::Transition::BUBBLE_ISECT_OWNER: { + transition.threshold = 0.5f; + transition.baseOffset = transition.noiseOffset; + /* const glm::vec3 cameraPos = renderContext->args->getViewFrustum().getPosition(); glm::vec3 delta = itemBounds.bound.calcCenter() - cameraPos; float distance = glm::length(delta); @@ -637,7 +644,8 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re case render::Transition::BUBBLE_ISECT_TRESPASSER: { - // _editBaseOffset = glm::vec3{ 0.f, 0.f, 0.f }; + transition.threshold = 0.5f; + transition.baseOffset = transition.noiseOffset; } break; @@ -645,11 +653,8 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re case render::Transition::USER_LEAVE_DOMAIN: { transition.threshold = computeElementEnterRatio(transition.time, eventConfig.duration, timing); - transition.noiseOffset = aabb.calcCenter(); transition.baseOffset = transition.noiseOffset - dimensions.y / 2.f; - transition.baseInvSize.x = 1.f / eventConfig.baseSize.x; transition.baseInvSize.y = 1.f / dimensions.y; - transition.baseInvSize.z = 1.f / eventConfig.baseSize.z; continueTransition = transition.threshold < 1.f; if (transition.eventType == render::Transition::USER_LEAVE_DOMAIN) { transition.threshold = 1.f - transition.threshold; @@ -665,6 +670,7 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re } } + transition.noiseOffset += eventConfig.noiseSpeed * (float)transition.time; transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[fadeCategory] + 0.5f; transition.time += deltaTime; diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 40c46203a0..01829d8216 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -31,12 +31,18 @@ void Transaction::removeItem(ItemID id) { _removedItems.emplace_back(id); } -void Transaction::transitionItem(ItemID id, Transition::Type transition, ItemID boundId) { +void Transaction::addTransitionToItem(ItemID id, Transition::Type transition, ItemID boundId) { _transitioningItems.emplace_back(id); _transitioningItemBounds.emplace_back(boundId); _transitionTypes.emplace_back(transition); } +void Transaction::removeTransitionFromItem(ItemID id) { + _transitioningItems.emplace_back(id); + _transitioningItemBounds.emplace_back(render::Item::INVALID_ITEM_ID); + _transitionTypes.emplace_back(render::Transition::NONE); +} + void Transaction::updateItem(ItemID id, const UpdateFunctorPointer& functor) { _updatedItems.emplace_back(id); _updateFunctors.emplace_back(functor); diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 3be31c10a6..aea006394b 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -40,7 +40,8 @@ public: void resetItem(ItemID id, const PayloadPointer& payload); void removeItem(ItemID id); - void transitionItem(ItemID id, Transition::Type transition, ItemID boundId = render::Item::INVALID_ITEM_ID); + void addTransitionToItem(ItemID id, Transition::Type transition, ItemID boundId = render::Item::INVALID_ITEM_ID); + void removeTransitionFromItem(ItemID id); template void updateItem(ItemID id, std::function func) { updateItem(id, std::make_shared>(func)); From 2d2722bfc500a2bec809732fd54571cf6ba60431 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 13 Jul 2017 11:05:04 +0200 Subject: [PATCH 50/86] Added async transition query on scene --- interface/src/avatar/AvatarManager.cpp | 9 +- interface/src/ui/overlays/Overlays.cpp | 2 +- .../src/avatars-renderer/Avatar.cpp | 29 ++--- .../src/avatars-renderer/Avatar.h | 5 +- libraries/render-utils/src/FadeEffect.cpp | 23 +--- libraries/render-utils/src/FadeEffect.h | 2 +- libraries/render/src/render/Scene.cpp | 113 ++++++++++-------- libraries/render/src/render/Scene.h | 51 +++++--- libraries/render/src/render/Transition.h | 2 +- 9 files changed, 122 insertions(+), 114 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 7aa2f4b78d..5c2da8e0e5 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -282,10 +282,11 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { const render::ScenePointer& scene = qApp->getMain3DScene(); while (avatarItr != _avatarsToFade.end()) { auto avatar = std::static_pointer_cast(*avatarItr); - // TEMP OP avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE); - // TEMP OP avatar->animateScaleChanges(deltaTime); - // TEMP OP if (avatar->getTargetScale() <= MIN_FADE_SCALE) { - if (!avatar->isFading(scene)) { + // avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE); + // avatar->animateScaleChanges(deltaTime); + // if (avatar->getTargetScale() <= MIN_FADE_SCALE) { + avatar->updateFadingStatus(scene); + if (!avatar->isFading()) { // fading to zero is such a rare event we push a unique transaction for each if (avatar->isInScene()) { render::Transaction transaction; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 72682fcb8c..6190027b05 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -96,7 +96,7 @@ void Overlays::cleanupOverlaysToDelete() { } while (!_overlaysToDelete.isEmpty()); } - if (transaction._removedItems.size() > 0) { + if (transaction.hasRemovedItems()) { scene->enqueueTransaction(transaction); } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 7ad2dd219d..58ee6782fd 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -498,15 +498,6 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc _mustFadeIn = true; } -bool Avatar::isFading(render::ScenePointer scene) const { - if (isInScene()) { - const auto& item = scene->getItem(_renderItemID); - auto transitionId = item.getTransitionId(); - return _isWaitingForFade || transitionId!= render::TransitionStage::INVALID_INDEX; - } - return _isWaitingForFade; -} - void Avatar::fadeIn(render::ScenePointer scene) { render::Transaction transaction; fade(transaction, render::Transition::USER_ENTER_DOMAIN); @@ -534,7 +525,17 @@ void Avatar::fade(render::Transaction& transaction, render::Transition::Type typ transaction.addTransitionToItem(itemId, type, _renderItemID); } } - _isWaitingForFade = true; + _isFading = true; +} + +void Avatar::updateFadingStatus(render::ScenePointer scene) { + render::Transaction transaction; + transaction.queryTransitionOnItem(_renderItemID, [this](render::ItemID id, const render::Transition* transition) { + if (transition == nullptr || transition->isFinished) { + _isFading = false; + } + }); + scene->enqueueTransaction(transaction); } void Avatar::removeFromScene(AvatarSharedPointer self, const render::ScenePointer& scene, render::Transaction& transaction) { @@ -712,14 +713,6 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { _mustFadeIn = false; } - if (isInScene()) { - const auto& item = scene->getItem(_renderItemID); - auto transitionId = item.getTransitionId(); - if (_isWaitingForFade && transitionId != render::TransitionStage::INVALID_INDEX) { - _isWaitingForFade = false; - } - } - for (auto attachmentModelToRemove : _attachmentsToRemove) { attachmentModelToRemove->removeFromScene(scene, transaction); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index b1a7c48bfb..10710bd631 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -252,7 +252,8 @@ public: void fadeIn(render::ScenePointer scene); void fadeOut(render::ScenePointer scene, KillAvatarReason reason); - bool isFading(render::ScenePointer scene) const; + bool isFading() const { return _isFading; } + void updateFadingStatus(render::ScenePointer scene); public slots: @@ -356,7 +357,7 @@ private: bool _isLookAtTarget { false }; bool _isAnimatingScale { false }; bool _mustFadeIn{ false }; - bool _isWaitingForFade{ false }; + bool _isFading{ false }; static int _jointConesID; diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 3131944c90..222224ed5f 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -548,8 +548,6 @@ void FadeJob::run(const render::RenderContextPointer& renderContext, FadeJob::Ou auto transitionStage = scene->getStage(render::TransitionStage::getName()); uint64_t now = usecTimestampNow(); const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND); - render::Transaction transaction; - bool hasTransactions = false; bool isFirstItem = true; output = (FadeConfig::Category) jobConfig->editedCategory; @@ -557,21 +555,12 @@ void FadeJob::run(const render::RenderContextPointer& renderContext, FadeJob::Ou // And now update fade effect for (auto transitionId : *transitionStage) { auto& state = transitionStage->editTransition(transitionId); - if (!update(*jobConfig, scene, state, deltaTime)) { - // Remove transition for this item - transaction.addTransitionToItem(state.itemId, render::Transition::NONE); - hasTransactions = true; - } - + update(*jobConfig, scene, state, deltaTime); if (isFirstItem) { jobConfig->setProperty("threshold", state.threshold); isFirstItem = false; } } - - if (hasTransactions) { - scene->enqueueTransaction(transaction); - } _previousTime = now; } @@ -585,13 +574,12 @@ const FadeConfig::Category FadeJob::transitionToCategory[render::Transition::TYP FadeConfig::AVATAR_CHANGE }; -bool FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const { +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; - bool continueTransition = true; if (item.exist()) { auto aabb = item.getBound(); @@ -619,7 +607,7 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re transition.baseInvSize.x = 1.f / dimensions.x; transition.baseInvSize.y = 1.f / dimensions.y; transition.baseInvSize.z = 1.f / dimensions.z; - continueTransition = transition.threshold < 1.f; + transition.isFinished = transition.threshold >= 1.f; if (transition.eventType == render::Transition::ELEMENT_ENTER_DOMAIN) { transition.threshold = 1.f - transition.threshold; } @@ -655,7 +643,7 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re transition.threshold = computeElementEnterRatio(transition.time, eventConfig.duration, timing); transition.baseOffset = transition.noiseOffset - dimensions.y / 2.f; transition.baseInvSize.y = 1.f / dimensions.y; - continueTransition = transition.threshold < 1.f; + transition.isFinished = transition.threshold >= 1.f; if (transition.eventType == render::Transition::USER_LEAVE_DOMAIN) { transition.threshold = 1.f - transition.threshold; } @@ -671,10 +659,9 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re } transition.noiseOffset += eventConfig.noiseSpeed * (float)transition.time; + 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; - - return continueTransition; } float FadeJob::computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing) { diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 242e05ef72..431a069ee6 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -236,7 +236,7 @@ private: float _thresholdScale[FadeConfig::CATEGORY_COUNT]; uint64_t _previousTime{ 0 }; - bool update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const; + 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; diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 01829d8216..18aef8ff70 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -19,8 +19,7 @@ using namespace render; void Transaction::resetItem(ItemID id, const PayloadPointer& payload) { if (payload) { - _resetItems.emplace_back(id); - _resetPayloads.emplace_back(payload); + _resetItems.emplace_back(Reset{ id, payload }); } else { qCDebug(renderlogging) << "WARNING: Transaction::resetItem with a null payload!"; removeItem(id); @@ -32,20 +31,19 @@ void Transaction::removeItem(ItemID id) { } void Transaction::addTransitionToItem(ItemID id, Transition::Type transition, ItemID boundId) { - _transitioningItems.emplace_back(id); - _transitioningItemBounds.emplace_back(boundId); - _transitionTypes.emplace_back(transition); + _addedTransitions.emplace_back(TransitionAdd{ id, transition, boundId }); } void Transaction::removeTransitionFromItem(ItemID id) { - _transitioningItems.emplace_back(id); - _transitioningItemBounds.emplace_back(render::Item::INVALID_ITEM_ID); - _transitionTypes.emplace_back(render::Transition::NONE); + _addedTransitions.emplace_back(TransitionAdd{ id, Transition::NONE, render::Item::INVALID_ITEM_ID }); +} + +void Transaction::queryTransitionOnItem(ItemID id, TransitionQueryFunc func) { + _queriedTransitions.emplace_back(TransitionQuery{ id, func }); } void Transaction::updateItem(ItemID id, const UpdateFunctorPointer& functor) { - _updatedItems.emplace_back(id); - _updateFunctors.emplace_back(functor); + _updatedItems.emplace_back(Update{ id, functor }); } void Transaction::resetSelection(const Selection& selection) { @@ -54,14 +52,11 @@ void Transaction::resetSelection(const Selection& selection) { void Transaction::merge(const Transaction& transaction) { _resetItems.insert(_resetItems.end(), transaction._resetItems.begin(), transaction._resetItems.end()); - _resetPayloads.insert(_resetPayloads.end(), transaction._resetPayloads.begin(), transaction._resetPayloads.end()); _removedItems.insert(_removedItems.end(), transaction._removedItems.begin(), transaction._removedItems.end()); _updatedItems.insert(_updatedItems.end(), transaction._updatedItems.begin(), transaction._updatedItems.end()); - _updateFunctors.insert(_updateFunctors.end(), transaction._updateFunctors.begin(), transaction._updateFunctors.end()); _resetSelections.insert(_resetSelections.end(), transaction._resetSelections.begin(), transaction._resetSelections.end()); - _transitioningItems.insert(_transitioningItems.end(), transaction._transitioningItems.begin(), transaction._transitioningItems.end()); - _transitioningItemBounds.insert(_transitioningItemBounds.end(), transaction._transitioningItemBounds.begin(), transaction._transitioningItemBounds.end()); - _transitionTypes.insert(_transitionTypes.end(), transaction._transitionTypes.begin(), transaction._transitionTypes.end()); + _addedTransitions.insert(_addedTransitions.end(), transaction._addedTransitions.begin(), transaction._addedTransitions.end()); + _queriedTransitions.insert(_queriedTransitions.end(), transaction._queriedTransitions.begin(), transaction._queriedTransitions.end()); } @@ -120,19 +115,21 @@ void Scene::processTransactionQueue() { // capture anything coming from the transaction // resets and potential NEW items - resetItems(consolidatedTransaction._resetItems, consolidatedTransaction._resetPayloads); + resetItems(consolidatedTransaction._resetItems); // Update the numItemsAtomic counter AFTER the reset changes went through _numAllocatedItems.exchange(maxID); // updates - updateItems(consolidatedTransaction._updatedItems, consolidatedTransaction._updateFunctors); + updateItems(consolidatedTransaction._updatedItems); // removes removeItems(consolidatedTransaction._removedItems); - // Transitions - transitionItems(consolidatedTransaction._transitioningItems, consolidatedTransaction._transitionTypes, consolidatedTransaction._transitioningItemBounds); + // add transitions + transitionItems(consolidatedTransaction._addedTransitions); + + queryTransitionItems(consolidatedTransaction._queriedTransitions); // Update the numItemsAtomic counter AFTER the pending changes went through _numAllocatedItems.exchange(maxID); @@ -146,34 +143,31 @@ void Scene::processTransactionQueue() { } } -void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) { - auto resetPayload = payloads.begin(); - for (auto resetID : ids) { +void Scene::resetItems(const Transaction::Resets& transactions) { + for (auto& reset : transactions) { // Access the true item - auto& item = _items[resetID]; + auto itemId = std::get<0>(reset); + auto& item = _items[itemId]; auto oldKey = item.getKey(); auto oldCell = item.getCell(); // Reset the item with a new payload - item.resetPayload(*resetPayload); + item.resetPayload(std::get<1>(reset)); auto newKey = item.getKey(); // Update the item's container assert((oldKey.isSpatial() == newKey.isSpatial()) || oldKey._flags.none()); if (newKey.isSpatial()) { - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), resetID, newKey); + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), itemId, newKey); item.resetCell(newCell, newKey.isSmall()); } else { - _masterNonspatialSet.insert(resetID); + _masterNonspatialSet.insert(itemId); } - - // next loop - resetPayload++; } } -void Scene::removeItems(const ItemIDs& ids) { - for (auto removedID :ids) { +void Scene::removeItems(const Transaction::Removes& transactions) { + for (auto removedID : transactions) { // Access the true item auto& item = _items[removedID]; auto oldCell = item.getCell(); @@ -197,12 +191,10 @@ void Scene::removeItems(const ItemIDs& ids) { } } -void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) { - - auto updateFunctor = functors.begin(); - for (auto updateID : ids) { +void Scene::updateItems(const Transaction::Updates& transactions) { + for (auto& update : transactions) { + auto updateID = std::get<0>(update); if (updateID == Item::INVALID_ITEM_ID) { - updateFunctor++; continue; } @@ -212,7 +204,7 @@ void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) { auto oldKey = item.getKey(); // Update the item - item.update((*updateFunctor)); + item.update(std::get<1>(update)); auto newKey = item.getKey(); // Update the item's container @@ -234,39 +226,54 @@ void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) { _masterNonspatialSet.insert(updateID); } } - - - // next loop - updateFunctor++; } } -void Scene::transitionItems(const ItemIDs& ids, const TransitionTypes& types, const ItemIDs& boundIds) { - auto transitionType = types.begin(); - auto boundId = boundIds.begin(); +void Scene::transitionItems(const Transaction::TransitionAdds& transactions) { auto transitionStage = getStage(TransitionStage::getName()); - for (auto itemId : ids) { + for (auto& add : transactions) { + auto itemId = std::get<0>(add); // Access the true item const auto& item = _items[itemId]; if (item.exist()) { auto transitionId = INVALID_INDEX; + auto transitionType = std::get<1>(add); + auto boundId = std::get<2>(add); // Remove pre-existing transition, if need be - if (item.getTransitionId() != render::TransitionStage::INVALID_INDEX) { + if (TransitionStage::isIndexInvalid(item.getTransitionId())) { transitionStage->removeTransition(item.getTransitionId()); } // Add a new one. - if (*transitionType != Transition::NONE) { - transitionId = transitionStage->addTransition(itemId, *transitionType, *boundId); + if (transitionType != Transition::NONE) { + transitionId = transitionStage->addTransition(itemId, transitionType, boundId); } setItemTransition(itemId, transitionId); } + } +} - // next loop - transitionType++; - boundId++; +void Scene::queryTransitionItems(const Transaction::TransitionQueries& transactions) { + auto transitionStage = getStage(TransitionStage::getName()); + + for (auto& query : transactions) { + auto itemId = std::get<0>(query); + // Access the true item + const auto& item = _items[itemId]; + auto func = std::get<1>(query); + if (item.exist() && func != nullptr) { + auto transitionId = item.getTransitionId(); + + if (TransitionStage::isIndexInvalid(transitionId)) { + auto& transition = transitionStage->getTransition(transitionId); + func(itemId, &transition); + } + else { + func(itemId, nullptr); + } + } } } @@ -325,8 +332,8 @@ Selection Scene::getSelection(const Selection::Name& name) const { } } -void Scene::resetSelections(const Selections& selections) { - for (auto selection : selections) { +void Scene::resetSelections(const Transaction::SelectionResets& transactions) { + for (auto selection : transactions) { auto found = _selections.find(selection.getName()); if (found == _selections.end()) { _selections.insert(SelectionMap::value_type(selection.getName(), selection)); diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index aea006394b..b24cde240f 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -21,6 +21,7 @@ namespace render { class Engine; +class Scene; // Transaction is the mechanism to make any change to the scene. // Whenever a new item need to be reset, @@ -32,16 +33,22 @@ class Engine; // of updating the scene before it s rendered. // class Transaction { + friend class Scene; public: + + typedef std::function TransitionQueryFunc; + Transaction() {} ~Transaction() {} // Item transactions void resetItem(ItemID id, const PayloadPointer& payload); void removeItem(ItemID id); + bool hasRemovedItems() const { return !_removedItems.empty(); } void addTransitionToItem(ItemID id, Transition::Type transition, ItemID boundId = render::Item::INVALID_ITEM_ID); void removeTransitionFromItem(ItemID id); + void queryTransitionOnItem(ItemID id, TransitionQueryFunc func); template void updateItem(ItemID id, std::function func) { updateItem(id, std::make_shared>(func)); @@ -58,18 +65,28 @@ public: // Checkers if there is work to do when processing the transaction bool touchTransactions() const { return !_resetSelections.empty(); } - ItemIDs _resetItems; - Payloads _resetPayloads; - ItemIDs _removedItems; - ItemIDs _updatedItems; - ItemIDs _transitioningItems; - ItemIDs _transitioningItemBounds; - TransitionTypes _transitionTypes; - UpdateFunctors _updateFunctors; - - Selections _resetSelections; - protected: + + using Reset = std::tuple; + using Remove = ItemID; + using Update = std::tuple; + using TransitionAdd = std::tuple; + using TransitionQuery = std::tuple; + using SelectionReset = Selection; + + using Resets = std::vector; + using Removes = std::vector; + using Updates = std::vector; + using TransitionAdds = std::vector; + using TransitionQueries = std::vector; + using SelectionResets = std::vector; + + Resets _resetItems; + Removes _removedItems; + Updates _updatedItems; + TransitionAdds _addedTransitions; + TransitionQueries _queriedTransitions; + SelectionResets _resetSelections; }; typedef std::queue TransactionQueue; @@ -134,6 +151,7 @@ public: void resetItemTransition(ItemID id); protected: + // Thread safe elements that can be accessed from anywhere std::atomic _IDAllocator{ 1 }; // first valid itemID will be One std::atomic _numAllocatedItems{ 1 }; // num of allocated items, matching the _items.size() @@ -147,10 +165,11 @@ protected: ItemSpatialTree _masterSpatialTree; ItemIDSet _masterNonspatialSet; - void resetItems(const ItemIDs& ids, Payloads& payloads); - void removeItems(const ItemIDs& ids); - void updateItems(const ItemIDs& ids, UpdateFunctors& functors); - void transitionItems(const ItemIDs& ids, const TransitionTypes& types, const ItemIDs& boundIds); + void resetItems(const Transaction::Resets& transactions); + void removeItems(const Transaction::Removes& transactions); + void updateItems(const Transaction::Updates& transactions); + void transitionItems(const Transaction::TransitionAdds& transactions); + void queryTransitionItems(const Transaction::TransitionQueries& transactions); void collectSubItems(ItemID parentId, ItemIDs& subItems) const; @@ -158,7 +177,7 @@ protected: mutable std::mutex _selectionsMutex; // mutable so it can be used in the thread safe getSelection const method SelectionMap _selections; - void resetSelections(const Selections& selections); + void resetSelections(const Transaction::SelectionResets& transactions); // More actions coming to selections soon: // void removeFromSelection(const Selection& selection); // void appendToSelection(const Selection& selection); diff --git a/libraries/render/src/render/Transition.h b/libraries/render/src/render/Transition.h index 20efe524cf..a87595e4ce 100644 --- a/libraries/render/src/render/Transition.h +++ b/libraries/render/src/render/Transition.h @@ -41,7 +41,7 @@ namespace render { glm::vec3 baseOffset{ 0.f, 0.f, 0.f }; glm::vec3 baseInvSize{ 1.f, 1.f, 1.f }; float threshold{ 0.f }; - + bool isFinished{ false }; }; typedef std::shared_ptr TransitionPointer; From 53a92c15065af578bb85ab8af50a00f896a8c73a Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 13 Jul 2017 12:31:10 +0200 Subject: [PATCH 51/86] Fade edit is working again and time based transitions are garbage collected --- libraries/render-utils/src/FadeEffect.cpp | 96 +++++++++++++-------- libraries/render-utils/src/FadeEffect.h | 13 +-- libraries/render/src/render/Scene.cpp | 4 +- libraries/render/src/render/Transition.h | 2 +- scripts/developer/utilities/render/fade.qml | 6 +- 5 files changed, 76 insertions(+), 45 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 222224ed5f..b5e0c53973 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -22,32 +22,59 @@ inline float valueToParameterPow(float value, const double minValue, const doubl 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 jobConfig = static_cast(renderContext->jobConfig.get()); - auto& itemBounds = inputs.get0(); + auto scene = renderContext->_scene; - if (jobConfig->editFade) { + if (_isEditEnabled) { float minIsectDistance = std::numeric_limits::max(); - auto itemId = findNearestItem(renderContext, itemBounds, minIsectDistance); + auto& itemBounds = inputs.get0(); + auto editedItem = findNearestItem(renderContext, itemBounds, minIsectDistance); + render::Transaction transaction; + bool hasTransaction{ false }; - if (itemId != render::Item::INVALID_ITEM_ID) { - const auto& item = renderContext->_scene->getItem(itemId); - - if (item.getTransitionId() == render::TransitionStage::INVALID_INDEX) { - 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 - }; - - // Relaunch transition - render::Transaction transaction; - transaction.addTransitionToItem(itemId, categoryToTransition[inputs.get1()]); - renderContext->_scene->enqueueTransaction(transaction); - } + if (editedItem != _editedItem && _editedItem != render::Item::INVALID_ITEM_ID) { + // Remove transition from previously edited item as we've changed edited item + hasTransaction = true; + transaction.removeTransitionFromItem(_editedItem); } + _editedItem = editedItem; + + if (_editedItem != render::Item::INVALID_ITEM_ID) { + 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 (_editedItem != render::Item::INVALID_ITEM_ID) { + // 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; } } @@ -66,10 +93,10 @@ render::ItemID FadeEditJob::findNearestItem(const render::RenderContextPointer& if (isectDistance>minDistance && isectDistance < minIsectDistance) { auto& item = scene->getItem(itemBound.id); - if (item.getKey().isShape() && !item.getKey().isMeta()) { + // if (!item.getKey().isMeta()) { nearestItem = itemBound.id; minIsectDistance = isectDistance; - } + // } } } } @@ -607,7 +634,7 @@ void FadeJob::update(const Config& config, const render::ScenePointer& scene, re 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; + transition.isFinished += (transition.threshold >= 1.f) & 1; if (transition.eventType == render::Transition::ELEMENT_ENTER_DOMAIN) { transition.threshold = 1.f - transition.threshold; } @@ -618,15 +645,6 @@ void FadeJob::update(const Config& config, const render::ScenePointer& scene, re { transition.threshold = 0.5f; transition.baseOffset = transition.noiseOffset; - - /* const glm::vec3 cameraPos = renderContext->args->getViewFrustum().getPosition(); - glm::vec3 delta = itemBounds.bound.calcCenter() - cameraPos; - float distance = glm::length(delta); - - delta = glm::normalize(delta) * std::max(0.f, distance - 0.5f); - - _editBaseOffset = cameraPos + delta*_editThreshold; - _editThreshold = 0.33f;*/ } break; @@ -643,7 +661,7 @@ void FadeJob::update(const Config& config, const render::ScenePointer& scene, re transition.threshold = computeElementEnterRatio(transition.time, eventConfig.duration, timing); transition.baseOffset = transition.noiseOffset - dimensions.y / 2.f; transition.baseInvSize.y = 1.f / dimensions.y; - transition.isFinished = transition.threshold >= 1.f; + transition.isFinished += (transition.threshold >= 1.f) & 1; if (transition.eventType == render::Transition::USER_LEAVE_DOMAIN) { transition.threshold = 1.f - transition.threshold; } @@ -659,9 +677,19 @@ void FadeJob::update(const Config& config, const render::ScenePointer& scene, re } 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) { diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 431a069ee6..30c233ad29 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -18,15 +18,11 @@ class FadeEditConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(bool manualFade MEMBER manualFade NOTIFY dirty) - Q_PROPERTY(float manualThreshold MEMBER manualThreshold NOTIFY dirty) Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty) public: - float manualThreshold{ 0.f }; bool editFade{ false }; - bool manualFade{ false }; signals: @@ -60,6 +56,8 @@ class FadeConfig : public render::Job::Config { 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: @@ -173,6 +171,8 @@ public: 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(); @@ -196,11 +196,14 @@ public: FadeEditJob() {} - void configure(const Config& config) {} + 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; }; diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 18aef8ff70..8bbcca0691 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -242,7 +242,7 @@ void Scene::transitionItems(const Transaction::TransitionAdds& transactions) { auto boundId = std::get<2>(add); // Remove pre-existing transition, if need be - if (TransitionStage::isIndexInvalid(item.getTransitionId())) { + if (!TransitionStage::isIndexInvalid(item.getTransitionId())) { transitionStage->removeTransition(item.getTransitionId()); } // Add a new one. @@ -266,7 +266,7 @@ void Scene::queryTransitionItems(const Transaction::TransitionQueries& transacti if (item.exist() && func != nullptr) { auto transitionId = item.getTransitionId(); - if (TransitionStage::isIndexInvalid(transitionId)) { + if (!TransitionStage::isIndexInvalid(transitionId)) { auto& transition = transitionStage->getTransition(transitionId); func(itemId, &transition); } diff --git a/libraries/render/src/render/Transition.h b/libraries/render/src/render/Transition.h index a87595e4ce..622e6f69ce 100644 --- a/libraries/render/src/render/Transition.h +++ b/libraries/render/src/render/Transition.h @@ -41,7 +41,7 @@ namespace render { glm::vec3 baseOffset{ 0.f, 0.f, 0.f }; glm::vec3 baseInvSize{ 1.f, 1.f, 1.f }; float threshold{ 0.f }; - bool isFinished{ false }; + uint8_t isFinished{ 0 }; }; typedef std::shared_ptr TransitionPointer; diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index cc25cdfde6..f4e4a167d9 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -54,15 +54,15 @@ Column { CheckBox { text: "Manual" - checked: root.configEdit["manualFade"] + checked: root.config["manualFade"] onCheckedChanged: { - root.configEdit["manualFade"] = checked; + root.config["manualFade"] = checked; } } ConfigSlider { label: "Threshold" integral: false - config: root.configEdit + config: root.config property: "manualThreshold" max: 1.0 min: 0.0 From 21a11d72c4a7887955458746ae26c5d1ea7a8d61 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 13 Jul 2017 12:44:26 +0200 Subject: [PATCH 52/86] Added define to activate/deactivate transition support (fade) in Scene --- libraries/render/src/render/Scene.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 8bbcca0691..3c3ace90f4 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -15,6 +15,9 @@ #include "Logging.h" #include "TransitionStage.h" +// Comment this to disable transitions (fades) +#define SCENE_ENABLE_TRANSITIONS + using namespace render; void Transaction::resetItem(ItemID id, const PayloadPointer& payload) { @@ -126,11 +129,12 @@ void Scene::processTransactionQueue() { // removes removeItems(consolidatedTransaction._removedItems); +#ifdef SCENE_ENABLE_TRANSITIONS // add transitions transitionItems(consolidatedTransaction._addedTransitions); queryTransitionItems(consolidatedTransaction._queriedTransitions); - +#endif // Update the numItemsAtomic counter AFTER the pending changes went through _numAllocatedItems.exchange(maxID); } From 736ecf0082227a2d0355261b7ae8b0662beab00a Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 13 Jul 2017 14:43:41 +0200 Subject: [PATCH 53/86] Fixed infinite recursion in collectMetaSubItems due to meta sending itself as sub-item --- libraries/render-utils/src/FadeEffect.cpp | 10 +++++----- libraries/render/src/render/Scene.cpp | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index b5e0c53973..df1d4e20f6 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -36,14 +36,14 @@ void FadeEditJob::run(const render::RenderContextPointer& renderContext, const F render::Transaction transaction; bool hasTransaction{ false }; - if (editedItem != _editedItem && _editedItem != render::Item::INVALID_ITEM_ID) { + 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 (_editedItem != render::Item::INVALID_ITEM_ID) { + if (render::Item::isValidID(_editedItem)) { static const render::Transition::Type categoryToTransition[FadeConfig::CATEGORY_COUNT] = { render::Transition::ELEMENT_ENTER_DOMAIN, render::Transition::BUBBLE_ISECT_OWNER, @@ -69,7 +69,7 @@ void FadeEditJob::run(const render::RenderContextPointer& renderContext, const F scene->enqueueTransaction(transaction); } } - else if (_editedItem != render::Item::INVALID_ITEM_ID) { + else if (render::Item::isValidID(_editedItem)) { // Remove transition from previously edited item as we've disabled fade edition render::Transaction transaction; transaction.removeTransitionFromItem(_editedItem); @@ -131,7 +131,7 @@ FadeConfig::FadeConfig() 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, 0.2f, 1.0f }; + 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; @@ -150,7 +150,7 @@ FadeConfig::FadeConfig() 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{ 78.f / 255.f, 215.f / 255.f, 255.f / 255.f, 0.25f }; + 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 }; diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 3c3ace90f4..bc412089be 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -290,7 +290,11 @@ void Scene::collectSubItems(ItemID parentId, ItemIDs& subItems) const { auto subItemBeginIndex = subItems.size(); auto subItemCount = item.fetchMetaSubItems(subItems); for (auto i = subItemBeginIndex; i < (subItemBeginIndex + subItemCount); i++) { - collectSubItems(subItems[i], subItems); + auto subItemId = subItems[i]; + // Bizarrely, subItemId == parentId can happen for metas... See metaFetchMetaSubItems in RenderableEntityItem.cpp + if (subItemId != parentId) { + collectSubItems(subItemId, subItems); + } } } } From c583de4d96e6d7550c744d97498da921aec88659 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 13 Jul 2017 15:22:10 +0200 Subject: [PATCH 54/86] Fade working on voxel objects --- .../src/RenderablePolyVoxEntityItem.cpp | 14 ++++++++++++-- .../src/RenderablePolyVoxEntityItem.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 60aaefcb6f..0766acdbb1 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -807,6 +807,10 @@ bool RenderablePolyVoxEntityItem::addToScene(const EntityItemPointer& self, renderPayload->addStatusGetters(statusGetters); transaction.resetItem(_myItem, renderPayload); + if (_mesh && _mesh->getIndexBuffer()._buffer) { + transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); + _hasTransitioned = true; + } return true; } @@ -830,11 +834,9 @@ render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render:: gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), render::ShapePipeline::Slot::BUFFER::FADE_PARAMETERS)); slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0)); slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2)); - slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), render::ShapePipeline::Slot::MAP::FADE_MASK)); auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); @@ -1387,6 +1389,14 @@ void RenderablePolyVoxEntityItem::setMesh(model::MeshPointer mesh) { if (neighborsNeedUpdate) { bonkNeighbors(); } + + if (!_hasTransitioned) { + render::Transaction transaction; + render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); + transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); + scene->enqueueTransaction(transaction); + _hasTransitioned = true; + } } void RenderablePolyVoxEntityItem::computeShapeInfoWorker() { diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 507391d59e..5cb9527281 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -177,6 +177,7 @@ private: gpu::Stream::FormatPointer _vertexFormat; bool _meshDirty { true }; // does collision-shape need to be recomputed? bool _meshReady { false }; + bool _hasTransitioned{ false }; NetworkTexturePointer _xTexture; NetworkTexturePointer _yTexture; From 1b8696fddaa18ddfe00eb31eeb5aa6efd07a79fc Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 13 Jul 2017 17:09:49 +0200 Subject: [PATCH 55/86] First draft of custom pipeline on geometry cache --- .../src/RenderableEntityItem.cpp | 39 +++++++++++++++ .../src/RenderableEntityItem.h | 39 ++------------- .../src/RenderableShapeEntityItem.cpp | 21 ++++++++ .../src/RenderableShapeEntityItem.h | 14 ++++++ libraries/render-utils/src/GeometryCache.cpp | 48 +++++++++++++++++-- libraries/render-utils/src/GeometryCache.h | 25 ++++++---- libraries/render/src/render/Item.h | 1 + 7 files changed, 139 insertions(+), 48 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index f8d155600a..d44ec04e9f 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -130,3 +130,42 @@ void makeEntityItemStatusGetters(EntityItemPointer entity, render::Item::Status: (unsigned char)RenderItemStatusIcon::CLIENT_ONLY); }); } + +bool SimplerRenderableEntitySupport::addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) { + _myItem = scene->allocateID(); + + auto renderData = std::make_shared(self, _myItem); + auto renderPayload = std::make_shared(renderData); + + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(self, statusGetters); + renderPayload->addStatusGetters(statusGetters); + + transaction.resetItem(_myItem, renderPayload); + + return true; +} + +void SimplerRenderableEntitySupport::removeFromScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) { + transaction.removeItem(_myItem); + render::Item::clearID(_myItem); +} + +void SimplerRenderableEntitySupport::notifyChanged() { + if (!render::Item::isValidID(_myItem)) { + return; + } + + render::Transaction transaction; + render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); + + if (scene) { + transaction.updateItem(_myItem, [](RenderableEntityItemProxy& data) { + }); + + scene->enqueueTransaction(transaction); + } + else { + qCWarning(entitiesrenderer) << "SimpleRenderableEntityItem::notifyChanged(), Unexpected null scene, possibly during application shutdown"; + } +} diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index c848b10f6a..93cd524acd 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -70,44 +70,13 @@ namespace render { // Mixin class for implementing basic single item rendering class SimplerRenderableEntitySupport : public RenderableEntityInterface { public: - bool addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override { - _myItem = scene->allocateID(); - auto renderData = std::make_shared(self, _myItem); - auto renderPayload = std::make_shared(renderData); + bool addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override; + void removeFromScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override; + void notifyChanged(); - render::Item::Status::Getters statusGetters; - makeEntityItemStatusGetters(self, statusGetters); - renderPayload->addStatusGetters(statusGetters); +protected: - transaction.resetItem(_myItem, renderPayload); - - return true; - } - - void removeFromScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override { - transaction.removeItem(_myItem); - render::Item::clearID(_myItem); - } - - void notifyChanged() { - if (!render::Item::isValidID(_myItem)) { - return; - } - - render::Transaction transaction; - render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - - if (scene) { - transaction.updateItem(_myItem, [](RenderableEntityItemProxy& data) { - }); - - scene->enqueueTransaction(transaction); - } else { - qCWarning(entitiesrenderer) << "SimpleRenderableEntityItem::notifyChanged(), Unexpected null scene, possibly during application shutdown"; - } - } -private: render::ItemID _myItem { render::Item::INVALID_ITEM_ID }; }; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index a56965b0ec..dcc969f546 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -82,6 +82,27 @@ bool RenderableShapeEntityItem::isTransparent() { } } +namespace render { + template <> const ShapeKey shapeGetShapeKey(const ShapePayload::Pointer& payload) { + return ShapeKey::Builder().withCustom(GeometryCache::CUSTOM_PIPELINE_NUMBER).build(); + } +} + +bool RenderableShapeEntityItem::addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) { + _myItem = scene->allocateID(); + + auto renderData = std::make_shared(self, _myItem); + auto renderPayload = std::make_shared(renderData); + + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(self, statusGetters); + renderPayload->addStatusGetters(statusGetters); + + transaction.resetItem(_myItem, renderPayload); + + return true; +} + void RenderableShapeEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); //Q_ASSERT(getType() == EntityTypes::Shape); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 0cc6a54f81..aca013b36d 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -14,6 +14,19 @@ #include "RenderableEntityItem.h" +class ShapePayload : public RenderableEntityItemProxy { +public: + ShapePayload(const EntityItemPointer& entity, render::ItemID metaID) + : RenderableEntityItemProxy(entity, metaID) {} + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + +}; + +namespace render { + template <> const ShapeKey shapeGetShapeKey(const ShapePayload::Pointer& payload); +} + class RenderableShapeEntityItem : public ShapeEntityItem, private SimplerRenderableEntitySupport { using Pointer = std::shared_ptr; static Pointer baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties); @@ -23,6 +36,7 @@ public: static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID) {} + bool addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override; void render(RenderArgs* args) override; void setUserData(const QString& value) override; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 9f2e2f14a3..504eb800ab 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -450,14 +450,50 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() { return INSTANCED_SOLID_STREAM_FORMAT; } +QHash GeometryCache::_simplePrograms; + +gpu::ShaderPointer GeometryCache::_simpleShader; +gpu::ShaderPointer GeometryCache::_unlitShader; +gpu::ShaderPointer GeometryCache::_simpleFadeShader; +gpu::ShaderPointer GeometryCache::_unlitFadeShader; + render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline; render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline; render::ShapePipelinePointer GeometryCache::_simpleOpaqueFadePipeline; render::ShapePipelinePointer GeometryCache::_simpleTransparentFadePipeline; render::ShapePipelinePointer GeometryCache::_simpleWirePipeline; +uint8_t GeometryCache::CUSTOM_PIPELINE_NUMBER = 0; + +render::ShapePipelinePointer GeometryCache::shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key) { + initializeShapePipelines(); + + if (key.isWireframe()) { + return _simpleWirePipeline; + } + + if (key.isFaded()) { + if (key.isTranslucent()) { + return _simpleTransparentFadePipeline; + } + else { + return _simpleOpaqueFadePipeline; + } + } + else { + if (key.isTranslucent()) { + return _simpleTransparentPipeline; + } + else { + return _simpleOpaquePipeline; + } + } +} + GeometryCache::GeometryCache() : _nextID(0) { + // Let's register its special shapePipeline factory: + registerShapePipeline(); buildShapes(); } @@ -504,11 +540,13 @@ void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { } void GeometryCache::initializeShapePipelines() { - GeometryCache::_simpleOpaquePipeline = getShapePipeline(false, false, true, false); - GeometryCache::_simpleTransparentPipeline = getShapePipeline(false, true, true, false); - GeometryCache::_simpleOpaqueFadePipeline = getShapePipeline(false, false, true, false, false, true); - GeometryCache::_simpleTransparentFadePipeline = getShapePipeline(false, true, true, false, false, true); - GeometryCache::_simpleWirePipeline = getShapePipeline(false, false, true, true); + if (!_simpleOpaquePipeline) { + _simpleOpaquePipeline = getShapePipeline(false, false, true, false); + _simpleTransparentPipeline = getShapePipeline(false, true, true, false); + _simpleOpaqueFadePipeline = getShapePipeline(false, false, true, false, false, true); + _simpleTransparentFadePipeline = getShapePipeline(false, true, true, false, false, true); + _simpleWirePipeline = getShapePipeline(false, false, true, true); + } } render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool culled, diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 5be086d084..b4f1b02292 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -147,6 +147,14 @@ public: NUM_SHAPES, }; + static uint8_t CUSTOM_PIPELINE_NUMBER; + static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key); + static void registerShapePipeline() { + if (!CUSTOM_PIPELINE_NUMBER) { + CUSTOM_PIPELINE_NUMBER = render::ShapePipeline::registerCustomShapePipelineFactory(shapePipelineFactory); + } + } + int allocateID() { return _nextID++; } void releaseID(int id); static const int UNKNOWN_ID; @@ -155,7 +163,7 @@ public: void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool transparent = false, bool culled = true, bool unlit = false, bool depthBias = false); // Get the pipeline to render static geometry - gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true, + static gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true, bool unlit = false, bool depthBias = false, bool fading = false); void bindOpaqueWebBrowserProgram(gpu::Batch& batch, bool isAA); @@ -164,9 +172,9 @@ public: void bindTransparentWebBrowserProgram(gpu::Batch& batch, bool isAA); gpu::PipelinePointer getTransparentWebBrowserProgram(bool isAA); - void initializeShapePipelines(); + static void initializeShapePipelines(); - render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true, + static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true, bool unlit = false, bool depthBias = false, bool fading = false); render::ShapePipelinePointer getOpaqueShapePipeline() { assert(_simpleOpaquePipeline != nullptr); return _simpleOpaquePipeline; } @@ -426,10 +434,10 @@ private: QHash _lastRegisteredGridBuffer; QHash _registeredGridBuffers; - gpu::ShaderPointer _simpleShader; - gpu::ShaderPointer _unlitShader; - gpu::ShaderPointer _simpleFadeShader; - gpu::ShaderPointer _unlitFadeShader; + static gpu::ShaderPointer _simpleShader; + static gpu::ShaderPointer _unlitShader; + static gpu::ShaderPointer _simpleFadeShader; + static gpu::ShaderPointer _unlitFadeShader; static render::ShapePipelinePointer _simpleOpaquePipeline; static render::ShapePipelinePointer _simpleTransparentPipeline; static render::ShapePipelinePointer _simpleOpaqueFadePipeline; @@ -438,7 +446,8 @@ private: static render::ShapePipelinePointer _simpleTransparentOverlayPipeline; static render::ShapePipelinePointer _simpleWirePipeline; gpu::PipelinePointer _glowLinePipeline; - QHash _simplePrograms; + + static QHash _simplePrograms; gpu::ShaderPointer _simpleOpaqueWebBrowserShader; gpu::PipelinePointer _simpleOpaqueWebBrowserPipeline; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index cdd915364d..b53a90ac2f 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -71,6 +71,7 @@ public: Flags _flags{ 0 }; public: Builder() {} + Builder(const ItemKey& key) : _flags{ key._flags } {} ItemKey build() const { return ItemKey(_flags); } From 93218da473a77956fa16652af4690c9f79f22995 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 13 Jul 2017 17:51:16 +0200 Subject: [PATCH 56/86] Fixed compilation errors on Mac and Linux --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 1 + libraries/entities-renderer/src/RenderableModelEntityItem.h | 2 -- libraries/render/src/render/IndexedContainer.h | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 03d22e8598..dd6b5d20ef 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "EntityTreeRenderer.h" #include "EntitiesRendererLogging.h" diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index bfe64c04d9..e0e98b6a2d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -16,8 +16,6 @@ #include #include -#include -#include #include "RenderableEntityItem.h" diff --git a/libraries/render/src/render/IndexedContainer.h b/libraries/render/src/render/IndexedContainer.h index 5aca12f83e..4b51f8eb3c 100644 --- a/libraries/render/src/render/IndexedContainer.h +++ b/libraries/render/src/render/IndexedContainer.h @@ -14,6 +14,7 @@ #include #include +#include namespace render { namespace indexed_container { From 96f0c35b79a81f214eb852fe92642328c423f681 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 13 Jul 2017 18:22:18 +0200 Subject: [PATCH 57/86] Yet some more compilation fixes for Mac and Linux --- libraries/render-utils/src/FadeEffect.cpp | 12 ++++-------- libraries/render/src/render/Item.cpp | 3 +++ libraries/render/src/render/Item.h | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index df1d4e20f6..5a415c933b 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -91,12 +91,8 @@ render::ItemID FadeEditJob::findNearestItem(const render::RenderContextPointer& for (const auto& itemBound : inputs) { if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { if (isectDistance>minDistance && isectDistance < minIsectDistance) { - auto& item = scene->getItem(itemBound.id); - - // if (!item.getKey().isMeta()) { - nearestItem = itemBound.id; - minIsectDistance = isectDistance; - // } + nearestItem = itemBound.id; + minIsectDistance = isectDistance; } } } @@ -629,7 +625,7 @@ void FadeJob::update(const Config& config, const render::ScenePointer& scene, re case render::Transition::ELEMENT_ENTER_DOMAIN: case render::Transition::ELEMENT_LEAVE_DOMAIN: { - transition.threshold = computeElementEnterRatio(transition.time, eventConfig.duration, timing); + 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; @@ -658,7 +654,7 @@ void FadeJob::update(const Config& config, const render::ScenePointer& scene, re case render::Transition::USER_ENTER_DOMAIN: case render::Transition::USER_LEAVE_DOMAIN: { - transition.threshold = computeElementEnterRatio(transition.time, eventConfig.duration, timing); + 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; diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 3657b9611b..afc32ea629 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -17,6 +17,9 @@ using namespace render; +const Item::ID Item::INVALID_ITEM_ID = 0; +const ItemCell Item::INVALID_CELL = -1; + const Item::Status::Value Item::Status::Value::INVALID = Item::Status::Value(); const float Item::Status::Value::RED = 0.0f; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index cdd915364d..d6119a6ad8 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -243,8 +243,8 @@ public: typedef std::vector Vector; typedef ItemID ID; - static const ID INVALID_ITEM_ID = 0; - static const ItemCell INVALID_CELL = -1; + static const ID INVALID_ITEM_ID; + static const ItemCell INVALID_CELL; // Convenient function to clear an ID or check it s valid static void clearID(ID& id) { id = INVALID_ITEM_ID; } From 4d5f2ebdfece1cdea88440b7b3c25ca065000ca4 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 13 Jul 2017 18:45:08 +0200 Subject: [PATCH 58/86] Removed unused variable that prevented build on Linux --- libraries/render-utils/src/FadeEffect.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 5a415c933b..b2fd7c0c7e 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -81,7 +81,6 @@ void FadeEditJob::run(const render::RenderContextPointer& renderContext, const F render::ItemID FadeEditJob::findNearestItem(const render::RenderContextPointer& renderContext, const render::ItemBounds& inputs, float& minIsectDistance) const { const glm::vec3 rayOrigin = renderContext->args->getViewFrustum().getPosition(); const glm::vec3 rayDirection = renderContext->args->getViewFrustum().getDirection(); - auto& scene = renderContext->_scene; BoxFace face; glm::vec3 normal; float isectDistance; From b125fba2e18e1c85be28257a967afa11f443b562 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 13 Jul 2017 23:04:55 +0200 Subject: [PATCH 59/86] Removed untested avatar bubble fade code. Made changes as requested by Andrew --- interface/src/avatar/AvatarManager.cpp | 6 - .../src/avatars-renderer/Avatar.h | 4 +- libraries/avatars/src/AvatarHashMap.cpp | 9 +- .../src/RenderableModelEntityItem.cpp | 2 +- libraries/render/src/render/Scene.cpp | 6 +- scripts/developer/utilities/render/fade.qml | 708 +++++++++--------- 6 files changed, 360 insertions(+), 375 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index d3fa87b163..961e168fa5 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -273,17 +273,11 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { return; } - //const float SHRINK_RATE = 0.15f; - //const float MIN_FADE_SCALE = MIN_AVATAR_SCALE; - QReadLocker locker(&_hashLock); QVector::iterator avatarItr = _avatarsToFade.begin(); const render::ScenePointer& scene = qApp->getMain3DScene(); while (avatarItr != _avatarsToFade.end()) { auto avatar = std::static_pointer_cast(*avatarItr); - // avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE); - // avatar->animateScaleChanges(deltaTime); - // if (avatar->getTargetScale() <= MIN_FADE_SCALE) { avatar->updateFadingStatus(scene); if (!avatar->isFading()) { // fading to zero is such a rare event we push a unique transaction for each diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 10710bd631..d078514e2e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -356,8 +356,8 @@ private: bool _initialized { false }; bool _isLookAtTarget { false }; bool _isAnimatingScale { false }; - bool _mustFadeIn{ false }; - bool _isFading{ false }; + bool _mustFadeIn { false }; + bool _isFading { false }; static int _jointConesID; diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 68df528d7c..540fd583c8 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -173,14 +173,7 @@ void AvatarHashMap::processKillAvatar(QSharedPointer message, S void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) { QWriteLocker locker(&_hashLock); - AvatarSharedPointer removedAvatar; - - if (removalReason != KillAvatarReason::TheirAvatarEnteredYourBubble && removalReason != KillAvatarReason::YourAvatarEnteredTheirBubble) { - removedAvatar = _avatarHash.take(sessionUUID); - } - else { - removedAvatar = _avatarHash[sessionUUID]; - } + AvatarSharedPointer removedAvatar = _avatarHash.take(sessionUUID); if (removedAvatar) { handleRemovedAvatar(removedAvatar, removalReason); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index dd6b5d20ef..77070a064f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -219,7 +219,7 @@ namespace render { template <> uint32_t metaFetchMetaSubItems(const RenderableModelEntityItemMeta::Pointer& payload, ItemIDs& subItems) { auto modelEntity = std::static_pointer_cast(payload->entity); auto model = modelEntity->getModelNotSafe(); - if (modelEntity->hasModel() && model) { + if (model && modelEntity->hasModel()) { auto& metaSubItems = model->fetchRenderItemIDs(); subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end()); return (uint32_t) metaSubItems.size(); diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index bc412089be..3e266a6fdf 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -273,8 +273,7 @@ void Scene::queryTransitionItems(const Transaction::TransitionQueries& transacti if (!TransitionStage::isIndexInvalid(transitionId)) { auto& transition = transitionStage->getTransition(transitionId); func(itemId, &transition); - } - else { + } else { func(itemId, nullptr); } } @@ -314,8 +313,7 @@ void Scene::setItemTransition(ItemID itemId, Index transitionId) { auto& subItem = _items[subItemId]; subItem.setTransitionId(transitionId); } - } - else { + } else { qWarning() << "Collecting sub items on item without payload"; } } diff --git a/scripts/developer/utilities/render/fade.qml b/scripts/developer/utilities/render/fade.qml index f4e4a167d9..1dffd0fbbb 100644 --- a/scripts/developer/utilities/render/fade.qml +++ b/scripts/developer/utilities/render/fade.qml @@ -14,384 +14,384 @@ import "configSlider" import "../lib/plotperf" Column { - id: root - property var config: Render.getConfig("RenderMainView.Fade"); - property var configEdit: Render.getConfig("RenderMainView.FadeEdit"); - spacing: 8 + id: root + property var config: Render.getConfig("RenderMainView.Fade"); + property var configEdit: Render.getConfig("RenderMainView.FadeEdit"); + spacing: 8 - Row { - spacing: 8 + Row { + spacing: 8 - CheckBox { - text: "Edit Fade" - checked: root.configEdit["editFade"] - onCheckedChanged: { - root.configEdit["editFade"] = checked; - Render.getConfig("RenderMainView.DrawFadedOpaqueBounds").enabled = checked; - } - } - ComboBox { - id: categoryBox - width: 400 - model: ["Elements enter/leave domain", "Bubble isect. - Owner POV", "Bubble isect. - Trespasser POV", "Another user leaves/arrives", "Changing an avatar"] - Timer { - id: postpone - interval: 100; running: false; repeat: false - onTriggered: { paramWidgetLoader.sourceComponent = paramWidgets } - } - onCurrentIndexChanged: { - root.config["editedCategory"] = currentIndex; - // This is a hack to be sure the widgets below properly reflect the change of category: delete the Component - // by setting the loader source to Null and then recreate it 100ms later - paramWidgetLoader.sourceComponent = undefined; - postpone.interval = 100 - postpone.start() - } - } - } - Row { - spacing: 8 + CheckBox { + text: "Edit Fade" + checked: root.configEdit["editFade"] + onCheckedChanged: { + root.configEdit["editFade"] = checked; + Render.getConfig("RenderMainView.DrawFadedOpaqueBounds").enabled = checked; + } + } + ComboBox { + id: categoryBox + width: 400 + model: ["Elements enter/leave domain", "Bubble isect. - Owner POV", "Bubble isect. - Trespasser POV", "Another user leaves/arrives", "Changing an avatar"] + Timer { + id: postpone + interval: 100; running: false; repeat: false + onTriggered: { paramWidgetLoader.sourceComponent = paramWidgets } + } + onCurrentIndexChanged: { + root.config["editedCategory"] = currentIndex; + // This is a hack to be sure the widgets below properly reflect the change of category: delete the Component + // by setting the loader source to Null and then recreate it 100ms later + paramWidgetLoader.sourceComponent = undefined; + postpone.interval = 100 + postpone.start() + } + } + } + Row { + spacing: 8 - 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 - } - } + 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 + } + } - Action { + Action { id: saveAction text: "Save" onTriggered: { - root.config.save() - } + root.config.save() + } } - Action { + Action { id: loadAction text: "Load" onTriggered: { - root.config.load() - // This is a hack to be sure the widgets below properly reflect the change of category: delete the Component - // by setting the loader source to Null and then recreate it 500ms later - paramWidgetLoader.sourceComponent = undefined; - postpone.interval = 500 - postpone.start() - } + root.config.load() + // This is a hack to be sure the widgets below properly reflect the change of category: delete the Component + // by setting the loader source to Null and then recreate it 500ms later + paramWidgetLoader.sourceComponent = undefined; + postpone.interval = 500 + postpone.start() + } } - Component { - id: paramWidgets + Component { + id: paramWidgets - Column { - spacing: 8 + Column { + spacing: 8 - CheckBox { - text: "Invert" - checked: root.config["isInverted"] - onCheckedChanged: { root.config["isInverted"] = checked } - } - Row { - spacing: 8 - - GroupBox { - title: "Base Gradient" - width: 450 - Column { - spacing: 8 + CheckBox { + text: "Invert" + checked: root.config["isInverted"] + onCheckedChanged: { root.config["isInverted"] = checked } + } + Row { + spacing: 8 - ConfigSlider { - label: "Size X" - integral: false - config: root.config - property: "baseSizeX" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Y" - integral: false - config: root.config - property: "baseSizeY" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Z" - integral: false - config: root.config - property: "baseSizeZ" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Level" - integral: false - config: root.config - property: "baseLevel" - max: 1.0 - min: 0.0 - width: 400 - } - } - } - GroupBox { - title: "Noise Gradient" - width: 450 - Column { - spacing: 8 + GroupBox { + title: "Base Gradient" + width: 450 + Column { + spacing: 8 - ConfigSlider { - label: "Size X" - integral: false - config: root.config - property: "noiseSizeX" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Y" - integral: false - config: root.config - property: "noiseSizeY" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Size Z" - integral: false - config: root.config - property: "noiseSizeZ" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Level" - integral: false - config: root.config - property: "noiseLevel" - max: 1.0 - min: 0.0 - width: 400 - } - } - } - } - Row { - spacing: 8 + ConfigSlider { + label: "Size X" + integral: false + config: root.config + property: "baseSizeX" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Y" + integral: false + config: root.config + property: "baseSizeY" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Z" + integral: false + config: root.config + property: "baseSizeZ" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Level" + integral: false + config: root.config + property: "baseLevel" + max: 1.0 + min: 0.0 + width: 400 + } + } + } + GroupBox { + title: "Noise Gradient" + width: 450 + Column { + spacing: 8 - GroupBox { - title: "Edge" - width: 450 - Column { - spacing: 8 + ConfigSlider { + label: "Size X" + integral: false + config: root.config + property: "noiseSizeX" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Y" + integral: false + config: root.config + property: "noiseSizeY" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Size Z" + integral: false + config: root.config + property: "noiseSizeZ" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Level" + integral: false + config: root.config + property: "noiseLevel" + max: 1.0 + min: 0.0 + width: 400 + } + } + } + } + Row { + spacing: 8 - ConfigSlider { - label: "Width" - integral: false - config: root.config - property: "edgeWidth" - max: 1.0 - min: 0.0 - width: 400 - } - GroupBox { - title: "Inner color" - Column { - spacing: 8 - ConfigSlider { - label: "Color R" - integral: false - config: root.config - property: "edgeInnerColorR" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color G" - integral: false - config: root.config - property: "edgeInnerColorG" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color B" - integral: false - config: root.config - property: "edgeInnerColorB" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color intensity" - integral: false - config: root.config - property: "edgeInnerIntensity" - max: 5.0 - min: 0.0 - width: 400 - } - } - } - GroupBox { - title: "Outer color" - Column { - spacing: 8 - ConfigSlider { - label: "Color R" - integral: false - config: root.config - property: "edgeOuterColorR" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color G" - integral: false - config: root.config - property: "edgeOuterColorG" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color B" - integral: false - config: root.config - property: "edgeOuterColorB" - max: 1.0 - min: 0.0 - width: 400 - } - ConfigSlider { - label: "Color intensity" - integral: false - config: root.config - property: "edgeOuterIntensity" - max: 5.0 - min: 0.0 - width: 400 - } - } - } - } - } + GroupBox { + title: "Edge" + width: 450 + Column { + spacing: 8 - Column { - GroupBox { - title: "Timing" - width: 450 - Column { - spacing: 8 + ConfigSlider { + label: "Width" + integral: false + config: root.config + property: "edgeWidth" + max: 1.0 + min: 0.0 + width: 400 + } + GroupBox { + title: "Inner color" + Column { + spacing: 8 + ConfigSlider { + label: "Color R" + integral: false + config: root.config + property: "edgeInnerColorR" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color G" + integral: false + config: root.config + property: "edgeInnerColorG" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color B" + integral: false + config: root.config + property: "edgeInnerColorB" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color intensity" + integral: false + config: root.config + property: "edgeInnerIntensity" + max: 5.0 + min: 0.0 + width: 400 + } + } + } + GroupBox { + title: "Outer color" + Column { + spacing: 8 + ConfigSlider { + label: "Color R" + integral: false + config: root.config + property: "edgeOuterColorR" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color G" + integral: false + config: root.config + property: "edgeOuterColorG" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color B" + integral: false + config: root.config + property: "edgeOuterColorB" + max: 1.0 + min: 0.0 + width: 400 + } + ConfigSlider { + label: "Color intensity" + integral: false + config: root.config + property: "edgeOuterIntensity" + max: 5.0 + min: 0.0 + width: 400 + } + } + } + } + } - ConfigSlider { - label: "Duration" - integral: false - config: root.config - property: "duration" - max: 10.0 - min: 0.1 - width: 400 - } - ComboBox { - width: 400 - model: ["Linear", "Ease In", "Ease Out", "Ease In / Out"] - currentIndex: root.config["timing"] - onCurrentIndexChanged: { - root.config["timing"] = currentIndex; - } - } - GroupBox { - title: "Noise Animation" - Column { - spacing: 8 - ConfigSlider { - label: "Speed X" - integral: false - config: root.config - property: "noiseSpeedX" - max: 1.0 - min: -1.0 - width: 400 - } - ConfigSlider { - label: "Speed Y" - integral: false - config: root.config - property: "noiseSpeedY" - max: 1.0 - min: -1.0 - width: 400 - } - ConfigSlider { - label: "Speed Z" - integral: false - config: root.config - property: "noiseSpeedZ" - max: 1.0 - min: -1.0 - width: 400 - } - } - } + Column { + GroupBox { + title: "Timing" + width: 450 + Column { + spacing: 8 - PlotPerf { - title: "Threshold" - height: parent.evalEvenHeight() - object: config - valueUnit: "%" - valueScale: 0.01 - valueNumDigits: "1" - plots: [ - { - prop: "threshold", - label: "Threshold", - color: "#FFBB77" - } - ] - } + ConfigSlider { + label: "Duration" + integral: false + config: root.config + property: "duration" + max: 10.0 + min: 0.1 + width: 400 + } + ComboBox { + width: 400 + model: ["Linear", "Ease In", "Ease Out", "Ease In / Out"] + currentIndex: root.config["timing"] + onCurrentIndexChanged: { + root.config["timing"] = currentIndex; + } + } + GroupBox { + title: "Noise Animation" + Column { + spacing: 8 + ConfigSlider { + label: "Speed X" + integral: false + config: root.config + property: "noiseSpeedX" + max: 1.0 + min: -1.0 + width: 400 + } + ConfigSlider { + label: "Speed Y" + integral: false + config: root.config + property: "noiseSpeedY" + max: 1.0 + min: -1.0 + width: 400 + } + ConfigSlider { + label: "Speed Z" + integral: false + config: root.config + property: "noiseSpeedZ" + max: 1.0 + min: -1.0 + width: 400 + } + } + } - } - } + PlotPerf { + title: "Threshold" + height: parent.evalEvenHeight() + object: config + valueUnit: "%" + valueScale: 0.01 + valueNumDigits: "1" + plots: [ + { + prop: "threshold", + label: "Threshold", + color: "#FFBB77" + } + ] + } - Row { - spacing: 8 - Button { - action: saveAction - } - Button { - action: loadAction - } - } + } + } - } - } - } - } + Row { + spacing: 8 + Button { + action: saveAction + } + Button { + action: loadAction + } + } - Loader { - id: paramWidgetLoader - sourceComponent: paramWidgets - } + } + } + } + } + + Loader { + id: paramWidgetLoader + sourceComponent: paramWidgets + } } From 290d106cf488c1dcc7367343ac6c54fa9264739c Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 17 Jul 2017 11:37:50 +0200 Subject: [PATCH 60/86] Shapes are working again. Had to re-specialize all the payload hooks for ShapePayload::Pointer... --- .../src/RenderableShapeEntityItem.cpp | 13 +++++++++++++ .../src/RenderableShapeEntityItem.h | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index dcc969f546..ec4f96f69f 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -83,6 +83,19 @@ bool RenderableShapeEntityItem::isTransparent() { } namespace render { + template <> const ItemKey payloadGetKey(const ShapePayload::Pointer& payload) { + return payloadGetKey(std::static_pointer_cast(payload)); + } + template <> const Item::Bound payloadGetBound(const ShapePayload::Pointer& payload) { + return payloadGetBound(std::static_pointer_cast(payload)); + } + template <> void payloadRender(const ShapePayload::Pointer& payload, RenderArgs* args) { + payloadRender(std::static_pointer_cast(payload), args); + } + template <> uint32_t metaFetchMetaSubItems(const ShapePayload::Pointer& payload, ItemIDs& subItems) { + return metaFetchMetaSubItems(std::static_pointer_cast(payload), subItems); + } + template <> const ShapeKey shapeGetShapeKey(const ShapePayload::Pointer& payload) { return ShapeKey::Builder().withCustom(GeometryCache::CUSTOM_PIPELINE_NUMBER).build(); } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index aca013b36d..b0ddf316c1 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -24,6 +24,10 @@ public: }; namespace render { + template <> const ItemKey payloadGetKey(const ShapePayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const ShapePayload::Pointer& payload); + template <> void payloadRender(const ShapePayload::Pointer& payload, RenderArgs* args); + template <> uint32_t metaFetchMetaSubItems(const ShapePayload::Pointer& payload, ItemIDs& subItems); template <> const ShapeKey shapeGetShapeKey(const ShapePayload::Pointer& payload); } From 146f934019d4c502e40c25806ddd5e37d63cee4b Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 17 Jul 2017 11:59:10 +0200 Subject: [PATCH 61/86] Cleaned up shader code as fade position is now world position --- libraries/entities-renderer/src/polyvox_fade.slf | 3 +-- libraries/entities-renderer/src/polyvox_fade.slv | 4 ---- libraries/render-utils/src/Fade.slh | 7 ------- libraries/render-utils/src/model_fade.slf | 4 ++-- libraries/render-utils/src/model_fade.slv | 6 ++---- libraries/render-utils/src/model_lightmap_fade.slf | 4 ++-- libraries/render-utils/src/model_lightmap_fade.slv | 6 ++---- .../render-utils/src/model_lightmap_normal_map_fade.slf | 4 ++-- .../render-utils/src/model_lightmap_normal_map_fade.slv | 6 ++---- .../src/model_lightmap_normal_specular_map_fade.slf | 4 ++-- .../render-utils/src/model_lightmap_specular_map_fade.slf | 4 ++-- libraries/render-utils/src/model_normal_map_fade.slf | 4 ++-- libraries/render-utils/src/model_normal_map_fade.slv | 6 ++---- .../render-utils/src/model_normal_specular_map_fade.slf | 4 ++-- libraries/render-utils/src/model_shadow_fade.slf | 4 ++-- libraries/render-utils/src/model_shadow_fade.slv | 6 ++---- libraries/render-utils/src/model_specular_map_fade.slf | 4 ++-- libraries/render-utils/src/model_translucent_fade.slf | 4 ++-- .../render-utils/src/model_translucent_unlit_fade.slf | 4 ++-- libraries/render-utils/src/model_unlit_fade.slf | 4 ++-- libraries/render-utils/src/simple_fade.slf | 4 ++-- libraries/render-utils/src/simple_fade.slv | 6 ++---- libraries/render-utils/src/simple_textured_fade.slf | 4 ++-- libraries/render-utils/src/simple_textured_unlit_fade.slf | 4 ++-- .../render-utils/src/simple_transparent_textured_fade.slf | 4 ++-- .../src/simple_transparent_textured_unlit_fade.slf | 4 ++-- libraries/render-utils/src/skin_model_fade.slv | 6 ++---- libraries/render-utils/src/skin_model_normal_map_fade.slv | 6 ++---- libraries/render-utils/src/skin_model_shadow_fade.slf | 4 ++-- libraries/render-utils/src/skin_model_shadow_fade.slv | 6 ++---- 30 files changed, 55 insertions(+), 85 deletions(-) diff --git a/libraries/entities-renderer/src/polyvox_fade.slf b/libraries/entities-renderer/src/polyvox_fade.slf index 29bd51200a..7aac6049e3 100644 --- a/libraries/entities-renderer/src/polyvox_fade.slf +++ b/libraries/entities-renderer/src/polyvox_fade.slf @@ -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); diff --git a/libraries/entities-renderer/src/polyvox_fade.slv b/libraries/entities-renderer/src/polyvox_fade.slv index f024957677..490a2a9ff0 100644 --- a/libraries/entities-renderer/src/polyvox_fade.slv +++ b/libraries/entities-renderer/src/polyvox_fade.slv @@ -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; } diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 9d403da7b6..488964f843 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -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()@> diff --git a/libraries/render-utils/src/model_fade.slf b/libraries/render-utils/src/model_fade.slf index 7d145bc76b..172d7ddbee 100644 --- a/libraries/render-utils/src/model_fade.slf +++ b/libraries/render-utils/src/model_fade.slf @@ -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); diff --git a/libraries/render-utils/src/model_fade.slv b/libraries/render-utils/src/model_fade.slv index cd0140c78c..4c6bc534a9 100644 --- a/libraries/render-utils/src/model_fade.slv +++ b/libraries/render-utils/src/model_fade.slv @@ -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)$> } diff --git a/libraries/render-utils/src/model_lightmap_fade.slf b/libraries/render-utils/src/model_lightmap_fade.slf index ccad86214a..7ca5fc0a22 100644 --- a/libraries/render-utils/src/model_lightmap_fade.slf +++ b/libraries/render-utils/src/model_lightmap_fade.slf @@ -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); diff --git a/libraries/render-utils/src/model_lightmap_fade.slv b/libraries/render-utils/src/model_lightmap_fade.slv index 8ba9717b4c..561049d614 100644 --- a/libraries/render-utils/src/model_lightmap_fade.slv +++ b/libraries/render-utils/src/model_lightmap_fade.slv @@ -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)$> } diff --git a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf index a1dbd398ee..82c5a11529 100644 --- a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf @@ -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); diff --git a/libraries/render-utils/src/model_lightmap_normal_map_fade.slv b/libraries/render-utils/src/model_lightmap_normal_map_fade.slv index e081db103b..4049fb0077 100644 --- a/libraries/render-utils/src/model_lightmap_normal_map_fade.slv +++ b/libraries/render-utils/src/model_lightmap_normal_map_fade.slv @@ -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)$> } diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf index d7a8697b7a..7314753ae6 100644 --- a/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf +++ b/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf @@ -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); diff --git a/libraries/render-utils/src/model_lightmap_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_specular_map_fade.slf index c4280ed6d1..e17512fe7f 100644 --- a/libraries/render-utils/src/model_lightmap_specular_map_fade.slf +++ b/libraries/render-utils/src/model_lightmap_specular_map_fade.slf @@ -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); diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf index d5f0c56b4b..6134e871da 100644 --- a/libraries/render-utils/src/model_normal_map_fade.slf +++ b/libraries/render-utils/src/model_normal_map_fade.slf @@ -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); diff --git a/libraries/render-utils/src/model_normal_map_fade.slv b/libraries/render-utils/src/model_normal_map_fade.slv index 7250c1e842..a71900d5c3 100644 --- a/libraries/render-utils/src/model_normal_map_fade.slv +++ b/libraries/render-utils/src/model_normal_map_fade.slv @@ -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)$> } diff --git a/libraries/render-utils/src/model_normal_specular_map_fade.slf b/libraries/render-utils/src/model_normal_specular_map_fade.slf index bdf917efea..59ee0e9927 100644 --- a/libraries/render-utils/src/model_normal_specular_map_fade.slf +++ b/libraries/render-utils/src/model_normal_specular_map_fade.slf @@ -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); diff --git a/libraries/render-utils/src/model_shadow_fade.slf b/libraries/render-utils/src/model_shadow_fade.slf index 76720d6053..a697ba4f12 100644 --- a/libraries/render-utils/src/model_shadow_fade.slf +++ b/libraries/render-utils/src/model_shadow_fade.slf @@ -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); diff --git a/libraries/render-utils/src/model_shadow_fade.slv b/libraries/render-utils/src/model_shadow_fade.slv index 4b6e2e1dc1..8762f1dd90 100644 --- a/libraries/render-utils/src/model_shadow_fade.slv +++ b/libraries/render-utils/src/model_shadow_fade.slv @@ -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)$> } diff --git a/libraries/render-utils/src/model_specular_map_fade.slf b/libraries/render-utils/src/model_specular_map_fade.slf index 75db1d72a2..a43027a034 100644 --- a/libraries/render-utils/src/model_specular_map_fade.slf +++ b/libraries/render-utils/src/model_specular_map_fade.slf @@ -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); diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf index 9802e863b0..cc4611586d 100644 --- a/libraries/render-utils/src/model_translucent_fade.slf +++ b/libraries/render-utils/src/model_translucent_fade.slf @@ -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); diff --git a/libraries/render-utils/src/model_translucent_unlit_fade.slf b/libraries/render-utils/src/model_translucent_unlit_fade.slf index 6c6846228e..cb7739d1b7 100644 --- a/libraries/render-utils/src/model_translucent_unlit_fade.slf +++ b/libraries/render-utils/src/model_translucent_unlit_fade.slf @@ -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); diff --git a/libraries/render-utils/src/model_unlit_fade.slf b/libraries/render-utils/src/model_unlit_fade.slf index 59fdc87bee..179b16a3b1 100644 --- a/libraries/render-utils/src/model_unlit_fade.slf +++ b/libraries/render-utils/src/model_unlit_fade.slf @@ -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); diff --git a/libraries/render-utils/src/simple_fade.slf b/libraries/render-utils/src/simple_fade.slf index 526b7157d9..a402c740f0 100644 --- a/libraries/render-utils/src/simple_fade.slf +++ b/libraries/render-utils/src/simple_fade.slf @@ -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); diff --git a/libraries/render-utils/src/simple_fade.slv b/libraries/render-utils/src/simple_fade.slv index 866d4cc35e..78ecb95c51 100644 --- a/libraries/render-utils/src/simple_fade.slv +++ b/libraries/render-utils/src/simple_fade.slv @@ -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)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf index 5130720277..0f9ff15e9f 100644 --- a/libraries/render-utils/src/simple_textured_fade.slf +++ b/libraries/render-utils/src/simple_textured_fade.slf @@ -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; diff --git a/libraries/render-utils/src/simple_textured_unlit_fade.slf b/libraries/render-utils/src/simple_textured_unlit_fade.slf index 60b6921ae3..e9bf2f6499 100644 --- a/libraries/render-utils/src/simple_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_textured_unlit_fade.slf @@ -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; diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf index 8aa7bf176b..f3f02653af 100644 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_fade.slf @@ -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; diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf index 9f74eacc96..a7a38f05f1 100644 --- a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf @@ -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; diff --git a/libraries/render-utils/src/skin_model_fade.slv b/libraries/render-utils/src/skin_model_fade.slv index bce60b4242..fa8e1f8991 100644 --- a/libraries/render-utils/src/skin_model_fade.slv +++ b/libraries/render-utils/src/skin_model_fade.slv @@ -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)$> } diff --git a/libraries/render-utils/src/skin_model_normal_map_fade.slv b/libraries/render-utils/src/skin_model_normal_map_fade.slv index 7c88c68537..4e638866fc 100644 --- a/libraries/render-utils/src/skin_model_normal_map_fade.slv +++ b/libraries/render-utils/src/skin_model_normal_map_fade.slv @@ -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)$> diff --git a/libraries/render-utils/src/skin_model_shadow_fade.slf b/libraries/render-utils/src/skin_model_shadow_fade.slf index 666525a3ae..9d720c7bee 100644 --- a/libraries/render-utils/src/skin_model_shadow_fade.slf +++ b/libraries/render-utils/src/skin_model_shadow_fade.slf @@ -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); diff --git a/libraries/render-utils/src/skin_model_shadow_fade.slv b/libraries/render-utils/src/skin_model_shadow_fade.slv index 03b060b59b..7b27263569 100644 --- a/libraries/render-utils/src/skin_model_shadow_fade.slv +++ b/libraries/render-utils/src/skin_model_shadow_fade.slv @@ -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)$> } From 3f8daa21ec455d10c7265ea9053173ce8aeb308d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 17 Jul 2017 14:26:41 +0200 Subject: [PATCH 62/86] Created FadeEffect singleton to be able to get fade item & batch setters for every special entity render --- libraries/render-utils/src/FadeEffect.cpp | 737 +----------------- libraries/render-utils/src/FadeEffect.h | 232 +----- libraries/render-utils/src/FadeEffectJobs.cpp | 720 +++++++++++++++++ libraries/render-utils/src/FadeEffectJobs.h | 248 ++++++ .../render-utils/src/RenderDeferredTask.cpp | 13 +- .../render-utils/src/RenderDeferredTask.h | 2 +- 6 files changed, 1012 insertions(+), 940 deletions(-) create mode 100644 libraries/render-utils/src/FadeEffectJobs.cpp create mode 100644 libraries/render-utils/src/FadeEffectJobs.h diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index b2fd7c0c7e..aec19ce32f 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -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 -#include -#include -#include -#include - -#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()->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("Fade"); + auto& fadeJob = task._jobs.back(); + _configurations = fadeJob.get().getConfigurationBuffer(); + + const auto fadeEditInput = FadeEditJob::Input(editableItems, editedFadeCategory).asVarying(); + task.addJob("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::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(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()->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(renderContext->jobConfig.get()); - auto scene = renderContext->args->_scene; - auto transitionStage = scene->getStage(render::TransitionStage::getName()); - uint64_t now = usecTimestampNow(); - const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND); - 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); diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 30c233ad29..8677609892 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -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 -#include -#include -#include +#include +#include -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; - using JobModel = render::Job::ModelI; - - 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(); - - 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 _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 diff --git a/libraries/render-utils/src/FadeEffectJobs.cpp b/libraries/render-utils/src/FadeEffectJobs.cpp new file mode 100644 index 0000000000..242d26a445 --- /dev/null +++ b/libraries/render-utils/src/FadeEffectJobs.cpp @@ -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 +#include +#include + +#include + +#include + +#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::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(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(renderContext->jobConfig.get()); + auto scene = renderContext->args->_scene; + auto transitionStage = scene->getStage(render::TransitionStage::getName()); + uint64_t now = usecTimestampNow(); + const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND); + 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; +} diff --git a/libraries/render-utils/src/FadeEffectJobs.h b/libraries/render-utils/src/FadeEffectJobs.h new file mode 100644 index 0000000000..ca29f40b5c --- /dev/null +++ b/libraries/render-utils/src/FadeEffectJobs.h @@ -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 +#include +#include +#include + +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; + using JobModel = render::Job::ModelI; + + 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(); + + 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; + + 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 diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index f6a715efa3..32903ad0d2 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -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(); +} + void RenderDeferredTask::configure(const Config& config) { } void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { const auto& items = input.get(); - - auto editedFadeCategory = task.addJob("Fade"); - auto& fadeJob = task._jobs.back().get(); + auto fadeEffect = DependencyManager::get(); // Prepare the ShapePipelines ShapePlumberPointer shapePlumber = std::make_shared(); - 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("FadeEdit", fadeEditInput); + fadeEffect->build(task, opaques); // Filter the non antialiaased overlays const int LAYER_NO_AA = 3; diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 65ae062a9a..e7575a1c95 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -185,7 +185,7 @@ public: using Config = RenderDeferredTaskConfig; using JobModel = render::Task::ModelI; - RenderDeferredTask() {} + RenderDeferredTask(); void configure(const Config& config); void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); From 95059e26c18ce6e7534ff316ba8de400858b5ffc Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 17 Jul 2017 14:32:05 +0200 Subject: [PATCH 63/86] Fading working on voxels --- .../entities-renderer/src/RenderablePolyVoxEntityItem.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 0766acdbb1..9addd7b5ce 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -20,6 +20,8 @@ #include #include "ModelScriptingInterface.h" +#include + #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(); if (key.isWireframe()) { - return std::make_shared(_wireframePipelines[1], nullptr, nullptr, nullptr); + return std::make_shared(_wireframePipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemSetter()); } else { - return std::make_shared(_pipelines[1], nullptr, nullptr, nullptr); + return std::make_shared(_pipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemSetter()); } } else { From f8b2ffe3593beee5cb7fb41837edea84eb76efbe Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 17 Jul 2017 15:06:32 +0200 Subject: [PATCH 64/86] Removed transparency on fading shapes --- .../src/RenderableShapeEntityItem.cpp | 10 +------ libraries/render-utils/src/GeometryCache.cpp | 26 ++++++++++++++++--- libraries/render-utils/src/GeometryCache.h | 8 +++--- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index ec4f96f69f..40fc5cd4a1 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -73,13 +73,7 @@ void RenderableShapeEntityItem::setUserData(const QString& value) { } bool RenderableShapeEntityItem::isTransparent() { - if (_procedural && _procedural->isFading()) { - float isFading = Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) < 1.0f; - _procedural->setIsFading(isFading); - return isFading; - } else { - return getLocalRenderAlpha() < 1.0f || EntityItem::isTransparent(); - } + return getLocalRenderAlpha() < 1.0f || EntityItem::isTransparent(); } namespace render { @@ -148,7 +142,6 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { if (_procedural->ready()) { _procedural->prepare(batch, getPosition(), getDimensions(), getOrientation()); auto outColor = _procedural->getColor(color); - outColor.a *= _procedural->isFading() ? Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) : 1.0f; batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { DependencyManager::get()->renderWireShape(batch, MAPPING[_shape]); @@ -156,7 +149,6 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { DependencyManager::get()->renderShape(batch, MAPPING[_shape]); } } else { - color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; // FIXME, support instanced multi-shape rendering using multidraw indirect auto geometryCache = DependencyManager::get(); auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 504eb800ab..8056e45ccf 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -25,6 +25,7 @@ #include "TextureCache.h" #include "RenderUtilsLogging.h" #include "StencilMaskPass.h" +#include "FadeEffect.h" #include "gpu/StandardShaderLib.h" @@ -543,15 +544,16 @@ void GeometryCache::initializeShapePipelines() { if (!_simpleOpaquePipeline) { _simpleOpaquePipeline = getShapePipeline(false, false, true, false); _simpleTransparentPipeline = getShapePipeline(false, true, true, false); - _simpleOpaqueFadePipeline = getShapePipeline(false, false, true, false, false, true); - _simpleTransparentFadePipeline = getShapePipeline(false, true, true, false, false, true); + _simpleOpaqueFadePipeline = getFadingShapePipeline(false, false, true, false, false); + _simpleTransparentFadePipeline = getFadingShapePipeline(false, true, true, false, false); _simpleWirePipeline = getShapePipeline(false, false, true, true); } } render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool culled, - bool unlit, bool depthBias, bool fading) { - return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, fading), nullptr, + bool unlit, bool depthBias) { + + return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false), nullptr, [](const render::ShapePipeline&, gpu::Batch& batch, render::Args*) { // Set the defaults needed for a simple program batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, @@ -560,6 +562,22 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool ); } +render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool culled, + bool unlit, bool depthBias) { + auto fadeEffect = DependencyManager::get(); + auto fadeBatchSetter = fadeEffect->getBatchSetter(); + auto fadeItemSetter = fadeEffect->getItemSetter(); + return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true), nullptr, + [fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) { + // Set the defaults needed for a simple program + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, + DependencyManager::get()->getWhiteTexture()); + fadeBatchSetter(pipeline, batch, args); + }, + fadeItemSetter + ); +} + render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading) { return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline; } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index b4f1b02292..46d74a9bb4 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -174,9 +174,6 @@ public: static void initializeShapePipelines(); - static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true, - bool unlit = false, bool depthBias = false, bool fading = false); - render::ShapePipelinePointer getOpaqueShapePipeline() { assert(_simpleOpaquePipeline != nullptr); return _simpleOpaquePipeline; } render::ShapePipelinePointer getTransparentShapePipeline() { assert(_simpleTransparentPipeline != nullptr); return _simpleTransparentPipeline; } render::ShapePipelinePointer getOpaqueFadeShapePipeline() { assert(_simpleOpaqueFadePipeline != nullptr); return _simpleOpaqueFadePipeline; } @@ -458,6 +455,11 @@ private: gpu::PipelinePointer _simpleOpaqueWebBrowserOverlayPipeline; gpu::ShaderPointer _simpleTransparentWebBrowserOverlayShader; gpu::PipelinePointer _simpleTransparentWebBrowserOverlayPipeline; + + static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true, + bool unlit = false, bool depthBias = false); + static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool culled = true, + bool unlit = false, bool depthBias = false); }; #endif // hifi_GeometryCache_h From 1f14b6ef38eed9748362f30cc6a5b3daaed522f0 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 17 Jul 2017 17:50:59 +0200 Subject: [PATCH 65/86] Shape entities have the correct pipeline picked when fading is activated. Still need to support instanced rendering --- .../src/RenderablePolyVoxEntityItem.cpp | 1 + .../src/RenderableShapeEntityItem.cpp | 17 +++++++++------ libraries/render-utils/src/FadeEffectJobs.cpp | 3 ++- libraries/render-utils/src/GeometryCache.cpp | 21 +++++++++---------- libraries/render-utils/src/simple_fade.slf | 2 +- libraries/render-utils/src/simple_fade.slv | 2 +- .../render-utils/src/simple_textured_fade.slf | 4 +++- .../src/simple_textured_unlit_fade.slf | 4 +++- .../src/simple_transparent_textured_fade.slf | 4 +++- ...simple_transparent_textured_unlit_fade.slf | 4 +++- libraries/render/src/render/Item.cpp | 3 ++- 11 files changed, 40 insertions(+), 25 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 9addd7b5ce..a717005f97 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -839,6 +839,7 @@ render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render:: slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0)); slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2)); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), 3)); auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 40fc5cd4a1..7462d45968 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -91,7 +91,12 @@ namespace render { } template <> const ShapeKey shapeGetShapeKey(const ShapePayload::Pointer& payload) { - return ShapeKey::Builder().withCustom(GeometryCache::CUSTOM_PIPELINE_NUMBER).build(); + auto shapeKey = ShapeKey::Builder().withCustom(GeometryCache::CUSTOM_PIPELINE_NUMBER); + auto entity = payload->_entity; + if (entity->getLocalRenderAlpha() < 1.f) { + shapeKey.withTranslucent(); + } + return shapeKey.build(); } } @@ -151,14 +156,14 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { } else { // FIXME, support instanced multi-shape rendering using multidraw indirect auto geometryCache = DependencyManager::get(); - auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); + auto shapeKey = render::ShapeKey(args->_globalShapeKey); - assert(pipeline != nullptr); + assert(args->_shapePipeline != nullptr); - if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { - geometryCache->renderWireShapeInstance(args, batch, MAPPING[_shape], color, pipeline); + if (shapeKey.isWireframe()) { + geometryCache->renderWireShapeInstance(args, batch, MAPPING[_shape], color, args->_shapePipeline); } else { - geometryCache->renderSolidShapeInstance(args, batch, MAPPING[_shape], color, pipeline); + geometryCache->renderSolidShapeInstance(args, batch, MAPPING[_shape], color, args->_shapePipeline); } } diff --git a/libraries/render-utils/src/FadeEffectJobs.cpp b/libraries/render-utils/src/FadeEffectJobs.cpp index 242d26a445..2e3bbaff3a 100644 --- a/libraries/render-utils/src/FadeEffectJobs.cpp +++ b/libraries/render-utils/src/FadeEffectJobs.cpp @@ -98,7 +98,8 @@ render::ItemID FadeEditJob::findNearestItem(const render::RenderContextPointer& for (const auto& itemBound : inputs) { if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { - if (isectDistance>minDistance && isectDistance < minIsectDistance) { + auto& item = renderContext->_scene->getItem(itemBound.id); + if (item.getKey().isWorldSpace() && isectDistance>minDistance && isectDistance < minIsectDistance) { nearestItem = itemBound.id; minIsectDistance = isectDistance; } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 8056e45ccf..9e97540d53 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -544,8 +544,8 @@ void GeometryCache::initializeShapePipelines() { if (!_simpleOpaquePipeline) { _simpleOpaquePipeline = getShapePipeline(false, false, true, false); _simpleTransparentPipeline = getShapePipeline(false, true, true, false); - _simpleOpaqueFadePipeline = getFadingShapePipeline(false, false, true, false, false); - _simpleTransparentFadePipeline = getFadingShapePipeline(false, true, true, false, false); + _simpleOpaqueFadePipeline = getFadingShapePipeline(false, false, false, false, false); + _simpleTransparentFadePipeline = getFadingShapePipeline(false, true, false, false, false); _simpleWirePipeline = getShapePipeline(false, false, true, true); } } @@ -554,10 +554,8 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool bool unlit, bool depthBias) { return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false), nullptr, - [](const render::ShapePipeline&, gpu::Batch& batch, render::Args*) { - // Set the defaults needed for a simple program - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, - DependencyManager::get()->getWhiteTexture()); + [](const render::ShapePipeline& , gpu::Batch& batch, render::Args*) { + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); } ); } @@ -568,11 +566,9 @@ render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured auto fadeBatchSetter = fadeEffect->getBatchSetter(); auto fadeItemSetter = fadeEffect->getItemSetter(); return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true), nullptr, - [fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) { - // Set the defaults needed for a simple program - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, - DependencyManager::get()->getWhiteTexture()); - fadeBatchSetter(pipeline, batch, args); + [fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) { + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); + fadeBatchSetter(shapePipeline, batch, args); }, fadeItemSetter ); @@ -1970,6 +1966,7 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp _unlitShader = gpu::Shader::createProgram(VS, PSUnlit); gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), render::ShapePipeline::Slot::MAP::ALBEDO)); gpu::Shader::makeProgram(*_simpleShader, slotBindings); gpu::Shader::makeProgram(*_unlitShader, slotBindings); }); @@ -1984,6 +1981,8 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp _unlitFadeShader = gpu::Shader::createProgram(VS, PSUnlit); gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), render::ShapePipeline::Slot::MAP::ALBEDO)); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), render::ShapePipeline::Slot::MAP::FADE_MASK)); gpu::Shader::makeProgram(*_simpleFadeShader, slotBindings); gpu::Shader::makeProgram(*_unlitFadeShader, slotBindings); }); diff --git a/libraries/render-utils/src/simple_fade.slf b/libraries/render-utils/src/simple_fade.slf index a402c740f0..3424af15f5 100644 --- a/libraries/render-utils/src/simple_fade.slf +++ b/libraries/render-utils/src/simple_fade.slf @@ -43,7 +43,7 @@ void main(void) { vec3 specular = DEFAULT_SPECULAR; float shininess = DEFAULT_SHININESS; float emissiveAmount = 0.0; - + #ifdef PROCEDURAL #ifdef PROCEDURAL_V1 diff --git a/libraries/render-utils/src/simple_fade.slv b/libraries/render-utils/src/simple_fade.slv index 78ecb95c51..02f69677d3 100644 --- a/libraries/render-utils/src/simple_fade.slv +++ b/libraries/render-utils/src/simple_fade.slv @@ -5,7 +5,7 @@ // simple_fade.vert // vertex shader // -// Created by Olivier Prat on 06/045/17. +// Created by Olivier Prat on 06/04/17. // Copyright 2017 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf index 0f9ff15e9f..659280f88b 100644 --- a/libraries/render-utils/src/simple_textured_fade.slf +++ b/libraries/render-utils/src/simple_textured_fade.slf @@ -17,7 +17,6 @@ <@include model/Material.slh@> <@include Fade.slh@> -<$declareFadeFragment()$> // the albedo texture uniform sampler2D originalTexture; @@ -28,6 +27,9 @@ in vec4 _color; in vec2 _texCoord0; in vec4 _worldPosition; +// Declare after all samplers to prevent sampler location mix up with originalTexture +<$declareFadeFragment()$> + void main(void) { vec3 fadeEmissive; diff --git a/libraries/render-utils/src/simple_textured_unlit_fade.slf b/libraries/render-utils/src/simple_textured_unlit_fade.slf index e9bf2f6499..f3c50bef9b 100644 --- a/libraries/render-utils/src/simple_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_textured_unlit_fade.slf @@ -16,7 +16,6 @@ <@include DeferredBufferWrite.slh@> <@include Fade.slh@> -<$declareFadeFragment()$> // the albedo texture uniform sampler2D originalTexture; @@ -27,6 +26,9 @@ in vec4 _color; in vec2 _texCoord0; in vec4 _worldPosition; +// Declare after all samplers to prevent sampler location mix up with originalTexture +<$declareFadeFragment()$> + void main(void) { vec3 fadeEmissive; diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf index f3f02653af..31dc6f166a 100644 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_fade.slf @@ -22,7 +22,6 @@ <$declareStandardCameraTransform()$> <@include Fade.slh@> -<$declareFadeFragment()$> // the albedo texture uniform sampler2D originalTexture; @@ -34,6 +33,9 @@ in vec4 _color; in vec2 _texCoord0; in vec4 _worldPosition; +// Declare after all samplers to prevent sampler location mix up with originalTexture +<$declareFadeFragment()$> + void main(void) { vec3 fadeEmissive; diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf index a7a38f05f1..bd403b0634 100644 --- a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf @@ -15,7 +15,6 @@ <@include gpu/Color.slh@> <@include Fade.slh@> -<$declareFadeFragment()$> // the albedo texture uniform sampler2D originalTexture; @@ -28,6 +27,9 @@ in vec4 _worldPosition; layout(location = 0) out vec4 _fragColor0; +// Declare after all samplers to prevent sampler location mix up with originalTexture +<$declareFadeFragment()$> + void main(void) { vec3 fadeEmissive; diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index afc32ea629..9e4fc09701 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -86,7 +86,8 @@ void Item::resetPayload(const PayloadPointer& payload) { const ShapeKey Item::getShapeKey() const { auto shapeKey = _payload->getShapeKey(); - if (_transitionId != TransitionStage::INVALID_INDEX) { + if (!TransitionStage::isIndexInvalid(_transitionId)) { + // Objects that are fading are rendered double-sided to give a sense of volume return ShapeKey::Builder(shapeKey).withFade().withoutCullFace(); } return shapeKey; From 4b8545e8b5c35793fcdef6627b0b66795af97d4e Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 18 Jul 2017 10:04:08 +0200 Subject: [PATCH 66/86] Removed all bubble fade event code on avatar side --- interface/src/avatar/AvatarManager.cpp | 11 +++++++---- libraries/avatars/src/AvatarHashMap.cpp | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 961e168fa5..bd545c64e0 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -273,15 +273,19 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { return; } + const float SHRINK_RATE = 0.15f; + const float MIN_FADE_SCALE = MIN_AVATAR_SCALE; + QReadLocker locker(&_hashLock); QVector::iterator avatarItr = _avatarsToFade.begin(); - const render::ScenePointer& scene = qApp->getMain3DScene(); while (avatarItr != _avatarsToFade.end()) { auto avatar = std::static_pointer_cast(*avatarItr); - avatar->updateFadingStatus(scene); - if (!avatar->isFading()) { + avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE); + avatar->animateScaleChanges(deltaTime); + if (avatar->getTargetScale() <= MIN_FADE_SCALE) { // fading to zero is such a rare event we push a unique transaction for each if (avatar->isInScene()) { + const render::ScenePointer& scene = qApp->getMain3DScene(); render::Transaction transaction; avatar->removeFromScene(*avatarItr, scene, transaction); scene->enqueueTransaction(transaction); @@ -321,7 +325,6 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar DependencyManager::get()->avatarDisconnected(avatar->getSessionUUID()); } _avatarsToFade.push_back(removedAvatar); - avatar->fadeOut(qApp->getMain3DScene(), removalReason); } void AvatarManager::clearOtherAvatars() { diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 540fd583c8..3712080cdb 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -173,7 +173,7 @@ void AvatarHashMap::processKillAvatar(QSharedPointer message, S void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) { QWriteLocker locker(&_hashLock); - AvatarSharedPointer removedAvatar = _avatarHash.take(sessionUUID); + auto removedAvatar = _avatarHash.take(sessionUUID); if (removedAvatar) { handleRemovedAvatar(removedAvatar, removalReason); From 10a6ad2ac9ed687adcfa38e309053e50d3a325ef Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 18 Jul 2017 10:58:49 +0200 Subject: [PATCH 67/86] Added 3 more texture coord vec4f stream attributes --- libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp | 12 +++++++++--- libraries/gpu/src/gpu/Stream.cpp | 10 ++++++++-- libraries/gpu/src/gpu/Stream.h | 5 ++++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp index ffc8140b25..0c1b6880cb 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp @@ -485,9 +485,15 @@ void GLBackend::makeProgramBindings(ShaderObject& shaderObject) { glBindAttribLocation(glprogram, gpu::Stream::TANGENT, "inTangent"); } - loc = glGetAttribLocation(glprogram, "inTexCoord1"); - if (loc >= 0 && loc != gpu::Stream::TEXCOORD1) { - glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "inTexCoord1"); + char attribName[] = "inTexCoordn"; + for (auto i = 0; i < 4; i++) { + auto streamId = gpu::Stream::TEXCOORD1 + i; + + attribName[strlen(attribName) - 1] = '1' + i; + loc = glGetAttribLocation(glprogram, attribName); + if (loc >= 0 && loc != streamId) { + glBindAttribLocation(glprogram, streamId, attribName); + } } loc = glGetAttribLocation(glprogram, "inSkinClusterIndex"); diff --git a/libraries/gpu/src/gpu/Stream.cpp b/libraries/gpu/src/gpu/Stream.cpp index cdb972d8bf..427af1e78d 100644 --- a/libraries/gpu/src/gpu/Stream.cpp +++ b/libraries/gpu/src/gpu/Stream.cpp @@ -36,8 +36,14 @@ const ElementArray& getDefaultElements() { //SKIN_CLUSTER_WEIGHT = 6, Element::VEC4F_XYZW, //TEXCOORD1 = 7, - Element::VEC2F_UV - }}; + Element::VEC2F_UV, + //TEXCOORD2 = 7, + Element::VEC4F_XYZW, + //TEXCOORD3 = 7, + Element::VEC4F_XYZW, + //TEXCOORD4 = 7, + Element::VEC4F_XYZW + }}; return defaultElements; } diff --git a/libraries/gpu/src/gpu/Stream.h b/libraries/gpu/src/gpu/Stream.h index 0642131edf..336e34ecb4 100644 --- a/libraries/gpu/src/gpu/Stream.h +++ b/libraries/gpu/src/gpu/Stream.h @@ -38,8 +38,11 @@ public: SKIN_CLUSTER_INDEX = 5, SKIN_CLUSTER_WEIGHT = 6, TEXCOORD1 = 7, - NUM_INPUT_SLOTS = TEXCOORD1 + 1, + TEXCOORD2 = 8, + TEXCOORD3 = 9, + TEXCOORD4 = 10, + NUM_INPUT_SLOTS, DRAW_CALL_INFO = 15, // Reserve last input slot for draw call infos }; From dbf0b64dfbc2ce7c34adc7b34bf2d8d08387db13 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 18 Jul 2017 12:49:34 +0200 Subject: [PATCH 68/86] Refactored Fade.slh to take into account differences between instanced draw and normal draw --- .../src/RenderablePolyVoxEntityItem.cpp | 4 +- .../src/RenderableShapeEntityItem.cpp | 26 +++- .../entities-renderer/src/polyvox_fade.slf | 5 +- libraries/render-utils/src/Fade.slh | 115 +++++++++++++---- libraries/render-utils/src/FadeEffect.cpp | 72 ++++++++--- libraries/render-utils/src/FadeEffect.h | 20 ++- libraries/render-utils/src/GeometryCache.cpp | 119 ++++++++++++++++-- libraries/render-utils/src/GeometryCache.h | 12 ++ .../render-utils/src/RenderDeferredTask.cpp | 2 +- libraries/render-utils/src/model_fade.slf | 4 +- .../render-utils/src/model_lightmap_fade.slf | 4 +- .../src/model_lightmap_normal_map_fade.slf | 4 +- ...odel_lightmap_normal_specular_map_fade.slf | 4 +- .../src/model_lightmap_specular_map_fade.slf | 4 +- .../src/model_normal_map_fade.slf | 4 +- .../src/model_normal_specular_map_fade.slf | 4 +- .../render-utils/src/model_shadow_fade.slf | 5 +- .../src/model_specular_map_fade.slf | 4 +- .../src/model_translucent_fade.slf | 4 +- .../src/model_translucent_unlit_fade.slf | 4 +- .../render-utils/src/model_unlit_fade.slf | 4 +- libraries/render-utils/src/simple_fade.slf | 6 +- libraries/render-utils/src/simple_fade.slv | 4 + .../render-utils/src/simple_textured_fade.slf | 6 +- .../src/simple_textured_unlit_fade.slf | 6 +- .../src/simple_transparent_textured_fade.slf | 6 +- ...simple_transparent_textured_unlit_fade.slf | 6 +- .../src/skin_model_shadow_fade.slf | 5 +- 28 files changed, 378 insertions(+), 85 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index a717005f97..602f09b466 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -865,10 +865,10 @@ render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render:: if (key.isFaded()) { const auto& fadeEffect = DependencyManager::get(); if (key.isWireframe()) { - return std::make_shared(_wireframePipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemSetter()); + return std::make_shared(_wireframePipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); } else { - return std::make_shared(_pipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemSetter()); + return std::make_shared(_pipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); } } else { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 7462d45968..4424d3aa17 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -19,6 +19,7 @@ #include #include +#include // Sphere entities should fit inside a cube entity of the same size, so a sphere that has dimensions 1x1x1 // is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down. @@ -160,10 +161,29 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { assert(args->_shapePipeline != nullptr); - if (shapeKey.isWireframe()) { - geometryCache->renderWireShapeInstance(args, batch, MAPPING[_shape], color, args->_shapePipeline); + if (shapeKey.isFaded()) { + auto fadeEffect = DependencyManager::get(); + auto fadeCategory = fadeEffect->getLastCategory(); + auto fadeThreshold = fadeEffect->getLastThreshold(); + auto fadeNoiseOffset = fadeEffect->getLastNoiseOffset(); + auto fadeBaseOffset = fadeEffect->getLastBaseOffset(); + auto fadeBaseInvSize = fadeEffect->getLastBaseInvSize(); + + if (shapeKey.isWireframe()) { + geometryCache->renderWireFadeShapeInstance(args, batch, MAPPING[_shape], color, fadeCategory, fadeThreshold, + fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, args->_shapePipeline); + } + else { + geometryCache->renderSolidFadeShapeInstance(args, batch, MAPPING[_shape], color, fadeCategory, fadeThreshold, + fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, args->_shapePipeline); + } } else { - geometryCache->renderSolidShapeInstance(args, batch, MAPPING[_shape], color, args->_shapePipeline); + if (shapeKey.isWireframe()) { + geometryCache->renderWireShapeInstance(args, batch, MAPPING[_shape], color, args->_shapePipeline); + } + else { + geometryCache->renderSolidShapeInstance(args, batch, MAPPING[_shape], color, args->_shapePipeline); + } } } diff --git a/libraries/entities-renderer/src/polyvox_fade.slf b/libraries/entities-renderer/src/polyvox_fade.slf index 7aac6049e3..ad4950f64c 100644 --- a/libraries/entities-renderer/src/polyvox_fade.slf +++ b/libraries/entities-renderer/src/polyvox_fade.slf @@ -30,7 +30,10 @@ uniform vec3 voxelVolumeSize; void main(void) { vec3 emissive; - applyFade(_worldPosition.xyz, emissive); + FadeObjectParams fadeParams; + + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, emissive); vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); worldNormal = normalize(worldNormal); diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 488964f843..6b801d0746 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -9,7 +9,7 @@ <@if not FADE_SLH@> <@def FADE_SLH@> -<@func declareFadeFragment()@> +<@func declareFadeFragmentCommon()@> #define CATEGORY_COUNT 5 @@ -19,25 +19,28 @@ uniform fadeParametersBuffer { FadeParameters fadeParameters[CATEGORY_COUNT]; }; -uniform int fadeCategory; -uniform vec3 fadeNoiseOffset; -uniform vec3 fadeBaseOffset; -uniform vec3 fadeBaseInvSize; -uniform float fadeThreshold; uniform sampler2D fadeMaskMap; +struct FadeObjectParams { + int category; + float threshold; + vec3 noiseOffset; + vec3 baseOffset; + vec3 baseInvSize; +}; + vec2 hash2D(vec3 position) { return position.xy* vec2(0.1677, 0.221765) + position.z*0.561; } float noise3D(vec3 position) { float n = textureLod(fadeMaskMap, hash2D(position), 0).r; - return pow(n, 1.0/2.2); // Need to fix this later directly in the texture + return pow(n, 1.0/2.2); // Remove sRGB. Need to fix this later directly in the texture } -float evalFadeNoiseGradient(vec3 position) { +float evalFadeNoiseGradient(FadeObjectParams params, vec3 position) { // Do tri-linear interpolation - vec3 noisePosition = position * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.xyz + fadeNoiseOffset; + vec3 noisePosition = position * fadeParameters[params.category]._noiseInvSizeAndLevel.xyz + params.noiseOffset; vec3 noisePositionFloored = floor(noisePosition); vec3 noisePositionFraction = fract(noisePosition); @@ -58,39 +61,37 @@ float evalFadeNoiseGradient(vec3 position) { float noise = mix(maskY.x, maskY.y, noisePositionFraction.y); noise -= 0.5; // Center on value 0 - return noise * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.w; + return noise * fadeParameters[params.category]._noiseInvSizeAndLevel.w; } -float evalFadeBaseGradient(vec3 position) { - float gradient = length((position - fadeBaseOffset) * fadeBaseInvSize.xyz); +float evalFadeBaseGradient(FadeObjectParams params, vec3 position) { + float gradient = length((position - params.baseOffset) * params.baseInvSize.xyz); gradient = gradient-0.5; // Center on value 0.5 - gradient *= fadeParameters[fadeCategory]._baseLevel; + gradient *= fadeParameters[params.category]._baseLevel; return gradient; } -float evalFadeGradient(vec3 position) { - float baseGradient = evalFadeBaseGradient(position); - float noiseGradient = evalFadeNoiseGradient(position); +float evalFadeGradient(FadeObjectParams params, vec3 position) { + float baseGradient = evalFadeBaseGradient(params, position); + float noiseGradient = evalFadeNoiseGradient(params, position); float gradient = noiseGradient+baseGradient+0.5; return gradient; } -float evalFadeAlpha(vec3 position) { - float cutoff = fadeThreshold; - - return evalFadeGradient(position)-cutoff; +float evalFadeAlpha(FadeObjectParams params, vec3 position) { + return evalFadeGradient(params, position)-params.threshold; } -void applyFadeClip(vec3 position) { - if (evalFadeAlpha(position) < 0) { +void applyFadeClip(FadeObjectParams params, vec3 position) { + if (evalFadeAlpha(params, position) < 0) { discard; } } -void applyFade(vec3 position, out vec3 emissive) { - float alpha = evalFadeAlpha(position); - if (fadeParameters[fadeCategory]._isInverted!=0) { +void applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) { + float alpha = evalFadeAlpha(params, position); + if (fadeParameters[params.category]._isInverted!=0) { alpha = -alpha; } @@ -98,15 +99,75 @@ void applyFade(vec3 position, out vec3 emissive) { discard; } - float edgeMask = alpha * fadeParameters[fadeCategory]._edgeWidthInvWidth.y; + float edgeMask = alpha * fadeParameters[params.category]._edgeWidthInvWidth.y; float edgeAlpha = 1.0-clamp(edgeMask, 0, 1); edgeMask = step(edgeMask, 1.f); edgeAlpha *= edgeAlpha; // Square to have a nice ease out - vec4 color = mix(fadeParameters[fadeCategory]._innerEdgeColor, fadeParameters[fadeCategory]._outerEdgeColor, edgeAlpha); + vec4 color = mix(fadeParameters[params.category]._innerEdgeColor, fadeParameters[params.category]._outerEdgeColor, edgeAlpha); emissive = color.rgb * edgeMask * color.a; } <@endfunc@> +<@func declareFadeFragmentUniform()@> + +uniform int fadeCategory; +uniform vec3 fadeNoiseOffset; +uniform vec3 fadeBaseOffset; +uniform vec3 fadeBaseInvSize; +uniform float fadeThreshold; + +<@endfunc@> + +<@func fetchFadeObjectParams(fadeParams)@> + <$fadeParams$>.category = fadeCategory; + <$fadeParams$>.threshold = fadeThreshold; + <$fadeParams$>.noiseOffset = fadeNoiseOffset; + <$fadeParams$>.baseOffset = fadeBaseOffset; + <$fadeParams$>.baseInvSize = fadeBaseInvSize; +<@endfunc@> + +<@func declareFadeFragmentVertexInput()@> + +in vec4 _fadeData1; +in vec4 _fadeData2; +in vec4 _fadeData3; + +<@endfunc@> + +<@func fetchFadeObjectParamsInstanced(fadeParams)@> + <$fadeParams$>.category = int(_fadeData1.w); + <$fadeParams$>.threshold = _fadeData2.w; + <$fadeParams$>.noiseOffset = _fadeData1.xyz; + <$fadeParams$>.baseOffset = _fadeData2.xyz; + <$fadeParams$>.baseInvSize = _fadeData3.xyz; +<@endfunc@> + +<@func declareFadeFragment()@> +<$declareFadeFragmentCommon()$> +<$declareFadeFragmentUniform()$> +<@endfunc@> + +<@func declareFadeFragmentInstanced()@> +<$declareFadeFragmentCommon()$> +<$declareFadeFragmentVertexInput()$> +<@endfunc@> + +<@func declareFadeVertexInstanced()@> +in vec4 _texCoord2; +in vec4 _texCoord3; +in vec4 _texCoord4; + +out vec4 _fadeData1; +out vec4 _fadeData2; +out vec4 _fadeData3; +<@endfunc@> + +<@func passThroughFadeObjectParams()@> + _fadeData1 = _texCoord2; + _fadeData2 = _texCoord3; + _fadeData3 = _texCoord4; +<@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 aec19ce32f..d8e7b5c9b1 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -39,35 +39,67 @@ render::ShapePipeline::BatchSetter FadeEffect::getBatchSetter() const { }; } -render::ShapePipeline::ItemSetter FadeEffect::getItemSetter() const { +render::ShapePipeline::ItemSetter FadeEffect::getItemUniformSetter() 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; auto transitionStage = scene->getStage(render::TransitionStage::getName()); auto& transitionState = transitionStage->getTransition(item.getTransitionId()); - render::ShapeKey shapeKey(args->_globalShapeKey); + auto program = shapePipeline.pipeline->getProgram(); + auto& uniforms = program->getUniforms(); + auto fadeNoiseOffsetLocation = uniforms.findLocation("fadeNoiseOffset"); + auto fadeBaseOffsetLocation = uniforms.findLocation("fadeBaseOffset"); + auto fadeBaseInvSizeLocation = uniforms.findLocation("fadeBaseInvSize"); + auto fadeThresholdLocation = uniforms.findLocation("fadeThreshold"); + auto fadeCategoryLocation = uniforms.findLocation("fadeCategory"); - // This is the normal case where we need to push the parameters in uniforms - { - auto program = shapePipeline.pipeline->getProgram(); - auto& uniforms = program->getUniforms(); - auto fadeNoiseOffsetLocation = uniforms.findLocation("fadeNoiseOffset"); - auto fadeBaseOffsetLocation = uniforms.findLocation("fadeBaseOffset"); - auto fadeBaseInvSizeLocation = uniforms.findLocation("fadeBaseInvSize"); - auto fadeThresholdLocation = uniforms.findLocation("fadeThreshold"); - auto fadeCategoryLocation = uniforms.findLocation("fadeCategory"); + if (fadeNoiseOffsetLocation >= 0 || fadeBaseInvSizeLocation >= 0 || fadeBaseOffsetLocation >= 0 || fadeThresholdLocation >= 0 || fadeCategoryLocation >= 0) { + const auto fadeCategory = FadeJob::transitionToCategory[transitionState.eventType]; - if (fadeNoiseOffsetLocation >= 0 || fadeBaseInvSizeLocation >= 0 || fadeBaseOffsetLocation >= 0 || fadeThresholdLocation >= 0 || fadeCategoryLocation >= 0) { - const auto fadeCategory = FadeJob::transitionToCategory[transitionState.eventType]; - - batch->_glUniform1i(fadeCategoryLocation, fadeCategory); - batch->_glUniform1f(fadeThresholdLocation, transitionState.threshold); - batch->_glUniform3f(fadeNoiseOffsetLocation, transitionState.noiseOffset.x, transitionState.noiseOffset.y, transitionState.noiseOffset.z); - batch->_glUniform3f(fadeBaseOffsetLocation, transitionState.baseOffset.x, transitionState.baseOffset.y, transitionState.baseOffset.z); - batch->_glUniform3f(fadeBaseInvSizeLocation, transitionState.baseInvSize.x, transitionState.baseInvSize.y, transitionState.baseInvSize.z); - } + batch->_glUniform1i(fadeCategoryLocation, fadeCategory); + batch->_glUniform1f(fadeThresholdLocation, transitionState.threshold); + batch->_glUniform3f(fadeNoiseOffsetLocation, transitionState.noiseOffset.x, transitionState.noiseOffset.y, transitionState.noiseOffset.z); + batch->_glUniform3f(fadeBaseOffsetLocation, transitionState.baseOffset.x, transitionState.baseOffset.y, transitionState.baseOffset.z); + batch->_glUniform3f(fadeBaseInvSizeLocation, transitionState.baseInvSize.x, transitionState.baseInvSize.y, transitionState.baseInvSize.z); } } }; } + +render::ShapePipeline::ItemSetter FadeEffect::getItemStoredSetter() { + return [this](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; + auto transitionStage = scene->getStage(render::TransitionStage::getName()); + auto& transitionState = transitionStage->getTransition(item.getTransitionId()); + const auto fadeCategory = FadeJob::transitionToCategory[transitionState.eventType]; + + _lastCategory = fadeCategory; + _lastThreshold = transitionState.threshold; + _lastNoiseOffset = transitionState.noiseOffset; + _lastBaseOffset = transitionState.baseOffset; + _lastBaseInvSize = transitionState.baseInvSize; + } + }; +} + +void FadeEffect::packToAttributes(const int category, const float threshold, const glm::vec3& noiseOffset, + const glm::vec3& baseOffset, const glm::vec3& baseInvSize, + glm::vec4& packedData1, glm::vec4& packedData2, glm::vec4& packedData3) { + packedData1.x = noiseOffset.x; + packedData1.y = noiseOffset.y; + packedData1.z = noiseOffset.z; + packedData1.w = (float)category; + + packedData2.x = baseOffset.x; + packedData2.y = baseOffset.y; + packedData2.z = baseOffset.z; + packedData2.w = threshold; + + packedData3.x = baseInvSize.x; + packedData3.y = baseInvSize.y; + packedData3.z = baseInvSize.z; + packedData3.w = 0.f; +} diff --git a/libraries/render-utils/src/FadeEffect.h b/libraries/render-utils/src/FadeEffect.h index 8677609892..4b4e401332 100644 --- a/libraries/render-utils/src/FadeEffect.h +++ b/libraries/render-utils/src/FadeEffect.h @@ -22,13 +22,31 @@ public: void build(render::Task::TaskConcept& task, const task::Varying& editableItems); render::ShapePipeline::BatchSetter getBatchSetter() const; - render::ShapePipeline::ItemSetter getItemSetter() const; + render::ShapePipeline::ItemSetter getItemUniformSetter() const; + render::ShapePipeline::ItemSetter getItemStoredSetter(); + + int getLastCategory() const { return _lastCategory; } + float getLastThreshold() const { return _lastThreshold; } + const glm::vec3& getLastNoiseOffset() const { return _lastNoiseOffset; } + const glm::vec3& getLastBaseOffset() const { return _lastBaseOffset; } + const glm::vec3& getLastBaseInvSize() const { return _lastBaseInvSize; } + + static void packToAttributes(const int category, const float threshold, const glm::vec3& noiseOffset, + const glm::vec3& baseOffset, const glm::vec3& baseInvSize, + glm::vec4& packedData1, glm::vec4& packedData2, glm::vec4& packedData3); private: gpu::BufferView _configurations; gpu::TexturePointer _maskMap; + // The last fade set through the stored item setter + int _lastCategory { 0 }; + float _lastThreshold { 0.f }; + glm::vec3 _lastNoiseOffset { 0.f, 0.f, 0.f }; + glm::vec3 _lastBaseOffset { 0.f, 0.f, 0.f }; + glm::vec3 _lastBaseInvSize { 1.f, 1.f, 1.f }; + explicit FadeEffect(); virtual ~FadeEffect() { } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 9e97540d53..7a68baa978 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -60,9 +60,11 @@ static const int VERTICES_PER_TRIANGLE = 3; static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA }; +static const gpu::Element TEXCOORD4_ELEMENT { gpu::VEC4, gpu::HALF, gpu::XYZW }; static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT; static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT; +static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT; static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 2; // vertices and normals static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3); @@ -451,6 +453,19 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() { return INSTANCED_SOLID_STREAM_FORMAT; } +gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() { + if (!INSTANCED_SOLID_FADE_STREAM_FORMAT) { + INSTANCED_SOLID_FADE_STREAM_FORMAT = std::make_shared(); // 1 for everyone + INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); + INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); + INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); + INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); + INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); + INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD4, gpu::Stream::TEXCOORD4, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); + } + return INSTANCED_SOLID_FADE_STREAM_FORMAT; +} + QHash GeometryCache::_simplePrograms; gpu::ShaderPointer GeometryCache::_simpleShader; @@ -535,11 +550,6 @@ void GeometryCache::releaseID(int id) { _registeredGridBuffers.remove(id); } -void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { - gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); - batch.setInputBuffer(gpu::Stream::COLOR, colorView); -} - void GeometryCache::initializeShapePipelines() { if (!_simpleOpaquePipeline) { _simpleOpaquePipeline = getShapePipeline(false, false, true, false); @@ -564,7 +574,7 @@ render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured bool unlit, bool depthBias) { auto fadeEffect = DependencyManager::get(); auto fadeBatchSetter = fadeEffect->getBatchSetter(); - auto fadeItemSetter = fadeEffect->getItemSetter(); + auto fadeItemSetter = fadeEffect->getItemStoredSetter(); return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true), nullptr, [fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) { batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); @@ -592,6 +602,11 @@ void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) { _shapes[shape].drawWire(batch); } +void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { + gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); + batch.setInputBuffer(gpu::Stream::COLOR, colorView); +} + void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) { batch.setInputFormat(getInstancedSolidStreamFormat()); setupBatchInstance(batch, colorBuffer); @@ -604,6 +619,32 @@ void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, siz _shapes[shape].drawWireInstances(batch, count); } +void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer, + gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) { + gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); + gpu::BufferView texCoord2View(fadeBuffer1, TEXCOORD4_ELEMENT); + gpu::BufferView texCoord3View(fadeBuffer2, TEXCOORD4_ELEMENT); + gpu::BufferView texCoord4View(fadeBuffer3, TEXCOORD4_ELEMENT); + batch.setInputBuffer(gpu::Stream::COLOR, colorView); + batch.setInputBuffer(gpu::Stream::TEXCOORD2, texCoord2View); + batch.setInputBuffer(gpu::Stream::TEXCOORD3, texCoord3View); + batch.setInputBuffer(gpu::Stream::TEXCOORD4, texCoord4View); +} + +void GeometryCache::renderFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, + gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) { + batch.setInputFormat(getInstancedSolidFadeStreamFormat()); + setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3); + _shapes[shape].drawInstances(batch, count); +} + +void GeometryCache::renderWireFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, + gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) { + batch.setInputFormat(getInstancedSolidFadeStreamFormat()); + setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3); + _shapes[shape].drawWireInstances(batch, count); +} + void GeometryCache::renderCube(gpu::Batch& batch) { renderShape(batch, Cube); } @@ -2046,12 +2087,62 @@ void renderInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color if (isWire) { DependencyManager::get()->renderWireShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); - } else { + } + else { DependencyManager::get()->renderShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); } }); } +static const size_t INSTANCE_FADE_BUFFER1 = 1; +static const size_t INSTANCE_FADE_BUFFER2 = 2; +static const size_t INSTANCE_FADE_BUFFER3 = 3; + +void renderFadeInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, int fadeCategory, float fadeThreshold, + const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, bool isWire, + const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) { + // Add pipeline to name + std::string instanceName = (isWire ? "wire_fade_shapes_" : "solid_fade_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash()(pipeline)); + + // Add color to named buffer + { + gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(instanceName, INSTANCE_COLOR_BUFFER); + auto compactColor = toCompactColor(color); + instanceColorBuffer->append(compactColor); + } + // Add fade parameters to named buffers + { + gpu::BufferPointer fadeBuffer1 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER1); + gpu::BufferPointer fadeBuffer2 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER2); + gpu::BufferPointer fadeBuffer3 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER3); + // Pack parameters in 3 vec4s + glm::vec4 fadeData1; + glm::vec4 fadeData2; + glm::vec4 fadeData3; + FadeEffect::packToAttributes(fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, + fadeData1, fadeData2, fadeData3); + fadeBuffer1->append(fadeData1); + fadeBuffer2->append(fadeData2); + fadeBuffer3->append(fadeData3); + } + + // Add call to named buffer + batch.setupNamedCalls(instanceName, [args, isWire, pipeline, shape](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { + auto& buffers = data.buffers; + batch.setPipeline(pipeline->pipeline); + pipeline->prepare(batch, args); + + if (isWire) { + DependencyManager::get()->renderWireFadeShapeInstances(batch, shape, data.count(), + buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]); + } + else { + DependencyManager::get()->renderFadeShapeInstances(batch, shape, data.count(), + buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]); + } + }); +} + void GeometryCache::renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { assert(pipeline != nullptr); renderInstances(args, batch, color, false, pipeline, shape); @@ -2062,6 +2153,20 @@ void GeometryCache::renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, renderInstances(args, batch, color, true, pipeline, shape); } +void GeometryCache::renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, + int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, + const render::ShapePipelinePointer& pipeline) { + assert(pipeline != nullptr); + renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, false, pipeline, shape); +} + +void GeometryCache::renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, + int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, + const render::ShapePipelinePointer& pipeline) { + assert(pipeline != nullptr); + renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, true, pipeline, shape); +} + void GeometryCache::renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { assert(pipeline != nullptr); renderInstances(args, batch, color, false, pipeline, GeometryCache::Sphere); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 46d74a9bb4..40aa829444 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -187,6 +187,11 @@ public: void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); + void renderFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, + gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3); + void renderWireFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, + gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3); + void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1), const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec3& color, @@ -201,6 +206,13 @@ public: renderWireShapeInstance(args, batch, shape, glm::vec4(color, 1.0f), pipeline); } + void renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color, int fadeCategory, float fadeThreshold, + const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, + const render::ShapePipelinePointer& pipeline); + void renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color, int fadeCategory, float fadeThreshold, + const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, + const render::ShapePipelinePointer& pipeline); + void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 32903ad0d2..3ce2f01705 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -62,7 +62,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Prepare the ShapePipelines ShapePlumberPointer shapePlumber = std::make_shared(); - initDeferredPipelines(*shapePlumber, fadeEffect->getBatchSetter(), fadeEffect->getItemSetter()); + initDeferredPipelines(*shapePlumber, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); // Extract opaques / transparents / lights / metas / overlays / background const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE]; diff --git a/libraries/render-utils/src/model_fade.slf b/libraries/render-utils/src/model_fade.slf index 172d7ddbee..d232667660 100644 --- a/libraries/render-utils/src/model_fade.slf +++ b/libraries/render-utils/src/model_fade.slf @@ -31,8 +31,10 @@ in vec2 _texCoord1; void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_lightmap_fade.slf b/libraries/render-utils/src/model_lightmap_fade.slf index 7ca5fc0a22..92d00a2046 100644 --- a/libraries/render-utils/src/model_lightmap_fade.slf +++ b/libraries/render-utils/src/model_lightmap_fade.slf @@ -32,8 +32,10 @@ in vec4 _worldPosition; void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf index 82c5a11529..825e84d666 100644 --- a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf @@ -33,8 +33,10 @@ in vec4 _worldPosition; void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf index 7314753ae6..791d5bf552 100644 --- a/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf +++ b/libraries/render-utils/src/model_lightmap_normal_specular_map_fade.slf @@ -33,8 +33,10 @@ in vec4 _worldPosition; void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_lightmap_specular_map_fade.slf b/libraries/render-utils/src/model_lightmap_specular_map_fade.slf index e17512fe7f..e82018eefb 100644 --- a/libraries/render-utils/src/model_lightmap_specular_map_fade.slf +++ b/libraries/render-utils/src/model_lightmap_specular_map_fade.slf @@ -32,8 +32,10 @@ in vec4 _worldPosition; void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf index 6134e871da..d8b864260c 100644 --- a/libraries/render-utils/src/model_normal_map_fade.slf +++ b/libraries/render-utils/src/model_normal_map_fade.slf @@ -32,8 +32,10 @@ in vec3 _color; void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_normal_specular_map_fade.slf b/libraries/render-utils/src/model_normal_specular_map_fade.slf index 59ee0e9927..5492b24763 100644 --- a/libraries/render-utils/src/model_normal_specular_map_fade.slf +++ b/libraries/render-utils/src/model_normal_specular_map_fade.slf @@ -32,8 +32,10 @@ in vec4 _worldPosition; void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_shadow_fade.slf b/libraries/render-utils/src/model_shadow_fade.slf index a697ba4f12..c00eed622c 100644 --- a/libraries/render-utils/src/model_shadow_fade.slf +++ b/libraries/render-utils/src/model_shadow_fade.slf @@ -20,7 +20,10 @@ layout(location = 0) out vec4 _fragColor; in vec4 _worldPosition; void main(void) { - applyFadeClip(_worldPosition.xyz); + FadeObjectParams fadeParams; + + <$fetchFadeObjectParams(fadeParams)$> + applyFadeClip(fadeParams, _worldPosition.xyz); // pass-through to set z-buffer _fragColor = vec4(1.0, 1.0, 1.0, 0.0); diff --git a/libraries/render-utils/src/model_specular_map_fade.slf b/libraries/render-utils/src/model_specular_map_fade.slf index a43027a034..6eb56c0929 100644 --- a/libraries/render-utils/src/model_specular_map_fade.slf +++ b/libraries/render-utils/src/model_specular_map_fade.slf @@ -31,8 +31,10 @@ in vec4 _worldPosition; void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf index cc4611586d..c46b396ebc 100644 --- a/libraries/render-utils/src/model_translucent_fade.slf +++ b/libraries/render-utils/src/model_translucent_fade.slf @@ -39,8 +39,10 @@ out vec4 _fragColor; void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_translucent_unlit_fade.slf b/libraries/render-utils/src/model_translucent_unlit_fade.slf index cb7739d1b7..6a77efe4ca 100644 --- a/libraries/render-utils/src/model_translucent_unlit_fade.slf +++ b/libraries/render-utils/src/model_translucent_unlit_fade.slf @@ -30,8 +30,10 @@ out vec4 _fragColor; void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/model_unlit_fade.slf b/libraries/render-utils/src/model_unlit_fade.slf index 179b16a3b1..0fe9f2ebac 100644 --- a/libraries/render-utils/src/model_unlit_fade.slf +++ b/libraries/render-utils/src/model_unlit_fade.slf @@ -30,8 +30,10 @@ in vec4 _worldPosition; void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material mat = getMaterial(); int matKey = getMaterialKey(mat); diff --git a/libraries/render-utils/src/simple_fade.slf b/libraries/render-utils/src/simple_fade.slf index 3424af15f5..245d32e81e 100644 --- a/libraries/render-utils/src/simple_fade.slf +++ b/libraries/render-utils/src/simple_fade.slf @@ -16,7 +16,7 @@ <@include model/Material.slh@> <@include Fade.slh@> -<$declareFadeFragment()$> +<$declareFadeFragmentInstanced()$> // the interpolated normal in vec3 _normal; @@ -34,8 +34,10 @@ in vec4 _worldPosition; #line 2030 void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParamsInstanced(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); Material material = getMaterial(); vec3 normal = normalize(_normal.xyz); diff --git a/libraries/render-utils/src/simple_fade.slv b/libraries/render-utils/src/simple_fade.slv index 02f69677d3..3d9eb2c812 100644 --- a/libraries/render-utils/src/simple_fade.slv +++ b/libraries/render-utils/src/simple_fade.slv @@ -17,6 +17,9 @@ <@include gpu/Transform.slh@> <$declareStandardTransform()$> +<@include Fade.slh@> +<$declareFadeVertexInstanced()$> + // the interpolated normal out vec3 _normal; out vec3 _modelNormal; @@ -37,4 +40,5 @@ void main(void) { <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> + <$passThroughFadeObjectParams()$> } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf index 659280f88b..025fe5fca6 100644 --- a/libraries/render-utils/src/simple_textured_fade.slf +++ b/libraries/render-utils/src/simple_textured_fade.slf @@ -28,12 +28,14 @@ in vec2 _texCoord0; in vec4 _worldPosition; // Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragment()$> +<$declareFadeFragmentInstanced()$> void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParamsInstanced(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0); float colorAlpha = _color.a; diff --git a/libraries/render-utils/src/simple_textured_unlit_fade.slf b/libraries/render-utils/src/simple_textured_unlit_fade.slf index f3c50bef9b..6f03c6746f 100644 --- a/libraries/render-utils/src/simple_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_textured_unlit_fade.slf @@ -27,12 +27,14 @@ in vec2 _texCoord0; in vec4 _worldPosition; // Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragment()$> +<$declareFadeFragmentInstanced()$> void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParamsInstanced(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0.st); float colorAlpha = _color.a; diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf index 31dc6f166a..20c7907bbe 100644 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_fade.slf @@ -34,12 +34,14 @@ in vec2 _texCoord0; in vec4 _worldPosition; // Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragment()$> +<$declareFadeFragmentInstanced()$> void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParamsInstanced(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0.st); float opacity = _color.a; diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf index bd403b0634..1c42a1f724 100644 --- a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf @@ -28,12 +28,14 @@ in vec4 _worldPosition; layout(location = 0) out vec4 _fragColor0; // Declare after all samplers to prevent sampler location mix up with originalTexture -<$declareFadeFragment()$> +<$declareFadeFragmentInstanced()$> void main(void) { vec3 fadeEmissive; + FadeObjectParams fadeParams; - applyFade(_worldPosition.xyz, fadeEmissive); + <$fetchFadeObjectParamsInstanced(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0.st); float colorAlpha = _color.a; diff --git a/libraries/render-utils/src/skin_model_shadow_fade.slf b/libraries/render-utils/src/skin_model_shadow_fade.slf index 9d720c7bee..aaf29076b8 100644 --- a/libraries/render-utils/src/skin_model_shadow_fade.slf +++ b/libraries/render-utils/src/skin_model_shadow_fade.slf @@ -20,7 +20,10 @@ in vec4 _worldPosition; layout(location = 0) out vec4 _fragColor; void main(void) { - applyFadeClip(_worldPosition.xyz); + FadeObjectParams fadeParams; + + <$fetchFadeObjectParams(fadeParams)$> + applyFadeClip(fadeParams, _worldPosition.xyz); // pass-through to set z-buffer _fragColor = vec4(1.0, 1.0, 1.0, 0.0); From 2bba6aa8160fa05ece863b6b5ececda6fcc144ec Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 18 Jul 2017 14:07:07 +0200 Subject: [PATCH 69/86] Revert "Removed all bubble fade event code on avatar side" This reverts commit 4b8545e8b5c35793fcdef6627b0b66795af97d4e. --- interface/src/avatar/AvatarManager.cpp | 11 ++++------- libraries/avatars/src/AvatarHashMap.cpp | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index bd545c64e0..961e168fa5 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -273,19 +273,15 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { return; } - const float SHRINK_RATE = 0.15f; - const float MIN_FADE_SCALE = MIN_AVATAR_SCALE; - QReadLocker locker(&_hashLock); QVector::iterator avatarItr = _avatarsToFade.begin(); + const render::ScenePointer& scene = qApp->getMain3DScene(); while (avatarItr != _avatarsToFade.end()) { auto avatar = std::static_pointer_cast(*avatarItr); - avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE); - avatar->animateScaleChanges(deltaTime); - if (avatar->getTargetScale() <= MIN_FADE_SCALE) { + avatar->updateFadingStatus(scene); + if (!avatar->isFading()) { // fading to zero is such a rare event we push a unique transaction for each if (avatar->isInScene()) { - const render::ScenePointer& scene = qApp->getMain3DScene(); render::Transaction transaction; avatar->removeFromScene(*avatarItr, scene, transaction); scene->enqueueTransaction(transaction); @@ -325,6 +321,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar DependencyManager::get()->avatarDisconnected(avatar->getSessionUUID()); } _avatarsToFade.push_back(removedAvatar); + avatar->fadeOut(qApp->getMain3DScene(), removalReason); } void AvatarManager::clearOtherAvatars() { diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 3712080cdb..540fd583c8 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -173,7 +173,7 @@ void AvatarHashMap::processKillAvatar(QSharedPointer message, S void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) { QWriteLocker locker(&_hashLock); - auto removedAvatar = _avatarHash.take(sessionUUID); + AvatarSharedPointer removedAvatar = _avatarHash.take(sessionUUID); if (removedAvatar) { handleRemovedAvatar(removedAvatar, removalReason); From 9130c51319a3afd533617a1a05c6d2c1860a11e4 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 18 Jul 2017 14:46:49 +0200 Subject: [PATCH 70/86] Fixed incorrect removal of ALL avatar fade events. Fade out should now work again when avatar leaves domain --- interface/src/avatar/AvatarManager.cpp | 2 +- libraries/avatars/src/AvatarHashMap.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 961e168fa5..3d48540a64 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -319,9 +319,9 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar // remove from node sets, if present DependencyManager::get()->removeFromIgnoreMuteSets(avatar->getSessionUUID()); DependencyManager::get()->avatarDisconnected(avatar->getSessionUUID()); + avatar->fadeOut(qApp->getMain3DScene(), removalReason); } _avatarsToFade.push_back(removedAvatar); - avatar->fadeOut(qApp->getMain3DScene(), removalReason); } void AvatarManager::clearOtherAvatars() { diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 540fd583c8..3712080cdb 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -173,7 +173,7 @@ void AvatarHashMap::processKillAvatar(QSharedPointer message, S void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) { QWriteLocker locker(&_hashLock); - AvatarSharedPointer removedAvatar = _avatarHash.take(sessionUUID); + auto removedAvatar = _avatarHash.take(sessionUUID); if (removedAvatar) { handleRemovedAvatar(removedAvatar, removalReason); From 3316be4deabd44aeafd6eca94c10bd27623591df Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 18 Jul 2017 17:01:17 +0200 Subject: [PATCH 71/86] Working fade parameters through instanced draw calls --- .../src/RenderableShapeEntityItem.cpp | 2 +- libraries/gpu/src/gpu/Inputs.slh | 3 +++ libraries/render-utils/src/Fade.slh | 10 +++------- libraries/render-utils/src/GeometryCache.cpp | 6 +++--- libraries/render-utils/src/MeshPartPayload.cpp | 18 ------------------ libraries/render/src/render/Args.h | 3 ++- libraries/render/src/render/DrawTask.cpp | 14 ++++++++++---- 7 files changed, 22 insertions(+), 34 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 4424d3aa17..0ccbb387f7 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -157,7 +157,7 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { } else { // FIXME, support instanced multi-shape rendering using multidraw indirect auto geometryCache = DependencyManager::get(); - auto shapeKey = render::ShapeKey(args->_globalShapeKey); + auto shapeKey = render::ShapeKey(args->_itemShapeKey); assert(args->_shapePipeline != nullptr); diff --git a/libraries/gpu/src/gpu/Inputs.slh b/libraries/gpu/src/gpu/Inputs.slh index 843d1059f2..109762136e 100644 --- a/libraries/gpu/src/gpu/Inputs.slh +++ b/libraries/gpu/src/gpu/Inputs.slh @@ -18,4 +18,7 @@ layout(location = 4) in vec4 inTangent; layout(location = 5) in ivec4 inSkinClusterIndex; layout(location = 6) in vec4 inSkinClusterWeight; layout(location = 7) in vec4 inTexCoord1; +layout(location = 8) in vec4 inTexCoord2; +layout(location = 9) in vec4 inTexCoord3; +layout(location = 10) in vec4 inTexCoord4; <@endif@> diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 6b801d0746..e4c2407448 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -155,19 +155,15 @@ in vec4 _fadeData3; <@endfunc@> <@func declareFadeVertexInstanced()@> -in vec4 _texCoord2; -in vec4 _texCoord3; -in vec4 _texCoord4; - out vec4 _fadeData1; out vec4 _fadeData2; out vec4 _fadeData3; <@endfunc@> <@func passThroughFadeObjectParams()@> - _fadeData1 = _texCoord2; - _fadeData2 = _texCoord3; - _fadeData3 = _texCoord4; + _fadeData1 = inTexCoord2; + _fadeData2 = inTexCoord3; + _fadeData3 = inTexCoord4; <@endfunc@> <@endif@> \ No newline at end of file diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 7a68baa978..34557e7b75 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -60,7 +60,7 @@ static const int VERTICES_PER_TRIANGLE = 3; static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA }; -static const gpu::Element TEXCOORD4_ELEMENT { gpu::VEC4, gpu::HALF, gpu::XYZW }; +static const gpu::Element TEXCOORD4_ELEMENT { gpu::VEC4, gpu::FLOAT, gpu::XYZW }; static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT; static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT; @@ -620,7 +620,7 @@ void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, siz } void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer, - gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) { + gpu::BufferPointer fadeBuffer1, gpu::BufferPointer fadeBuffer2, gpu::BufferPointer fadeBuffer3) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); gpu::BufferView texCoord2View(fadeBuffer1, TEXCOORD4_ELEMENT); gpu::BufferView texCoord3View(fadeBuffer2, TEXCOORD4_ELEMENT); @@ -2102,7 +2102,7 @@ void renderFadeInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& c const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, bool isWire, const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) { // Add pipeline to name - std::string instanceName = (isWire ? "wire_fade_shapes_" : "solid_fade_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash()(pipeline)); + std::string instanceName = (isWire ? "wire_shapes_" : "solid_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash()(pipeline)); // Add color to named buffer { diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index b837702582..517fe97dba 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -532,13 +532,6 @@ void ModelMeshPartPayload::render(RenderArgs* args) { if (_state == WAITING_TO_START) { if (model->isLoaded()) { - /* // FIXME as far as I can tell this is the ONLY reason render-util depends on entities. - if (EntityItem::getEntitiesShouldFadeFunction()()) { - _fadeStartTime = usecTimestampNow(); - _fadeState = STATE_IN_PROGRESS; - } else { - _fadeState = STATE_COMPLETE; - }*/ _state = STARTED; model->setRenderItemsNeedUpdate(); } else { @@ -570,17 +563,6 @@ void ModelMeshPartPayload::render(RenderArgs* args) { // apply material properties bindMaterial(batch, locations, args->_enableTexturing); - /* if (args->_enableFade) { - // Apply fade effect - if (!FadeRenderJob::bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime)) { - _fadeState = STATE_COMPLETE; - } - }*/ - /* else { - // TODO : very ugly way to update the fade state. Need to improve this with global fade manager. - _fadeState = STATE_COMPLETE; - }*/ - args->_details._materialSwitches++; // Draw! diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index 4810437518..1e4b626b89 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -115,7 +115,8 @@ namespace render { DebugFlags _debugFlags { RENDER_DEBUG_NONE }; gpu::Batch* _batch = nullptr; - uint32_t _globalShapeKey { 0 }; + uint32_t _globalShapeKey{ 0 }; + uint32_t _itemShapeKey{ 0 }; bool _enableTexturing { true }; bool _enableFade{ false }; diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index a3175ffdec..8372231597 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -42,6 +42,7 @@ void render::renderItems(const RenderContextPointer& renderContext, const ItemBo void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, const Item& item, const ShapeKey& globalKey) { assert(item.getKey().isShape()); auto key = item.getShapeKey() | globalKey; + args->_itemShapeKey = key._flags.to_ulong(); if (key.isValid() && !key.hasOwnPipeline()) { args->_shapePipeline = shapeContext->pickPipeline(args, key); if (args->_shapePipeline) { @@ -54,6 +55,7 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons } else { qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key; } + args->_itemShapeKey = 0; } void render::renderShapes(const RenderContextPointer& renderContext, @@ -85,10 +87,10 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext, using SortedShapes = std::unordered_map, render::ShapeKey::Hash, render::ShapeKey::KeyEqual>; SortedPipelines sortedPipelines; SortedShapes sortedShapes; - std::vector ownPipelineBucket; + std::vector< std::tuple > ownPipelineBucket; for (auto i = 0; i < numItemsToDraw; ++i) { - auto item = scene->getItem(inItems[i].id); + auto& item = scene->getItem(inItems[i].id); { assert(item.getKey().isShape()); @@ -100,7 +102,7 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext, } bucket.push_back(item); } else if (key.hasOwnPipeline()) { - ownPipelineBucket.push_back(item); + ownPipelineBucket.push_back( std::make_tuple(item, key) ); } else { qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key; } @@ -114,15 +116,19 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext, if (!args->_shapePipeline) { continue; } + args->_itemShapeKey = pipelineKey._flags.to_ulong(); for (auto& item : bucket) { args->_shapePipeline->prepareShapeItem(args, pipelineKey, item); item.render(args); } } args->_shapePipeline = nullptr; - for (auto& item : ownPipelineBucket) { + for (auto& itemAndKey : ownPipelineBucket) { + auto& item = std::get<0>(itemAndKey); + args->_itemShapeKey = std::get<1>(itemAndKey)._flags.to_ulong(); item.render(args); } + args->_itemShapeKey = 0; } void DrawLight::run(const RenderContextPointer& renderContext, const ItemBounds& inLights) { From abc751ef9cb5091f75596c451c6852b6be33c268 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 18 Jul 2017 18:25:54 +0200 Subject: [PATCH 72/86] Fade seems to be working on shape items with instanced drawing. --- .../entities-renderer/src/RenderableShapeEntityItem.cpp | 1 + libraries/render-utils/src/FadeEffect.cpp | 2 +- libraries/render-utils/src/FadeEffectJobs.cpp | 7 ++++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 0ccbb387f7..ded0553fc1 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -112,6 +112,7 @@ bool RenderableShapeEntityItem::addToScene(const EntityItemPointer& self, const renderPayload->addStatusGetters(statusGetters); transaction.resetItem(_myItem, renderPayload); + transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); return true; } diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index d8e7b5c9b1..6007315abf 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -91,7 +91,7 @@ void FadeEffect::packToAttributes(const int category, const float threshold, con packedData1.x = noiseOffset.x; packedData1.y = noiseOffset.y; packedData1.z = noiseOffset.z; - packedData1.w = (float)category; + packedData1.w = (float)(category+0.1f); // GLSL hack so that casting back from float to int in fragment shader returns the correct value. packedData2.x = baseOffset.x; packedData2.y = baseOffset.y; diff --git a/libraries/render-utils/src/FadeEffectJobs.cpp b/libraries/render-utils/src/FadeEffectJobs.cpp index 2e3bbaff3a..386fe244a8 100644 --- a/libraries/render-utils/src/FadeEffectJobs.cpp +++ b/libraries/render-utils/src/FadeEffectJobs.cpp @@ -94,12 +94,13 @@ render::ItemID FadeEditJob::findNearestItem(const render::RenderContextPointer& glm::vec3 normal; float isectDistance; render::ItemID nearestItem = render::Item::INVALID_ITEM_ID; - const float minDistance = 2.f; + const float minDistance = 1.f; + const float maxDistance = 50.f; for (const auto& itemBound : inputs) { if (!itemBound.bound.contains(rayOrigin) && itemBound.bound.findRayIntersection(rayOrigin, rayDirection, isectDistance, face, normal)) { auto& item = renderContext->_scene->getItem(itemBound.id); - if (item.getKey().isWorldSpace() && isectDistance>minDistance && isectDistance < minIsectDistance) { + if (item.getKey().isWorldSpace() && isectDistance>minDistance && isectDistance < minIsectDistance && isectDistance Date: Wed, 19 Jul 2017 16:40:20 +0200 Subject: [PATCH 73/86] Modified PolyLines to use the new custom pipeline system --- .../src/RenderablePolyLineEntityItem.cpp | 85 ++++++++++++------- .../src/RenderablePolyLineEntityItem.h | 38 +++++++-- 2 files changed, 89 insertions(+), 34 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index d2bf8e3532..3ffb2dd784 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -22,17 +22,65 @@ #include "paintStroke_vert.h" #include "paintStroke_frag.h" +uint8_t PolyLinePayload::CUSTOM_PIPELINE_NUMBER = 0; +gpu::PipelinePointer PolyLinePayload::_pipeline; +const int32_t PolyLinePayload::PAINTSTROKE_TEXTURE_SLOT; +const int32_t PolyLinePayload::PAINTSTROKE_UNIFORM_SLOT; + +render::ShapePipelinePointer PolyLinePayload::shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key) { + if (!_pipeline) { + auto VS = gpu::Shader::createVertex(std::string(paintStroke_vert)); + auto PS = gpu::Shader::createPixel(std::string(paintStroke_frag)); + gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), PAINTSTROKE_TEXTURE_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("polyLineBuffer"), PAINTSTROKE_UNIFORM_SLOT)); + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + PrepareStencil::testMask(*state); + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + _pipeline = gpu::Pipeline::create(program, state); + } + return std::make_shared(_pipeline, nullptr, nullptr, nullptr); +} + +namespace render { + template <> const ItemKey payloadGetKey(const PolyLinePayload::Pointer& payload) { + return payloadGetKey(std::static_pointer_cast(payload)); + } + template <> const Item::Bound payloadGetBound(const PolyLinePayload::Pointer& payload) { + return payloadGetBound(std::static_pointer_cast(payload)); + } + template <> void payloadRender(const PolyLinePayload::Pointer& payload, RenderArgs* args) { + payloadRender(std::static_pointer_cast(payload), args); + } + template <> uint32_t metaFetchMetaSubItems(const PolyLinePayload::Pointer& payload, ItemIDs& subItems) { + return metaFetchMetaSubItems(std::static_pointer_cast(payload), subItems); + } + + template <> const ShapeKey shapeGetShapeKey(const PolyLinePayload::Pointer& payload) { + auto shapeKey = ShapeKey::Builder().withCustom(PolyLinePayload::CUSTOM_PIPELINE_NUMBER); + return shapeKey.build(); + } +} struct PolyLineUniforms { glm::vec3 color; }; - - EntityItemPointer RenderablePolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer entity{ new RenderablePolyLineEntityItem(entityID) }; entity->setProperties(properties); + + // As we create the first PolyLine entity, let's register its special shapePipeline factory: + PolyLinePayload::registerShapePipeline(); + return entity; } @@ -45,12 +93,9 @@ _numVertices(0) _uniformBuffer = std::make_shared(sizeof(PolyLineUniforms), (const gpu::Byte*) &uniforms); } -gpu::PipelinePointer RenderablePolyLineEntityItem::_pipeline; gpu::Stream::FormatPointer RenderablePolyLineEntityItem::_format; -const int32_t RenderablePolyLineEntityItem::PAINTSTROKE_TEXTURE_SLOT; -const int32_t RenderablePolyLineEntityItem::PAINTSTROKE_UNIFORM_SLOT; -void RenderablePolyLineEntityItem::createPipeline() { +void RenderablePolyLineEntityItem::createStreamFormat() { static const int NORMAL_OFFSET = 12; static const int TEXTURE_OFFSET = 24; @@ -58,23 +103,6 @@ void RenderablePolyLineEntityItem::createPipeline() { _format->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); _format->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), NORMAL_OFFSET); _format->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), TEXTURE_OFFSET); - - auto VS = gpu::Shader::createVertex(std::string(paintStroke_vert)); - auto PS = gpu::Shader::createPixel(std::string(paintStroke_frag)); - gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS); - - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), PAINTSTROKE_TEXTURE_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("polyLineBuffer"), PAINTSTROKE_UNIFORM_SLOT)); - gpu::Shader::makeProgram(*program, slotBindings); - - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - PrepareStencil::testMask(*state); - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - _pipeline = gpu::Pipeline::create(program, state); } void RenderablePolyLineEntityItem::updateGeometry() { @@ -180,8 +208,8 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) { return; } - if (!_pipeline) { - createPipeline(); + if (!_format) { + createStreamFormat(); } if (!_texture || _texturesChangedFlag) { @@ -199,14 +227,13 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) { Transform transform = Transform(); transform.setTranslation(getPosition()); transform.setRotation(getRotation()); - batch.setUniformBuffer(PAINTSTROKE_UNIFORM_SLOT, _uniformBuffer); + batch.setUniformBuffer(PolyLinePayload::PAINTSTROKE_UNIFORM_SLOT, _uniformBuffer); batch.setModelTransform(transform); - batch.setPipeline(_pipeline); if (_texture->isLoaded()) { - batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, _texture->getGPUTexture()); + batch.setResourceTexture(PolyLinePayload::PAINTSTROKE_TEXTURE_SLOT, _texture->getGPUTexture()); } else { - batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, nullptr); + batch.setResourceTexture(PolyLinePayload::PAINTSTROKE_TEXTURE_SLOT, nullptr); } batch.setInputFormat(_format); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index 8a62a761e0..b8adae08ce 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -22,10 +22,39 @@ #include +class PolyLinePayload : public RenderableEntityItemProxy { +public: + + static uint8_t CUSTOM_PIPELINE_NUMBER; + static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key); + static void registerShapePipeline() { + if (!CUSTOM_PIPELINE_NUMBER) { + CUSTOM_PIPELINE_NUMBER = render::ShapePipeline::registerCustomShapePipelineFactory(shapePipelineFactory); + } + } + static gpu::PipelinePointer _pipeline; + + static const int32_t PAINTSTROKE_TEXTURE_SLOT{ 0 }; + static const int32_t PAINTSTROKE_UNIFORM_SLOT{ 0 }; + + PolyLinePayload(const EntityItemPointer& entity, render::ItemID metaID) + : RenderableEntityItemProxy(entity, metaID) {} + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + +}; + +namespace render { + template <> const ItemKey payloadGetKey(const PolyLinePayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const PolyLinePayload::Pointer& payload); + template <> void payloadRender(const PolyLinePayload::Pointer& payload, RenderArgs* args); + template <> uint32_t metaFetchMetaSubItems(const PolyLinePayload::Pointer& payload, ItemIDs& subItems); + template <> const ShapeKey shapeGetShapeKey(const PolyLinePayload::Pointer& payload); +} + class RenderablePolyLineEntityItem : public PolyLineEntityItem, public SimplerRenderableEntitySupport { public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); - static void createPipeline(); RenderablePolyLineEntityItem(const EntityItemID& entityItemID); virtual void render(RenderArgs* args) override; @@ -38,15 +67,14 @@ public: NetworkTexturePointer _texture; - static gpu::PipelinePointer _pipeline; static gpu::Stream::FormatPointer _format; - static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 }; - static const int32_t PAINTSTROKE_UNIFORM_SLOT { 0 }; - protected: void updateGeometry(); void updateVertices(); + + static void createStreamFormat(); + gpu::BufferPointer _verticesBuffer; gpu::BufferView _uniformBuffer; unsigned int _numVertices; From b652d94a432f30513e1d4b1d3cbeef5b2b144b4a Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 19 Jul 2017 17:11:06 +0200 Subject: [PATCH 74/86] Added fade on poly line entities --- .../src/RenderablePolyLineEntityItem.cpp | 41 +++++++++++--- .../src/RenderablePolyLineEntityItem.h | 4 ++ .../src/paintStroke_fade.slf | 54 +++++++++++++++++++ .../src/paintStroke_fade.slv | 43 +++++++++++++++ .../render-utils/src/DeferredBufferWrite.slh | 5 ++ 5 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 libraries/entities-renderer/src/paintStroke_fade.slf create mode 100644 libraries/entities-renderer/src/paintStroke_fade.slv diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 3ffb2dd784..138835c8a5 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -22,9 +22,14 @@ #include "paintStroke_vert.h" #include "paintStroke_frag.h" +#include "paintStroke_fade_vert.h" +#include "paintStroke_fade_frag.h" + uint8_t PolyLinePayload::CUSTOM_PIPELINE_NUMBER = 0; gpu::PipelinePointer PolyLinePayload::_pipeline; +gpu::PipelinePointer PolyLinePayload::_fadePipeline; + const int32_t PolyLinePayload::PAINTSTROKE_TEXTURE_SLOT; const int32_t PolyLinePayload::PAINTSTROKE_UNIFORM_SLOT; @@ -32,12 +37,16 @@ render::ShapePipelinePointer PolyLinePayload::shapePipelineFactory(const render: if (!_pipeline) { auto VS = gpu::Shader::createVertex(std::string(paintStroke_vert)); auto PS = gpu::Shader::createPixel(std::string(paintStroke_frag)); + auto fadeVS = gpu::Shader::createVertex(std::string(paintStroke_fade_vert)); + auto fadePS = gpu::Shader::createPixel(std::string(paintStroke_fade_frag)); gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS); + gpu::ShaderPointer fadeProgram = gpu::Shader::createProgram(fadeVS, fadePS); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), PAINTSTROKE_TEXTURE_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("polyLineBuffer"), PAINTSTROKE_UNIFORM_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); + gpu::Shader::makeProgram(*fadeProgram, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(true, true, gpu::LESS_EQUAL); @@ -46,8 +55,14 @@ render::ShapePipelinePointer PolyLinePayload::shapePipelineFactory(const render: gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); _pipeline = gpu::Pipeline::create(program, state); + _fadePipeline = gpu::Pipeline::create(fadeProgram, state); + } + + if (key.isFaded()) { + return std::make_shared(_fadePipeline, nullptr, nullptr, nullptr); + } else { + return std::make_shared(_pipeline, nullptr, nullptr, nullptr); } - return std::make_shared(_pipeline, nullptr, nullptr, nullptr); } namespace render { @@ -201,6 +216,24 @@ void RenderablePolyLineEntityItem::update(const quint64& now) { } +bool RenderablePolyLineEntityItem::addToScene(const EntityItemPointer& self, + const render::ScenePointer& scene, + render::Transaction& transaction) { + _myItem = scene->allocateID(); + + auto renderData = std::make_shared(self, _myItem); + auto renderPayload = std::make_shared(renderData); + + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(self, statusGetters); + renderPayload->addStatusGetters(statusGetters); + + transaction.resetItem(_myItem, renderPayload); + transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); + + return true; +} + void RenderablePolyLineEntityItem::render(RenderArgs* args) { checkFading(); @@ -239,11 +272,5 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) { batch.setInputFormat(_format); batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride); - if (_isFading) { - batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime)); - } else { - batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } - batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0); }; diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index b8adae08ce..8aaa05c0a5 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -33,6 +33,7 @@ public: } } static gpu::PipelinePointer _pipeline; + static gpu::PipelinePointer _fadePipeline; static const int32_t PAINTSTROKE_TEXTURE_SLOT{ 0 }; static const int32_t PAINTSTROKE_UNIFORM_SLOT{ 0 }; @@ -60,6 +61,9 @@ public: virtual void render(RenderArgs* args) override; virtual void update(const quint64& now) override; virtual bool needsToCallUpdate() const override { return true; } + virtual bool addToScene(const EntityItemPointer& self, + const render::ScenePointer& scene, + render::Transaction& transaction) override; bool isTransparent() override { return true; } diff --git a/libraries/entities-renderer/src/paintStroke_fade.slf b/libraries/entities-renderer/src/paintStroke_fade.slf new file mode 100644 index 0000000000..cc9dec3338 --- /dev/null +++ b/libraries/entities-renderer/src/paintStroke_fade.slf @@ -0,0 +1,54 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// paintStroke_fade.slf +// fragment shader +// +// Created by Olivier Prat on 19/07/17. +// 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 DeferredBufferWrite.slh@> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 interpolatedNormal; +in vec2 varTexcoord; +in vec4 varColor; +in vec4 _worldPosition; + +struct PolyLineUniforms { + vec3 color; +}; + +uniform polyLineBuffer { + PolyLineUniforms polyline; +}; + +void main(void) { + vec3 fadeEmissive; + FadeObjectParams fadeParams; + + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); + + vec4 texel = texture(originalTexture, varTexcoord); + int frontCondition = 1 -int(gl_FrontFacing) * 2; + vec3 color = varColor.rgb; + packDeferredFragmentTranslucentEmissive( + interpolatedNormal * frontCondition, + texel.a * varColor.a, + polyline.color * texel.rgb, + vec3(0.01, 0.01, 0.01), + 10.0, + fadeEmissive); +} diff --git a/libraries/entities-renderer/src/paintStroke_fade.slv b/libraries/entities-renderer/src/paintStroke_fade.slv new file mode 100644 index 0000000000..9f10fa5d91 --- /dev/null +++ b/libraries/entities-renderer/src/paintStroke_fade.slv @@ -0,0 +1,43 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// paintStroke_fade.slv +// vertex shader +// +// Created by Olivier Prat on 19/07/17. +// 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +// the interpolated normal +out vec3 interpolatedNormal; + +//the diffuse texture +out vec2 varTexcoord; + +out vec4 varColor; +out vec4 _worldPosition; + +void main(void) { + + varTexcoord = inTexCoord0.st; + + // pass along the diffuse color + varColor = colorToLinearRGBA(inColor); + + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyeDir(cam, obj, inNormal.xyz, interpolatedNormal)$> + <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> +} \ No newline at end of file diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 2f6bfaeb61..c83e49ba4c 100644 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -77,4 +77,9 @@ void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 } +void packDeferredFragmentTranslucentEmissive(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness, vec3 emissive) { + packDeferredFragmentTranslucent(normal, alpha, albedo, fresnel, roughness); + _fragColor3 = vec4(emissive, 1.0); +} + <@endif@> From 7cfccc03a482654f39c9e84f2d9e3e43cc8f7656 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 20 Jul 2017 10:31:35 +0200 Subject: [PATCH 75/86] Fixed bug on AMD due to improper alignement issues on UBO with layout(std140) in GLSL --- libraries/render-utils/src/Fade.slh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 488964f843..b8eb58e235 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -16,7 +16,7 @@ <@include Fade_shared.slh@> -uniform fadeParametersBuffer { +layout(std140) uniform fadeParametersBuffer { FadeParameters fadeParameters[CATEGORY_COUNT]; }; uniform int fadeCategory; From a50c267d0b3907a3ecca3002ec6be042b683521e Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 20 Jul 2017 12:45:14 +0200 Subject: [PATCH 76/86] Fading on polyline now works when the polyline is added to the scene --- .../src/RenderablePolyLineEntityItem.cpp | 20 ++++++++++++------- .../src/RenderablePolyLineEntityItem.h | 1 + .../src/RenderableShapeEntityItem.cpp | 3 +-- .../src/paintStroke_fade.slf | 7 +++---- .../render-utils/src/DeferredBufferWrite.slh | 5 ----- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 138835c8a5..54bdd9d9f5 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include "RenderablePolyLineEntityItem.h" @@ -46,6 +47,8 @@ render::ShapePipelinePointer PolyLinePayload::shapePipelineFactory(const render: slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), PAINTSTROKE_TEXTURE_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("polyLineBuffer"), PAINTSTROKE_UNIFORM_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), PAINTSTROKE_TEXTURE_SLOT + 1)); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), PAINTSTROKE_UNIFORM_SLOT+1)); gpu::Shader::makeProgram(*fadeProgram, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); @@ -59,7 +62,8 @@ render::ShapePipelinePointer PolyLinePayload::shapePipelineFactory(const render: } if (key.isFaded()) { - return std::make_shared(_fadePipeline, nullptr, nullptr, nullptr); + auto fadeEffect = DependencyManager::get(); + return std::make_shared(_fadePipeline, nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); } else { return std::make_shared(_pipeline, nullptr, nullptr, nullptr); } @@ -201,10 +205,7 @@ void RenderablePolyLineEntityItem::updateVertices() { } -void RenderablePolyLineEntityItem::update(const quint64& now) { - PolyLineUniforms uniforms; - uniforms.color = toGlm(getXColor()); - memcpy(&_uniformBuffer.edit(), &uniforms, sizeof(PolyLineUniforms)); +void RenderablePolyLineEntityItem::updateMesh() { if (_pointsChanged || _strokeWidthsChanged || _normalsChanged) { QWriteLocker lock(&_quadReadWriteLock); _empty = (_points.size() < 2 || _normals.size() < 2 || _strokeWidths.size() < 2); @@ -213,7 +214,13 @@ void RenderablePolyLineEntityItem::update(const quint64& now) { updateGeometry(); } } +} +void RenderablePolyLineEntityItem::update(const quint64& now) { + PolyLineUniforms uniforms; + uniforms.color = toGlm(getXColor()); + memcpy(&_uniformBuffer.edit(), &uniforms, sizeof(PolyLineUniforms)); + updateMesh(); } bool RenderablePolyLineEntityItem::addToScene(const EntityItemPointer& self, @@ -230,13 +237,12 @@ bool RenderablePolyLineEntityItem::addToScene(const EntityItemPointer& self, transaction.resetItem(_myItem, renderPayload); transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); + updateMesh(); return true; } void RenderablePolyLineEntityItem::render(RenderArgs* args) { - checkFading(); - if (_empty) { return; } diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index 8aaa05c0a5..4dda6da489 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -76,6 +76,7 @@ public: protected: void updateGeometry(); void updateVertices(); + void updateMesh(); static void createStreamFormat(); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index ded0553fc1..4ab64a67e9 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -74,7 +74,7 @@ void RenderableShapeEntityItem::setUserData(const QString& value) { } bool RenderableShapeEntityItem::isTransparent() { - return getLocalRenderAlpha() < 1.0f || EntityItem::isTransparent(); + return getLocalRenderAlpha() < 1.0f; } namespace render { @@ -121,7 +121,6 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); //Q_ASSERT(getType() == EntityTypes::Shape); Q_ASSERT(args->_batch); - checkFading(); if (!_procedural) { _procedural.reset(new Procedural(getUserData())); diff --git a/libraries/entities-renderer/src/paintStroke_fade.slf b/libraries/entities-renderer/src/paintStroke_fade.slf index cc9dec3338..cc037aeac4 100644 --- a/libraries/entities-renderer/src/paintStroke_fade.slf +++ b/libraries/entities-renderer/src/paintStroke_fade.slf @@ -44,11 +44,10 @@ void main(void) { vec4 texel = texture(originalTexture, varTexcoord); int frontCondition = 1 -int(gl_FrontFacing) * 2; vec3 color = varColor.rgb; - packDeferredFragmentTranslucentEmissive( + packDeferredFragmentTranslucent( interpolatedNormal * frontCondition, texel.a * varColor.a, - polyline.color * texel.rgb, + polyline.color * texel.rgb + fadeEmissive, vec3(0.01, 0.01, 0.01), - 10.0, - fadeEmissive); + 10.0); } diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index c83e49ba4c..2f6bfaeb61 100644 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -77,9 +77,4 @@ void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 } -void packDeferredFragmentTranslucentEmissive(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness, vec3 emissive) { - packDeferredFragmentTranslucent(normal, alpha, albedo, fresnel, roughness); - _fragColor3 = vec4(emissive, 1.0); -} - <@endif@> From 8f9deb3b0d9144e699cf34f14907a3cdc9d0febb Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 20 Jul 2017 14:44:01 +0200 Subject: [PATCH 77/86] Modified fade version of voxel shaders to use real world position --- libraries/entities-renderer/src/polyvox_fade.slf | 3 ++- libraries/entities-renderer/src/polyvox_fade.slv | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/polyvox_fade.slf b/libraries/entities-renderer/src/polyvox_fade.slf index ad4950f64c..7af43be53f 100644 --- a/libraries/entities-renderer/src/polyvox_fade.slf +++ b/libraries/entities-renderer/src/polyvox_fade.slf @@ -19,6 +19,7 @@ in vec3 _normal; in vec4 _position; in vec4 _worldPosition; +in vec4 _worldFadePosition; uniform sampler2D xMap; uniform sampler2D yMap; @@ -33,7 +34,7 @@ void main(void) { FadeObjectParams fadeParams; <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _worldPosition.xyz, emissive); + applyFade(fadeParams, _worldFadePosition.xyz, emissive); vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); worldNormal = normalize(worldNormal); diff --git a/libraries/entities-renderer/src/polyvox_fade.slv b/libraries/entities-renderer/src/polyvox_fade.slv index 490a2a9ff0..506b5d16e7 100644 --- a/libraries/entities-renderer/src/polyvox_fade.slv +++ b/libraries/entities-renderer/src/polyvox_fade.slv @@ -19,6 +19,7 @@ out vec4 _position; out vec4 _worldPosition; +out vec4 _worldFadePosition; out vec3 _normal; void main(void) { @@ -27,5 +28,6 @@ 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; } From b08e2598c2ad61dcda9e5bcd0b0e90e0f8620cf7 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 21 Jul 2017 12:49:51 +0200 Subject: [PATCH 78/86] Some factorization in transition management and transition item application is now completely recursive on sub items and not just level 1 subitems --- libraries/render-utils/src/FadeEffectJobs.cpp | 29 +++++--- libraries/render-utils/src/FadeEffectJobs.h | 2 +- libraries/render/src/render/Scene.cpp | 71 +++++++++++-------- libraries/render/src/render/Scene.h | 5 ++ 4 files changed, 66 insertions(+), 41 deletions(-) diff --git a/libraries/render-utils/src/FadeEffectJobs.cpp b/libraries/render-utils/src/FadeEffectJobs.cpp index 386fe244a8..90459cf0e6 100644 --- a/libraries/render-utils/src/FadeEffectJobs.cpp +++ b/libraries/render-utils/src/FadeEffectJobs.cpp @@ -173,7 +173,7 @@ FadeConfig::FadeConfig() } void FadeConfig::setEditedCategory(int value) { - assert(value < CATEGORY_COUNT); + assert(value < FADE_CATEGORY_COUNT); editedCategory = std::min(FADE_CATEGORY_COUNT, value); emit dirtyCategory(); emit dirty(); @@ -578,20 +578,31 @@ void FadeJob::run(const render::RenderContextPointer& renderContext, FadeJob::Ou auto transitionStage = scene->getStage(render::TransitionStage::getName()); uint64_t now = usecTimestampNow(); const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND); + render::Transaction transaction; bool isFirstItem = true; + bool hasTransaction = false; output = (FadeCategory) jobConfig->editedCategory; // And now update fade effect for (auto transitionId : *transitionStage) { auto& state = transitionStage->editTransition(transitionId); - update(*jobConfig, scene, state, deltaTime); +#ifdef DEBUG + auto& item = scene->getItem(state.itemId); + assert(item.getTransitionId() == transitionId); +#endif + if (update(*jobConfig, scene, transaction, state, deltaTime)) { + hasTransaction = true; + } if (isFirstItem) { jobConfig->setProperty("threshold", state.threshold); isFirstItem = false; } } _previousTime = now; + if (hasTransaction) { + scene->enqueueTransaction(transaction); + } } const FadeCategory FadeJob::transitionToCategory[render::Transition::TYPE_COUNT] = { @@ -604,17 +615,17 @@ const FadeCategory FadeJob::transitionToCategory[render::Transition::TYPE_COUNT] FADE_AVATAR_CHANGE }; -void FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transition& transition, const double deltaTime) const { +bool FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const { const auto fadeCategory = transitionToCategory[transition.eventType]; auto& eventConfig = config.events[fadeCategory]; - auto& item = scene->getItem(transition.itemId); + auto item = scene->getItemSafe(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); + auto boundItem = scene->getItemSafe(transition.boundItemId); if (boundItem.exist()) { aabb = boundItem.getBound(); } @@ -687,12 +698,12 @@ void FadeJob::update(const Config& config, const render::ScenePointer& scene, re 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; + // If the transition is finished for more than a number of frames (here 1), garbage collect it. + if (transition.isFinished > 1) { transaction.removeTransitionFromItem(transition.itemId); - scene->enqueueTransaction(transaction); + return true; } + return false; } float FadeJob::computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing) { diff --git a/libraries/render-utils/src/FadeEffectJobs.h b/libraries/render-utils/src/FadeEffectJobs.h index ca29f40b5c..f827bb6e99 100644 --- a/libraries/render-utils/src/FadeEffectJobs.h +++ b/libraries/render-utils/src/FadeEffectJobs.h @@ -240,7 +240,7 @@ private: 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; + bool update(const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const; static float computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing); }; diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 3e266a6fdf..d2d3ad6de6 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -41,6 +41,10 @@ void Transaction::removeTransitionFromItem(ItemID id) { _addedTransitions.emplace_back(TransitionAdd{ id, Transition::NONE, render::Item::INVALID_ITEM_ID }); } +void Transaction::reApplyTransitionToItem(ItemID id) { + _reAppliedTransitions.emplace_back(TransitionReApply{ id }); +} + void Transaction::queryTransitionOnItem(ItemID id, TransitionQueryFunc func) { _queriedTransitions.emplace_back(TransitionQuery{ id, func }); } @@ -60,6 +64,7 @@ void Transaction::merge(const Transaction& transaction) { _resetSelections.insert(_resetSelections.end(), transaction._resetSelections.begin(), transaction._resetSelections.end()); _addedTransitions.insert(_addedTransitions.end(), transaction._addedTransitions.begin(), transaction._addedTransitions.end()); _queriedTransitions.insert(_queriedTransitions.end(), transaction._queriedTransitions.begin(), transaction._queriedTransitions.end()); + _reAppliedTransitions.insert(_reAppliedTransitions.end(), transaction._reAppliedTransitions.begin(), transaction._reAppliedTransitions.end()); } @@ -132,7 +137,7 @@ void Scene::processTransactionQueue() { #ifdef SCENE_ENABLE_TRANSITIONS // add transitions transitionItems(consolidatedTransaction._addedTransitions); - + reApplyTransitions(consolidatedTransaction._reAppliedTransitions); queryTransitionItems(consolidatedTransaction._queriedTransitions); #endif // Update the numItemsAtomic counter AFTER the pending changes went through @@ -184,11 +189,8 @@ void Scene::removeItems(const Transaction::Removes& transactions) { _masterNonspatialSet.erase(removedID); } - // If there is a transition on this item, remove it - if (item.getTransitionId() != render::TransitionStage::INVALID_INDEX) { - auto transitionStage = getStage(TransitionStage::getName()); - transitionStage->removeTransition(item.getTransitionId()); - } + // Remove the transition to prevent updating it for nothing + resetItemTransition(removedID); // Kill it item.kill(); @@ -240,22 +242,30 @@ void Scene::transitionItems(const Transaction::TransitionAdds& transactions) { auto itemId = std::get<0>(add); // Access the true item const auto& item = _items[itemId]; - if (item.exist()) { - auto transitionId = INVALID_INDEX; - auto transitionType = std::get<1>(add); - auto boundId = std::get<2>(add); + auto transitionId = item.getTransitionId(); + auto transitionType = std::get<1>(add); + auto boundId = std::get<2>(add); - // Remove pre-existing transition, if need be - if (!TransitionStage::isIndexInvalid(item.getTransitionId())) { - transitionStage->removeTransition(item.getTransitionId()); - } - // Add a new one. - if (transitionType != Transition::NONE) { - transitionId = transitionStage->addTransition(itemId, transitionType, boundId); - } - - setItemTransition(itemId, transitionId); + // Remove pre-existing transition, if need be + if (!TransitionStage::isIndexInvalid(transitionId)) { + transitionStage->removeTransition(transitionId); + transitionId = TransitionStage::INVALID_INDEX; } + // Add a new one. + if (transitionType != Transition::NONE) { + transitionId = transitionStage->addTransition(itemId, transitionType, boundId); + } + + setItemTransition(itemId, transitionId); + } +} + +void Scene::reApplyTransitions(const Transaction::TransitionReApplies& transactions) { + for (auto itemId : transactions) { + // Access the true item + const auto& item = _items[itemId]; + auto transitionId = item.getTransitionId(); + setItemTransition(itemId, transitionId); } } @@ -302,29 +312,28 @@ void Scene::setItemTransition(ItemID itemId, Index transitionId) { // Access the true item auto& item = _items[itemId]; + item.setTransitionId(transitionId); if (item.exist()) { ItemIDs subItems; - item.setTransitionId(transitionId); - // Sub-items share the same transition Id collectSubItems(itemId, subItems); for (auto subItemId : subItems) { - auto& subItem = _items[subItemId]; - subItem.setTransitionId(transitionId); + // Curiously... this can happen + if (subItemId != itemId) { + setItemTransition(subItemId, transitionId); + } } - } else { - qWarning() << "Collecting sub items on item without payload"; } } void Scene::resetItemTransition(ItemID itemId) { - // Access the true item auto& item = _items[itemId]; - auto transitionStage = getStage(TransitionStage::getName()); - - transitionStage->removeTransition(item.getTransitionId()); - setItemTransition(itemId, Transition::NONE); + if (!render::TransitionStage::isIndexInvalid(item.getTransitionId())) { + auto transitionStage = getStage(TransitionStage::getName()); + transitionStage->removeTransition(item.getTransitionId()); + setItemTransition(itemId, render::TransitionStage::INVALID_INDEX); + } } // THis fucntion is thread safe diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index b24cde240f..3b61a20f24 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -48,6 +48,7 @@ public: void addTransitionToItem(ItemID id, Transition::Type transition, ItemID boundId = render::Item::INVALID_ITEM_ID); void removeTransitionFromItem(ItemID id); + void reApplyTransitionToItem(ItemID id); void queryTransitionOnItem(ItemID id, TransitionQueryFunc func); template void updateItem(ItemID id, std::function func) { @@ -72,6 +73,7 @@ protected: using Update = std::tuple; using TransitionAdd = std::tuple; using TransitionQuery = std::tuple; + using TransitionReApply = ItemID; using SelectionReset = Selection; using Resets = std::vector; @@ -79,6 +81,7 @@ protected: using Updates = std::vector; using TransitionAdds = std::vector; using TransitionQueries = std::vector; + using TransitionReApplies = std::vector; using SelectionResets = std::vector; Resets _resetItems; @@ -86,6 +89,7 @@ protected: Updates _updatedItems; TransitionAdds _addedTransitions; TransitionQueries _queriedTransitions; + TransitionReApplies _reAppliedTransitions; SelectionResets _resetSelections; }; typedef std::queue TransactionQueue; @@ -169,6 +173,7 @@ protected: void removeItems(const Transaction::Removes& transactions); void updateItems(const Transaction::Updates& transactions); void transitionItems(const Transaction::TransitionAdds& transactions); + void reApplyTransitions(const Transaction::TransitionReApplies& transactions); void queryTransitionItems(const Transaction::TransitionQueries& transactions); void collectSubItems(ItemID parentId, ItemIDs& subItems) const; From 22acf1aeaf2e43b768c1b8bd0be97bf14266702d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 21 Jul 2017 13:57:00 +0200 Subject: [PATCH 79/86] Removed unused variable to suppress warning on Mac and Ubuntu --- libraries/render-utils/src/FadeEffect.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/render-utils/src/FadeEffect.cpp b/libraries/render-utils/src/FadeEffect.cpp index 6007315abf..c94fe717f1 100644 --- a/libraries/render-utils/src/FadeEffect.cpp +++ b/libraries/render-utils/src/FadeEffect.cpp @@ -71,7 +71,6 @@ render::ShapePipeline::ItemSetter FadeEffect::getItemStoredSetter() { return [this](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; auto transitionStage = scene->getStage(render::TransitionStage::getName()); auto& transitionState = transitionStage->getTransition(item.getTransitionId()); const auto fadeCategory = FadeJob::transitionToCategory[transitionState.eventType]; From 0415364c0ec68ab1c14ec0027e24ab69cebb0789 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 31 Jul 2017 12:29:11 +0200 Subject: [PATCH 80/86] Removed fade transition on shape entities. Fixed broken custom shaders on shapes --- .../src/RenderableShapeEntityItem.cpp | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 4ab64a67e9..087cf1a0b5 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -19,7 +19,11 @@ #include #include -#include + +//#define USE_FADE_EFFECT +#ifdef USE_FADE_EFFECT +# include +#endif // Sphere entities should fit inside a cube entity of the same size, so a sphere that has dimensions 1x1x1 // is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down. @@ -74,7 +78,17 @@ void RenderableShapeEntityItem::setUserData(const QString& value) { } bool RenderableShapeEntityItem::isTransparent() { +#ifdef USE_FADE_EFFECT return getLocalRenderAlpha() < 1.0f; +#else + if (_procedural && _procedural->isFading()) { + float isFading = Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) < 1.0f; + _procedural->setIsFading(isFading); + return isFading; + } else { + return getLocalRenderAlpha() < 1.0f || EntityItem::isTransparent(); + } +#endif } namespace render { @@ -92,7 +106,10 @@ namespace render { } template <> const ShapeKey shapeGetShapeKey(const ShapePayload::Pointer& payload) { - auto shapeKey = ShapeKey::Builder().withCustom(GeometryCache::CUSTOM_PIPELINE_NUMBER); + auto shapeKey = ShapeKey::Builder(); +#ifdef USE_FADE_EFFECT + shapeKey.withCustom(GeometryCache::CUSTOM_PIPELINE_NUMBER); +#endif auto entity = payload->_entity; if (entity->getLocalRenderAlpha() < 1.f) { shapeKey.withTranslucent(); @@ -112,8 +129,9 @@ bool RenderableShapeEntityItem::addToScene(const EntityItemPointer& self, const renderPayload->addStatusGetters(statusGetters); transaction.resetItem(_myItem, renderPayload); +#ifdef USE_FADE_EFFECT transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); - +#endif return true; } @@ -121,6 +139,9 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); //Q_ASSERT(getType() == EntityTypes::Shape); Q_ASSERT(args->_batch); +#ifndef USE_FADE_EFFECT + checkFading(); +#endif if (!_procedural) { _procedural.reset(new Procedural(getUserData())); @@ -148,6 +169,9 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { if (_procedural->ready()) { _procedural->prepare(batch, getPosition(), getDimensions(), getOrientation()); auto outColor = _procedural->getColor(color); +#ifndef USE_FADE_EFFECT + outColor.a *= _procedural->isFading() ? Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) : 1.0f; +#endif batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { DependencyManager::get()->renderWireShape(batch, MAPPING[_shape]); @@ -157,6 +181,7 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { } else { // FIXME, support instanced multi-shape rendering using multidraw indirect auto geometryCache = DependencyManager::get(); +#ifdef USE_FADE_EFFECT auto shapeKey = render::ShapeKey(args->_itemShapeKey); assert(args->_shapePipeline != nullptr); @@ -185,6 +210,16 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { geometryCache->renderSolidShapeInstance(args, batch, MAPPING[_shape], color, args->_shapePipeline); } } +#else + color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; + auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); + if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { + geometryCache->renderWireShapeInstance(args, batch, MAPPING[_shape], color, pipeline); + } + else { + geometryCache->renderSolidShapeInstance(args, batch, MAPPING[_shape], color, pipeline); + } +#endif } static const auto triCount = DependencyManager::get()->getShapeTriangleCount(MAPPING[_shape]); From 027c82c341111aa75167cc5287166226c7908b62 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 31 Jul 2017 12:44:23 +0200 Subject: [PATCH 81/86] Removed fade transition on polyline entities. --- .../src/RenderablePolyLineEntityItem.cpp | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 54bdd9d9f5..0071a03d51 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -16,7 +16,11 @@ #include #include #include -#include + +//#define USE_FADE_EFFECT +#ifdef USE_FADE_EFFECT +# include +#endif #include "RenderablePolyLineEntityItem.h" @@ -38,19 +42,21 @@ render::ShapePipelinePointer PolyLinePayload::shapePipelineFactory(const render: if (!_pipeline) { auto VS = gpu::Shader::createVertex(std::string(paintStroke_vert)); auto PS = gpu::Shader::createPixel(std::string(paintStroke_frag)); + gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS); +#ifdef USE_FADE_EFFECT auto fadeVS = gpu::Shader::createVertex(std::string(paintStroke_fade_vert)); auto fadePS = gpu::Shader::createPixel(std::string(paintStroke_fade_frag)); - gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS); gpu::ShaderPointer fadeProgram = gpu::Shader::createProgram(fadeVS, fadePS); - +#endif gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), PAINTSTROKE_TEXTURE_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("polyLineBuffer"), PAINTSTROKE_UNIFORM_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); +#ifdef USE_FADE_EFFECT slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), PAINTSTROKE_TEXTURE_SLOT + 1)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), PAINTSTROKE_UNIFORM_SLOT+1)); gpu::Shader::makeProgram(*fadeProgram, slotBindings); - +#endif gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(true, true, gpu::LESS_EQUAL); PrepareStencil::testMask(*state); @@ -58,15 +64,21 @@ render::ShapePipelinePointer PolyLinePayload::shapePipelineFactory(const render: gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); _pipeline = gpu::Pipeline::create(program, state); +#ifdef USE_FADE_EFFECT _fadePipeline = gpu::Pipeline::create(fadeProgram, state); +#endif } +#ifdef USE_FADE_EFFECT if (key.isFaded()) { auto fadeEffect = DependencyManager::get(); return std::make_shared(_fadePipeline, nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); } else { +#endif return std::make_shared(_pipeline, nullptr, nullptr, nullptr); +#ifdef USE_FADE_EFFECT } +#endif } namespace render { @@ -236,13 +248,18 @@ bool RenderablePolyLineEntityItem::addToScene(const EntityItemPointer& self, renderPayload->addStatusGetters(statusGetters); transaction.resetItem(_myItem, renderPayload); +#ifdef USE_FADE_EFFECT transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); +#endif updateMesh(); return true; } void RenderablePolyLineEntityItem::render(RenderArgs* args) { +#ifndef USE_FADE_EFFECT + checkFading(); +#endif if (_empty) { return; } @@ -278,5 +295,14 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) { batch.setInputFormat(_format); batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride); +#ifndef USE_FADE_EFFECT + if (_isFading) { + batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime)); + } + else { + batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + } +#endif + batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0); -}; +} From e7282c67e628ab33fb2fe88533a9a1082823be5b Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 31 Jul 2017 13:02:42 +0200 Subject: [PATCH 82/86] Removed fade transition on poly voxel entities. --- .../src/RenderablePolyVoxEntityItem.cpp | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 0cda844905..3d6795ab8a 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -20,7 +20,10 @@ #include #include "ModelScriptingInterface.h" -#include +//#define USE_FADE_EFFECT +#ifdef USE_FADE_EFFECT +# include +#endif #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -57,8 +60,8 @@ #include "EntityTreeRenderer.h" #include "polyvox_vert.h" -#include "polyvox_fade_vert.h" #include "polyvox_frag.h" +#include "polyvox_fade_vert.h" #include "polyvox_fade_frag.h" #include "RenderablePolyVoxEntityItem.h" @@ -809,10 +812,12 @@ bool RenderablePolyVoxEntityItem::addToScene(const EntityItemPointer& self, renderPayload->addStatusGetters(statusGetters); transaction.resetItem(_myItem, renderPayload); +#ifdef USE_FADE_EFFECT if (_mesh && _mesh->getIndexBuffer()._buffer) { transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); _hasTransitioned = true; } +#endif return true; } @@ -839,7 +844,9 @@ render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render:: slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0)); slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2)); +#ifdef USE_FADE_EFFECT slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), 3)); +#endif auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); @@ -862,6 +869,7 @@ render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render:: } } +#ifdef USE_FADE_EFFECT if (key.isFaded()) { const auto& fadeEffect = DependencyManager::get(); if (key.isWireframe()) { @@ -870,15 +878,17 @@ render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render:: else { return std::make_shared(_pipelines[1], nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); } - } - else { + } else { +#endif if (key.isWireframe()) { return std::make_shared(_wireframePipelines[0], nullptr, nullptr, nullptr); } else { return std::make_shared(_pipelines[0], nullptr, nullptr, nullptr); } +#ifdef USE_FADE_EFFECT } +#endif } namespace render { @@ -1394,6 +1404,7 @@ void RenderablePolyVoxEntityItem::setMesh(model::MeshPointer mesh) { bonkNeighbors(); } +#ifdef USE_FADE_EFFECT if (!_hasTransitioned) { render::Transaction transaction; render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); @@ -1401,6 +1412,7 @@ void RenderablePolyVoxEntityItem::setMesh(model::MeshPointer mesh) { scene->enqueueTransaction(transaction); _hasTransitioned = true; } +#endif } void RenderablePolyVoxEntityItem::computeShapeInfoWorker() { From 1336582c6b36008cd5679ad39791b1f01dfac283 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 31 Jul 2017 15:06:24 +0200 Subject: [PATCH 83/86] Removed fade transition on model entities. --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index eaa73e8c4b..d6f3ae3f5d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -32,6 +32,8 @@ #include "RenderableModelEntityItem.h" #include "RenderableEntityItem.h" +//#define USE_FADE_EFFECT + static CollisionRenderMeshCache collisionMeshCache; @@ -244,11 +246,12 @@ bool RenderableModelEntityItem::addToScene(const EntityItemPointer& self, const // note: we don't mind if the model fails to add, we'll retry (in render()) until it succeeds _model->addToScene(scene, transaction, statusGetters); - +#ifdef USE_FADE_EFFECT if (!_hasTransitioned) { transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); _hasTransitioned = true; } +#endif } // we've successfully added _myMetaItem so we always return true @@ -483,11 +486,12 @@ void RenderableModelEntityItem::render(RenderArgs* args) { makeEntityItemStatusGetters(getThisPointer(), statusGetters); _model->addToScene(scene, transaction, statusGetters); +#ifdef USE_FADE_EFFECT if (!_hasTransitioned) { transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); _hasTransitioned = true; } - +#endif scene->enqueueTransaction(transaction); } From 8a2fd01e814d9017d13d3580dcf745f462f101df Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 31 Jul 2017 15:31:37 +0200 Subject: [PATCH 84/86] Added check on EntityItem::getEntitiesShouldFadeFunction and reactivated fade on model, voxels and polylines --- .../src/RenderableModelEntityItem.cpp | 10 +++++++--- .../src/RenderablePolyLineEntityItem.cpp | 6 ++++-- .../src/RenderablePolyVoxEntityItem.cpp | 10 +++++++--- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index d6f3ae3f5d..326f069f97 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -32,7 +32,7 @@ #include "RenderableModelEntityItem.h" #include "RenderableEntityItem.h" -//#define USE_FADE_EFFECT +#define USE_FADE_EFFECT static CollisionRenderMeshCache collisionMeshCache; @@ -248,7 +248,9 @@ bool RenderableModelEntityItem::addToScene(const EntityItemPointer& self, const _model->addToScene(scene, transaction, statusGetters); #ifdef USE_FADE_EFFECT if (!_hasTransitioned) { - transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); + if (EntityItem::getEntitiesShouldFadeFunction()()) { + transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); + } _hasTransitioned = true; } #endif @@ -488,7 +490,9 @@ void RenderableModelEntityItem::render(RenderArgs* args) { #ifdef USE_FADE_EFFECT if (!_hasTransitioned) { - transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); + if (EntityItem::getEntitiesShouldFadeFunction()()) { + transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); + } _hasTransitioned = true; } #endif diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 0071a03d51..5a79213219 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -17,7 +17,7 @@ #include #include -//#define USE_FADE_EFFECT +#define USE_FADE_EFFECT #ifdef USE_FADE_EFFECT # include #endif @@ -249,7 +249,9 @@ bool RenderablePolyLineEntityItem::addToScene(const EntityItemPointer& self, transaction.resetItem(_myItem, renderPayload); #ifdef USE_FADE_EFFECT - transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); + if (EntityItem::getEntitiesShouldFadeFunction()()) { + transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); + } #endif updateMesh(); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 3d6795ab8a..82ec57a136 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -20,7 +20,7 @@ #include #include "ModelScriptingInterface.h" -//#define USE_FADE_EFFECT +#define USE_FADE_EFFECT #ifdef USE_FADE_EFFECT # include #endif @@ -814,7 +814,9 @@ bool RenderablePolyVoxEntityItem::addToScene(const EntityItemPointer& self, transaction.resetItem(_myItem, renderPayload); #ifdef USE_FADE_EFFECT if (_mesh && _mesh->getIndexBuffer()._buffer) { - transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); + if (EntityItem::getEntitiesShouldFadeFunction()()) { + transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); + } _hasTransitioned = true; } #endif @@ -1408,7 +1410,9 @@ void RenderablePolyVoxEntityItem::setMesh(model::MeshPointer mesh) { if (!_hasTransitioned) { render::Transaction transaction; render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); + if (EntityItem::getEntitiesShouldFadeFunction()()) { + transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); + } scene->enqueueTransaction(transaction); _hasTransitioned = true; } From 5f1d45d4decfe98cae2a40f5f9df06731f2d2ca7 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 31 Jul 2017 18:06:51 +0200 Subject: [PATCH 85/86] Revert "Added check on EntityItem::getEntitiesShouldFadeFunction and reactivated fade on model, voxels and polylines" This reverts commit 8a2fd01e814d9017d13d3580dcf745f462f101df. --- .../src/RenderableModelEntityItem.cpp | 10 +++------- .../src/RenderablePolyLineEntityItem.cpp | 6 ++---- .../src/RenderablePolyVoxEntityItem.cpp | 10 +++------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 326f069f97..d6f3ae3f5d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -32,7 +32,7 @@ #include "RenderableModelEntityItem.h" #include "RenderableEntityItem.h" -#define USE_FADE_EFFECT +//#define USE_FADE_EFFECT static CollisionRenderMeshCache collisionMeshCache; @@ -248,9 +248,7 @@ bool RenderableModelEntityItem::addToScene(const EntityItemPointer& self, const _model->addToScene(scene, transaction, statusGetters); #ifdef USE_FADE_EFFECT if (!_hasTransitioned) { - if (EntityItem::getEntitiesShouldFadeFunction()()) { - transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); - } + transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); _hasTransitioned = true; } #endif @@ -490,9 +488,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { #ifdef USE_FADE_EFFECT if (!_hasTransitioned) { - if (EntityItem::getEntitiesShouldFadeFunction()()) { - transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); - } + transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); _hasTransitioned = true; } #endif diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 5a79213219..0071a03d51 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -17,7 +17,7 @@ #include #include -#define USE_FADE_EFFECT +//#define USE_FADE_EFFECT #ifdef USE_FADE_EFFECT # include #endif @@ -249,9 +249,7 @@ bool RenderablePolyLineEntityItem::addToScene(const EntityItemPointer& self, transaction.resetItem(_myItem, renderPayload); #ifdef USE_FADE_EFFECT - if (EntityItem::getEntitiesShouldFadeFunction()()) { - transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); - } + transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); #endif updateMesh(); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 82ec57a136..3d6795ab8a 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -20,7 +20,7 @@ #include #include "ModelScriptingInterface.h" -#define USE_FADE_EFFECT +//#define USE_FADE_EFFECT #ifdef USE_FADE_EFFECT # include #endif @@ -814,9 +814,7 @@ bool RenderablePolyVoxEntityItem::addToScene(const EntityItemPointer& self, transaction.resetItem(_myItem, renderPayload); #ifdef USE_FADE_EFFECT if (_mesh && _mesh->getIndexBuffer()._buffer) { - if (EntityItem::getEntitiesShouldFadeFunction()()) { - transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); - } + transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); _hasTransitioned = true; } #endif @@ -1410,9 +1408,7 @@ void RenderablePolyVoxEntityItem::setMesh(model::MeshPointer mesh) { if (!_hasTransitioned) { render::Transaction transaction; render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - if (EntityItem::getEntitiesShouldFadeFunction()()) { - transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); - } + transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); scene->enqueueTransaction(transaction); _hasTransitioned = true; } From e85bb6fd0841f3fe4185b196ca1498f4594f461d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 31 Jul 2017 19:19:00 +0200 Subject: [PATCH 86/86] Fixed compilation warnings on Mac --- .../src/RenderableModelEntityItem.cpp | 6 ++---- .../src/RenderableModelEntityItem.h | 5 ++++- .../src/RenderablePolyLineEntityItem.cpp | 20 +++++++++---------- .../src/RenderablePolyVoxEntityItem.cpp | 13 ++++++------ .../src/RenderablePolyVoxEntityItem.h | 5 ++++- .../src/RenderableShapeEntityItem.cpp | 16 +++++++-------- 6 files changed, 34 insertions(+), 31 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index d6f3ae3f5d..4217675cac 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -32,8 +32,6 @@ #include "RenderableModelEntityItem.h" #include "RenderableEntityItem.h" -//#define USE_FADE_EFFECT - static CollisionRenderMeshCache collisionMeshCache; @@ -246,7 +244,7 @@ bool RenderableModelEntityItem::addToScene(const EntityItemPointer& self, const // note: we don't mind if the model fails to add, we'll retry (in render()) until it succeeds _model->addToScene(scene, transaction, statusGetters); -#ifdef USE_FADE_EFFECT +#ifdef MODEL_ENTITY_USE_FADE_EFFECT if (!_hasTransitioned) { transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); _hasTransitioned = true; @@ -486,7 +484,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { makeEntityItemStatusGetters(getThisPointer(), statusGetters); _model->addToScene(scene, transaction, statusGetters); -#ifdef USE_FADE_EFFECT +#ifdef MODEL_ENTITY_USE_FADE_EFFECT if (!_hasTransitioned) { transaction.addTransitionToItem(_myMetaItem, render::Transition::ELEMENT_ENTER_DOMAIN); _hasTransitioned = true; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index eb7444ed06..63c212891f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -22,6 +22,8 @@ class Model; class EntityTreeRenderer; +//#define MODEL_ENTITY_USE_FADE_EFFECT + class RenderableModelEntityItem : public ModelEntityItem, RenderableEntityInterface { public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); @@ -134,8 +136,9 @@ private: QVariantMap _originalTextures; bool _originalTexturesRead = false; bool _dimensionsInitialized = true; +#ifdef MODEL_ENTITY_USE_FADE_EFFECT bool _hasTransitioned{ false }; - +#endif AnimationPropertyGroup _renderAnimationProperties; render::ItemID _myMetaItem{ render::Item::INVALID_ITEM_ID }; diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 0071a03d51..86c547dd2d 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -17,8 +17,8 @@ #include #include -//#define USE_FADE_EFFECT -#ifdef USE_FADE_EFFECT +//#define POLYLINE_ENTITY_USE_FADE_EFFECT +#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT # include #endif @@ -43,7 +43,7 @@ render::ShapePipelinePointer PolyLinePayload::shapePipelineFactory(const render: auto VS = gpu::Shader::createVertex(std::string(paintStroke_vert)); auto PS = gpu::Shader::createPixel(std::string(paintStroke_frag)); gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS); -#ifdef USE_FADE_EFFECT +#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT auto fadeVS = gpu::Shader::createVertex(std::string(paintStroke_fade_vert)); auto fadePS = gpu::Shader::createPixel(std::string(paintStroke_fade_frag)); gpu::ShaderPointer fadeProgram = gpu::Shader::createProgram(fadeVS, fadePS); @@ -52,7 +52,7 @@ render::ShapePipelinePointer PolyLinePayload::shapePipelineFactory(const render: slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), PAINTSTROKE_TEXTURE_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("polyLineBuffer"), PAINTSTROKE_UNIFORM_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); -#ifdef USE_FADE_EFFECT +#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), PAINTSTROKE_TEXTURE_SLOT + 1)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), PAINTSTROKE_UNIFORM_SLOT+1)); gpu::Shader::makeProgram(*fadeProgram, slotBindings); @@ -64,19 +64,19 @@ render::ShapePipelinePointer PolyLinePayload::shapePipelineFactory(const render: gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); _pipeline = gpu::Pipeline::create(program, state); -#ifdef USE_FADE_EFFECT +#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT _fadePipeline = gpu::Pipeline::create(fadeProgram, state); #endif } -#ifdef USE_FADE_EFFECT +#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT if (key.isFaded()) { auto fadeEffect = DependencyManager::get(); return std::make_shared(_fadePipeline, nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); } else { #endif return std::make_shared(_pipeline, nullptr, nullptr, nullptr); -#ifdef USE_FADE_EFFECT +#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT } #endif } @@ -248,7 +248,7 @@ bool RenderablePolyLineEntityItem::addToScene(const EntityItemPointer& self, renderPayload->addStatusGetters(statusGetters); transaction.resetItem(_myItem, renderPayload); -#ifdef USE_FADE_EFFECT +#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); #endif updateMesh(); @@ -257,7 +257,7 @@ bool RenderablePolyLineEntityItem::addToScene(const EntityItemPointer& self, } void RenderablePolyLineEntityItem::render(RenderArgs* args) { -#ifndef USE_FADE_EFFECT +#ifndef POLYLINE_ENTITY_USE_FADE_EFFECT checkFading(); #endif if (_empty) { @@ -295,7 +295,7 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) { batch.setInputFormat(_format); batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride); -#ifndef USE_FADE_EFFECT +#ifndef POLYLINE_ENTITY_USE_FADE_EFFECT if (_isFading) { batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime)); } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 3d6795ab8a..566a7cd488 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -20,8 +20,7 @@ #include #include "ModelScriptingInterface.h" -//#define USE_FADE_EFFECT -#ifdef USE_FADE_EFFECT +#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT # include #endif @@ -812,7 +811,7 @@ bool RenderablePolyVoxEntityItem::addToScene(const EntityItemPointer& self, renderPayload->addStatusGetters(statusGetters); transaction.resetItem(_myItem, renderPayload); -#ifdef USE_FADE_EFFECT +#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT if (_mesh && _mesh->getIndexBuffer()._buffer) { transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); _hasTransitioned = true; @@ -844,7 +843,7 @@ render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render:: slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0)); slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2)); -#ifdef USE_FADE_EFFECT +#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), 3)); #endif @@ -869,7 +868,7 @@ render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render:: } } -#ifdef USE_FADE_EFFECT +#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT if (key.isFaded()) { const auto& fadeEffect = DependencyManager::get(); if (key.isWireframe()) { @@ -886,7 +885,7 @@ render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render:: else { return std::make_shared(_pipelines[0], nullptr, nullptr, nullptr); } -#ifdef USE_FADE_EFFECT +#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT } #endif } @@ -1404,7 +1403,7 @@ void RenderablePolyVoxEntityItem::setMesh(model::MeshPointer mesh) { bonkNeighbors(); } -#ifdef USE_FADE_EFFECT +#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT if (!_hasTransitioned) { render::Transaction transaction; render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 5cb9527281..5741931ea2 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -26,6 +26,8 @@ #include "RenderableEntityItem.h" +//#define POLYVOX_ENTITY_USE_FADE_EFFECT + class PolyVoxPayload { public: @@ -177,8 +179,9 @@ private: gpu::Stream::FormatPointer _vertexFormat; bool _meshDirty { true }; // does collision-shape need to be recomputed? bool _meshReady { false }; +#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT bool _hasTransitioned{ false }; - +#endif NetworkTexturePointer _xTexture; NetworkTexturePointer _yTexture; NetworkTexturePointer _zTexture; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 087cf1a0b5..3123c1fc84 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -20,8 +20,8 @@ #include #include -//#define USE_FADE_EFFECT -#ifdef USE_FADE_EFFECT +//#define SHAPE_ENTITY_USE_FADE_EFFECT +#ifdef SHAPE_ENTITY_USE_FADE_EFFECT # include #endif @@ -78,7 +78,7 @@ void RenderableShapeEntityItem::setUserData(const QString& value) { } bool RenderableShapeEntityItem::isTransparent() { -#ifdef USE_FADE_EFFECT +#ifdef SHAPE_ENTITY_USE_FADE_EFFECT return getLocalRenderAlpha() < 1.0f; #else if (_procedural && _procedural->isFading()) { @@ -107,7 +107,7 @@ namespace render { template <> const ShapeKey shapeGetShapeKey(const ShapePayload::Pointer& payload) { auto shapeKey = ShapeKey::Builder(); -#ifdef USE_FADE_EFFECT +#ifdef SHAPE_ENTITY_USE_FADE_EFFECT shapeKey.withCustom(GeometryCache::CUSTOM_PIPELINE_NUMBER); #endif auto entity = payload->_entity; @@ -129,7 +129,7 @@ bool RenderableShapeEntityItem::addToScene(const EntityItemPointer& self, const renderPayload->addStatusGetters(statusGetters); transaction.resetItem(_myItem, renderPayload); -#ifdef USE_FADE_EFFECT +#ifdef SHAPE_ENTITY_USE_FADE_EFFECT transaction.addTransitionToItem(_myItem, render::Transition::ELEMENT_ENTER_DOMAIN); #endif return true; @@ -139,7 +139,7 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); //Q_ASSERT(getType() == EntityTypes::Shape); Q_ASSERT(args->_batch); -#ifndef USE_FADE_EFFECT +#ifndef SHAPE_ENTITY_USE_FADE_EFFECT checkFading(); #endif @@ -169,7 +169,7 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { if (_procedural->ready()) { _procedural->prepare(batch, getPosition(), getDimensions(), getOrientation()); auto outColor = _procedural->getColor(color); -#ifndef USE_FADE_EFFECT +#ifndef SHAPE_ENTITY_USE_FADE_EFFECT outColor.a *= _procedural->isFading() ? Interpolate::calculateFadeRatio(_procedural->getFadeStartTime()) : 1.0f; #endif batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); @@ -181,7 +181,7 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { } else { // FIXME, support instanced multi-shape rendering using multidraw indirect auto geometryCache = DependencyManager::get(); -#ifdef USE_FADE_EFFECT +#ifdef SHAPE_ENTITY_USE_FADE_EFFECT auto shapeKey = render::ShapeKey(args->_itemShapeKey); assert(args->_shapePipeline != nullptr);