First working fade

This commit is contained in:
Olivier Prat 2017-07-10 15:27:09 +02:00
parent 06d69d04c3
commit 267531cc1a
9 changed files with 221 additions and 87 deletions

View file

@ -61,7 +61,7 @@ namespace render {
template <> uint32_t metaFetchMetaSubItems(const AvatarSharedPointer& avatar, ItemIDs& subItems) { template <> uint32_t metaFetchMetaSubItems(const AvatarSharedPointer& avatar, ItemIDs& subItems) {
auto avatarPtr = static_pointer_cast<Avatar>(avatar); auto avatarPtr = static_pointer_cast<Avatar>(avatar);
if (avatarPtr->getSkeletonModel()) { if (avatarPtr->getSkeletonModel()) {
auto metaSubItems = avatarPtr->getSkeletonModel()->fetchRenderItemIDs(); auto& metaSubItems = avatarPtr->getSkeletonModel()->fetchRenderItemIDs();
subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end()); subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end());
return (uint32_t) metaSubItems.size(); return (uint32_t) metaSubItems.size();
} }

View file

@ -217,8 +217,9 @@ namespace render {
} }
template <> uint32_t metaFetchMetaSubItems(const RenderableModelEntityItemMeta::Pointer& payload, ItemIDs& subItems) { template <> uint32_t metaFetchMetaSubItems(const RenderableModelEntityItemMeta::Pointer& payload, ItemIDs& subItems) {
auto modelEntity = std::static_pointer_cast<RenderableModelEntityItem>(payload->entity); auto modelEntity = std::static_pointer_cast<RenderableModelEntityItem>(payload->entity);
if (modelEntity->hasModel()) { auto model = modelEntity->getModelNotSafe();
auto metaSubItems = modelEntity->getModelNotSafe()->fetchRenderItemIDs(); if (modelEntity->hasModel() && model) {
auto& metaSubItems = model->fetchRenderItemIDs();
subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end()); subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end());
return (uint32_t) metaSubItems.size(); return (uint32_t) metaSubItems.size();
} }
@ -489,6 +490,17 @@ ModelPointer RenderableModelEntityItem::getModelNotSafe() {
return _model; 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() { ModelPointer RenderableModelEntityItem::getModel() {
// make sure our renderer is setup // make sure our renderer is setup
if (!_myRenderer) { if (!_myRenderer) {
@ -506,6 +518,7 @@ ModelPointer RenderableModelEntityItem::getModel() {
// If we don't have a model, allocate one *immediately* // If we don't have a model, allocate one *immediately*
if (!_model) { if (!_model) {
_model = _myRenderer->allocateModel(getModelURL(), _myRenderer->getEntityLoadingPriority(*this), this); _model = _myRenderer->allocateModel(getModelURL(), _myRenderer->getEntityLoadingPriority(*this), this);
QObject::connect(_model.get(), &Model::setURLFinished, this, &RenderableModelEntityItem::setModelURLFinished);
_needsInitialSimulation = true; _needsInitialSimulation = true;
// If we need to change URLs, update it *after rendering* (to avoid access violations) // If we need to change URLs, update it *after rendering* (to avoid access violations)
} else if (QUrl(getModelURL()) != _model->getURL()) { } else if (QUrl(getModelURL()) != _model->getURL()) {

View file

@ -12,16 +12,21 @@
#ifndef hifi_RenderableModelEntityItem_h #ifndef hifi_RenderableModelEntityItem_h
#define hifi_RenderableModelEntityItem_h #define hifi_RenderableModelEntityItem_h
#include <QObject>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <ModelEntityItem.h> #include <ModelEntityItem.h>
#include <AnimationCache.h> #include <AnimationCache.h>
#include <model-networking\ModelCache.h>
#include "RenderableEntityItem.h"
class Model; class Model;
class EntityTreeRenderer; class EntityTreeRenderer;
class RenderableModelEntityItem : public ModelEntityItem, RenderableEntityInterface { class RenderableModelEntityItem : public QObject, public ModelEntityItem, RenderableEntityInterface {
Q_OBJECT
public: public:
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
@ -116,6 +121,10 @@ public:
return _animation; return _animation;
} }
public slots:
void setModelURLFinished(bool success);
private: private:
QVariantMap parseTexturesToMap(QString textures); QVariantMap parseTexturesToMap(QString textures);
void remapTextures(); void remapTextures();

View file

@ -464,6 +464,7 @@ FadeJob::FadeJob()
{ {
auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png"; auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png";
_fadeMaskMap = DependencyManager::get<TextureCache>()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); _fadeMaskMap = DependencyManager::get<TextureCache>()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE);
_previousTime = usecTimestampNow();
} }
void FadeJob::configure(const Config& config) { void FadeJob::configure(const Config& config) {
@ -493,76 +494,91 @@ void FadeJob::run(const render::RenderContextPointer& renderContext) {
auto transitionStage = scene->getStage<render::TransitionStage>(render::TransitionStage::getName()); auto transitionStage = scene->getStage<render::TransitionStage>(render::TransitionStage::getName());
uint64_t now = usecTimestampNow(); uint64_t now = usecTimestampNow();
const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND); const double deltaTime = (int64_t(now) - int64_t(_previousTime)) / double(USECS_PER_SECOND);
render::Transaction transaction;
bool hasTransactions = false;
// And now update fade effect // And now update fade effect
for (auto transitionId : *transitionStage) { for (auto transitionId : *transitionStage) {
auto& state = transitionStage->editTransition(transitionId); 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; _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& eventConfig = config.events[transition.eventType];
auto& item = scene->getItem(transition.itemId); auto& item = scene->getItem(transition.itemId);
auto& aabb = item.getBound();
auto& dimensions = aabb.getDimensions();
const double eventDuration = (double)eventConfig.duration; const double eventDuration = (double)eventConfig.duration;
const FadeConfig::Timing timing = (FadeConfig::Timing) eventConfig.timing; 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) { assert(timing < render::Transition::EVENT_CATEGORY_COUNT);
case render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN:
transition.threshold = 1.f - computeElementEnterThreshold(transition.time, eventConfig.duration, timing); switch (transition.eventType) {
transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[transition.eventType] + 0.5f; case render::Transition::ELEMENT_ENTER_LEAVE_DOMAIN:
transition.noiseOffset = aabb.calcCenter(); transition.threshold = 1.f - computeElementEnterRatio(transition.time, eventConfig.duration, timing);
transition.baseOffset = transition.noiseOffset - dimensions.y; transition.threshold = (transition.threshold - 0.5f)*_thresholdScale[transition.eventType] + 0.5f;
transition.baseInvSize.x = 1.f / dimensions.x; transition.noiseOffset = aabb.calcCenter();
transition.baseInvSize.y = 1.f / dimensions.y; transition.baseOffset = transition.noiseOffset - dimensions.y;
transition.baseInvSize.z = 1.f / dimensions.z; 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; break;
case render::Transition::BUBBLE_ISECT_OWNER: case render::Transition::BUBBLE_ISECT_TRESPASSER:
{ {
/* const glm::vec3 cameraPos = renderContext->args->getViewFrustum().getPosition(); // _editBaseOffset = glm::vec3{ 0.f, 0.f, 0.f };
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; break;
default: case render::Transition::USER_ENTER_LEAVE_DOMAIN:
assert(false); {
/* _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; transition.time += deltaTime;
// renderContext->jobConfig->setProperty("threshold", threshold); // 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); assert(period > 0.0);
float fadeAlpha = 1.0f; float fadeAlpha = 1.0f;
const double INV_FADE_PERIOD = 1.0 / period; const double INV_FADE_PERIOD = 1.0 / period;

View file

@ -193,8 +193,8 @@ private:
float _thresholdScale[render::Transition::EVENT_CATEGORY_COUNT]; float _thresholdScale[render::Transition::EVENT_CATEGORY_COUNT];
uint64_t _previousTime{ 0 }; 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::Transition& transition, const double deltaTime) const;
float computeElementEnterThreshold(double time, const double period, FadeConfig::Timing timing) 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; const render::Item* findNearestItem(const render::RenderContextPointer& renderContext, const render::Varying& input, float& minIsectDistance) const;
}; };

View file

@ -104,7 +104,8 @@ void initDeferredPipelines(ShapePlumber& plumber, const render::ShapePipeline::B
void initForwardPipelines(ShapePlumber& plumber); void initForwardPipelines(ShapePlumber& plumber);
void addPlumberPipeline(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 batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);
void lightBatchSetter(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)); auto simpleTranslucentUnlitFadePixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_unlit_fade_frag));
using Key = render::ShapeKey; 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 // TODO: Refactor this to use a filter
// Opaques // Opaques
addPipeline( addPipeline(
Key::Builder().withMaterial(), Key::Builder().withMaterial(),
modelVertex, modelPixel); modelVertex, modelPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder(), Key::Builder(),
simpleVertex, simplePixel); simpleVertex, simplePixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withUnlit(), Key::Builder().withMaterial().withUnlit(),
modelVertex, modelUnlitPixel); modelVertex, modelUnlitPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withUnlit(), Key::Builder().withUnlit(),
simpleVertex, simpleUnlitPixel); simpleVertex, simpleUnlitPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withTangents(), Key::Builder().withMaterial().withTangents(),
modelNormalMapVertex, modelNormalMapPixel); modelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withSpecular(), Key::Builder().withMaterial().withSpecular(),
modelVertex, modelSpecularMapPixel); modelVertex, modelSpecularMapPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withTangents().withSpecular(), Key::Builder().withMaterial().withTangents().withSpecular(),
modelNormalMapVertex, modelNormalSpecularMapPixel); modelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr);
// Same thing but with Fade on // Same thing but with Fade on
addPipeline( addPipeline(
Key::Builder().withMaterial().withFade(), Key::Builder().withMaterial().withFade(),
@ -278,29 +279,29 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Translucents // Translucents
addPipeline( addPipeline(
Key::Builder().withMaterial().withTranslucent(), Key::Builder().withMaterial().withTranslucent(),
modelVertex, modelTranslucentPixel); modelVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withTranslucent(), Key::Builder().withTranslucent(),
simpleVertex, simpleTranslucentPixel); simpleVertex, simpleTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withTranslucent().withUnlit(), Key::Builder().withMaterial().withTranslucent().withUnlit(),
modelVertex, modelTranslucentUnlitPixel); modelVertex, modelTranslucentUnlitPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withTranslucent().withUnlit(), Key::Builder().withTranslucent().withUnlit(),
simpleVertex, simpleTranslucentUnlitPixel); simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withTranslucent().withTangents(), Key::Builder().withMaterial().withTranslucent().withTangents(),
modelNormalMapVertex, modelTranslucentPixel); modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withTranslucent().withSpecular(), Key::Builder().withMaterial().withTranslucent().withSpecular(),
modelVertex, modelTranslucentPixel); modelVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(), Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(),
modelNormalMapVertex, modelTranslucentPixel); modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
// FIXME: Ignore lightmap for translucents meshpart // FIXME: Ignore lightmap for translucents meshpart
Key::Builder().withMaterial().withTranslucent().withLightmap(), Key::Builder().withMaterial().withTranslucent().withLightmap(),
modelVertex, modelTranslucentPixel); modelVertex, modelTranslucentPixel, nullptr, nullptr);
// Same thing but with Fade on // Same thing but with Fade on
addPipeline( addPipeline(
Key::Builder().withMaterial().withTranslucent().withFade(), Key::Builder().withMaterial().withTranslucent().withFade(),
@ -331,16 +332,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Lightmapped // Lightmapped
addPipeline( addPipeline(
Key::Builder().withMaterial().withLightmap(), Key::Builder().withMaterial().withLightmap(),
modelLightmapVertex, modelLightmapPixel); modelLightmapVertex, modelLightmapPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withLightmap().withTangents(), Key::Builder().withMaterial().withLightmap().withTangents(),
modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); modelLightmapNormalMapVertex, modelLightmapNormalMapPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withLightmap().withSpecular(), Key::Builder().withMaterial().withLightmap().withSpecular(),
modelLightmapVertex, modelLightmapSpecularMapPixel); modelLightmapVertex, modelLightmapSpecularMapPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withLightmap().withTangents().withSpecular(), Key::Builder().withMaterial().withLightmap().withTangents().withSpecular(),
modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel, nullptr, nullptr);
// Same thing but with Fade on // Same thing but with Fade on
addPipeline( addPipeline(
Key::Builder().withMaterial().withLightmap().withFade(), Key::Builder().withMaterial().withLightmap().withFade(),
@ -358,16 +359,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Skinned // Skinned
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned(), Key::Builder().withMaterial().withSkinned(),
skinModelVertex, modelPixel); skinModelVertex, modelPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTangents(), Key::Builder().withMaterial().withSkinned().withTangents(),
skinModelNormalMapVertex, modelNormalMapPixel); skinModelNormalMapVertex, modelNormalMapPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withSpecular(), Key::Builder().withMaterial().withSkinned().withSpecular(),
skinModelVertex, modelSpecularMapPixel); skinModelVertex, modelSpecularMapPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(), Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(),
skinModelNormalMapVertex, modelNormalSpecularMapPixel); skinModelNormalMapVertex, modelNormalSpecularMapPixel, nullptr, nullptr);
// Same thing but with Fade on // Same thing but with Fade on
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withFade(), Key::Builder().withMaterial().withSkinned().withFade(),
@ -385,16 +386,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Skinned and Translucent // Skinned and Translucent
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent(), Key::Builder().withMaterial().withSkinned().withTranslucent(),
skinModelVertex, modelTranslucentPixel); skinModelVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(),
skinModelNormalMapVertex, modelTranslucentPixel); skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(), Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(),
skinModelVertex, modelTranslucentPixel); skinModelVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(), Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(),
skinModelNormalMapVertex, modelTranslucentPixel); skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr);
// Same thing but with Fade on // Same thing but with Fade on
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(), Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(),
@ -412,10 +413,10 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Depth-only // Depth-only
addPipeline( addPipeline(
Key::Builder().withDepthOnly(), Key::Builder().withDepthOnly(),
modelShadowVertex, modelShadowPixel); modelShadowVertex, modelShadowPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withSkinned().withDepthOnly(), Key::Builder().withSkinned().withDepthOnly(),
skinModelShadowVertex, modelShadowPixel); skinModelShadowVertex, modelShadowPixel, nullptr, nullptr);
// Same thing but with Fade on // Same thing but with Fade on
addPipeline( addPipeline(
Key::Builder().withDepthOnly().withFade(), 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)); auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(forward_model_normal_specular_map_frag));
using Key = render::ShapeKey; 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 // Opaques
addPipeline( addPipeline(
Key::Builder().withMaterial(), Key::Builder().withMaterial(),
@ -473,7 +474,8 @@ void initForwardPipelines(render::ShapePlumber& plumber) {
} }
void addPlumberPipeline(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 // These key-values' pipelines are added by this functor in addition to the key passed
assert(!key.isWireframe()); assert(!key.isWireframe());
assert(!key.isDepthBiased()); assert(!key.isDepthBiased());
@ -510,8 +512,18 @@ void addPlumberPipeline(ShapePlumber& plumber,
state->setDepthBiasSlopeScale(1.0f); state->setDepthBiasSlopeScale(1.0f);
} }
plumber.addPipeline(builder.build(), program, state, auto baseBatchSetter = key.isTranslucent() ? &lightBatchSetter : &batchSetter;
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);
} }
} }

View file

@ -13,6 +13,7 @@
#include <numeric> #include <numeric>
#include <gpu/Batch.h> #include <gpu/Batch.h>
#include "Logging.h" #include "Logging.h"
#include "TransitionStage.h"
using namespace render; using namespace render;
@ -30,6 +31,11 @@ void Transaction::removeItem(ItemID id) {
_removedItems.emplace_back(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) { void Transaction::updateItem(ItemID id, const UpdateFunctorPointer& functor) {
_updatedItems.emplace_back(id); _updatedItems.emplace_back(id);
_updateFunctors.emplace_back(functor); _updateFunctors.emplace_back(functor);
@ -46,6 +52,8 @@ void Transaction::merge(const Transaction& transaction) {
_updatedItems.insert(_updatedItems.end(), transaction._updatedItems.begin(), transaction._updatedItems.end()); _updatedItems.insert(_updatedItems.end(), transaction._updatedItems.begin(), transaction._updatedItems.end());
_updateFunctors.insert(_updateFunctors.end(), transaction._updateFunctors.begin(), transaction._updateFunctors.end()); _updateFunctors.insert(_updateFunctors.end(), transaction._updateFunctors.begin(), transaction._updateFunctors.end());
_resetSelections.insert(_resetSelections.end(), transaction._resetSelections.begin(), transaction._resetSelections.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 // removes
removeItems(consolidatedTransaction._removedItems); removeItems(consolidatedTransaction._removedItems);
// Transitions
transitionItems(consolidatedTransaction._transitioningItems, consolidatedTransaction._transitionTypes);
// Update the numItemsAtomic counter AFTER the pending changes went through // Update the numItemsAtomic counter AFTER the pending changes went through
_numAllocatedItems.exchange(maxID); _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>(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>(TransitionStage::getName());
transitionStage->removeTransition(item.getTransitionId());
setItemTransition(itemId, Transition::NONE);
}
// THis fucntion is thread safe // THis fucntion is thread safe
Selection Scene::getSelection(const Selection::Name& name) const { Selection Scene::getSelection(const Selection::Name& name) const {
std::unique_lock<std::mutex> lock(_selectionsMutex); std::unique_lock<std::mutex> lock(_selectionsMutex);

View file

@ -16,6 +16,7 @@
#include "SpatialTree.h" #include "SpatialTree.h"
#include "Stage.h" #include "Stage.h"
#include "Selection.h" #include "Selection.h"
#include "Transition.h"
namespace render { namespace render {
@ -39,6 +40,8 @@ public:
void resetItem(ItemID id, const PayloadPointer& payload); void resetItem(ItemID id, const PayloadPointer& payload);
void removeItem(ItemID id); void removeItem(ItemID id);
void transitionItem(ItemID id, Transition::Type transition);
template <class T> void updateItem(ItemID id, std::function<void(T&)> func) { template <class T> void updateItem(ItemID id, std::function<void(T&)> func) {
updateItem(id, std::make_shared<UpdateFunctor<T>>(func)); updateItem(id, std::make_shared<UpdateFunctor<T>>(func));
} }
@ -54,10 +57,12 @@ public:
// Checkers if there is work to do when processing the transaction // Checkers if there is work to do when processing the transaction
bool touchTransactions() const { return !_resetSelections.empty(); } bool touchTransactions() const { return !_resetSelections.empty(); }
ItemIDs _resetItems; ItemIDs _resetItems;
Payloads _resetPayloads; Payloads _resetPayloads;
ItemIDs _removedItems; ItemIDs _removedItems;
ItemIDs _updatedItems; ItemIDs _updatedItems;
ItemIDs _transitioningItems;
TransitionTypes _transitionTypes;
UpdateFunctors _updateFunctors; UpdateFunctors _updateFunctors;
Selections _resetSelections; Selections _resetSelections;
@ -123,6 +128,8 @@ public:
} }
void resetStage(const Stage::Name& name, const StagePointer& stage); void resetStage(const Stage::Name& name, const StagePointer& stage);
void setItemTransition(ItemID id, Index transitionId);
void resetItemTransition(ItemID id);
protected: protected:
// Thread safe elements that can be accessed from anywhere // Thread safe elements that can be accessed from anywhere
@ -141,6 +148,9 @@ protected:
void resetItems(const ItemIDs& ids, Payloads& payloads); void resetItems(const ItemIDs& ids, Payloads& payloads);
void removeItems(const ItemIDs& ids); void removeItems(const ItemIDs& ids);
void updateItems(const ItemIDs& ids, UpdateFunctors& functors); 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 // The Selection map
mutable std::mutex _selectionsMutex; // mutable so it can be used in the thread safe getSelection const method mutable std::mutex _selectionsMutex; // mutable so it can be used in the thread safe getSelection const method

View file

@ -27,7 +27,8 @@ namespace render {
AVATAR_CHANGE, AVATAR_CHANGE,
// Don't forget to modify Fade.slh to reflect the change in number of categories // 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 }; Type eventType{ ELEMENT_ENTER_LEAVE_DOMAIN };
@ -41,6 +42,7 @@ namespace render {
}; };
typedef std::shared_ptr<Transition> TransitionPointer; typedef std::shared_ptr<Transition> TransitionPointer;
typedef std::vector<Transition::Type> TransitionTypes;
} }
#endif // hifi_render_Transition_h #endif // hifi_render_Transition_h