diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index c9b3449cec..4abd561dc5 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -188,7 +188,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { { // lock the hash for read to check the size QReadLocker lock(&_hashLock); - if (_avatarHash.size() < 2 && _avatarsToFade.isEmpty()) { + if (_avatarHash.size() < 2 && _avatarsToFadeOut.isEmpty()) { return; } } @@ -346,23 +346,23 @@ void AvatarManager::sendIdentityRequest(const QUuid& avatarID) const { } void AvatarManager::simulateAvatarFades(float deltaTime) { - if (_avatarsToFade.empty()) { + if (_avatarsToFadeOut.empty()) { return; } QReadLocker locker(&_hashLock); - QVector::iterator avatarItr = _avatarsToFade.begin(); + QVector::iterator avatarItr = _avatarsToFadeOut.begin(); const render::ScenePointer& scene = qApp->getMain3DScene(); render::Transaction transaction; - while (avatarItr != _avatarsToFade.end()) { + while (avatarItr != _avatarsToFadeOut.end()) { auto avatar = std::static_pointer_cast(*avatarItr); - avatar->updateFadingStatus(scene); + avatar->updateFadingStatus(); if (!avatar->isFading()) { // fading to zero is such a rare event we push a unique transaction for each if (avatar->isInScene()) { avatar->removeFromScene(*avatarItr, scene, transaction); } - avatarItr = _avatarsToFade.erase(avatarItr); + avatarItr = _avatarsToFadeOut.erase(avatarItr); } else { ++avatarItr; } @@ -457,7 +457,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar DependencyManager::get()->avatarDisconnected(avatar->getSessionUUID()); avatar->fadeOut(qApp->getMain3DScene(), removalReason); } - _avatarsToFade.push_back(removedAvatar); + _avatarsToFadeOut.push_back(removedAvatar); } void AvatarManager::clearOtherAvatars() { diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 34aa4f2cc0..9d5b02d748 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -222,7 +222,7 @@ private: void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override; - QVector _avatarsToFade; + QVector _avatarsToFadeOut; using SetOfOtherAvatars = std::set; SetOfOtherAvatars _avatarsToChangeInPhysics; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a7c8c3e179..38df7b9b06 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -857,6 +857,8 @@ void MyAvatar::simulate(float deltaTime) { } updateAvatarEntities(); + + updateFadingStatus(); } // As far as I know no HMD system supports a play area of a kilometer in radius. diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 6770cd7f96..c6e6a5e8ca 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -612,6 +612,8 @@ void Avatar::simulate(float deltaTime, bool inView) { PROFILE_RANGE(simulation, "entities"); updateAvatarEntities(); } + + updateFadingStatus(); } float Avatar::getSimulationRate(const QString& rateName) const { @@ -775,14 +777,15 @@ void Avatar::fade(render::Transaction& transaction, render::Transition::Type typ _isFading = true; } -void Avatar::updateFadingStatus(render::ScenePointer scene) { +void Avatar::updateFadingStatus() { render::Transaction transaction; transaction.queryTransitionOnItem(_renderItemID, [this](render::ItemID id, const render::Transition* transition) { - if (transition == nullptr || transition->isFinished) { + if (!transition || transition->isFinished) { + AbstractViewStateInterface::instance()->getMain3DScene()->resetItemTransition(id); _isFading = false; } }); - scene->enqueueTransaction(transaction); + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); } void Avatar::removeFromScene(AvatarSharedPointer self, const render::ScenePointer& scene, render::Transaction& transaction) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 3f4cf7b8c2..014be23fa5 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -402,7 +402,7 @@ public: void fadeIn(render::ScenePointer scene); void fadeOut(render::ScenePointer scene, KillAvatarReason reason); bool isFading() const { return _isFading; } - void updateFadingStatus(render::ScenePointer scene); + void updateFadingStatus(); // JSDoc is in AvatarData.h. Q_INVOKABLE virtual float getEyeHeight() const override; diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 47347ba135..940aabe2bd 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -85,7 +85,11 @@ float evalFadeGradient(FadeObjectParams params, vec3 position) { } float evalFadeAlpha(FadeObjectParams params, vec3 position) { - return evalFadeGradient(params, position)-params.threshold; + float alpha = evalFadeGradient(params, position)-params.threshold; + if (fadeParameters[params.category]._isInverted != 0) { + alpha = -alpha; + } + return alpha; } void applyFadeClip(FadeObjectParams params, vec3 position) { @@ -96,9 +100,6 @@ void applyFadeClip(FadeObjectParams params, vec3 position) { void applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) { float alpha = evalFadeAlpha(params, position); - if (fadeParameters[params.category]._isInverted!=0) { - alpha = -alpha; - } if (alpha < 0.0) { discard; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 1215c9abea..38c3106af6 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -826,7 +826,7 @@ render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured bool unlit, bool depthBias) { auto fadeEffect = DependencyManager::get(); auto fadeBatchSetter = fadeEffect->getBatchSetter(); - auto fadeItemSetter = fadeEffect->getItemStoredSetter(); + auto fadeItemSetter = fadeEffect->getItemUniformSetter(); 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(gr::Texture::MaterialAlbedo, DependencyManager::get()->getWhiteTexture()); diff --git a/libraries/render-utils/src/HighlightEffect.cpp b/libraries/render-utils/src/HighlightEffect.cpp index 2d4aee7880..176480e35c 100644 --- a/libraries/render-utils/src/HighlightEffect.cpp +++ b/libraries/render-utils/src/HighlightEffect.cpp @@ -22,6 +22,8 @@ #include "GeometryCache.h" #include "CubeProjectedPolygon.h" +#include "FadeEffect.h" + #include "render-utils/ShaderConstants.h" using namespace render; @@ -37,7 +39,7 @@ namespace gr { #define OUTLINE_STENCIL_MASK 1 -extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); +extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter); HighlightResources::HighlightResources() { } @@ -156,7 +158,6 @@ void DrawHighlightMask::run(const render::RenderContextPointer& renderContext, c auto& highlight = highlightStage->getHighlight(highlightId); RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder; // Render full screen outputs = args->_viewport; @@ -177,10 +178,6 @@ void DrawHighlightMask::run(const render::RenderContextPointer& renderContext, c gpu::doInBatch("DrawHighlightMask::run", args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; - auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); - auto maskDeformedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withDeformed()); - auto maskDeformedDQPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withDeformed().withDualQuatSkinned()); - // Setup camera, projection and viewport for all items glm::mat4 projMat; Transform viewMat; @@ -191,38 +188,54 @@ void DrawHighlightMask::run(const render::RenderContextPointer& renderContext, c batch.setProjectionJitter(jitter.x, jitter.y); batch.setViewTransform(viewMat); - std::vector deformedShapeKeys; - std::vector deformedDQShapeKeys; + const std::vector keys = { + ShapeKey::Builder(), ShapeKey::Builder().withFade(), + ShapeKey::Builder().withDeformed(), ShapeKey::Builder().withDeformed().withFade(), + ShapeKey::Builder().withDeformed().withDualQuatSkinned(), ShapeKey::Builder().withDeformed().withDualQuatSkinned().withFade(), + ShapeKey::Builder().withOwnPipeline(), ShapeKey::Builder().withOwnPipeline().withFade() + }; + std::vector> sortedShapeKeys(keys.size()); - // Iterate through all inShapes and render the unskinned - args->_shapePipeline = maskPipeline; - batch.setPipeline(maskPipeline->pipeline); + const int OWN_PIPELINE_INDEX = 6; for (const auto& items : inShapes) { itemBounds.insert(itemBounds.end(), items.second.begin(), items.second.end()); - if (items.first.isDeformed() && items.first.isDualQuatSkinned()) { - deformedDQShapeKeys.push_back(items.first); - } else if (items.first.isDeformed()) { - deformedShapeKeys.push_back(items.first); - } else { - renderItems(renderContext, items.second); + + int index = items.first.hasOwnPipeline() ? OWN_PIPELINE_INDEX : 0; + if (items.first.isDeformed()) { + index += 2; + if (items.first.isDualQuatSkinned()) { + index += 2; + } + } + + if (items.first.isFaded()) { + index += 1; + } + + sortedShapeKeys[index].push_back(items.first); + } + + // Render non-withOwnPipeline things + for (size_t i = 0; i < OWN_PIPELINE_INDEX; i++) { + auto& shapeKeys = sortedShapeKeys[i]; + if (shapeKeys.size() > 0) { + const auto& shapePipeline = _shapePlumber->pickPipeline(args, keys[i]); + args->_shapePipeline = shapePipeline; + for (const auto& key : shapeKeys) { + renderShapes(renderContext, _shapePlumber, inShapes.at(key)); + } } } - // Reiterate to render the skinned - if (deformedShapeKeys.size() > 0) { - args->_shapePipeline = maskDeformedPipeline; - batch.setPipeline(maskDeformedPipeline->pipeline); - for (const auto& key : deformedShapeKeys) { - renderItems(renderContext, inShapes.at(key)); - } - } - - // Reiterate to render the DQ skinned - if (deformedDQShapeKeys.size() > 0) { - args->_shapePipeline = maskDeformedDQPipeline; - batch.setPipeline(maskDeformedDQPipeline->pipeline); - for (const auto& key : deformedDQShapeKeys) { - renderItems(renderContext, inShapes.at(key)); + // Render withOwnPipeline things + for (size_t i = OWN_PIPELINE_INDEX; i < keys.size(); i++) { + auto& shapeKeys = sortedShapeKeys[i]; + if (shapeKeys.size() > 0) { + args->_shapePipeline = nullptr; + for (const auto& key : shapeKeys) { + args->_itemShapeKey = key._flags.to_ulong(); + renderShapes(renderContext, _shapePlumber, inShapes.at(key)); + } } } @@ -502,7 +515,9 @@ void DrawHighlightTask::build(JobModel& task, const render::Varying& inputs, ren state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setColorWriteMask(false, false, false, false); - initZPassPipelines(*shapePlumber, state); + + auto fadeEffect = DependencyManager::get(); + initZPassPipelines(*shapePlumber, state, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); } auto sharedParameters = std::make_shared(); diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 4626264756..98596a3d88 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -40,7 +40,7 @@ namespace gr { void initDeferredPipelines(ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter); void initForwardPipelines(ShapePlumber& plumber); -void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); +void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter); void addPlumberPipeline(ShapePlumber& plumber, const ShapeKey& key, int programId, @@ -364,37 +364,29 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderAr } } -void initZPassPipelines(ShapePlumber& shapePlumber, gpu::StatePointer state) { +void initZPassPipelines(ShapePlumber& shapePlumber, gpu::StatePointer state, const render::ShapePipeline::BatchSetter& extraBatchSetter, const render::ShapePipeline::ItemSetter& itemSetter) { using namespace shader::render_utils::program; - gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(model_shadow); + shapePlumber.addPipeline( ShapeKey::Filter::Builder().withoutDeformed().withoutFade(), - modelProgram, state); - - gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(deformed_model_shadow); - shapePlumber.addPipeline( - ShapeKey::Filter::Builder().withDeformed().withoutDualQuatSkinned().withoutFade(), - skinProgram, state); - - gpu::ShaderPointer modelFadeProgram = gpu::Shader::createProgram(model_shadow_fade); + gpu::Shader::createProgram(model_shadow), state); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withoutDeformed().withFade(), - modelFadeProgram, state); + gpu::Shader::createProgram(model_shadow_fade), state, extraBatchSetter, itemSetter); - gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(deformed_model_shadow_fade); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withDeformed().withoutDualQuatSkinned().withoutFade(), + gpu::Shader::createProgram(deformed_model_shadow), state); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withDeformed().withoutDualQuatSkinned().withFade(), - skinFadeProgram, state); + gpu::Shader::createProgram(deformed_model_shadow_fade), state, extraBatchSetter, itemSetter); - gpu::ShaderPointer skinModelShadowDualQuatProgram = gpu::Shader::createProgram(deformed_model_shadow_dq); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withDeformed().withDualQuatSkinned().withoutFade(), - skinModelShadowDualQuatProgram, state); - - gpu::ShaderPointer skinModelShadowFadeDualQuatProgram = gpu::Shader::createProgram(deformed_model_shadow_fade_dq); + gpu::Shader::createProgram(deformed_model_shadow_dq), state); shapePlumber.addPipeline( ShapeKey::Filter::Builder().withDeformed().withDualQuatSkinned().withFade(), - skinModelShadowFadeDualQuatProgram, state); + gpu::Shader::createProgram(deformed_model_shadow_fade_dq), state, extraBatchSetter, itemSetter); } // FIXME find a better way to setup the default textures diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index c4fa297965..0b6aebadd7 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -26,6 +26,8 @@ #include "RenderCommonTask.h" +#include "FadeEffect.h" + // These values are used for culling the objects rendered in the shadow map // but are readjusted afterwards #define SHADOW_FRUSTUM_NEAR 1.0f @@ -33,7 +35,7 @@ using namespace render; -extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); +extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter); void RenderShadowTask::configure(const Config& configuration) { DependencyManager::get()->setShadowMapEnabled(configuration.enabled); @@ -49,7 +51,8 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende state->setCullMode(gpu::State::CULL_BACK); state->setDepthTest(true, true, gpu::LESS_EQUAL); - initZPassPipelines(*shapePlumber, state); + auto fadeEffect = DependencyManager::get(); + initZPassPipelines(*shapePlumber, state, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); } // FIXME: calling this here before the zones/lights are drawn during the deferred/forward passes means we're actually using the frames from the previous draw @@ -222,7 +225,6 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con auto& fbo = cascade.framebuffer; RenderArgs* args = renderContext->args; - ShapeKey::Builder defaultKeyBuilder; auto adjustedShadowFrustum = args->getViewFrustum(); // Adjust the frustum near and far depths based on the rendered items bounding box to have @@ -253,53 +255,56 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat, false); - auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); - auto shadowDeformedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withDeformed()); - auto shadowDeformedDQPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withDeformed().withDualQuatSkinned()); + const std::vector keys = { + ShapeKey::Builder(), ShapeKey::Builder().withFade(), + ShapeKey::Builder().withDeformed(), ShapeKey::Builder().withDeformed().withFade(), + ShapeKey::Builder().withDeformed().withDualQuatSkinned(), ShapeKey::Builder().withDeformed().withDualQuatSkinned().withFade(), + ShapeKey::Builder().withOwnPipeline(), ShapeKey::Builder().withOwnPipeline().withFade() + }; + std::vector> sortedShapeKeys(keys.size()); - std::vector deformedShapeKeys{}; - std::vector deformedDQShapeKeys{}; - std::vector ownPipelineShapeKeys{}; - - // Iterate through all inShapes and render the unskinned - args->_shapePipeline = shadowPipeline; - batch.setPipeline(shadowPipeline->pipeline); - for (auto items : inShapes) { + const int OWN_PIPELINE_INDEX = 6; + for (const auto& items : inShapes) { + int index = items.first.hasOwnPipeline() ? OWN_PIPELINE_INDEX : 0; if (items.first.isDeformed()) { + index += 2; if (items.first.isDualQuatSkinned()) { - deformedDQShapeKeys.push_back(items.first); - } else { - deformedShapeKeys.push_back(items.first); + index += 2; + } + } + + if (items.first.isFaded()) { + index += 1; + } + + sortedShapeKeys[index].push_back(items.first); + } + + // Render non-withOwnPipeline things + for (size_t i = 0; i < OWN_PIPELINE_INDEX; i++) { + auto& shapeKeys = sortedShapeKeys[i]; + if (shapeKeys.size() > 0) { + const auto& shapePipeline = _shapePlumber->pickPipeline(args, keys[i]); + args->_shapePipeline = shapePipeline; + for (const auto& key : shapeKeys) { + renderShapes(renderContext, _shapePlumber, inShapes.at(key)); } - } else if (!items.first.hasOwnPipeline()) { - renderItems(renderContext, items.second); - } else { - ownPipelineShapeKeys.push_back(items.first); } } - // Reiterate to render the skinned - args->_shapePipeline = shadowDeformedPipeline; - batch.setPipeline(shadowDeformedPipeline->pipeline); - for (const auto& key : deformedShapeKeys) { - renderItems(renderContext, inShapes.at(key)); + // Render withOwnPipeline things + for (size_t i = OWN_PIPELINE_INDEX; i < keys.size(); i++) { + auto& shapeKeys = sortedShapeKeys[i]; + if (shapeKeys.size() > 0) { + args->_shapePipeline = nullptr; + for (const auto& key : shapeKeys) { + args->_itemShapeKey = key._flags.to_ulong(); + renderShapes(renderContext, _shapePlumber, inShapes.at(key)); + } + } } - // Reiterate to render the DQ skinned - args->_shapePipeline = shadowDeformedDQPipeline; - batch.setPipeline(shadowDeformedDQPipeline->pipeline); - for (const auto& key : deformedDQShapeKeys) { - renderItems(renderContext, inShapes.at(key)); - } - - // Finally render the items with their own pipeline last to prevent them from breaking the - // render state. This is probably a temporary code as there is probably something better - // to do in the render call of objects that have their own pipeline. args->_shapePipeline = nullptr; - for (const auto& key : ownPipelineShapeKeys) { - args->_itemShapeKey = key._flags.to_ulong(); - renderItems(renderContext, inShapes.at(key)); - } } args->_batch = nullptr;