mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 21:17:01 +02:00
Merge pull request #15 from kasenvr/feature/sam+domainport
Feature/sam+domainport
This commit is contained in:
commit
d9b202f4da
53 changed files with 777 additions and 348 deletions
|
@ -2107,6 +2107,23 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
EntityTree::setGetUnscaledDimensionsForIDOperator([this](const QUuid& id) {
|
||||||
|
if (_aboutToQuit) {
|
||||||
|
return glm::vec3(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto entity = getEntities()->getEntity(id);
|
||||||
|
if (entity) {
|
||||||
|
return entity->getUnscaledDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto avatarManager = DependencyManager::get<AvatarManager>();
|
||||||
|
auto avatar = static_pointer_cast<Avatar>(avatarManager->getAvatarBySessionID(id));
|
||||||
|
if (avatar) {
|
||||||
|
return avatar->getSNScale();
|
||||||
|
}
|
||||||
|
return glm::vec3(1.0f);
|
||||||
|
});
|
||||||
Procedural::opaqueStencil = [](gpu::StatePointer state) { PrepareStencil::testMaskDrawShape(*state); };
|
Procedural::opaqueStencil = [](gpu::StatePointer state) { PrepareStencil::testMaskDrawShape(*state); };
|
||||||
Procedural::transparentStencil = [](gpu::StatePointer state) { PrepareStencil::testMask(*state); };
|
Procedural::transparentStencil = [](gpu::StatePointer state) { PrepareStencil::testMask(*state); };
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace render {
|
||||||
PerformanceTimer perfTimer("worldBox");
|
PerformanceTimer perfTimer("worldBox");
|
||||||
|
|
||||||
auto& batch = *args->_batch;
|
auto& batch = *args->_batch;
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, false, false, true, args->_renderMethod == Args::RenderMethod::FORWARD);
|
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, false, true, args->_renderMethod == Args::RenderMethod::FORWARD);
|
||||||
WorldBoxRenderData::renderWorldBox(args, batch);
|
WorldBoxRenderData::renderWorldBox(args, batch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -791,7 +791,7 @@ void Avatar::render(RenderArgs* renderArgs) {
|
||||||
pointerTransform.setTranslation(position);
|
pointerTransform.setTranslation(position);
|
||||||
pointerTransform.setRotation(rotation);
|
pointerTransform.setRotation(rotation);
|
||||||
batch.setModelTransform(pointerTransform);
|
batch.setModelTransform(pointerTransform);
|
||||||
geometryCache->bindSimpleProgram(batch, false, false, true, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD);
|
geometryCache->bindSimpleProgram(batch, false, false, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD);
|
||||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _leftPointerGeometryID);
|
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _leftPointerGeometryID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -815,7 +815,7 @@ void Avatar::render(RenderArgs* renderArgs) {
|
||||||
pointerTransform.setTranslation(position);
|
pointerTransform.setTranslation(position);
|
||||||
pointerTransform.setRotation(rotation);
|
pointerTransform.setRotation(rotation);
|
||||||
batch.setModelTransform(pointerTransform);
|
batch.setModelTransform(pointerTransform);
|
||||||
geometryCache->bindSimpleProgram(batch, false, false, true, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD);
|
geometryCache->bindSimpleProgram(batch, false, false, false, false, true, renderArgs->_renderMethod == render::Args::FORWARD);
|
||||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _rightPointerGeometryID);
|
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, laserLength, 0.0f), laserColor, _rightPointerGeometryID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1103,7 +1103,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const
|
||||||
|
|
||||||
{
|
{
|
||||||
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect");
|
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect");
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true, true, forward);
|
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, true, forward);
|
||||||
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
|
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
|
||||||
bevelDistance, backgroundColor, _nameRectGeometryID);
|
bevelDistance, backgroundColor, _nameRectGeometryID);
|
||||||
}
|
}
|
||||||
|
@ -2121,6 +2121,8 @@ void Avatar::updateAttachmentRenderIDs() {
|
||||||
|
|
||||||
void Avatar::updateDescendantRenderIDs() {
|
void Avatar::updateDescendantRenderIDs() {
|
||||||
_subItemLock.withWriteLock([&] {
|
_subItemLock.withWriteLock([&] {
|
||||||
|
auto oldRenderingDescendantEntityIDs = _renderingDescendantEntityIDs;
|
||||||
|
_renderingDescendantEntityIDs.clear();
|
||||||
_descendantRenderIDs.clear();
|
_descendantRenderIDs.clear();
|
||||||
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||||
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
|
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
|
||||||
|
@ -2130,7 +2132,12 @@ void Avatar::updateDescendantRenderIDs() {
|
||||||
if (object && object->getNestableType() == NestableType::Entity) {
|
if (object && object->getNestableType() == NestableType::Entity) {
|
||||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
|
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
|
||||||
if (entity->isVisible()) {
|
if (entity->isVisible()) {
|
||||||
auto renderer = entityTreeRenderer->renderableForEntityId(object->getID());
|
auto id = object->getID();
|
||||||
|
_renderingDescendantEntityIDs.insert(id);
|
||||||
|
oldRenderingDescendantEntityIDs.erase(id);
|
||||||
|
entity->setCullWithParent(true);
|
||||||
|
|
||||||
|
auto renderer = entityTreeRenderer->renderableForEntityId(id);
|
||||||
if (renderer) {
|
if (renderer) {
|
||||||
render::ItemIDs renderableSubItems;
|
render::ItemIDs renderableSubItems;
|
||||||
uint32_t numRenderableSubItems = renderer->metaFetchMetaSubItems(renderableSubItems);
|
uint32_t numRenderableSubItems = renderer->metaFetchMetaSubItems(renderableSubItems);
|
||||||
|
@ -2141,6 +2148,13 @@ void Avatar::updateDescendantRenderIDs() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (auto& oldRenderingDescendantEntityID : oldRenderingDescendantEntityIDs) {
|
||||||
|
auto entity = entityTree->findEntityByEntityItemID(oldRenderingDescendantEntityID);
|
||||||
|
if (entity) {
|
||||||
|
entity->setCullWithParent(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -782,6 +782,7 @@ protected:
|
||||||
render::ItemIDs _attachmentRenderIDs;
|
render::ItemIDs _attachmentRenderIDs;
|
||||||
void updateDescendantRenderIDs();
|
void updateDescendantRenderIDs();
|
||||||
render::ItemIDs _descendantRenderIDs;
|
render::ItemIDs _descendantRenderIDs;
|
||||||
|
std::unordered_set<EntityItemID> _renderingDescendantEntityIDs;
|
||||||
uint32_t _lastAncestorChainRenderableVersion { 0 };
|
uint32_t _lastAncestorChainRenderableVersion { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,8 @@ render::hifi::Layer EntityRenderer::getHifiRenderLayer() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKey EntityRenderer::getKey() {
|
ItemKey EntityRenderer::getKey() {
|
||||||
ItemKey::Builder builder = ItemKey::Builder().withTypeShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
ItemKey::Builder builder =
|
||||||
|
ItemKey::Builder().withTypeShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||||
|
|
||||||
if (isTransparent()) {
|
if (isTransparent()) {
|
||||||
builder.withTransparent();
|
builder.withTransparent();
|
||||||
|
@ -176,6 +177,10 @@ ItemKey EntityRenderer::getKey() {
|
||||||
builder.withShadowCaster();
|
builder.withShadowCaster();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_cullWithParent) {
|
||||||
|
builder.withSubMetaCulled();
|
||||||
|
}
|
||||||
|
|
||||||
if (!_visible) {
|
if (!_visible) {
|
||||||
builder.withInvisible();
|
builder.withInvisible();
|
||||||
}
|
}
|
||||||
|
@ -419,6 +424,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa
|
||||||
setRenderLayer(entity->getRenderLayer());
|
setRenderLayer(entity->getRenderLayer());
|
||||||
setPrimitiveMode(entity->getPrimitiveMode());
|
setPrimitiveMode(entity->getPrimitiveMode());
|
||||||
_canCastShadow = entity->getCanCastShadow();
|
_canCastShadow = entity->getCanCastShadow();
|
||||||
|
setCullWithParent(entity->getCullWithParent());
|
||||||
_cauterized = entity->getCauterized();
|
_cauterized = entity->getCauterized();
|
||||||
entity->setNeedsRenderUpdate(false);
|
entity->setNeedsRenderUpdate(false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -108,6 +108,16 @@ protected:
|
||||||
virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
|
virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
|
||||||
virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; }
|
virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; }
|
||||||
virtual void setPrimitiveMode(PrimitiveMode value) { _primitiveMode = value; }
|
virtual void setPrimitiveMode(PrimitiveMode value) { _primitiveMode = value; }
|
||||||
|
virtual void setCullWithParent(bool value) { _cullWithParent = value; }
|
||||||
|
|
||||||
|
template <typename F, typename T>
|
||||||
|
T withReadLockResult(const std::function<T()>& f) {
|
||||||
|
T result;
|
||||||
|
withReadLock([&] {
|
||||||
|
result = f();
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void requestRenderUpdate();
|
void requestRenderUpdate();
|
||||||
|
@ -130,6 +140,7 @@ protected:
|
||||||
bool _visible { false };
|
bool _visible { false };
|
||||||
bool _isVisibleInSecondaryCamera { false };
|
bool _isVisibleInSecondaryCamera { false };
|
||||||
bool _canCastShadow { false };
|
bool _canCastShadow { false };
|
||||||
|
bool _cullWithParent { false };
|
||||||
RenderLayer _renderLayer { RenderLayer::WORLD };
|
RenderLayer _renderLayer { RenderLayer::WORLD };
|
||||||
PrimitiveMode _primitiveMode { PrimitiveMode::SOLID };
|
PrimitiveMode _primitiveMode { PrimitiveMode::SOLID };
|
||||||
bool _cauterized { false };
|
bool _cauterized { false };
|
||||||
|
|
|
@ -253,7 +253,7 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) {
|
||||||
});
|
});
|
||||||
|
|
||||||
bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
||||||
geometryCache->bindSimpleProgram(batch, false, isTransparent(), false, wireframe, true, true, forward);
|
geometryCache->bindSimpleProgram(batch, false, isTransparent(), wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE);
|
||||||
|
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ void LineEntityRenderer::doRender(RenderArgs* args) {
|
||||||
transform.setRotation(modelTransform.getRotation());
|
transform.setRotation(modelTransform.getRotation());
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
if (_linePoints.size() > 1) {
|
if (_linePoints.size() > 1) {
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, false, false, true,
|
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, false, true,
|
||||||
_renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD);
|
_renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD);
|
||||||
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
|
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,13 +153,13 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo
|
||||||
|
|
||||||
if (urlChanged && !usingMaterialData) {
|
if (urlChanged && !usingMaterialData) {
|
||||||
_networkMaterial = DependencyManager::get<MaterialCache>()->getMaterial(_materialURL);
|
_networkMaterial = DependencyManager::get<MaterialCache>()->getMaterial(_materialURL);
|
||||||
auto onMaterialRequestFinished = [this, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) {
|
auto onMaterialRequestFinished = [this, entity, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) {
|
||||||
if (success) {
|
if (success) {
|
||||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
deleteMaterial(oldParentID, oldParentMaterialName);
|
||||||
_texturesLoaded = false;
|
_texturesLoaded = false;
|
||||||
_parsedMaterials = _networkMaterial->parsedMaterials;
|
_parsedMaterials = _networkMaterial->parsedMaterials;
|
||||||
setCurrentMaterialName(newCurrentMaterialName);
|
setCurrentMaterialName(newCurrentMaterialName);
|
||||||
applyMaterial();
|
applyMaterial(entity);
|
||||||
} else {
|
} else {
|
||||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
deleteMaterial(oldParentID, oldParentMaterialName);
|
||||||
_retryApply = false;
|
_retryApply = false;
|
||||||
|
@ -183,13 +183,13 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo
|
||||||
_parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(_materialData.toUtf8()), _materialURL);
|
_parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(_materialData.toUtf8()), _materialURL);
|
||||||
// Since our material changed, the current name might not be valid anymore, so we need to update
|
// Since our material changed, the current name might not be valid anymore, so we need to update
|
||||||
setCurrentMaterialName(newCurrentMaterialName);
|
setCurrentMaterialName(newCurrentMaterialName);
|
||||||
applyMaterial();
|
applyMaterial(entity);
|
||||||
} else {
|
} else {
|
||||||
if (deleteNeeded) {
|
if (deleteNeeded) {
|
||||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
deleteMaterial(oldParentID, oldParentMaterialName);
|
||||||
}
|
}
|
||||||
if (addNeeded) {
|
if (addNeeded) {
|
||||||
applyMaterial();
|
applyMaterial(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,8 +210,7 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKey MaterialEntityRenderer::getKey() {
|
ItemKey MaterialEntityRenderer::getKey() {
|
||||||
ItemKey::Builder builder;
|
auto builder = ItemKey::Builder().withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||||
builder.withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
|
||||||
|
|
||||||
if (!_visible) {
|
if (!_visible) {
|
||||||
builder.withInvisible();
|
builder.withInvisible();
|
||||||
|
@ -382,7 +381,7 @@ void MaterialEntityRenderer::applyTextureTransform(std::shared_ptr<NetworkMateri
|
||||||
material->setTextureTransforms(textureTransform, _materialMappingMode, _materialRepeat);
|
material->setTextureTransforms(textureTransform, _materialMappingMode, _materialRepeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaterialEntityRenderer::applyMaterial() {
|
void MaterialEntityRenderer::applyMaterial(const TypedEntityPointer& entity) {
|
||||||
_retryApply = false;
|
_retryApply = false;
|
||||||
|
|
||||||
std::shared_ptr<NetworkMaterial> material = getMaterial();
|
std::shared_ptr<NetworkMaterial> material = getMaterial();
|
||||||
|
@ -396,6 +395,12 @@ void MaterialEntityRenderer::applyMaterial() {
|
||||||
|
|
||||||
graphics::MaterialLayer materialLayer = graphics::MaterialLayer(material, _priority);
|
graphics::MaterialLayer materialLayer = graphics::MaterialLayer(material, _priority);
|
||||||
|
|
||||||
|
if (material->isProcedural()) {
|
||||||
|
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(material);
|
||||||
|
procedural->setBoundOperator([this] { return getBound(); });
|
||||||
|
entity->setHasVertexShader(procedural->hasVertexShader());
|
||||||
|
}
|
||||||
|
|
||||||
// Our parent could be an entity or an avatar
|
// Our parent could be an entity or an avatar
|
||||||
std::string parentMaterialName = _parentMaterialName.toStdString();
|
std::string parentMaterialName = _parentMaterialName.toStdString();
|
||||||
if (EntityTreeRenderer::addMaterialToEntity(parentID, materialLayer, parentMaterialName)) {
|
if (EntityTreeRenderer::addMaterialToEntity(parentID, materialLayer, parentMaterialName)) {
|
||||||
|
|
|
@ -56,7 +56,7 @@ private:
|
||||||
void setCurrentMaterialName(const std::string& currentMaterialName);
|
void setCurrentMaterialName(const std::string& currentMaterialName);
|
||||||
|
|
||||||
void applyTextureTransform(std::shared_ptr<NetworkMaterial>& material);
|
void applyTextureTransform(std::shared_ptr<NetworkMaterial>& material);
|
||||||
void applyMaterial();
|
void applyMaterial(const TypedEntityPointer& entity);
|
||||||
void deleteMaterial(const QUuid& oldParentID, const QString& oldParentMaterialName);
|
void deleteMaterial(const QUuid& oldParentID, const QString& oldParentMaterialName);
|
||||||
|
|
||||||
NetworkMaterialResourcePointer _networkMaterial;
|
NetworkMaterialResourcePointer _networkMaterial;
|
||||||
|
|
|
@ -1057,8 +1057,10 @@ ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Pare
|
||||||
void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) {
|
void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) {
|
||||||
auto builder = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
auto builder = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||||
|
|
||||||
if (_model && _model->isGroupCulled()) {
|
if (!_cullWithParent && _model && _model->isGroupCulled()) {
|
||||||
builder.withMetaCullGroup();
|
builder.withMetaCullGroup();
|
||||||
|
} else if (_cullWithParent) {
|
||||||
|
builder.withSubMetaCulled();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (didVisualGeometryRequestSucceed) {
|
if (didVisualGeometryRequestSucceed) {
|
||||||
|
@ -1497,6 +1499,14 @@ void ModelEntityRenderer::setPrimitiveMode(PrimitiveMode value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModelEntityRenderer::setCullWithParent(bool value) {
|
||||||
|
Parent::setCullWithParent(value);
|
||||||
|
setKey(_didLastVisualGeometryRequestSucceed);
|
||||||
|
if (_model) {
|
||||||
|
_model->setCullWithParent(_cullWithParent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items
|
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items
|
||||||
void ModelEntityRenderer::doRender(RenderArgs* args) {
|
void ModelEntityRenderer::doRender(RenderArgs* args) {
|
||||||
DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender");
|
DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender");
|
||||||
|
|
|
@ -164,6 +164,7 @@ protected:
|
||||||
void setIsVisibleInSecondaryCamera(bool value) override;
|
void setIsVisibleInSecondaryCamera(bool value) override;
|
||||||
void setRenderLayer(RenderLayer value) override;
|
void setRenderLayer(RenderLayer value) override;
|
||||||
void setPrimitiveMode(PrimitiveMode value) override;
|
void setPrimitiveMode(PrimitiveMode value) override;
|
||||||
|
void setCullWithParent(bool value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void animate(const TypedEntityPointer& entity);
|
void animate(const TypedEntityPointer& entity);
|
||||||
|
|
|
@ -151,11 +151,17 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn
|
||||||
|
|
||||||
ItemKey ParticleEffectEntityRenderer::getKey() {
|
ItemKey ParticleEffectEntityRenderer::getKey() {
|
||||||
// FIXME: implement isTransparent() for particles and an opaque pipeline
|
// FIXME: implement isTransparent() for particles and an opaque pipeline
|
||||||
if (_visible) {
|
auto builder = ItemKey::Builder::transparentShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||||
return ItemKey::Builder::transparentShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
|
||||||
} else {
|
if (!_visible) {
|
||||||
return ItemKey::Builder().withInvisible().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()).build();
|
builder.withInvisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_cullWithParent) {
|
||||||
|
builder.withSubMetaCulled();
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
ShapeKey ParticleEffectEntityRenderer::getShapeKey() {
|
ShapeKey ParticleEffectEntityRenderer::getShapeKey() {
|
||||||
|
|
|
@ -97,9 +97,17 @@ void PolyLineEntityRenderer::buildPipelines() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKey PolyLineEntityRenderer::getKey() {
|
ItemKey PolyLineEntityRenderer::getKey() {
|
||||||
return isTransparent() ?
|
auto builder = ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||||
ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()) :
|
|
||||||
ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
if (isTransparent()) {
|
||||||
|
builder.withTransparent();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cullWithParent) {
|
||||||
|
builder.withSubMetaCulled();
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
ShapeKey PolyLineEntityRenderer::getShapeKey() {
|
ShapeKey PolyLineEntityRenderer::getShapeKey() {
|
||||||
|
|
|
@ -1783,6 +1783,16 @@ PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) :
|
||||||
_params = std::make_shared<gpu::Buffer>(sizeof(glm::vec4), nullptr);
|
_params = std::make_shared<gpu::Buffer>(sizeof(glm::vec4), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemKey PolyVoxEntityRenderer::getKey() {
|
||||||
|
auto builder = ItemKey::Builder::opaqueShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||||
|
|
||||||
|
if (_cullWithParent) {
|
||||||
|
builder.withSubMetaCulled();
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
ShapeKey PolyVoxEntityRenderer::getShapeKey() {
|
ShapeKey PolyVoxEntityRenderer::getShapeKey() {
|
||||||
auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER);
|
auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER);
|
||||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||||
|
|
|
@ -209,7 +209,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ItemKey getKey() override { return ItemKey::Builder::opaqueShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); }
|
virtual ItemKey getKey() override;
|
||||||
virtual ShapeKey getShapeKey() override;
|
virtual ShapeKey getShapeKey() override;
|
||||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||||
|
|
|
@ -200,6 +200,7 @@ ShapeKey ShapeEntityRenderer::getShapeKey() {
|
||||||
if (drawMaterialKey.isUnlit()) {
|
if (drawMaterialKey.isUnlit()) {
|
||||||
builder.withUnlit();
|
builder.withUnlit();
|
||||||
}
|
}
|
||||||
|
builder.withCullFaceMode(mat->second.getCullFaceMode());
|
||||||
} else if (pipelineType == Pipeline::PROCEDURAL) {
|
} else if (pipelineType == Pipeline::PROCEDURAL) {
|
||||||
builder.withOwnPipeline();
|
builder.withOwnPipeline();
|
||||||
}
|
}
|
||||||
|
@ -207,6 +208,18 @@ ShapeKey ShapeEntityRenderer::getShapeKey() {
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item::Bound ShapeEntityRenderer::getBound() {
|
||||||
|
auto mat = _materials.find("0");
|
||||||
|
if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() &&
|
||||||
|
mat->second.top().material->isReady()) {
|
||||||
|
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(mat->second.top().material);
|
||||||
|
if (procedural->hasVertexShader() && procedural->hasBoundOperator()) {
|
||||||
|
return procedural->getBound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Parent::getBound();
|
||||||
|
}
|
||||||
|
|
||||||
void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||||
PerformanceTimer perfTimer("RenderableShapeEntityItem::render");
|
PerformanceTimer perfTimer("RenderableShapeEntityItem::render");
|
||||||
Q_ASSERT(args->_batch);
|
Q_ASSERT(args->_batch);
|
||||||
|
@ -251,7 +264,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
||||||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
||||||
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||||
render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false,
|
render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false,
|
||||||
renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD);
|
renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD, materials.top().material->getCullFaceMode());
|
||||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) {
|
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) {
|
||||||
geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -26,6 +26,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ShapeKey getShapeKey() override;
|
ShapeKey getShapeKey() override;
|
||||||
|
Item::Bound getBound() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool needsRenderUpdate() const override;
|
virtual bool needsRenderUpdate() const override;
|
||||||
|
|
|
@ -3025,6 +3025,17 @@ void EntityItem::setCanCastShadow(bool value) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EntityItem::getCullWithParent() const {
|
||||||
|
return _cullWithParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityItem::setCullWithParent(bool value) {
|
||||||
|
withWriteLock([&] {
|
||||||
|
_needsRenderUpdate |= _cullWithParent != value;
|
||||||
|
_cullWithParent = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
bool EntityItem::isChildOfMyAvatar() const {
|
bool EntityItem::isChildOfMyAvatar() const {
|
||||||
QUuid ancestorID = findAncestorOfType(NestableType::Avatar);
|
QUuid ancestorID = findAncestorOfType(NestableType::Avatar);
|
||||||
return !ancestorID.isNull() && (ancestorID == Physics::getSessionUUID() || ancestorID == AVATAR_SELF_ID);
|
return !ancestorID.isNull() && (ancestorID == Physics::getSessionUUID() || ancestorID == AVATAR_SELF_ID);
|
||||||
|
|
|
@ -305,6 +305,9 @@ public:
|
||||||
bool getCanCastShadow() const;
|
bool getCanCastShadow() const;
|
||||||
void setCanCastShadow(bool value);
|
void setCanCastShadow(bool value);
|
||||||
|
|
||||||
|
bool getCullWithParent() const;
|
||||||
|
void setCullWithParent(bool value);
|
||||||
|
|
||||||
void setCauterized(bool value);
|
void setCauterized(bool value);
|
||||||
bool getCauterized() const;
|
bool getCauterized() const;
|
||||||
|
|
||||||
|
@ -762,6 +765,8 @@ protected:
|
||||||
|
|
||||||
QHash<QUuid, EntityDynamicPointer> _grabActions;
|
QHash<QUuid, EntityDynamicPointer> _grabActions;
|
||||||
|
|
||||||
|
bool _cullWithParent { false };
|
||||||
|
|
||||||
mutable bool _needsRenderUpdate { false };
|
mutable bool _needsRenderUpdate { false };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -3113,6 +3113,7 @@ std::function<QObject*(const QUuid&)> EntityTree::_getEntityObjectOperator = nul
|
||||||
std::function<QSizeF(const QUuid&, const QString&)> EntityTree::_textSizeOperator = nullptr;
|
std::function<QSizeF(const QUuid&, const QString&)> EntityTree::_textSizeOperator = nullptr;
|
||||||
std::function<bool()> EntityTree::_areEntityClicksCapturedOperator = nullptr;
|
std::function<bool()> EntityTree::_areEntityClicksCapturedOperator = nullptr;
|
||||||
std::function<void(const QUuid&, const QVariant&)> EntityTree::_emitScriptEventOperator = nullptr;
|
std::function<void(const QUuid&, const QVariant&)> EntityTree::_emitScriptEventOperator = nullptr;
|
||||||
|
std::function<glm::vec3(const QUuid&)> EntityTree::_getUnscaledDimensionsForIDOperator = nullptr;
|
||||||
|
|
||||||
QObject* EntityTree::getEntityObject(const QUuid& id) {
|
QObject* EntityTree::getEntityObject(const QUuid& id) {
|
||||||
if (_getEntityObjectOperator) {
|
if (_getEntityObjectOperator) {
|
||||||
|
@ -3141,6 +3142,13 @@ void EntityTree::emitScriptEvent(const QUuid& id, const QVariant& message) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 EntityTree::getUnscaledDimensionsForID(const QUuid& id) {
|
||||||
|
if (_getUnscaledDimensionsForIDOperator) {
|
||||||
|
return _getUnscaledDimensionsForIDOperator(id);
|
||||||
|
}
|
||||||
|
return glm::vec3(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
||||||
MovingEntitiesOperator& moveOperator, bool force, bool tellServer) {
|
MovingEntitiesOperator& moveOperator, bool force, bool tellServer) {
|
||||||
// if the queryBox has changed, tell the entity-server
|
// if the queryBox has changed, tell the entity-server
|
||||||
|
|
|
@ -271,6 +271,9 @@ public:
|
||||||
static void setEmitScriptEventOperator(std::function<void(const QUuid&, const QVariant&)> emitScriptEventOperator) { _emitScriptEventOperator = emitScriptEventOperator; }
|
static void setEmitScriptEventOperator(std::function<void(const QUuid&, const QVariant&)> emitScriptEventOperator) { _emitScriptEventOperator = emitScriptEventOperator; }
|
||||||
static void emitScriptEvent(const QUuid& id, const QVariant& message);
|
static void emitScriptEvent(const QUuid& id, const QVariant& message);
|
||||||
|
|
||||||
|
static void setGetUnscaledDimensionsForIDOperator(std::function<glm::vec3(const QUuid&)> getUnscaledDimensionsForIDOperator) { _getUnscaledDimensionsForIDOperator = getUnscaledDimensionsForIDOperator; }
|
||||||
|
static glm::vec3 getUnscaledDimensionsForID(const QUuid& id);
|
||||||
|
|
||||||
std::map<QString, QString> getNamedPaths() const { return _namedPaths; }
|
std::map<QString, QString> getNamedPaths() const { return _namedPaths; }
|
||||||
|
|
||||||
void updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
void updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
||||||
|
@ -386,6 +389,7 @@ private:
|
||||||
static std::function<QSizeF(const QUuid&, const QString&)> _textSizeOperator;
|
static std::function<QSizeF(const QUuid&, const QString&)> _textSizeOperator;
|
||||||
static std::function<bool()> _areEntityClicksCapturedOperator;
|
static std::function<bool()> _areEntityClicksCapturedOperator;
|
||||||
static std::function<void(const QUuid&, const QVariant&)> _emitScriptEventOperator;
|
static std::function<void(const QUuid&, const QVariant&)> _emitScriptEventOperator;
|
||||||
|
static std::function<glm::vec3(const QUuid&)> _getUnscaledDimensionsForIDOperator;
|
||||||
|
|
||||||
std::vector<int32_t> _staleProxies;
|
std::vector<int32_t> _staleProxies;
|
||||||
|
|
||||||
|
|
|
@ -139,10 +139,10 @@ void MaterialEntityItem::debugDump() const {
|
||||||
|
|
||||||
void MaterialEntityItem::setUnscaledDimensions(const glm::vec3& value) {
|
void MaterialEntityItem::setUnscaledDimensions(const glm::vec3& value) {
|
||||||
_desiredDimensions = value;
|
_desiredDimensions = value;
|
||||||
if (_materialMappingMode == MaterialMappingMode::UV) {
|
if (_hasVertexShader || _materialMappingMode == MaterialMappingMode::PROJECTED) {
|
||||||
EntityItem::setUnscaledDimensions(ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
|
||||||
} else if (_materialMappingMode == MaterialMappingMode::PROJECTED) {
|
|
||||||
EntityItem::setUnscaledDimensions(value);
|
EntityItem::setUnscaledDimensions(value);
|
||||||
|
} else if (_materialMappingMode == MaterialMappingMode::UV) {
|
||||||
|
EntityItem::setUnscaledDimensions(ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,6 +264,13 @@ void MaterialEntityItem::setMaterialRepeat(bool value) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MaterialEntityItem::setParentID(const QUuid& parentID) {
|
||||||
|
if (parentID != getParentID()) {
|
||||||
|
EntityItem::setParentID(parentID);
|
||||||
|
_hasVertexShader = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AACube MaterialEntityItem::calculateInitialQueryAACube(bool& success) {
|
AACube MaterialEntityItem::calculateInitialQueryAACube(bool& success) {
|
||||||
AACube aaCube = EntityItem::calculateInitialQueryAACube(success);
|
AACube aaCube = EntityItem::calculateInitialQueryAACube(success);
|
||||||
// A Material entity's queryAACube contains its parent's queryAACube
|
// A Material entity's queryAACube contains its parent's queryAACube
|
||||||
|
@ -278,3 +285,16 @@ AACube MaterialEntityItem::calculateInitialQueryAACube(bool& success) {
|
||||||
}
|
}
|
||||||
return aaCube;
|
return aaCube;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MaterialEntityItem::setHasVertexShader(bool hasVertexShader) {
|
||||||
|
bool prevHasVertexShader = _hasVertexShader;
|
||||||
|
_hasVertexShader = hasVertexShader;
|
||||||
|
|
||||||
|
if (hasVertexShader && !prevHasVertexShader) {
|
||||||
|
setLocalPosition(glm::vec3(0.0f));
|
||||||
|
setLocalOrientation(glm::quat());
|
||||||
|
setUnscaledDimensions(EntityTree::getUnscaledDimensionsForID(getParentID()));
|
||||||
|
} else if (!hasVertexShader && prevHasVertexShader) {
|
||||||
|
setUnscaledDimensions(_desiredDimensions);
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,6 +64,8 @@ public:
|
||||||
QString getParentMaterialName() const;
|
QString getParentMaterialName() const;
|
||||||
void setParentMaterialName(const QString& parentMaterialName);
|
void setParentMaterialName(const QString& parentMaterialName);
|
||||||
|
|
||||||
|
void setParentID(const QUuid& parentID) override;
|
||||||
|
|
||||||
glm::vec2 getMaterialMappingPos() const;
|
glm::vec2 getMaterialMappingPos() const;
|
||||||
void setMaterialMappingPos(const glm::vec2& materialMappingPos);
|
void setMaterialMappingPos(const glm::vec2& materialMappingPos);
|
||||||
glm::vec2 getMaterialMappingScale() const;
|
glm::vec2 getMaterialMappingScale() const;
|
||||||
|
@ -73,6 +75,8 @@ public:
|
||||||
|
|
||||||
AACube calculateInitialQueryAACube(bool& success) override;
|
AACube calculateInitialQueryAACube(bool& success) override;
|
||||||
|
|
||||||
|
void setHasVertexShader(bool hasVertexShader);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// URL for this material. Currently, only JSON format is supported. Set to "materialData" to use the material data to live edit a material.
|
// URL for this material. Currently, only JSON format is supported. Set to "materialData" to use the material data to live edit a material.
|
||||||
// The following fields are supported in the JSON:
|
// The following fields are supported in the JSON:
|
||||||
|
@ -108,6 +112,8 @@ private:
|
||||||
float _materialMappingRot { 0 };
|
float _materialMappingRot { 0 };
|
||||||
QString _materialData;
|
QString _materialData;
|
||||||
|
|
||||||
|
bool _hasVertexShader { false };
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_MaterialEntityItem_h
|
#endif // hifi_MaterialEntityItem_h
|
||||||
|
|
|
@ -225,18 +225,17 @@ int GLTFSerializer::getAccessorType(const QString& type)
|
||||||
return GLTFAccessorType::SCALAR;
|
return GLTFAccessorType::SCALAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GLTFSerializer::getMaterialAlphaMode(const QString& type)
|
graphics::MaterialKey::OpacityMapMode GLTFSerializer::getMaterialAlphaMode(const QString& type) {
|
||||||
{
|
|
||||||
if (type == "OPAQUE") {
|
if (type == "OPAQUE") {
|
||||||
return GLTFMaterialAlphaMode::OPAQUE;
|
return graphics::MaterialKey::OPACITY_MAP_OPAQUE;
|
||||||
}
|
}
|
||||||
if (type == "MASK") {
|
if (type == "MASK") {
|
||||||
return GLTFMaterialAlphaMode::MASK;
|
return graphics::MaterialKey::OPACITY_MAP_MASK;
|
||||||
}
|
}
|
||||||
if (type == "BLEND") {
|
if (type == "BLEND") {
|
||||||
return GLTFMaterialAlphaMode::BLEND;
|
return graphics::MaterialKey::OPACITY_MAP_BLEND;
|
||||||
}
|
}
|
||||||
return GLTFMaterialAlphaMode::OPAQUE;
|
return graphics::MaterialKey::OPACITY_MAP_BLEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GLTFSerializer::getCameraType(const QString& type)
|
int GLTFSerializer::getCameraType(const QString& type)
|
||||||
|
@ -484,9 +483,9 @@ bool GLTFSerializer::addMaterial(const QJsonObject& object) {
|
||||||
getIndexFromObject(object, "normalTexture", material.normalTexture, material.defined);
|
getIndexFromObject(object, "normalTexture", material.normalTexture, material.defined);
|
||||||
getIndexFromObject(object, "occlusionTexture", material.occlusionTexture, material.defined);
|
getIndexFromObject(object, "occlusionTexture", material.occlusionTexture, material.defined);
|
||||||
getBoolVal(object, "doubleSided", material.doubleSided, material.defined);
|
getBoolVal(object, "doubleSided", material.doubleSided, material.defined);
|
||||||
QString alphamode;
|
QString alphaMode;
|
||||||
if (getStringVal(object, "alphaMode", alphamode, material.defined)) {
|
if (getStringVal(object, "alphaMode", alphaMode, material.defined)) {
|
||||||
material.alphaMode = getMaterialAlphaMode(alphamode);
|
material.alphaMode = getMaterialAlphaMode(alphaMode);
|
||||||
}
|
}
|
||||||
getDoubleVal(object, "alphaCutoff", material.alphaCutoff, material.defined);
|
getDoubleVal(object, "alphaCutoff", material.alphaCutoff, material.defined);
|
||||||
QJsonObject jsMetallicRoughness;
|
QJsonObject jsMetallicRoughness;
|
||||||
|
@ -1764,62 +1763,72 @@ HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) {
|
||||||
return fbxtex;
|
return fbxtex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLTFSerializer::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material) {
|
void GLTFSerializer::setHFMMaterial(HFMMaterial& hfmMat, const GLTFMaterial& material) {
|
||||||
|
if (material.defined["alphaMode"]) {
|
||||||
|
hfmMat._material->setOpacityMapMode(material.alphaMode);
|
||||||
|
} else {
|
||||||
|
hfmMat._material->setOpacityMapMode(graphics::MaterialKey::OPACITY_MAP_OPAQUE); // GLTF defaults to opaque
|
||||||
|
}
|
||||||
|
|
||||||
|
if (material.defined["alphaCutoff"]) {
|
||||||
|
hfmMat._material->setOpacityCutoff(material.alphaCutoff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (material.defined["doubleSided"] && material.doubleSided) {
|
||||||
|
hfmMat._material->setCullFaceMode(graphics::MaterialKey::CullFaceMode::CULL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
if (material.defined["emissiveFactor"] && material.emissiveFactor.size() == 3) {
|
if (material.defined["emissiveFactor"] && material.emissiveFactor.size() == 3) {
|
||||||
glm::vec3 emissive = glm::vec3(material.emissiveFactor[0],
|
glm::vec3 emissive = glm::vec3(material.emissiveFactor[0], material.emissiveFactor[1], material.emissiveFactor[2]);
|
||||||
material.emissiveFactor[1],
|
hfmMat._material->setEmissive(emissive);
|
||||||
material.emissiveFactor[2]);
|
|
||||||
fbxmat._material->setEmissive(emissive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (material.defined["emissiveTexture"]) {
|
if (material.defined["emissiveTexture"]) {
|
||||||
fbxmat.emissiveTexture = getHFMTexture(_file.textures[material.emissiveTexture]);
|
hfmMat.emissiveTexture = getHFMTexture(_file.textures[material.emissiveTexture]);
|
||||||
fbxmat.useEmissiveMap = true;
|
hfmMat.useEmissiveMap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (material.defined["normalTexture"]) {
|
if (material.defined["normalTexture"]) {
|
||||||
fbxmat.normalTexture = getHFMTexture(_file.textures[material.normalTexture]);
|
hfmMat.normalTexture = getHFMTexture(_file.textures[material.normalTexture]);
|
||||||
fbxmat.useNormalMap = true;
|
hfmMat.useNormalMap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (material.defined["occlusionTexture"]) {
|
if (material.defined["occlusionTexture"]) {
|
||||||
fbxmat.occlusionTexture = getHFMTexture(_file.textures[material.occlusionTexture]);
|
hfmMat.occlusionTexture = getHFMTexture(_file.textures[material.occlusionTexture]);
|
||||||
fbxmat.useOcclusionMap = true;
|
hfmMat.useOcclusionMap = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (material.defined["pbrMetallicRoughness"]) {
|
if (material.defined["pbrMetallicRoughness"]) {
|
||||||
fbxmat.isPBSMaterial = true;
|
hfmMat.isPBSMaterial = true;
|
||||||
|
|
||||||
if (material.pbrMetallicRoughness.defined["metallicFactor"]) {
|
if (material.pbrMetallicRoughness.defined["metallicFactor"]) {
|
||||||
fbxmat.metallic = material.pbrMetallicRoughness.metallicFactor;
|
hfmMat.metallic = material.pbrMetallicRoughness.metallicFactor;
|
||||||
}
|
}
|
||||||
if (material.pbrMetallicRoughness.defined["baseColorTexture"]) {
|
if (material.pbrMetallicRoughness.defined["baseColorTexture"]) {
|
||||||
fbxmat.opacityTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]);
|
hfmMat.opacityTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]);
|
||||||
fbxmat.albedoTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]);
|
hfmMat.albedoTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]);
|
||||||
fbxmat.useAlbedoMap = true;
|
hfmMat.useAlbedoMap = true;
|
||||||
}
|
}
|
||||||
if (material.pbrMetallicRoughness.defined["metallicRoughnessTexture"]) {
|
if (material.pbrMetallicRoughness.defined["metallicRoughnessTexture"]) {
|
||||||
fbxmat.roughnessTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]);
|
hfmMat.roughnessTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]);
|
||||||
fbxmat.roughnessTexture.sourceChannel = image::ColorChannel::GREEN;
|
hfmMat.roughnessTexture.sourceChannel = image::ColorChannel::GREEN;
|
||||||
fbxmat.useRoughnessMap = true;
|
hfmMat.useRoughnessMap = true;
|
||||||
fbxmat.metallicTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]);
|
hfmMat.metallicTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]);
|
||||||
fbxmat.metallicTexture.sourceChannel = image::ColorChannel::BLUE;
|
hfmMat.metallicTexture.sourceChannel = image::ColorChannel::BLUE;
|
||||||
fbxmat.useMetallicMap = true;
|
hfmMat.useMetallicMap = true;
|
||||||
}
|
}
|
||||||
if (material.pbrMetallicRoughness.defined["roughnessFactor"]) {
|
if (material.pbrMetallicRoughness.defined["roughnessFactor"]) {
|
||||||
fbxmat._material->setRoughness(material.pbrMetallicRoughness.roughnessFactor);
|
hfmMat._material->setRoughness(material.pbrMetallicRoughness.roughnessFactor);
|
||||||
}
|
}
|
||||||
if (material.pbrMetallicRoughness.defined["baseColorFactor"] &&
|
if (material.pbrMetallicRoughness.defined["baseColorFactor"] &&
|
||||||
material.pbrMetallicRoughness.baseColorFactor.size() == 4) {
|
material.pbrMetallicRoughness.baseColorFactor.size() == 4) {
|
||||||
glm::vec3 dcolor = glm::vec3(material.pbrMetallicRoughness.baseColorFactor[0],
|
glm::vec3 dcolor =
|
||||||
material.pbrMetallicRoughness.baseColorFactor[1],
|
glm::vec3(material.pbrMetallicRoughness.baseColorFactor[0], material.pbrMetallicRoughness.baseColorFactor[1],
|
||||||
material.pbrMetallicRoughness.baseColorFactor[2]);
|
material.pbrMetallicRoughness.baseColorFactor[2]);
|
||||||
fbxmat.diffuseColor = dcolor;
|
hfmMat.diffuseColor = dcolor;
|
||||||
fbxmat._material->setAlbedo(dcolor);
|
hfmMat._material->setAlbedo(dcolor);
|
||||||
fbxmat._material->setOpacity(material.pbrMetallicRoughness.baseColorFactor[3]);
|
hfmMat._material->setOpacity(material.pbrMetallicRoughness.baseColorFactor[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -416,21 +416,13 @@ struct GLTFpbrMetallicRoughness {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace GLTFMaterialAlphaMode {
|
|
||||||
enum Values {
|
|
||||||
OPAQUE = 0,
|
|
||||||
MASK,
|
|
||||||
BLEND
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GLTFMaterial {
|
struct GLTFMaterial {
|
||||||
QString name;
|
QString name;
|
||||||
QVector<double> emissiveFactor;
|
QVector<double> emissiveFactor;
|
||||||
int emissiveTexture;
|
int emissiveTexture;
|
||||||
int normalTexture;
|
int normalTexture;
|
||||||
int occlusionTexture;
|
int occlusionTexture;
|
||||||
int alphaMode;
|
graphics::MaterialKey::OpacityMapMode alphaMode;
|
||||||
double alphaCutoff;
|
double alphaCutoff;
|
||||||
bool doubleSided;
|
bool doubleSided;
|
||||||
GLTFpbrMetallicRoughness pbrMetallicRoughness;
|
GLTFpbrMetallicRoughness pbrMetallicRoughness;
|
||||||
|
@ -451,6 +443,12 @@ struct GLTFMaterial {
|
||||||
if (defined["emissiveFactor"]) {
|
if (defined["emissiveFactor"]) {
|
||||||
qCDebug(modelformat) << "emissiveFactor: " << emissiveFactor;
|
qCDebug(modelformat) << "emissiveFactor: " << emissiveFactor;
|
||||||
}
|
}
|
||||||
|
if (defined["alphaMode"]) {
|
||||||
|
qCDebug(modelformat) << "alphaMode: " << alphaMode;
|
||||||
|
}
|
||||||
|
if (defined["alphaCutoff"]) {
|
||||||
|
qCDebug(modelformat) << "alphaCutoff: " << alphaCutoff;
|
||||||
|
}
|
||||||
if (defined["pbrMetallicRoughness"]) {
|
if (defined["pbrMetallicRoughness"]) {
|
||||||
pbrMetallicRoughness.dump();
|
pbrMetallicRoughness.dump();
|
||||||
}
|
}
|
||||||
|
@ -800,7 +798,7 @@ private:
|
||||||
|
|
||||||
hifi::ByteArray setGLBChunks(const hifi::ByteArray& data);
|
hifi::ByteArray setGLBChunks(const hifi::ByteArray& data);
|
||||||
|
|
||||||
int getMaterialAlphaMode(const QString& type);
|
graphics::MaterialKey::OpacityMapMode getMaterialAlphaMode(const QString& type);
|
||||||
int getAccessorType(const QString& type);
|
int getAccessorType(const QString& type);
|
||||||
int getAnimationSamplerInterpolation(const QString& interpolation);
|
int getAnimationSamplerInterpolation(const QString& interpolation);
|
||||||
int getCameraType(const QString& type);
|
int getCameraType(const QString& type);
|
||||||
|
@ -854,7 +852,7 @@ private:
|
||||||
bool doesResourceExist(const QString& url);
|
bool doesResourceExist(const QString& url);
|
||||||
|
|
||||||
|
|
||||||
void setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material);
|
void setHFMMaterial(HFMMaterial& hfmMat, const GLTFMaterial& material);
|
||||||
HFMTexture getHFMTexture(const GLTFTexture& texture);
|
HFMTexture getHFMTexture(const GLTFTexture& texture);
|
||||||
void glTFDebugDump();
|
void glTFDebugDump();
|
||||||
void hfmDebugDump(const HFMModel& hfmModel);
|
void hfmDebugDump(const HFMModel& hfmModel);
|
||||||
|
|
|
@ -65,6 +65,7 @@ namespace scriptable {
|
||||||
* @property {Mat4|string} texCoordTransform1
|
* @property {Mat4|string} texCoordTransform1
|
||||||
* @property {string} lightmapParams
|
* @property {string} lightmapParams
|
||||||
* @property {string} materialParams
|
* @property {string} materialParams
|
||||||
|
* @property {string} cullFaceMode
|
||||||
* @property {boolean} defaultFallthrough
|
* @property {boolean} defaultFallthrough
|
||||||
* @property {string} procedural
|
* @property {string} procedural
|
||||||
*/
|
*/
|
||||||
|
@ -99,6 +100,7 @@ namespace scriptable {
|
||||||
QString lightMap;
|
QString lightMap;
|
||||||
QString scatteringMap;
|
QString scatteringMap;
|
||||||
std::array<glm::mat4, graphics::Material::NUM_TEXCOORD_TRANSFORMS> texCoordTransforms;
|
std::array<glm::mat4, graphics::Material::NUM_TEXCOORD_TRANSFORMS> texCoordTransforms;
|
||||||
|
QString cullFaceMode;
|
||||||
bool defaultFallthrough;
|
bool defaultFallthrough;
|
||||||
std::unordered_map<uint, bool> propertyFallthroughs; // not actually exposed to script
|
std::unordered_map<uint, bool> propertyFallthroughs; // not actually exposed to script
|
||||||
|
|
||||||
|
|
|
@ -495,6 +495,11 @@ namespace scriptable {
|
||||||
obj.setProperty("materialParams", FALLTHROUGH);
|
obj.setProperty("materialParams", FALLTHROUGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::CULL_FACE_MODE)) {
|
||||||
|
obj.setProperty("cullFaceMode", FALLTHROUGH);
|
||||||
|
} else if (!material.cullFaceMode.isEmpty()) {
|
||||||
|
obj.setProperty("cullFaceMode", material.cullFaceMode);
|
||||||
|
}
|
||||||
} else if (material.model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) {
|
} else if (material.model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) {
|
||||||
obj.setProperty("procedural", material.procedural);
|
obj.setProperty("procedural", material.procedural);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ scriptable::ScriptableMaterial& scriptable::ScriptableMaterial::operator=(const
|
||||||
occlusionMap = material.occlusionMap;
|
occlusionMap = material.occlusionMap;
|
||||||
lightMap = material.lightMap;
|
lightMap = material.lightMap;
|
||||||
scatteringMap = material.scatteringMap;
|
scatteringMap = material.scatteringMap;
|
||||||
|
cullFaceMode = material.cullFaceMode;
|
||||||
} else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) {
|
} else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) {
|
||||||
procedural = material.procedural;
|
procedural = material.procedural;
|
||||||
}
|
}
|
||||||
|
@ -131,6 +132,8 @@ scriptable::ScriptableMaterial::ScriptableMaterial(const graphics::MaterialPoint
|
||||||
for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) {
|
for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) {
|
||||||
texCoordTransforms[i] = material->getTexCoordTransform(i);
|
texCoordTransforms[i] = material->getTexCoordTransform(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cullFaceMode = QString(graphics::MaterialKey::getCullFaceModeName(material->getCullFaceMode()).c_str());
|
||||||
} else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) {
|
} else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) {
|
||||||
procedural = material->getProceduralString();
|
procedural = material->getProceduralString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ const float Material::DEFAULT_ROUGHNESS { 1.0f };
|
||||||
const float Material::DEFAULT_SCATTERING{ 0.0f };
|
const float Material::DEFAULT_SCATTERING{ 0.0f };
|
||||||
const MaterialKey::OpacityMapMode Material::DEFAULT_OPACITY_MAP_MODE{ MaterialKey::OPACITY_MAP_OPAQUE };
|
const MaterialKey::OpacityMapMode Material::DEFAULT_OPACITY_MAP_MODE{ MaterialKey::OPACITY_MAP_OPAQUE };
|
||||||
const float Material::DEFAULT_OPACITY_CUTOFF { 0.5f };
|
const float Material::DEFAULT_OPACITY_CUTOFF { 0.5f };
|
||||||
|
const MaterialKey::CullFaceMode Material::DEFAULT_CULL_FACE_MODE { MaterialKey::CULL_BACK };
|
||||||
|
|
||||||
std::string MaterialKey::getOpacityMapModeName(OpacityMapMode mode) {
|
std::string MaterialKey::getOpacityMapModeName(OpacityMapMode mode) {
|
||||||
const std::string names[3] = { "OPACITY_MAP_OPAQUE", "OPACITY_MAP_MASK", "OPACITY_MAP_BLEND" };
|
const std::string names[3] = { "OPACITY_MAP_OPAQUE", "OPACITY_MAP_MASK", "OPACITY_MAP_BLEND" };
|
||||||
|
@ -44,6 +44,21 @@ bool MaterialKey::getOpacityMapModeFromName(const std::string& modeName, Materia
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string MaterialKey::getCullFaceModeName(CullFaceMode mode) {
|
||||||
|
const std::string names[3] = { "CULL_NONE", "CULL_FRONT", "CULL_BACK" };
|
||||||
|
return names[mode];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MaterialKey::getCullFaceModeFromName(const std::string& modeName, CullFaceMode& mode) {
|
||||||
|
for (int i = CULL_NONE; i < NUM_CULL_FACE_MODES; i++) {
|
||||||
|
mode = (CullFaceMode)i;
|
||||||
|
if (modeName == getCullFaceModeName(mode)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string Material::HIFI_PBR { "hifi_pbr" };
|
const std::string Material::HIFI_PBR { "hifi_pbr" };
|
||||||
const std::string Material::HIFI_SHADER_SIMPLE { "hifi_shader_simple" };
|
const std::string Material::HIFI_SHADER_SIMPLE { "hifi_shader_simple" };
|
||||||
|
|
||||||
|
@ -67,6 +82,7 @@ Material::Material(const Material& material) :
|
||||||
_texcoordTransforms(material._texcoordTransforms),
|
_texcoordTransforms(material._texcoordTransforms),
|
||||||
_lightmapParams(material._lightmapParams),
|
_lightmapParams(material._lightmapParams),
|
||||||
_materialParams(material._materialParams),
|
_materialParams(material._materialParams),
|
||||||
|
_cullFaceMode(material._cullFaceMode),
|
||||||
_textureMaps(material._textureMaps),
|
_textureMaps(material._textureMaps),
|
||||||
_defaultFallthrough(material._defaultFallthrough),
|
_defaultFallthrough(material._defaultFallthrough),
|
||||||
_propertyFallthroughs(material._propertyFallthroughs)
|
_propertyFallthroughs(material._propertyFallthroughs)
|
||||||
|
@ -89,6 +105,7 @@ Material& Material::operator=(const Material& material) {
|
||||||
_texcoordTransforms = material._texcoordTransforms;
|
_texcoordTransforms = material._texcoordTransforms;
|
||||||
_lightmapParams = material._lightmapParams;
|
_lightmapParams = material._lightmapParams;
|
||||||
_materialParams = material._materialParams;
|
_materialParams = material._materialParams;
|
||||||
|
_cullFaceMode = material._cullFaceMode;
|
||||||
_textureMaps = material._textureMaps;
|
_textureMaps = material._textureMaps;
|
||||||
|
|
||||||
_defaultFallthrough = material._defaultFallthrough;
|
_defaultFallthrough = material._defaultFallthrough;
|
||||||
|
@ -144,7 +161,7 @@ void Material::setOpacityMapMode(MaterialKey::OpacityMapMode opacityMapMode) {
|
||||||
_key.setOpacityMapMode(opacityMapMode);
|
_key.setOpacityMapMode(opacityMapMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialKey::OpacityMapMode Material::getOpacityMapMode() const {
|
MaterialKey::OpacityMapMode Material::getOpacityMapMode() const {
|
||||||
return _key.getOpacityMapMode();
|
return _key.getOpacityMapMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,8 +226,7 @@ bool Material::resetOpacityMap() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto newious = _key.getOpacityMapMode();
|
if (previous != _key.getOpacityMapMode()) {
|
||||||
if (previous != newious) {
|
|
||||||
//opacity change detected for this material
|
//opacity change detected for this material
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,16 @@ public:
|
||||||
// find the enum value from a string, return true if match found
|
// find the enum value from a string, return true if match found
|
||||||
static bool getOpacityMapModeFromName(const std::string& modeName, OpacityMapMode& mode);
|
static bool getOpacityMapModeFromName(const std::string& modeName, OpacityMapMode& mode);
|
||||||
|
|
||||||
|
enum CullFaceMode {
|
||||||
|
CULL_NONE = 0,
|
||||||
|
CULL_FRONT,
|
||||||
|
CULL_BACK,
|
||||||
|
|
||||||
|
NUM_CULL_FACE_MODES
|
||||||
|
};
|
||||||
|
static std::string getCullFaceModeName(CullFaceMode mode);
|
||||||
|
static bool getCullFaceModeFromName(const std::string& modeName, CullFaceMode& mode);
|
||||||
|
|
||||||
// The signature is the Flags
|
// The signature is the Flags
|
||||||
Flags _flags;
|
Flags _flags;
|
||||||
|
|
||||||
|
@ -349,6 +359,10 @@ public:
|
||||||
void setOpacityCutoff(float opacityCutoff);
|
void setOpacityCutoff(float opacityCutoff);
|
||||||
float getOpacityCutoff() const { return _opacityCutoff; }
|
float getOpacityCutoff() const { return _opacityCutoff; }
|
||||||
|
|
||||||
|
static const MaterialKey::CullFaceMode DEFAULT_CULL_FACE_MODE;
|
||||||
|
void setCullFaceMode(MaterialKey::CullFaceMode cullFaceMode) { _cullFaceMode = cullFaceMode; }
|
||||||
|
MaterialKey::CullFaceMode getCullFaceMode() const { return _cullFaceMode; }
|
||||||
|
|
||||||
void setUnlit(bool value);
|
void setUnlit(bool value);
|
||||||
bool isUnlit() const { return _key.isUnlit(); }
|
bool isUnlit() const { return _key.isUnlit(); }
|
||||||
|
|
||||||
|
@ -403,6 +417,7 @@ public:
|
||||||
TEXCOORDTRANSFORM1,
|
TEXCOORDTRANSFORM1,
|
||||||
LIGHTMAP_PARAMS,
|
LIGHTMAP_PARAMS,
|
||||||
MATERIAL_PARAMS,
|
MATERIAL_PARAMS,
|
||||||
|
CULL_FACE_MODE,
|
||||||
|
|
||||||
NUM_TOTAL_FLAGS
|
NUM_TOTAL_FLAGS
|
||||||
};
|
};
|
||||||
|
@ -436,6 +451,7 @@ private:
|
||||||
std::array<glm::mat4, NUM_TEXCOORD_TRANSFORMS> _texcoordTransforms;
|
std::array<glm::mat4, NUM_TEXCOORD_TRANSFORMS> _texcoordTransforms;
|
||||||
glm::vec2 _lightmapParams { 0.0, 1.0 };
|
glm::vec2 _lightmapParams { 0.0, 1.0 };
|
||||||
glm::vec2 _materialParams { 0.0, 1.0 };
|
glm::vec2 _materialParams { 0.0, 1.0 };
|
||||||
|
MaterialKey::CullFaceMode _cullFaceMode { DEFAULT_CULL_FACE_MODE };
|
||||||
TextureMaps _textureMaps;
|
TextureMaps _textureMaps;
|
||||||
|
|
||||||
bool _defaultFallthrough { false };
|
bool _defaultFallthrough { false };
|
||||||
|
@ -524,6 +540,9 @@ public:
|
||||||
graphics::MaterialKey getMaterialKey() const { return graphics::MaterialKey(_schemaBuffer.get<graphics::MultiMaterial::Schema>()._key); }
|
graphics::MaterialKey getMaterialKey() const { return graphics::MaterialKey(_schemaBuffer.get<graphics::MultiMaterial::Schema>()._key); }
|
||||||
const gpu::TextureTablePointer& getTextureTable() const { return _textureTable; }
|
const gpu::TextureTablePointer& getTextureTable() const { return _textureTable; }
|
||||||
|
|
||||||
|
void setCullFaceMode(graphics::MaterialKey::CullFaceMode cullFaceMode) { _cullFaceMode = cullFaceMode; }
|
||||||
|
graphics::MaterialKey::CullFaceMode getCullFaceMode() const { return _cullFaceMode; }
|
||||||
|
|
||||||
void setNeedsUpdate(bool needsUpdate) { _needsUpdate = needsUpdate; }
|
void setNeedsUpdate(bool needsUpdate) { _needsUpdate = needsUpdate; }
|
||||||
void setTexturesLoading(bool value) { _texturesLoading = value; }
|
void setTexturesLoading(bool value) { _texturesLoading = value; }
|
||||||
void setInitialized() { _initialized = true; }
|
void setInitialized() { _initialized = true; }
|
||||||
|
@ -536,6 +555,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gpu::BufferView _schemaBuffer;
|
gpu::BufferView _schemaBuffer;
|
||||||
|
graphics::MaterialKey::CullFaceMode _cullFaceMode { graphics::Material::DEFAULT_CULL_FACE_MODE };
|
||||||
gpu::TextureTablePointer _textureTable { std::make_shared<gpu::TextureTable>() };
|
gpu::TextureTablePointer _textureTable { std::make_shared<gpu::TextureTable>() };
|
||||||
bool _needsUpdate { false };
|
bool _needsUpdate { false };
|
||||||
bool _texturesLoading { false };
|
bool _texturesLoading { false };
|
||||||
|
|
|
@ -214,18 +214,18 @@ vec3 fetchLightMap(vec2 uv) {
|
||||||
}
|
}
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
<@func evalMaterialOpacityMask(fetchedOpacity, materialOpacityCutoff, opacity)@>
|
<@func evalMaterialOpacityMask(fetchedOpacity, materialOpacityCutoff, materialOpacity, matKey, opacity)@>
|
||||||
{
|
{
|
||||||
// This path only valid for opaque or texel opaque material
|
// This path only valid for opaque or texel opaque material
|
||||||
<$opacity$> = step(<$materialOpacityCutoff$>, <$fetchedOpacity$>);
|
<$opacity$> = mix(<$materialOpacity$>,
|
||||||
|
step(<$materialOpacityCutoff$>, <$fetchedOpacity$>),
|
||||||
|
float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0));
|
||||||
}
|
}
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
|
||||||
<@func evalMaterialOpacity(fetchedOpacity, materialOpacityCutoff, materialOpacity, matKey, opacity)@>
|
<@func evalMaterialOpacity(fetchedOpacity, materialOpacityCutoff, materialOpacity, matKey, opacity)@>
|
||||||
{
|
{
|
||||||
// This path only valid for transparent material
|
// This path only valid for transparent material
|
||||||
// Assert that float((<$matKey$> & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0)) == 1.0
|
|
||||||
<$opacity$> = mix(<$fetchedOpacity$>,
|
<$opacity$> = mix(<$fetchedOpacity$>,
|
||||||
step(<$materialOpacityCutoff$>, <$fetchedOpacity$>),
|
step(<$materialOpacityCutoff$>, <$fetchedOpacity$>),
|
||||||
float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0))
|
float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0))
|
||||||
|
|
|
@ -173,24 +173,27 @@ public:
|
||||||
void getTextureNames(QSet<QString>& textureList) const;
|
void getTextureNames(QSet<QString>& textureList) const;
|
||||||
void setMaxNumPixelsPerTexture(int maxNumPixels);
|
void setMaxNumPixelsPerTexture(int maxNumPixels);
|
||||||
|
|
||||||
glm::vec3 diffuseColor{ 1.0f };
|
glm::vec3 diffuseColor { 1.0f };
|
||||||
float diffuseFactor{ 1.0f };
|
float diffuseFactor { 1.0f };
|
||||||
glm::vec3 specularColor{ 0.02f };
|
glm::vec3 specularColor { 0.02f };
|
||||||
float specularFactor{ 1.0f };
|
float specularFactor { 1.0f };
|
||||||
|
|
||||||
glm::vec3 emissiveColor{ 0.0f };
|
glm::vec3 emissiveColor { 0.0f };
|
||||||
float emissiveFactor{ 0.0f };
|
float emissiveFactor { 0.0f };
|
||||||
|
|
||||||
float shininess{ 23.0f };
|
float shininess { 23.0f };
|
||||||
float opacity{ 1.0f };
|
float opacity { 1.0f };
|
||||||
|
|
||||||
float metallic{ 0.0f };
|
float metallic { 0.0f };
|
||||||
float roughness{ 1.0f };
|
float roughness { 1.0f };
|
||||||
float emissiveIntensity{ 1.0f };
|
float emissiveIntensity { 1.0f };
|
||||||
float ambientFactor{ 1.0f };
|
float ambientFactor { 1.0f };
|
||||||
|
|
||||||
float bumpMultiplier { 1.0f }; // TODO: to be implemented
|
float bumpMultiplier { 1.0f }; // TODO: to be implemented
|
||||||
|
|
||||||
|
graphics::MaterialKey::OpacityMapMode alphaMode { graphics::MaterialKey::OPACITY_MAP_BLEND };
|
||||||
|
float alphaCutoff { 0.5f };
|
||||||
|
|
||||||
QString materialID;
|
QString materialID;
|
||||||
QString name;
|
QString name;
|
||||||
QString shadingModel;
|
QString shadingModel;
|
||||||
|
@ -207,19 +210,19 @@ public:
|
||||||
Texture occlusionTexture;
|
Texture occlusionTexture;
|
||||||
Texture scatteringTexture;
|
Texture scatteringTexture;
|
||||||
Texture lightmapTexture;
|
Texture lightmapTexture;
|
||||||
glm::vec2 lightmapParams{ 0.0f, 1.0f };
|
glm::vec2 lightmapParams { 0.0f, 1.0f };
|
||||||
|
|
||||||
|
|
||||||
bool isPBSMaterial{ false };
|
bool isPBSMaterial { false };
|
||||||
// THe use XXXMap are not really used to drive which map are going or not, debug only
|
// THe use XXXMap are not really used to drive which map are going or not, debug only
|
||||||
bool useNormalMap{ false };
|
bool useNormalMap { false };
|
||||||
bool useAlbedoMap{ false };
|
bool useAlbedoMap { false };
|
||||||
bool useOpacityMap{ false };
|
bool useOpacityMap { false };
|
||||||
bool useRoughnessMap{ false };
|
bool useRoughnessMap { false };
|
||||||
bool useSpecularMap{ false };
|
bool useSpecularMap { false };
|
||||||
bool useMetallicMap{ false };
|
bool useMetallicMap { false };
|
||||||
bool useEmissiveMap{ false };
|
bool useEmissiveMap { false };
|
||||||
bool useOcclusionMap{ false };
|
bool useOcclusionMap { false };
|
||||||
|
|
||||||
bool needTangentSpace() const;
|
bool needTangentSpace() const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#ifndef hifi_DomainHandler_h
|
#ifndef hifi_DomainHandler_h
|
||||||
#define hifi_DomainHandler_h
|
#define hifi_DomainHandler_h
|
||||||
|
|
||||||
|
#include <QProcessEnvironment>
|
||||||
|
|
||||||
#include <QtCore/QJsonObject>
|
#include <QtCore/QJsonObject>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
@ -30,10 +32,37 @@
|
||||||
#include "ReceivedMessage.h"
|
#include "ReceivedMessage.h"
|
||||||
#include "NetworkingConstants.h"
|
#include "NetworkingConstants.h"
|
||||||
|
|
||||||
const unsigned short DEFAULT_DOMAIN_SERVER_PORT = 40102;
|
const unsigned short DEFAULT_DOMAIN_SERVER_PORT =
|
||||||
const unsigned short DEFAULT_DOMAIN_SERVER_DTLS_PORT = 40103;
|
QProcessEnvironment::systemEnvironment()
|
||||||
const quint16 DOMAIN_SERVER_HTTP_PORT = 40100;
|
.contains("HIFI_DOMAIN_SERVER_PORT")
|
||||||
const quint16 DOMAIN_SERVER_HTTPS_PORT = 40101;
|
? QProcessEnvironment::systemEnvironment()
|
||||||
|
.value("HIFI_DOMAIN_SERVER_PORT")
|
||||||
|
.toUShort()
|
||||||
|
: 40102;
|
||||||
|
|
||||||
|
const unsigned short DEFAULT_DOMAIN_SERVER_DTLS_PORT =
|
||||||
|
QProcessEnvironment::systemEnvironment()
|
||||||
|
.contains("HIFI_DOMAIN_SERVER_DTLS_PORT")
|
||||||
|
? QProcessEnvironment::systemEnvironment()
|
||||||
|
.value("HIFI_DOMAIN_SERVER_DTLS_PORT")
|
||||||
|
.toUShort()
|
||||||
|
: 40103;
|
||||||
|
|
||||||
|
const quint16 DOMAIN_SERVER_HTTP_PORT =
|
||||||
|
QProcessEnvironment::systemEnvironment()
|
||||||
|
.contains("HIFI_DOMAIN_SERVER_HTTP_PORT")
|
||||||
|
? QProcessEnvironment::systemEnvironment()
|
||||||
|
.value("HIFI_DOMAIN_SERVER_HTTP_PORT")
|
||||||
|
.toUInt()
|
||||||
|
: 40100;
|
||||||
|
|
||||||
|
const quint16 DOMAIN_SERVER_HTTPS_PORT =
|
||||||
|
QProcessEnvironment::systemEnvironment()
|
||||||
|
.contains("HIFI_DOMAIN_SERVER_HTTPS_PORT")
|
||||||
|
? QProcessEnvironment::systemEnvironment()
|
||||||
|
.value("HIFI_DOMAIN_SERVER_HTTPS_PORT")
|
||||||
|
.toUInt()
|
||||||
|
: 40101;
|
||||||
|
|
||||||
const int MAX_SILENT_DOMAIN_SERVER_CHECK_INS = 5;
|
const int MAX_SILENT_DOMAIN_SERVER_CHECK_INS = 5;
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ Q_LOGGING_CATEGORY(proceduralLog, "hifi.gpu.procedural")
|
||||||
|
|
||||||
// User-data parsing constants
|
// User-data parsing constants
|
||||||
static const QString PROCEDURAL_USER_DATA_KEY = "ProceduralEntity";
|
static const QString PROCEDURAL_USER_DATA_KEY = "ProceduralEntity";
|
||||||
|
static const QString VERTEX_URL_KEY = "vertexShaderURL";
|
||||||
static const QString FRAGMENT_URL_KEY = "fragmentShaderURL";
|
static const QString FRAGMENT_URL_KEY = "fragmentShaderURL";
|
||||||
static const QString URL_KEY = "shaderUrl";
|
static const QString URL_KEY = "shaderUrl";
|
||||||
static const QString VERSION_KEY = "version";
|
static const QString VERSION_KEY = "version";
|
||||||
|
@ -42,6 +43,7 @@ static const std::string PROCEDURAL_VERSION = "//PROCEDURAL_VERSION";
|
||||||
bool operator==(const ProceduralData& a, const ProceduralData& b) {
|
bool operator==(const ProceduralData& a, const ProceduralData& b) {
|
||||||
return ((a.version == b.version) &&
|
return ((a.version == b.version) &&
|
||||||
(a.fragmentShaderUrl == b.fragmentShaderUrl) &&
|
(a.fragmentShaderUrl == b.fragmentShaderUrl) &&
|
||||||
|
(a.vertexShaderUrl == b.vertexShaderUrl) &&
|
||||||
(a.uniforms == b.uniforms) &&
|
(a.uniforms == b.uniforms) &&
|
||||||
(a.channels == b.channels));
|
(a.channels == b.channels));
|
||||||
}
|
}
|
||||||
|
@ -101,9 +103,9 @@ void ProceduralData::parse(const QJsonObject& proceduralData) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty shader URL isn't valid
|
{ // Vertex shader URL
|
||||||
if (fragmentShaderUrl.isEmpty()) {
|
auto rawShaderUrl = proceduralData[VERTEX_URL_KEY].toString();
|
||||||
return;
|
vertexShaderUrl = DependencyManager::get<ResourceManager>()->normalizeURL(rawShaderUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
uniforms = proceduralData[UNIFORMS_KEY].toObject();
|
uniforms = proceduralData[UNIFORMS_KEY].toObject();
|
||||||
|
@ -172,29 +174,57 @@ void Procedural::setProceduralData(const ProceduralData& proceduralData) {
|
||||||
|
|
||||||
if (proceduralData.fragmentShaderUrl != _data.fragmentShaderUrl) {
|
if (proceduralData.fragmentShaderUrl != _data.fragmentShaderUrl) {
|
||||||
_data.fragmentShaderUrl = proceduralData.fragmentShaderUrl;
|
_data.fragmentShaderUrl = proceduralData.fragmentShaderUrl;
|
||||||
const auto& shaderUrl = _data.fragmentShaderUrl;
|
|
||||||
|
|
||||||
_shaderDirty = true;
|
_shaderDirty = true;
|
||||||
_networkFragmentShader.reset();
|
_networkFragmentShader.reset();
|
||||||
_fragmentShaderPath.clear();
|
_fragmentShaderPath.clear();
|
||||||
_fragmentShaderSource.clear();
|
_fragmentShaderSource.clear();
|
||||||
|
|
||||||
if (shaderUrl.isEmpty() || !shaderUrl.isValid()) {
|
if (!_data.fragmentShaderUrl.isValid()) {
|
||||||
|
qCWarning(proceduralLog) << "Invalid fragment shader URL: " << _data.fragmentShaderUrl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shaderUrl.isLocalFile()) {
|
if (_data.fragmentShaderUrl.isLocalFile()) {
|
||||||
if (!QFileInfo(shaderUrl.toLocalFile()).exists()) {
|
if (!QFileInfo(_data.fragmentShaderUrl.toLocalFile()).exists()) {
|
||||||
|
qCWarning(proceduralLog) << "Invalid fragment shader URL, missing local file: " << _data.fragmentShaderUrl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_fragmentShaderPath = shaderUrl.toLocalFile();
|
_fragmentShaderPath = _data.fragmentShaderUrl.toLocalFile();
|
||||||
} else if (shaderUrl.scheme() == URL_SCHEME_QRC) {
|
} else if (_data.fragmentShaderUrl.scheme() == URL_SCHEME_QRC) {
|
||||||
_fragmentShaderPath = ":" + shaderUrl.path();
|
_fragmentShaderPath = ":" + _data.fragmentShaderUrl.path();
|
||||||
} else {
|
} else {
|
||||||
_networkFragmentShader = ShaderCache::instance().getShader(shaderUrl);
|
_networkFragmentShader = ShaderCache::instance().getShader(_data.fragmentShaderUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (proceduralData.vertexShaderUrl != _data.vertexShaderUrl) {
|
||||||
|
_data.vertexShaderUrl = proceduralData.vertexShaderUrl;
|
||||||
|
|
||||||
|
_shaderDirty = true;
|
||||||
|
_networkVertexShader.reset();
|
||||||
|
_vertexShaderPath.clear();
|
||||||
|
_vertexShaderSource.clear();
|
||||||
|
|
||||||
|
if (!_data.vertexShaderUrl.isValid()) {
|
||||||
|
qCWarning(proceduralLog) << "Invalid vertex shader URL: " << _data.vertexShaderUrl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data.vertexShaderUrl.isLocalFile()) {
|
||||||
|
if (!QFileInfo(_data.vertexShaderUrl.toLocalFile()).exists()) {
|
||||||
|
qCWarning(proceduralLog) << "Invalid vertex shader URL, missing local file: " << _data.vertexShaderUrl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_vertexShaderPath = _data.vertexShaderUrl.toLocalFile();
|
||||||
|
} else if (_data.vertexShaderUrl.scheme() == URL_SCHEME_QRC) {
|
||||||
|
_vertexShaderPath = ":" + _data.vertexShaderUrl.path();
|
||||||
|
} else {
|
||||||
|
_networkVertexShader = ShaderCache::instance().getShader(_data.vertexShaderUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
_enabled = true;
|
_enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,8 +243,12 @@ bool Procedural::isReady() const {
|
||||||
_fadeStartTime = usecTimestampNow();
|
_fadeStartTime = usecTimestampNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do we have a network or local shader, and if so, is it loaded?
|
// We need to have at least one shader, and whichever ones we have need to be loaded
|
||||||
if (_fragmentShaderPath.isEmpty() && (!_networkFragmentShader || !_networkFragmentShader->isLoaded())) {
|
bool hasFragmentShader = !_fragmentShaderPath.isEmpty() || _networkFragmentShader;
|
||||||
|
bool fragmentShaderLoaded = !_fragmentShaderPath.isEmpty() || (_networkFragmentShader && _networkFragmentShader->isLoaded());
|
||||||
|
bool hasVertexShader = !_vertexShaderPath.isEmpty() || _networkVertexShader;
|
||||||
|
bool vertexShaderLoaded = !_vertexShaderPath.isEmpty() || (_networkVertexShader && _networkVertexShader->isLoaded());
|
||||||
|
if ((!hasFragmentShader && !hasVertexShader) || (hasFragmentShader && !fragmentShaderLoaded) || (hasVertexShader && !vertexShaderLoaded)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,6 +292,20 @@ void Procedural::prepare(gpu::Batch& batch,
|
||||||
_shaderDirty = true;
|
_shaderDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_vertexShaderPath.isEmpty()) {
|
||||||
|
auto lastModified = (uint64_t)QFileInfo(_vertexShaderPath).lastModified().toMSecsSinceEpoch();
|
||||||
|
if (lastModified > _vertexShaderModified) {
|
||||||
|
QFile file(_vertexShaderPath);
|
||||||
|
file.open(QIODevice::ReadOnly);
|
||||||
|
_vertexShaderSource = QTextStream(&file).readAll();
|
||||||
|
_shaderDirty = true;
|
||||||
|
_vertexShaderModified = lastModified;
|
||||||
|
}
|
||||||
|
} else if (_vertexShaderSource.isEmpty() && _networkVertexShader && _networkVertexShader->isLoaded()) {
|
||||||
|
_vertexShaderSource = _networkVertexShader->_source;
|
||||||
|
_shaderDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_shaderDirty) {
|
if (_shaderDirty) {
|
||||||
_proceduralPipelines.clear();
|
_proceduralPipelines.clear();
|
||||||
}
|
}
|
||||||
|
@ -276,25 +324,42 @@ void Procedural::prepare(gpu::Batch& batch,
|
||||||
|
|
||||||
gpu::Shader::Source& fragmentSource = (key.isTransparent() && _transparentFragmentSource.valid()) ? _transparentFragmentSource : _opaqueFragmentSource;
|
gpu::Shader::Source& fragmentSource = (key.isTransparent() && _transparentFragmentSource.valid()) ? _transparentFragmentSource : _opaqueFragmentSource;
|
||||||
|
|
||||||
// Build the fragment shader
|
// Build the fragment and vertex shaders
|
||||||
|
auto versionDefine = "#define PROCEDURAL_V" + std::to_string(_data.version);
|
||||||
fragmentSource.replacements.clear();
|
fragmentSource.replacements.clear();
|
||||||
fragmentSource.replacements[PROCEDURAL_VERSION] = "#define PROCEDURAL_V" + std::to_string(_data.version);
|
fragmentSource.replacements[PROCEDURAL_VERSION] = versionDefine;
|
||||||
fragmentSource.replacements[PROCEDURAL_BLOCK] = _fragmentShaderSource.toStdString();
|
if (!_fragmentShaderSource.isEmpty()) {
|
||||||
|
fragmentSource.replacements[PROCEDURAL_BLOCK] = _fragmentShaderSource.toStdString();
|
||||||
|
}
|
||||||
|
vertexSource.replacements.clear();
|
||||||
|
vertexSource.replacements[PROCEDURAL_VERSION] = versionDefine;
|
||||||
|
if (!_vertexShaderSource.isEmpty()) {
|
||||||
|
vertexSource.replacements[PROCEDURAL_BLOCK] = _vertexShaderSource.toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
// Set any userdata specified uniforms (if any)
|
// Set any userdata specified uniforms (if any)
|
||||||
if (!_data.uniforms.empty()) {
|
if (!_data.uniforms.empty()) {
|
||||||
// First grab all the possible dialect/variant/Reflections
|
// First grab all the possible dialect/variant/reflections
|
||||||
std::vector<shader::Reflection*> allReflections;
|
std::vector<shader::Reflection*> allFragmentReflections;
|
||||||
for (auto dialectIt = fragmentSource.dialectSources.begin(); dialectIt != fragmentSource.dialectSources.end(); ++dialectIt) {
|
for (auto dialectIt = fragmentSource.dialectSources.begin(); dialectIt != fragmentSource.dialectSources.end(); ++dialectIt) {
|
||||||
for (auto variantIt = (*dialectIt).second.variantSources.begin(); variantIt != (*dialectIt).second.variantSources.end(); ++variantIt) {
|
for (auto variantIt = (*dialectIt).second.variantSources.begin(); variantIt != (*dialectIt).second.variantSources.end(); ++variantIt) {
|
||||||
allReflections.push_back(&(*variantIt).second.reflection);
|
allFragmentReflections.push_back(&(*variantIt).second.reflection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::vector<shader::Reflection*> allVertexReflections;
|
||||||
|
for (auto dialectIt = vertexSource.dialectSources.begin(); dialectIt != vertexSource.dialectSources.end(); ++dialectIt) {
|
||||||
|
for (auto variantIt = (*dialectIt).second.variantSources.begin(); variantIt != (*dialectIt).second.variantSources.end(); ++variantIt) {
|
||||||
|
allVertexReflections.push_back(&(*variantIt).second.reflection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Then fill in every reflections the new custom bindings
|
// Then fill in every reflections the new custom bindings
|
||||||
int customSlot = procedural::slot::uniform::Custom;
|
int customSlot = procedural::slot::uniform::Custom;
|
||||||
for (const auto& key : _data.uniforms.keys()) {
|
for (const auto& key : _data.uniforms.keys()) {
|
||||||
std::string uniformName = key.toLocal8Bit().data();
|
std::string uniformName = key.toLocal8Bit().data();
|
||||||
for (auto reflection : allReflections) {
|
for (auto reflection : allFragmentReflections) {
|
||||||
|
reflection->uniforms[uniformName] = customSlot;
|
||||||
|
}
|
||||||
|
for (auto reflection : allVertexReflections) {
|
||||||
reflection->uniforms[uniformName] = customSlot;
|
reflection->uniforms[uniformName] = customSlot;
|
||||||
}
|
}
|
||||||
++customSlot;
|
++customSlot;
|
||||||
|
@ -303,6 +368,7 @@ void Procedural::prepare(gpu::Batch& batch,
|
||||||
|
|
||||||
// Leave this here for debugging
|
// Leave this here for debugging
|
||||||
//qCDebug(proceduralLog) << "FragmentShader:\n" << fragmentSource.getSource(shader::Dialect::glsl450, shader::Variant::Mono).c_str();
|
//qCDebug(proceduralLog) << "FragmentShader:\n" << fragmentSource.getSource(shader::Dialect::glsl450, shader::Variant::Mono).c_str();
|
||||||
|
//qCDebug(proceduralLog) << "VertexShader:\n" << vertexSource.getSource(shader::Dialect::glsl450, shader::Variant::Mono).c_str();
|
||||||
|
|
||||||
gpu::ShaderPointer vertexShader = gpu::Shader::createVertex(vertexSource);
|
gpu::ShaderPointer vertexShader = gpu::Shader::createVertex(vertexSource);
|
||||||
gpu::ShaderPointer fragmentShader = gpu::Shader::createPixel(fragmentSource);
|
gpu::ShaderPointer fragmentShader = gpu::Shader::createPixel(fragmentSource);
|
||||||
|
@ -453,6 +519,11 @@ glm::vec4 Procedural::getColor(const glm::vec4& entityColor) const {
|
||||||
return entityColor;
|
return entityColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Procedural::hasVertexShader() const {
|
||||||
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
|
return !_data.vertexShaderUrl.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
void graphics::ProceduralMaterial::initializeProcedural() {
|
void graphics::ProceduralMaterial::initializeProcedural() {
|
||||||
_procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural);
|
_procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural);
|
||||||
_procedural._vertexSourceSkinned = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural_deformed);
|
_procedural._vertexSourceSkinned = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural_deformed);
|
||||||
|
|
|
@ -36,6 +36,8 @@ const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 };
|
||||||
* The data used to define a Procedural shader material.
|
* The data used to define a Procedural shader material.
|
||||||
* @typedef {object} ProceduralData
|
* @typedef {object} ProceduralData
|
||||||
* @property {number} version=1 - The version of the procedural shader.
|
* @property {number} version=1 - The version of the procedural shader.
|
||||||
|
* @property {string} vertexShaderURL - A link to a vertex shader. Currently, only GLSL shaders are supported. The shader must implement a different method depending on the version.
|
||||||
|
* If a procedural material contains a vertex shader, the bounding box of the material entity is used to cull the object to which the material is applied.
|
||||||
* @property {string} fragmentShaderURL - A link to a fragment shader. Currently, only GLSL shaders are supported. The shader must implement a different method depending on the version.
|
* @property {string} fragmentShaderURL - A link to a fragment shader. Currently, only GLSL shaders are supported. The shader must implement a different method depending on the version.
|
||||||
* <code>shaderUrl</code> is an alias.
|
* <code>shaderUrl</code> is an alias.
|
||||||
* @property {string[]} channels=[] - An array of input texture URLs. Currently, up to 4 are supported.
|
* @property {string[]} channels=[] - An array of input texture URLs. Currently, up to 4 are supported.
|
||||||
|
@ -50,6 +52,7 @@ struct ProceduralData {
|
||||||
// Rendering object descriptions, from userData
|
// Rendering object descriptions, from userData
|
||||||
uint8_t version { 0 };
|
uint8_t version { 0 };
|
||||||
QUrl fragmentShaderUrl;
|
QUrl fragmentShaderUrl;
|
||||||
|
QUrl vertexShaderUrl;
|
||||||
QJsonObject uniforms;
|
QJsonObject uniforms;
|
||||||
QJsonArray channels;
|
QJsonArray channels;
|
||||||
};
|
};
|
||||||
|
@ -110,6 +113,11 @@ public:
|
||||||
void setIsFading(bool isFading) { _isFading = isFading; }
|
void setIsFading(bool isFading) { _isFading = isFading; }
|
||||||
void setDoesFade(bool doesFade) { _doesFade = doesFade; }
|
void setDoesFade(bool doesFade) { _doesFade = doesFade; }
|
||||||
|
|
||||||
|
bool hasVertexShader() const;
|
||||||
|
void setBoundOperator(const std::function<AABox()>& boundOperator) { _boundOperator = boundOperator; }
|
||||||
|
bool hasBoundOperator() const { return (bool)_boundOperator; }
|
||||||
|
AABox getBound() { return _boundOperator(); }
|
||||||
|
|
||||||
gpu::Shader::Source _vertexSource;
|
gpu::Shader::Source _vertexSource;
|
||||||
gpu::Shader::Source _vertexSourceSkinned;
|
gpu::Shader::Source _vertexSourceSkinned;
|
||||||
gpu::Shader::Source _vertexSourceSkinnedDQ;
|
gpu::Shader::Source _vertexSourceSkinnedDQ;
|
||||||
|
@ -156,7 +164,11 @@ protected:
|
||||||
uint64_t _firstCompile { 0 };
|
uint64_t _firstCompile { 0 };
|
||||||
int32_t _frameCount { 0 };
|
int32_t _frameCount { 0 };
|
||||||
|
|
||||||
// Rendering object descriptions, from userData
|
// Rendering object descriptions
|
||||||
|
QString _vertexShaderSource;
|
||||||
|
QString _vertexShaderPath;
|
||||||
|
uint64_t _vertexShaderModified { 0 };
|
||||||
|
NetworkShaderPointer _networkVertexShader;
|
||||||
QString _fragmentShaderSource;
|
QString _fragmentShaderSource;
|
||||||
QString _fragmentShaderPath;
|
QString _fragmentShaderPath;
|
||||||
uint64_t _fragmentShaderModified { 0 };
|
uint64_t _fragmentShaderModified { 0 };
|
||||||
|
@ -187,6 +199,9 @@ private:
|
||||||
mutable bool _isFading { false };
|
mutable bool _isFading { false };
|
||||||
bool _doesFade { true };
|
bool _doesFade { true };
|
||||||
ProceduralProgramKey _prevKey;
|
ProceduralProgramKey _prevKey;
|
||||||
|
|
||||||
|
std::function<AABox()> _boundOperator { nullptr };
|
||||||
|
|
||||||
mutable std::mutex _mutex;
|
mutable std::mutex _mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,6 +225,7 @@ public:
|
||||||
bool isFading() const { return _procedural.isFading(); }
|
bool isFading() const { return _procedural.isFading(); }
|
||||||
void setIsFading(bool isFading) { _procedural.setIsFading(isFading); }
|
void setIsFading(bool isFading) { _procedural.setIsFading(isFading); }
|
||||||
uint64_t getFadeStartTime() const { return _procedural.getFadeStartTime(); }
|
uint64_t getFadeStartTime() const { return _procedural.getFadeStartTime(); }
|
||||||
|
bool hasVertexShader() const { return _procedural.hasVertexShader(); }
|
||||||
void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation,
|
void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation,
|
||||||
const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) {
|
const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) {
|
||||||
_procedural.prepare(batch, position, size, orientation, created, key);
|
_procedural.prepare(batch, position, size, orientation, created, key);
|
||||||
|
@ -217,6 +233,10 @@ public:
|
||||||
|
|
||||||
void initializeProcedural();
|
void initializeProcedural();
|
||||||
|
|
||||||
|
void setBoundOperator(const std::function<AABox()>& boundOperator) { _procedural.setBoundOperator(boundOperator); }
|
||||||
|
bool hasBoundOperator() const { return _procedural.hasBoundOperator(); }
|
||||||
|
AABox getBound() { return _procedural.getBound(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString _proceduralString;
|
QString _proceduralString;
|
||||||
Procedural _procedural;
|
Procedural _procedural;
|
||||||
|
|
|
@ -60,6 +60,17 @@ LAYOUT_STD140(binding=PROCEDURAL_BUFFER_INPUTS) uniform standardInputsBuffer {
|
||||||
#define iChannelResolution standardInputs.channelResolution
|
#define iChannelResolution standardInputs.channelResolution
|
||||||
#define iWorldOrientation standardInputs.worldOrientation
|
#define iWorldOrientation standardInputs.worldOrientation
|
||||||
|
|
||||||
|
struct ProceduralVertexData {
|
||||||
|
vec4 position;
|
||||||
|
vec4 nonSkinnedPosition; // input only
|
||||||
|
vec3 normal;
|
||||||
|
vec3 nonSkinnedNormal; // input only
|
||||||
|
vec3 tangent; // input only
|
||||||
|
vec3 nonSkinnedTangent; // input only
|
||||||
|
vec4 color;
|
||||||
|
vec2 texCoord0;
|
||||||
|
};
|
||||||
|
|
||||||
struct ProceduralFragment {
|
struct ProceduralFragment {
|
||||||
vec3 normal;
|
vec3 normal;
|
||||||
vec3 diffuse;
|
vec3 diffuse;
|
||||||
|
|
|
@ -143,7 +143,7 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
||||||
* @property {string} opacityMap - The URL of the opacity texture image. Set the value the same as the <code>albedoMap</code>
|
* @property {string} opacityMap - The URL of the opacity texture image. Set the value the same as the <code>albedoMap</code>
|
||||||
* value for transparency.
|
* value for transparency.
|
||||||
* <code>"hifi_pbr"</code> model only.
|
* <code>"hifi_pbr"</code> model only.
|
||||||
* @property {number|string} opacityMapMode - The mode defining the interpretation of the opacity map. Values can be:
|
* @property {string} opacityMapMode - The mode defining the interpretation of the opacity map. Values can be:
|
||||||
* <code>"OPACITY_MAP_OPAQUE"</code> for ignoring the opacity map information.
|
* <code>"OPACITY_MAP_OPAQUE"</code> for ignoring the opacity map information.
|
||||||
* <code>"OPACITY_MAP_MASK"</code> for using the opacity map as a mask, where only the texel greater than opacityCutoff are visible and rendered opaque.
|
* <code>"OPACITY_MAP_MASK"</code> for using the opacity map as a mask, where only the texel greater than opacityCutoff are visible and rendered opaque.
|
||||||
* <code>"OPACITY_MAP_BLEND"</code> for using the opacity map for alpha blending the material surface with the background.
|
* <code>"OPACITY_MAP_BLEND"</code> for using the opacity map for alpha blending the material surface with the background.
|
||||||
|
@ -151,6 +151,13 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
||||||
* @property {number|string} opacityCutoff - The opacity cutoff threshold used to determine the opaque texels of the Opacity map
|
* @property {number|string} opacityCutoff - The opacity cutoff threshold used to determine the opaque texels of the Opacity map
|
||||||
* when opacityMapMode is "OPACITY_MAP_MASK", range <code>0.0</code> – <code>1.0</code>.
|
* when opacityMapMode is "OPACITY_MAP_MASK", range <code>0.0</code> – <code>1.0</code>.
|
||||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||||
|
* @property {string} cullFaceMode - The mode defining which side of the geometry should be rendered. Values can be:
|
||||||
|
* <ul>
|
||||||
|
* <li><code>"CULL_NONE"</code> for rendering both sides of the geometry.</li>
|
||||||
|
* <li><code>"CULL_FRONT"</code> for culling the front faces of the geometry.</li>
|
||||||
|
* <li><code>"CULL_BACK"</code> (the default) for culling the back faces of the geometry.</li>
|
||||||
|
* </ul>
|
||||||
|
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||||
* @property {string} roughnessMap - The URL of the roughness texture image. You can use this or <code>glossMap</code>, but not
|
* @property {string} roughnessMap - The URL of the roughness texture image. You can use this or <code>glossMap</code>, but not
|
||||||
* both.
|
* both.
|
||||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||||
|
@ -285,7 +292,20 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
||||||
} else if (value.isDouble()) {
|
} else if (value.isDouble()) {
|
||||||
material->setOpacityCutoff(value.toDouble());
|
material->setOpacityCutoff(value.toDouble());
|
||||||
}
|
}
|
||||||
} else if (key == "scattering") {
|
} else if (key == "cullFaceMode") {
|
||||||
|
auto value = materialJSON.value(key);
|
||||||
|
if (value.isString()) {
|
||||||
|
auto valueString = value.toString();
|
||||||
|
if (valueString == FALLTHROUGH) {
|
||||||
|
material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::CULL_FACE_MODE);
|
||||||
|
} else {
|
||||||
|
graphics::MaterialKey::CullFaceMode mode;
|
||||||
|
if (graphics::MaterialKey::getCullFaceModeFromName(valueString.toStdString(), mode)) {
|
||||||
|
material->setCullFaceMode(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (key == "scattering") {
|
||||||
auto value = materialJSON.value(key);
|
auto value = materialJSON.value(key);
|
||||||
if (value.isString() && value.toString() == FALLTHROUGH) {
|
if (value.isString() && value.toString() == FALLTHROUGH) {
|
||||||
material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::SCATTERING_VAL_BIT);
|
material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::SCATTERING_VAL_BIT);
|
||||||
|
|
|
@ -723,7 +723,7 @@ gpu::ShaderPointer GeometryCache::_forwardUnlitShader;
|
||||||
gpu::ShaderPointer GeometryCache::_forwardSimpleFadeShader;
|
gpu::ShaderPointer GeometryCache::_forwardSimpleFadeShader;
|
||||||
gpu::ShaderPointer GeometryCache::_forwardUnlitFadeShader;
|
gpu::ShaderPointer GeometryCache::_forwardUnlitFadeShader;
|
||||||
|
|
||||||
std::map<std::tuple<bool, bool, bool>, render::ShapePipelinePointer> GeometryCache::_shapePipelines;
|
std::map<std::tuple<bool, bool, bool, graphics::MaterialKey::CullFaceMode>, render::ShapePipelinePointer> GeometryCache::_shapePipelines;
|
||||||
|
|
||||||
GeometryCache::GeometryCache() :
|
GeometryCache::GeometryCache() :
|
||||||
_nextID(0) {
|
_nextID(0) {
|
||||||
|
@ -776,15 +776,18 @@ void GeometryCache::initializeShapePipelines() {
|
||||||
bool transparent = i & 1;
|
bool transparent = i & 1;
|
||||||
bool unlit = i & 2;
|
bool unlit = i & 2;
|
||||||
bool forward = i & 4;
|
bool forward = i & 4;
|
||||||
_shapePipelines[std::make_tuple(transparent, unlit, forward)] = getShapePipeline(false, transparent, true, unlit, false, forward);
|
for (int cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_NONE; cullFaceMode < graphics::MaterialKey::CullFaceMode::NUM_CULL_FACE_MODES; cullFaceMode++) {
|
||||||
|
auto cullMode = (graphics::MaterialKey::CullFaceMode)cullFaceMode;
|
||||||
|
_shapePipelines[std::make_tuple(transparent, unlit, forward, cullMode)] = getShapePipeline(false, transparent, unlit, false, forward, cullMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool culled,
|
render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool unlit, bool depthBias, bool forward,
|
||||||
bool unlit, bool depthBias, bool forward) {
|
graphics::MaterialKey::CullFaceMode cullFaceMode) {
|
||||||
|
|
||||||
return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false, true, forward), nullptr,
|
return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, unlit, depthBias, false, true, forward, cullFaceMode), nullptr,
|
||||||
[](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) {
|
[](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) {
|
||||||
batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||||
DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch);
|
DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch);
|
||||||
|
@ -792,12 +795,12 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool culled,
|
render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool unlit, bool depthBias, bool forward,
|
||||||
bool unlit, bool depthBias, bool forward) {
|
graphics::MaterialKey::CullFaceMode cullFaceMode) {
|
||||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||||
auto fadeBatchSetter = fadeEffect->getBatchSetter();
|
auto fadeBatchSetter = fadeEffect->getBatchSetter();
|
||||||
auto fadeItemSetter = fadeEffect->getItemUniformSetter();
|
auto fadeItemSetter = fadeEffect->getItemUniformSetter();
|
||||||
return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true, true, forward), nullptr,
|
return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, unlit, depthBias, true, true, forward, cullFaceMode), nullptr,
|
||||||
[fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) {
|
[fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) {
|
||||||
batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||||
fadeBatchSetter(shapePipeline, batch, args);
|
fadeBatchSetter(shapePipeline, batch, args);
|
||||||
|
@ -2049,54 +2052,60 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo
|
||||||
class SimpleProgramKey {
|
class SimpleProgramKey {
|
||||||
public:
|
public:
|
||||||
enum FlagBit {
|
enum FlagBit {
|
||||||
IS_TEXTURED_FLAG = 0,
|
IS_TEXTURED_BIT = 0,
|
||||||
IS_TRANSPARENT_FLAG,
|
IS_TRANSPARENT_BIT,
|
||||||
IS_CULLED_FLAG,
|
IS_UNLIT_BIT,
|
||||||
IS_UNLIT_FLAG,
|
IS_DEPTH_BIASED_BIT,
|
||||||
HAS_DEPTH_BIAS_FLAG,
|
IS_FADING_BIT,
|
||||||
IS_FADING_FLAG,
|
IS_ANTIALIASED_BIT,
|
||||||
IS_ANTIALIASED_FLAG,
|
IS_FORWARD_BIT,
|
||||||
IS_FORWARD_FLAG,
|
IS_CULL_FACE_NONE_BIT, // if neither of these are set, we're CULL_FACE_BACK
|
||||||
|
IS_CULL_FACE_FRONT_BIT,
|
||||||
|
|
||||||
NUM_FLAGS,
|
NUM_FLAGS,
|
||||||
};
|
};
|
||||||
|
typedef std::bitset<NUM_FLAGS> Flags;
|
||||||
|
|
||||||
enum Flag {
|
bool isTextured() const { return _flags[IS_TEXTURED_BIT]; }
|
||||||
IS_TEXTURED = (1 << IS_TEXTURED_FLAG),
|
bool isTransparent() const { return _flags[IS_TRANSPARENT_BIT]; }
|
||||||
IS_TRANSPARENT = (1 << IS_TRANSPARENT_FLAG),
|
bool isUnlit() const { return _flags[IS_UNLIT_BIT]; }
|
||||||
IS_CULLED = (1 << IS_CULLED_FLAG),
|
bool hasDepthBias() const { return _flags[IS_DEPTH_BIASED_BIT]; }
|
||||||
IS_UNLIT = (1 << IS_UNLIT_FLAG),
|
bool isFading() const { return _flags[IS_FADING_BIT]; }
|
||||||
HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG),
|
bool isAntiAliased() const { return _flags[IS_ANTIALIASED_BIT]; }
|
||||||
IS_FADING = (1 << IS_FADING_FLAG),
|
bool isForward() const { return _flags[IS_FORWARD_BIT]; }
|
||||||
IS_ANTIALIASED = (1 << IS_ANTIALIASED_FLAG),
|
bool isCullFaceNone() const { return _flags[IS_CULL_FACE_NONE_BIT]; }
|
||||||
IS_FORWARD = (1 << IS_FORWARD_FLAG),
|
bool isCullFaceFront() const { return _flags[IS_CULL_FACE_FRONT_BIT]; }
|
||||||
};
|
|
||||||
typedef unsigned short Flags;
|
|
||||||
|
|
||||||
bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); }
|
|
||||||
|
|
||||||
bool isTextured() const { return isFlag(IS_TEXTURED); }
|
|
||||||
bool isTransparent() const { return isFlag(IS_TRANSPARENT); }
|
|
||||||
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); }
|
|
||||||
bool isAntiAliased() const { return isFlag(IS_ANTIALIASED); }
|
|
||||||
bool isForward() const { return isFlag(IS_FORWARD); }
|
|
||||||
|
|
||||||
Flags _flags = 0;
|
Flags _flags = 0;
|
||||||
#if defined(__clang__)
|
|
||||||
__attribute__((unused))
|
|
||||||
#endif
|
|
||||||
short _spare = 0; // Padding
|
|
||||||
|
|
||||||
int getRaw() const { return *reinterpret_cast<const int*>(this); }
|
unsigned long getRaw() const { return _flags.to_ulong(); }
|
||||||
|
|
||||||
|
SimpleProgramKey(bool textured = false, bool transparent = false, bool unlit = false, bool depthBias = false, bool fading = false,
|
||||||
|
bool isAntiAliased = true, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CULL_BACK) {
|
||||||
|
_flags.set(IS_TEXTURED_BIT, textured);
|
||||||
|
_flags.set(IS_TRANSPARENT_BIT, transparent);
|
||||||
|
_flags.set(IS_UNLIT_BIT, unlit);
|
||||||
|
_flags.set(IS_DEPTH_BIASED_BIT, depthBias);
|
||||||
|
_flags.set(IS_FADING_BIT, fading);
|
||||||
|
_flags.set(IS_ANTIALIASED_BIT, isAntiAliased);
|
||||||
|
_flags.set(IS_FORWARD_BIT, forward);
|
||||||
|
|
||||||
SimpleProgramKey(bool textured = false, bool transparent = false, bool culled = true,
|
switch (cullFaceMode) {
|
||||||
bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true, bool forward = false) {
|
case graphics::MaterialKey::CullFaceMode::CULL_NONE:
|
||||||
_flags = (textured ? IS_TEXTURED : 0) | (transparent ? IS_TRANSPARENT : 0) | (culled ? IS_CULLED : 0) |
|
_flags.set(IS_CULL_FACE_NONE_BIT);
|
||||||
(unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0) | (fading ? IS_FADING : 0) | (isAntiAliased ? IS_ANTIALIASED : 0) | (forward ? IS_FORWARD : 0);
|
_flags.reset(IS_CULL_FACE_FRONT_BIT);
|
||||||
|
break;
|
||||||
|
case graphics::MaterialKey::CullFaceMode::CULL_FRONT:
|
||||||
|
_flags.reset(IS_CULL_FACE_NONE_BIT);
|
||||||
|
_flags.set(IS_CULL_FACE_FRONT_BIT);
|
||||||
|
break;
|
||||||
|
case graphics::MaterialKey::CullFaceMode::CULL_BACK:
|
||||||
|
_flags.reset(IS_CULL_FACE_NONE_BIT);
|
||||||
|
_flags.reset(IS_CULL_FACE_FRONT_BIT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleProgramKey(int bitmask) : _flags(bitmask) {}
|
SimpleProgramKey(int bitmask) : _flags(bitmask) {}
|
||||||
|
@ -2141,8 +2150,9 @@ gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent, bool
|
||||||
return _webPipelines[{ transparent, forward }];
|
return _webPipelines[{ transparent, forward }];
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool isAntiAliased, bool forward) {
|
void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool unlit, bool depthBiased, bool isAntiAliased,
|
||||||
batch.setPipeline(getSimplePipeline(textured, transparent, culled, unlit, depthBiased, false, isAntiAliased, forward));
|
bool forward, graphics::MaterialKey::CullFaceMode cullFaceMode) {
|
||||||
|
batch.setPipeline(getSimplePipeline(textured, transparent, unlit, depthBiased, false, isAntiAliased, forward, cullFaceMode));
|
||||||
|
|
||||||
// If not textured, set a default albedo map
|
// If not textured, set a default albedo map
|
||||||
if (!textured) {
|
if (!textured) {
|
||||||
|
@ -2151,8 +2161,9 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool tra
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool fading, bool isAntiAliased, bool forward) {
|
gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool unlit, bool depthBiased, bool fading, bool isAntiAliased,
|
||||||
SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased, fading, isAntiAliased, forward };
|
bool forward, graphics::MaterialKey::CullFaceMode cullFaceMode) {
|
||||||
|
SimpleProgramKey config { textured, transparent, unlit, depthBiased, fading, isAntiAliased, forward, cullFaceMode };
|
||||||
|
|
||||||
// If the pipeline already exists, return it
|
// If the pipeline already exists, return it
|
||||||
auto it = _simplePrograms.find(config);
|
auto it = _simplePrograms.find(config);
|
||||||
|
@ -2189,10 +2200,12 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
|
||||||
|
|
||||||
// If the pipeline did not exist, make it
|
// If the pipeline did not exist, make it
|
||||||
auto state = std::make_shared<gpu::State>();
|
auto state = std::make_shared<gpu::State>();
|
||||||
if (config.isCulled()) {
|
if (config.isCullFaceNone()) {
|
||||||
state->setCullMode(gpu::State::CULL_BACK);
|
|
||||||
} else {
|
|
||||||
state->setCullMode(gpu::State::CULL_NONE);
|
state->setCullMode(gpu::State::CULL_NONE);
|
||||||
|
} else if (config.isCullFaceFront()) {
|
||||||
|
state->setCullMode(gpu::State::CULL_FRONT);
|
||||||
|
} else {
|
||||||
|
state->setCullMode(gpu::State::CULL_BACK);
|
||||||
}
|
}
|
||||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||||
if (config.hasDepthBias()) {
|
if (config.hasDepthBias()) {
|
||||||
|
|
|
@ -162,18 +162,19 @@ public:
|
||||||
static const int UNKNOWN_ID;
|
static const int UNKNOWN_ID;
|
||||||
|
|
||||||
// Bind the pipeline and get the state to render static geometry
|
// Bind the pipeline and get the state to render static geometry
|
||||||
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool transparent = false, bool culled = true,
|
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool transparent = false, bool unlit = false, bool depthBias = false,
|
||||||
bool unlit = false, bool depthBias = false, bool isAntiAliased = true, bool forward = false);
|
bool isAntiAliased = true, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
|
||||||
// Get the pipeline to render static geometry
|
// Get the pipeline to render static geometry
|
||||||
static gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true,
|
static gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool unlit = false, bool depthBias = false,
|
||||||
bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true, bool forward = false);
|
bool fading = false, bool isAntiAliased = true, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
|
||||||
|
|
||||||
void bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward);
|
void bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward);
|
||||||
gpu::PipelinePointer getWebBrowserProgram(bool transparent, bool forward);
|
gpu::PipelinePointer getWebBrowserProgram(bool transparent, bool forward);
|
||||||
static std::map<std::pair<bool, bool>, gpu::PipelinePointer> _webPipelines;
|
static std::map<std::pair<bool, bool>, gpu::PipelinePointer> _webPipelines;
|
||||||
|
|
||||||
static void initializeShapePipelines();
|
static void initializeShapePipelines();
|
||||||
render::ShapePipelinePointer getShapePipelinePointer(bool transparent, bool unlit, bool forward) { return _shapePipelines[std::make_tuple(transparent, unlit, forward)]; }
|
render::ShapePipelinePointer getShapePipelinePointer(bool transparent, bool unlit, bool forward,
|
||||||
|
graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CULL_BACK) { return _shapePipelines[std::make_tuple(transparent, unlit, forward, cullFaceMode)]; }
|
||||||
|
|
||||||
// Static (instanced) geometry
|
// Static (instanced) geometry
|
||||||
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
||||||
|
@ -456,13 +457,13 @@ private:
|
||||||
static gpu::ShaderPointer _forwardSimpleFadeShader;
|
static gpu::ShaderPointer _forwardSimpleFadeShader;
|
||||||
static gpu::ShaderPointer _forwardUnlitFadeShader;
|
static gpu::ShaderPointer _forwardUnlitFadeShader;
|
||||||
|
|
||||||
static std::map<std::tuple<bool, bool, bool>, render::ShapePipelinePointer> _shapePipelines;
|
static std::map<std::tuple<bool, bool, bool, graphics::MaterialKey::CullFaceMode>, render::ShapePipelinePointer> _shapePipelines;
|
||||||
static QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
|
static QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
|
||||||
|
|
||||||
static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true,
|
static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool unlit = false,
|
||||||
bool unlit = false, bool depthBias = false, bool forward = false);
|
bool depthBias = false, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
|
||||||
static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool culled = true,
|
static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool unlit = false,
|
||||||
bool unlit = false, bool depthBias = false, bool forward = false);
|
bool depthBias = false, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_GeometryCache_h
|
#endif // hifi_GeometryCache_h
|
||||||
|
|
|
@ -102,6 +102,10 @@ void MeshPartPayload::updateKey(const render::ItemKey& key) {
|
||||||
builder.withTransparent();
|
builder.withTransparent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_cullWithParent) {
|
||||||
|
builder.withSubMetaCulled();
|
||||||
|
}
|
||||||
|
|
||||||
_itemKey = builder.build();
|
_itemKey = builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +114,13 @@ ItemKey MeshPartPayload::getKey() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Item::Bound MeshPartPayload::getBound() const {
|
Item::Bound MeshPartPayload::getBound() const {
|
||||||
|
graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material;
|
||||||
|
if (material && material->isProcedural() && material->isReady()) {
|
||||||
|
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(_drawMaterials.top().material);
|
||||||
|
if (procedural->hasVertexShader() && procedural->hasBoundOperator()) {
|
||||||
|
return procedural->getBound();
|
||||||
|
}
|
||||||
|
}
|
||||||
return _worldBound;
|
return _worldBound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +147,9 @@ ShapeKey MeshPartPayload::getShapeKey() const {
|
||||||
if (drawMaterialKey.isUnlit()) {
|
if (drawMaterialKey.isUnlit()) {
|
||||||
builder.withUnlit();
|
builder.withUnlit();
|
||||||
}
|
}
|
||||||
|
if (material) {
|
||||||
|
builder.withCullFaceMode(material->getCullFaceMode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
@ -175,6 +189,9 @@ void MeshPartPayload::render(RenderArgs* args) {
|
||||||
|
|
||||||
if (!_drawMaterials.empty() && _drawMaterials.top().material && _drawMaterials.top().material->isProcedural() &&
|
if (!_drawMaterials.empty() && _drawMaterials.top().material && _drawMaterials.top().material->isProcedural() &&
|
||||||
_drawMaterials.top().material->isReady()) {
|
_drawMaterials.top().material->isReady()) {
|
||||||
|
if (!enableMaterialProceduralShaders) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(_drawMaterials.top().material);
|
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(_drawMaterials.top().material);
|
||||||
auto& schema = _drawMaterials.getSchemaBuffer().get<graphics::MultiMaterial::Schema>();
|
auto& schema = _drawMaterials.getSchemaBuffer().get<graphics::MultiMaterial::Schema>();
|
||||||
glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity);
|
glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity);
|
||||||
|
@ -370,6 +387,10 @@ void ModelMeshPartPayload::updateKey(const render::ItemKey& key) {
|
||||||
builder.withTransparent();
|
builder.withTransparent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_cullWithParent) {
|
||||||
|
builder.withSubMetaCulled();
|
||||||
|
}
|
||||||
|
|
||||||
_itemKey = builder.build();
|
_itemKey = builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,6 +445,9 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode pr
|
||||||
if (isUnlit) {
|
if (isUnlit) {
|
||||||
builder.withUnlit();
|
builder.withUnlit();
|
||||||
}
|
}
|
||||||
|
if (material) {
|
||||||
|
builder.withCullFaceMode(material->getCullFaceMode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_shapeKey = builder.build();
|
_shapeKey = builder.build();
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
// Render Item interface
|
// Render Item interface
|
||||||
virtual render::ItemKey getKey() const;
|
virtual render::ItemKey getKey() const;
|
||||||
virtual render::Item::Bound getBound() const;
|
virtual render::Item::Bound getBound() const;
|
||||||
virtual render::ShapeKey getShapeKey() const; // shape interface
|
virtual render::ShapeKey getShapeKey() const;
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
|
|
||||||
// ModelMeshPartPayload functions to perform render
|
// ModelMeshPartPayload functions to perform render
|
||||||
|
@ -73,10 +73,13 @@ public:
|
||||||
void addMaterial(graphics::MaterialLayer material);
|
void addMaterial(graphics::MaterialLayer material);
|
||||||
void removeMaterial(graphics::MaterialPointer material);
|
void removeMaterial(graphics::MaterialPointer material);
|
||||||
|
|
||||||
|
void setCullWithParent(bool value) { _cullWithParent = value; }
|
||||||
|
|
||||||
static bool enableMaterialProceduralShaders;
|
static bool enableMaterialProceduralShaders;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() };
|
render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() };
|
||||||
|
bool _cullWithParent { false };
|
||||||
uint64_t _created;
|
uint64_t _created;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,7 +109,7 @@ public:
|
||||||
void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform);
|
void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform);
|
||||||
|
|
||||||
// Render Item interface
|
// Render Item interface
|
||||||
render::ShapeKey getShapeKey() const override; // shape interface
|
render::ShapeKey getShapeKey() const override;
|
||||||
void render(RenderArgs* args) override;
|
void render(RenderArgs* args) override;
|
||||||
|
|
||||||
void setShapeKey(bool invalidateShapeKey, PrimitiveMode primitiveMode, bool useDualQuaternionSkinning);
|
void setShapeKey(bool invalidateShapeKey, PrimitiveMode primitiveMode, bool useDualQuaternionSkinning);
|
||||||
|
|
|
@ -154,7 +154,7 @@ void Model::setOffset(const glm::vec3& offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::calculateTextureInfo() {
|
void Model::calculateTextureInfo() {
|
||||||
if (!_hasCalculatedTextureInfo && isLoaded() && getGeometry()->areTexturesLoaded() && !_modelMeshRenderItemsMap.isEmpty()) {
|
if (!_hasCalculatedTextureInfo && isLoaded() && getGeometry()->areTexturesLoaded() && !_modelMeshRenderItems.isEmpty()) {
|
||||||
size_t textureSize = 0;
|
size_t textureSize = 0;
|
||||||
int textureCount = 0;
|
int textureCount = 0;
|
||||||
bool allTexturesLoaded = true;
|
bool allTexturesLoaded = true;
|
||||||
|
@ -960,6 +960,22 @@ void Model::setCauterized(bool cauterized, const render::ScenePointer& scene) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Model::setCullWithParent(bool cullWithParent) {
|
||||||
|
if (_cullWithParent != cullWithParent) {
|
||||||
|
_cullWithParent = cullWithParent;
|
||||||
|
|
||||||
|
render::Transaction transaction;
|
||||||
|
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
||||||
|
for(auto item : _modelMeshRenderItemIDs) {
|
||||||
|
transaction.updateItem<ModelMeshPartPayload>(item, [cullWithParent, renderItemsKey](ModelMeshPartPayload& data) {
|
||||||
|
data.setCullWithParent(cullWithParent);
|
||||||
|
data.updateKey(renderItemsKey);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const render::ItemKey Model::getRenderItemKeyGlobalFlags() const {
|
const render::ItemKey Model::getRenderItemKeyGlobalFlags() const {
|
||||||
return _renderItemKeyGlobalFlags;
|
return _renderItemKeyGlobalFlags;
|
||||||
}
|
}
|
||||||
|
@ -1040,7 +1056,7 @@ void Model::renderDebugMeshBoxes(gpu::Batch& batch, bool forward) {
|
||||||
Transform meshToWorld(meshToWorldMatrix);
|
Transform meshToWorld(meshToWorldMatrix);
|
||||||
batch.setModelTransform(meshToWorld);
|
batch.setModelTransform(meshToWorld);
|
||||||
|
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, false, true, true, forward);
|
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, false, true, true, forward, graphics::MaterialKey::CULL_NONE);
|
||||||
|
|
||||||
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
|
for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
|
||||||
for (auto &partTriangleSet : meshTriangleSets) {
|
for (auto &partTriangleSet : meshTriangleSets) {
|
||||||
|
|
|
@ -129,6 +129,8 @@ public:
|
||||||
bool isCauterized() const { return _cauterized; }
|
bool isCauterized() const { return _cauterized; }
|
||||||
void setCauterized(bool value, const render::ScenePointer& scene);
|
void setCauterized(bool value, const render::ScenePointer& scene);
|
||||||
|
|
||||||
|
void setCullWithParent(bool value);
|
||||||
|
|
||||||
// Access the current RenderItemKey Global Flags used by the model and applied to the render items representing the parts of the model.
|
// Access the current RenderItemKey Global Flags used by the model and applied to the render items representing the parts of the model.
|
||||||
const render::ItemKey getRenderItemKeyGlobalFlags() const;
|
const render::ItemKey getRenderItemKeyGlobalFlags() const;
|
||||||
|
|
||||||
|
@ -503,6 +505,7 @@ protected:
|
||||||
//
|
//
|
||||||
render::ItemKey _renderItemKeyGlobalFlags;
|
render::ItemKey _renderItemKeyGlobalFlags;
|
||||||
bool _cauterized { false };
|
bool _cauterized { false };
|
||||||
|
bool _cullWithParent { false };
|
||||||
|
|
||||||
bool shouldInvalidatePayloadShapeKey(int meshIndex);
|
bool shouldInvalidatePayloadShapeKey(int meshIndex);
|
||||||
|
|
||||||
|
|
|
@ -259,46 +259,44 @@ void addPlumberPipeline(ShapePlumber& plumber,
|
||||||
|
|
||||||
gpu::ShaderPointer program = gpu::Shader::createProgram(programId);
|
gpu::ShaderPointer program = gpu::Shader::createProgram(programId);
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
bool isCulled = (i & 1);
|
bool isBiased = (i & 1);
|
||||||
bool isBiased = (i & 2);
|
bool isWireframed = (i & 2);
|
||||||
bool isWireframed = (i & 4);
|
for (int cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_NONE; cullFaceMode < graphics::MaterialKey::CullFaceMode::NUM_CULL_FACE_MODES; cullFaceMode++) {
|
||||||
|
auto state = std::make_shared<gpu::State>();
|
||||||
|
key.isTranslucent() ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state);
|
||||||
|
|
||||||
auto state = std::make_shared<gpu::State>();
|
// Depth test depends on transparency
|
||||||
key.isTranslucent() ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state);
|
state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);
|
||||||
|
state->setBlendFunction(key.isTranslucent(),
|
||||||
|
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);
|
||||||
|
|
||||||
// Depth test depends on transparency
|
ShapeKey::Builder builder(key);
|
||||||
state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);
|
builder.withCullFaceMode((graphics::MaterialKey::CullFaceMode)cullFaceMode);
|
||||||
state->setBlendFunction(key.isTranslucent(),
|
state->setCullMode((gpu::State::CullMode)cullFaceMode);
|
||||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
if (isWireframed) {
|
||||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
builder.withWireframe();
|
||||||
|
state->setFillMode(gpu::State::FILL_LINE);
|
||||||
|
}
|
||||||
|
if (isBiased) {
|
||||||
|
builder.withDepthBias();
|
||||||
|
state->setDepthBias(1.0f);
|
||||||
|
state->setDepthBiasSlopeScale(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
ShapeKey::Builder builder(key);
|
auto baseBatchSetter = (forceLightBatchSetter || key.isTranslucent()) ? &lightBatchSetter : &batchSetter;
|
||||||
if (!isCulled) {
|
render::ShapePipeline::BatchSetter finalBatchSetter;
|
||||||
builder.withoutCullFace();
|
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);
|
||||||
}
|
}
|
||||||
state->setCullMode(isCulled ? gpu::State::CULL_BACK : gpu::State::CULL_NONE);
|
|
||||||
if (isWireframed) {
|
|
||||||
builder.withWireframe();
|
|
||||||
state->setFillMode(gpu::State::FILL_LINE);
|
|
||||||
}
|
|
||||||
if (isBiased) {
|
|
||||||
builder.withDepthBias();
|
|
||||||
state->setDepthBias(1.0f);
|
|
||||||
state->setDepthBiasSlopeScale(1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto baseBatchSetter = (forceLightBatchSetter || 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,8 +385,10 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
||||||
std::call_once(once, [] {
|
std::call_once(once, [] {
|
||||||
for (int i = 0; i < graphics::Material::NUM_TOTAL_FLAGS; i++) {
|
for (int i = 0; i < graphics::Material::NUM_TOTAL_FLAGS; i++) {
|
||||||
// The opacity mask/map are derived from the albedo map
|
// The opacity mask/map are derived from the albedo map
|
||||||
|
// FIXME: OPACITY_MAP_MODE_BIT is supposed to support fallthrough
|
||||||
if (i != graphics::MaterialKey::OPACITY_MASK_MAP_BIT &&
|
if (i != graphics::MaterialKey::OPACITY_MASK_MAP_BIT &&
|
||||||
i != graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT) {
|
i != graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT &&
|
||||||
|
i != graphics::MaterialKey::OPACITY_MAP_MODE_BIT) {
|
||||||
allFlags.insert(i);
|
allFlags.insert(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -642,6 +642,12 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
||||||
wasSet = true;
|
wasSet = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case graphics::Material::CULL_FACE_MODE:
|
||||||
|
if (!fallthrough) {
|
||||||
|
multiMaterial.setCullFaceMode(material->getCullFaceMode());
|
||||||
|
wasSet = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -683,6 +689,8 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
||||||
case graphics::Material::MATERIAL_PARAMS:
|
case graphics::Material::MATERIAL_PARAMS:
|
||||||
// these are initialized to the correct default values in Schema()
|
// these are initialized to the correct default values in Schema()
|
||||||
break;
|
break;
|
||||||
|
case graphics::Material::CULL_FACE_MODE:
|
||||||
|
multiMaterial.setCullFaceMode(graphics::Material::DEFAULT_CULL_FACE_MODE);
|
||||||
case graphics::MaterialKey::ALBEDO_MAP_BIT:
|
case graphics::MaterialKey::ALBEDO_MAP_BIT:
|
||||||
if (schemaKey.isAlbedoMap()) {
|
if (schemaKey.isAlbedoMap()) {
|
||||||
drawMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, textureCache->getWhiteTexture());
|
drawMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, textureCache->getWhiteTexture());
|
||||||
|
|
|
@ -61,12 +61,12 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
||||||
const auto currentKeyLight = setupOutput.getN<RenderShadowSetup::Output>(4);
|
const auto currentKeyLight = setupOutput.getN<RenderShadowSetup::Output>(4);
|
||||||
// Fetch and cull the items from the scene
|
// Fetch and cull the items from the scene
|
||||||
|
|
||||||
static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask);
|
static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withOpaque().withoutLayered().withTagBits(tagBits, tagMask);
|
||||||
|
|
||||||
const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterReceiverFilter, queryResolution).asVarying();
|
const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterReceiverFilter, queryResolution).asVarying();
|
||||||
const auto shadowSelection = task.addJob<FetchSpatialTree>("FetchShadowTree", fetchInput);
|
const auto shadowSelection = task.addJob<FetchSpatialTree>("FetchShadowTree", fetchInput);
|
||||||
const auto selectionInputs = FilterSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying();
|
const auto selectionInputs = CullSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying();
|
||||||
const auto shadowItems = task.addJob<FilterSpatialSelection>("FilterShadowSelection", selectionInputs);
|
const auto shadowItems = task.addJob<CullSpatialSelection>("FilterShadowSelection", selectionInputs, nullptr, true, RenderDetails::SHADOW);
|
||||||
|
|
||||||
// Cull objects that are not visible in camera view. Hopefully the cull functor only performs LOD culling, not
|
// Cull objects that are not visible in camera view. Hopefully the cull functor only performs LOD culling, not
|
||||||
// frustum culling or this will make shadow casters out of the camera frustum disappear.
|
// frustum culling or this will make shadow casters out of the camera frustum disappear.
|
||||||
|
|
|
@ -110,7 +110,7 @@ void main(void) {
|
||||||
<@else@>
|
<@else@>
|
||||||
float cutoff = getMaterialOpacityCutoff(mat);
|
float cutoff = getMaterialOpacityCutoff(mat);
|
||||||
float opacity = 1.0;
|
float opacity = 1.0;
|
||||||
<$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity)$>;
|
<$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity, matKey, opacity)$>;
|
||||||
<$discardTransparent(opacity)$>;
|
<$discardTransparent(opacity)$>;
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ void main(void) {
|
||||||
<@else@>
|
<@else@>
|
||||||
float cutoff = getMaterialOpacityCutoff(mat);
|
float cutoff = getMaterialOpacityCutoff(mat);
|
||||||
float opacity = 1.0;
|
float opacity = 1.0;
|
||||||
<$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity)$>;
|
<$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity, matKey, opacity)$>;
|
||||||
<$discardTransparent(opacity)$>;
|
<$discardTransparent(opacity)$>;
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@>
|
<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@>
|
||||||
<@include MeshDeformer.slh@>
|
<@include MeshDeformer.slh@>
|
||||||
<@if HIFI_USE_DEFORMED@>
|
<@if HIFI_USE_DEFORMED@>
|
||||||
<$declareMeshDeformer(1, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$>
|
<$declareMeshDeformer(1, 1, 1, _SCRIBE_NULL, 1)$>
|
||||||
<@else@>
|
<@else@>
|
||||||
<$declareMeshDeformer(1, _SCRIBE_NULL, 1, 1, 1)$>
|
<$declareMeshDeformer(1, 1, 1, 1, 1)$>
|
||||||
<@endif@>
|
<@endif@>
|
||||||
<$declareMeshDeformerActivation(1, 1)$>
|
<$declareMeshDeformerActivation(1, 1)$>
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
@ -34,24 +34,56 @@ layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS;
|
||||||
layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color;
|
layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color;
|
||||||
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01;
|
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01;
|
||||||
|
|
||||||
|
<@include procedural/ProceduralCommon.slh@>
|
||||||
|
|
||||||
|
#line 1001
|
||||||
|
//PROCEDURAL_BLOCK_BEGIN
|
||||||
|
|
||||||
|
void getProceduralVertex(inout ProceduralVertexData proceduralData) {}
|
||||||
|
|
||||||
|
//PROCEDURAL_BLOCK_END
|
||||||
|
|
||||||
|
#line 2030
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 positionMS = inPosition;
|
vec4 positionMS = inPosition;
|
||||||
vec3 normalMS = inNormal.xyz;
|
vec3 normalMS = inNormal.xyz;
|
||||||
|
vec3 tangentMS = inTangent.xyz;
|
||||||
|
vec4 color = color_sRGBAToLinear(inColor);
|
||||||
|
vec2 texCoord0 = inTexCoord0.st;
|
||||||
|
|
||||||
<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@>
|
<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@>
|
||||||
evalMeshDeformer(inPosition, positionMS, inNormal.xyz, normalMS,
|
evalMeshDeformer(inPosition, positionMS, inNormal.xyz, normalMS, inTangent.xyz, tangentMS,
|
||||||
meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight,
|
meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight,
|
||||||
meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID);
|
meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID);
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
||||||
|
#if defined(PROCEDURAL_V1) || defined(PROCEDURAL_V2) || defined(PROCEDURAL_V3)
|
||||||
|
ProceduralVertexData proceduralData = ProceduralVertexData(
|
||||||
|
positionMS,
|
||||||
|
inPosition,
|
||||||
|
normalMS,
|
||||||
|
inNormal.xyz,
|
||||||
|
tangentMS,
|
||||||
|
inTangent.xyz,
|
||||||
|
color,
|
||||||
|
texCoord0
|
||||||
|
);
|
||||||
|
|
||||||
|
getProceduralVertex(proceduralData);
|
||||||
|
|
||||||
|
positionMS = proceduralData.position;
|
||||||
|
normalMS = proceduralData.normal;
|
||||||
|
color = proceduralData.color;
|
||||||
|
texCoord0 = proceduralData.texCoord0;
|
||||||
|
#endif
|
||||||
|
|
||||||
_positionMS = positionMS;
|
_positionMS = positionMS;
|
||||||
_normalMS = normalMS;
|
_normalMS = normalMS;
|
||||||
|
_color = color;
|
||||||
|
_texCoord01 = vec4(texCoord0, 0.0, 0.0);
|
||||||
|
|
||||||
TransformCamera cam = getTransformCamera();
|
TransformCamera cam = getTransformCamera();
|
||||||
TransformObject obj = getTransformObject();
|
TransformObject obj = getTransformObject();
|
||||||
<$transformModelToEyeAndClipPos(cam, obj, positionMS, _positionES, gl_Position)$>
|
<$transformModelToEyeAndClipPos(cam, obj, positionMS, _positionES, gl_Position)$>
|
||||||
<$transformModelToWorldDir(cam, obj, normalMS, _normalWS)$>
|
<$transformModelToWorldDir(cam, obj, normalMS, _normalWS)$>
|
||||||
|
|
||||||
_color = color_sRGBAToLinear(inColor);
|
|
||||||
_texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0);
|
|
||||||
}
|
}
|
|
@ -172,7 +172,7 @@ void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inpu
|
||||||
void CullSpatialSelection::configure(const Config& config) {
|
void CullSpatialSelection::configure(const Config& config) {
|
||||||
_justFrozeFrustum = _justFrozeFrustum || (config.freezeFrustum && !_freezeFrustum);
|
_justFrozeFrustum = _justFrozeFrustum || (config.freezeFrustum && !_freezeFrustum);
|
||||||
_freezeFrustum = config.freezeFrustum;
|
_freezeFrustum = config.freezeFrustum;
|
||||||
_skipCulling = config.skipCulling;
|
_overrideSkipCulling = config.skipCulling;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CullSpatialSelection::run(const RenderContextPointer& renderContext,
|
void CullSpatialSelection::run(const RenderContextPointer& renderContext,
|
||||||
|
@ -209,7 +209,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext,
|
||||||
// filter individually against the _filter
|
// filter individually against the _filter
|
||||||
// visibility cull if partially selected ( octree cell contianing it was partial)
|
// visibility cull if partially selected ( octree cell contianing it was partial)
|
||||||
// distance cull if was a subcell item ( octree cell is way bigger than the item bound itself, so now need to test per item)
|
// distance cull if was a subcell item ( octree cell is way bigger than the item bound itself, so now need to test per item)
|
||||||
if (_skipCulling) {
|
if (_skipCulling || _overrideSkipCulling) {
|
||||||
// inside & fit items: filter only, culling is disabled
|
// inside & fit items: filter only, culling is disabled
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("insideFitItems");
|
PerformanceTimer perfTimer("insideFitItems");
|
||||||
|
@ -444,69 +444,3 @@ void ApplyCullFunctorOnItemBounds::run(const RenderContextPointer& renderContext
|
||||||
args->popViewFrustum();
|
args->popViewFrustum();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilterSpatialSelection::run(const RenderContextPointer& renderContext,
|
|
||||||
const Inputs& inputs, ItemBounds& outItems) {
|
|
||||||
assert(renderContext->args);
|
|
||||||
auto& scene = renderContext->_scene;
|
|
||||||
auto& inSelection = inputs.get0();
|
|
||||||
|
|
||||||
// Now we have a selection of items to render
|
|
||||||
outItems.clear();
|
|
||||||
outItems.reserve(inSelection.numItems());
|
|
||||||
|
|
||||||
const auto filter = inputs.get1();
|
|
||||||
if (!filter.selectsNothing()) {
|
|
||||||
// Now get the bound, and
|
|
||||||
// filter individually against the _filter
|
|
||||||
|
|
||||||
// inside & fit items: filter only
|
|
||||||
{
|
|
||||||
PerformanceTimer perfTimer("insideFitItems");
|
|
||||||
for (auto id : inSelection.insideItems) {
|
|
||||||
auto& item = scene->getItem(id);
|
|
||||||
if (filter.test(item.getKey())) {
|
|
||||||
ItemBound itemBound(id, item.getBound());
|
|
||||||
outItems.emplace_back(itemBound);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// inside & subcell items: filter only
|
|
||||||
{
|
|
||||||
PerformanceTimer perfTimer("insideSmallItems");
|
|
||||||
for (auto id : inSelection.insideSubcellItems) {
|
|
||||||
auto& item = scene->getItem(id);
|
|
||||||
if (filter.test(item.getKey())) {
|
|
||||||
ItemBound itemBound(id, item.getBound());
|
|
||||||
outItems.emplace_back(itemBound);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// partial & fit items: filter only
|
|
||||||
{
|
|
||||||
PerformanceTimer perfTimer("partialFitItems");
|
|
||||||
for (auto id : inSelection.partialItems) {
|
|
||||||
auto& item = scene->getItem(id);
|
|
||||||
if (filter.test(item.getKey())) {
|
|
||||||
ItemBound itemBound(id, item.getBound());
|
|
||||||
outItems.emplace_back(itemBound);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// partial & subcell items: filter only
|
|
||||||
{
|
|
||||||
PerformanceTimer perfTimer("partialSmallItems");
|
|
||||||
for (auto id : inSelection.partialSubcellItems) {
|
|
||||||
auto& item = scene->getItem(id);
|
|
||||||
if (filter.test(item.getKey())) {
|
|
||||||
ItemBound itemBound(id, item.getBound());
|
|
||||||
outItems.emplace_back(itemBound);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -100,26 +100,25 @@ namespace render {
|
||||||
};
|
};
|
||||||
|
|
||||||
class CullSpatialSelection {
|
class CullSpatialSelection {
|
||||||
bool _freezeFrustum{ false }; // initialized by Config
|
|
||||||
bool _justFrozeFrustum{ false };
|
|
||||||
bool _skipCulling{ false };
|
|
||||||
ViewFrustum _frozenFrustum;
|
|
||||||
public:
|
public:
|
||||||
using Config = CullSpatialSelectionConfig;
|
using Config = CullSpatialSelectionConfig;
|
||||||
using Inputs = render::VaryingSet2<ItemSpatialTree::ItemSelection, ItemFilter>;
|
using Inputs = render::VaryingSet2<ItemSpatialTree::ItemSelection, ItemFilter>;
|
||||||
using JobModel = Job::ModelIO<CullSpatialSelection, Inputs, ItemBounds, Config>;
|
using JobModel = Job::ModelIO<CullSpatialSelection, Inputs, ItemBounds, Config>;
|
||||||
|
|
||||||
CullSpatialSelection(CullFunctor cullFunctor, RenderDetails::Type type) :
|
CullSpatialSelection(CullFunctor cullFunctor, bool skipCulling, RenderDetails::Type type) :
|
||||||
_cullFunctor{ cullFunctor },
|
_cullFunctor(cullFunctor),
|
||||||
|
_skipCulling(skipCulling),
|
||||||
_detailType(type) {}
|
_detailType(type) {}
|
||||||
|
|
||||||
CullSpatialSelection(CullFunctor cullFunctor) :
|
|
||||||
_cullFunctor{ cullFunctor } {
|
|
||||||
}
|
|
||||||
|
|
||||||
CullFunctor _cullFunctor;
|
CullFunctor _cullFunctor;
|
||||||
|
bool _skipCulling { false };
|
||||||
RenderDetails::Type _detailType{ RenderDetails::OTHER };
|
RenderDetails::Type _detailType{ RenderDetails::OTHER };
|
||||||
|
|
||||||
|
bool _freezeFrustum { false }; // initialized by Config
|
||||||
|
bool _justFrozeFrustum { false };
|
||||||
|
bool _overrideSkipCulling { false };
|
||||||
|
ViewFrustum _frozenFrustum;
|
||||||
|
|
||||||
void configure(const Config& config);
|
void configure(const Config& config);
|
||||||
void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems);
|
void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems);
|
||||||
};
|
};
|
||||||
|
@ -147,15 +146,6 @@ namespace render {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FilterSpatialSelection {
|
|
||||||
public:
|
|
||||||
using Inputs = render::VaryingSet2<ItemSpatialTree::ItemSelection, ItemFilter>;
|
|
||||||
using JobModel = Job::ModelIO<FilterSpatialSelection, Inputs, ItemBounds>;
|
|
||||||
|
|
||||||
FilterSpatialSelection() {}
|
|
||||||
void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems);
|
|
||||||
};
|
|
||||||
|
|
||||||
class ApplyCullFunctorOnItemBounds {
|
class ApplyCullFunctorOnItemBounds {
|
||||||
public:
|
public:
|
||||||
using Inputs = render::VaryingSet2<ItemBounds, ViewFrustumPointer>;
|
using Inputs = render::VaryingSet2<ItemBounds, ViewFrustumPointer>;
|
||||||
|
|
|
@ -625,7 +625,7 @@ template <> const ShapeKey shapeGetShapeKey(const PayloadProxyInterface::Pointer
|
||||||
|
|
||||||
|
|
||||||
typedef Item::PayloadPointer PayloadPointer;
|
typedef Item::PayloadPointer PayloadPointer;
|
||||||
typedef std::vector< PayloadPointer > Payloads;
|
typedef std::vector<PayloadPointer> Payloads;
|
||||||
|
|
||||||
// A map of items by ShapeKey to optimize rendering pipeline assignments
|
// A map of items by ShapeKey to optimize rendering pipeline assignments
|
||||||
using ShapeBounds = std::unordered_map<ShapeKey, ItemBounds, ShapeKey::Hash, ShapeKey::KeyEqual>;
|
using ShapeBounds = std::unordered_map<ShapeKey, ItemBounds, ShapeKey::Hash, ShapeKey::KeyEqual>;
|
||||||
|
|
|
@ -27,7 +27,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin
|
||||||
const auto fetchInput = FetchSpatialTree::Inputs(filter, glm::ivec2(0,0)).asVarying();
|
const auto fetchInput = FetchSpatialTree::Inputs(filter, glm::ivec2(0,0)).asVarying();
|
||||||
const auto spatialSelection = task.addJob<FetchSpatialTree>("FetchSceneSelection", fetchInput);
|
const auto spatialSelection = task.addJob<FetchSpatialTree>("FetchSceneSelection", fetchInput);
|
||||||
const auto cullInputs = CullSpatialSelection::Inputs(spatialSelection, spatialFilter).asVarying();
|
const auto cullInputs = CullSpatialSelection::Inputs(spatialSelection, spatialFilter).asVarying();
|
||||||
const auto culledSpatialSelection = task.addJob<CullSpatialSelection>("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM);
|
const auto culledSpatialSelection = task.addJob<CullSpatialSelection>("CullSceneSelection", cullInputs, cullFunctor, false, RenderDetails::ITEM);
|
||||||
|
|
||||||
// Layered objects are not culled
|
// Layered objects are not culled
|
||||||
const ItemFilter layeredFilter = ItemFilter::Builder::visibleWorldItems().withTagBits(tagBits, tagMask);
|
const ItemFilter layeredFilter = ItemFilter::Builder::visibleWorldItems().withTagBits(tagBits, tagMask);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <gpu/Batch.h>
|
#include <gpu/Batch.h>
|
||||||
|
#include <graphics/Material.h>
|
||||||
|
|
||||||
#include "Args.h"
|
#include "Args.h"
|
||||||
|
|
||||||
|
@ -34,8 +35,9 @@ public:
|
||||||
DUAL_QUAT_SKINNED,
|
DUAL_QUAT_SKINNED,
|
||||||
DEPTH_BIAS,
|
DEPTH_BIAS,
|
||||||
WIREFRAME,
|
WIREFRAME,
|
||||||
NO_CULL_FACE,
|
|
||||||
FADE,
|
FADE,
|
||||||
|
CULL_FACE_NONE, // if neither of these are set, we're CULL_FACE_BACK
|
||||||
|
CULL_FACE_FRONT,
|
||||||
|
|
||||||
OWN_PIPELINE,
|
OWN_PIPELINE,
|
||||||
INVALID,
|
INVALID,
|
||||||
|
@ -81,9 +83,29 @@ public:
|
||||||
Builder& withDualQuatSkinned() { _flags.set(DUAL_QUAT_SKINNED); return (*this); }
|
Builder& withDualQuatSkinned() { _flags.set(DUAL_QUAT_SKINNED); return (*this); }
|
||||||
Builder& withDepthBias() { _flags.set(DEPTH_BIAS); return (*this); }
|
Builder& withDepthBias() { _flags.set(DEPTH_BIAS); return (*this); }
|
||||||
Builder& withWireframe() { _flags.set(WIREFRAME); 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& withFade() { _flags.set(FADE); return (*this); }
|
||||||
|
|
||||||
|
Builder& withoutCullFace() { return withCullFaceMode(graphics::MaterialKey::CullFaceMode::CULL_NONE); }
|
||||||
|
Builder& withCullFaceMode(graphics::MaterialKey::CullFaceMode cullFaceMode) {
|
||||||
|
switch (cullFaceMode) {
|
||||||
|
case graphics::MaterialKey::CullFaceMode::CULL_NONE:
|
||||||
|
_flags.set(CULL_FACE_NONE);
|
||||||
|
_flags.reset(CULL_FACE_FRONT);
|
||||||
|
break;
|
||||||
|
case graphics::MaterialKey::CullFaceMode::CULL_FRONT:
|
||||||
|
_flags.reset(CULL_FACE_NONE);
|
||||||
|
_flags.set(CULL_FACE_FRONT);
|
||||||
|
break;
|
||||||
|
case graphics::MaterialKey::CullFaceMode::CULL_BACK:
|
||||||
|
_flags.reset(CULL_FACE_NONE);
|
||||||
|
_flags.reset(CULL_FACE_FRONT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
Builder& withOwnPipeline() { _flags.set(OWN_PIPELINE); return (*this); }
|
Builder& withOwnPipeline() { _flags.set(OWN_PIPELINE); return (*this); }
|
||||||
Builder& invalidate() { _flags.set(INVALID); return (*this); }
|
Builder& invalidate() { _flags.set(INVALID); return (*this); }
|
||||||
|
|
||||||
|
@ -137,8 +159,27 @@ public:
|
||||||
Builder& withWireframe() { _flags.set(WIREFRAME); _mask.set(WIREFRAME); return (*this); }
|
Builder& withWireframe() { _flags.set(WIREFRAME); _mask.set(WIREFRAME); return (*this); }
|
||||||
Builder& withoutWireframe() { _flags.reset(WIREFRAME); _mask.set(WIREFRAME); return (*this); }
|
Builder& withoutWireframe() { _flags.reset(WIREFRAME); _mask.set(WIREFRAME); return (*this); }
|
||||||
|
|
||||||
Builder& withCullFace() { _flags.reset(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); }
|
Builder& withCullFaceMode(graphics::MaterialKey::CullFaceMode cullFaceMode) {
|
||||||
Builder& withoutCullFace() { _flags.set(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); }
|
switch (cullFaceMode) {
|
||||||
|
case graphics::MaterialKey::CullFaceMode::CULL_NONE:
|
||||||
|
_flags.set(CULL_FACE_NONE);
|
||||||
|
_flags.reset(CULL_FACE_FRONT);
|
||||||
|
break;
|
||||||
|
case graphics::MaterialKey::CullFaceMode::CULL_FRONT:
|
||||||
|
_flags.reset(CULL_FACE_NONE);
|
||||||
|
_flags.set(CULL_FACE_FRONT);
|
||||||
|
break;
|
||||||
|
case graphics::MaterialKey::CullFaceMode::CULL_BACK:
|
||||||
|
_flags.reset(CULL_FACE_NONE);
|
||||||
|
_flags.reset(CULL_FACE_FRONT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_mask.set(CULL_FACE_NONE);
|
||||||
|
_mask.set(CULL_FACE_FRONT);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
Builder& withFade() { _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); }
|
Builder& withoutFade() { _flags.reset(FADE); _mask.set(FADE); return (*this); }
|
||||||
|
@ -168,7 +209,7 @@ public:
|
||||||
bool isDualQuatSkinned() const { return _flags[DUAL_QUAT_SKINNED]; }
|
bool isDualQuatSkinned() const { return _flags[DUAL_QUAT_SKINNED]; }
|
||||||
bool isDepthBiased() const { return _flags[DEPTH_BIAS]; }
|
bool isDepthBiased() const { return _flags[DEPTH_BIAS]; }
|
||||||
bool isWireframe() const { return _flags[WIREFRAME]; }
|
bool isWireframe() const { return _flags[WIREFRAME]; }
|
||||||
bool isCullFace() const { return !_flags[NO_CULL_FACE]; }
|
bool isCullFace() const { return !_flags[CULL_FACE_NONE] && !_flags[CULL_FACE_FRONT]; }
|
||||||
bool isFaded() const { return _flags[FADE]; }
|
bool isFaded() const { return _flags[FADE]; }
|
||||||
|
|
||||||
bool hasOwnPipeline() const { return _flags[OWN_PIPELINE]; }
|
bool hasOwnPipeline() const { return _flags[OWN_PIPELINE]; }
|
||||||
|
|
Loading…
Reference in a new issue