From 6e961b9f2fad7a7129f8a4b36e6c4f49d54d3e7a Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Fri, 15 Nov 2019 00:18:24 -0800 Subject: [PATCH 01/16] procedural vertex shaders Signed-off-by: Kasen IO --- interface/src/Application.cpp | 17 +++ .../src/RenderableMaterialEntityItem.cpp | 15 ++- .../src/RenderableMaterialEntityItem.h | 2 +- .../src/RenderableShapeEntityItem.cpp | 12 ++ .../src/RenderableShapeEntityItem.h | 1 + libraries/entities/src/EntityTree.cpp | 8 ++ libraries/entities/src/EntityTree.h | 4 + libraries/entities/src/MaterialEntityItem.cpp | 26 +++- libraries/entities/src/MaterialEntityItem.h | 6 + .../procedural/src/procedural/Procedural.cpp | 111 ++++++++++++++---- .../procedural/src/procedural/Procedural.h | 22 +++- .../src/procedural/ProceduralCommon.slh | 11 ++ .../render-utils/src/MeshPartPayload.cpp | 10 ++ .../render-utils/src/simple_procedural.slv | 44 ++++++- 14 files changed, 253 insertions(+), 36 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9c60139d06..492495808e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2107,6 +2107,23 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } return false; }); + EntityTree::setGetUnscaledDimensionsForEntityIDOperator([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(); + auto avatar = static_pointer_cast(avatarManager->getAvatarBySessionID(id)); + if (avatar) { + return avatar->getSNScale(); + } + return glm::vec3(1.0f); + }); Procedural::opaqueStencil = [](gpu::StatePointer state) { PrepareStencil::testMaskDrawShape(*state); }; Procedural::transparentStencil = [](gpu::StatePointer state) { PrepareStencil::testMask(*state); }; diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index a013ff75b7..af121f2957 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -153,13 +153,13 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo if (urlChanged && !usingMaterialData) { _networkMaterial = DependencyManager::get()->getMaterial(_materialURL); - auto onMaterialRequestFinished = [this, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) { + auto onMaterialRequestFinished = [this, entity, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) { if (success) { deleteMaterial(oldParentID, oldParentMaterialName); _texturesLoaded = false; _parsedMaterials = _networkMaterial->parsedMaterials; setCurrentMaterialName(newCurrentMaterialName); - applyMaterial(); + applyMaterial(entity); } else { deleteMaterial(oldParentID, oldParentMaterialName); _retryApply = false; @@ -183,13 +183,13 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo _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 setCurrentMaterialName(newCurrentMaterialName); - applyMaterial(); + applyMaterial(entity); } else { if (deleteNeeded) { deleteMaterial(oldParentID, oldParentMaterialName); } if (addNeeded) { - applyMaterial(); + applyMaterial(entity); } } @@ -382,7 +382,7 @@ void MaterialEntityRenderer::applyTextureTransform(std::shared_ptrsetTextureTransforms(textureTransform, _materialMappingMode, _materialRepeat); } -void MaterialEntityRenderer::applyMaterial() { +void MaterialEntityRenderer::applyMaterial(const TypedEntityPointer& entity) { _retryApply = false; std::shared_ptr material = getMaterial(); @@ -396,6 +396,11 @@ void MaterialEntityRenderer::applyMaterial() { graphics::MaterialLayer materialLayer = graphics::MaterialLayer(material, _priority); + if (auto procedural = std::static_pointer_cast(material)) { + procedural->setBoundOperator([this] { return getBound(); }); + entity->setHasVertexShader(procedural->hasVertexShader()); + } + // Our parent could be an entity or an avatar std::string parentMaterialName = _parentMaterialName.toStdString(); if (EntityTreeRenderer::addMaterialToEntity(parentID, materialLayer, parentMaterialName)) { diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h index ff7367a44e..3a73c988eb 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h @@ -56,7 +56,7 @@ private: void setCurrentMaterialName(const std::string& currentMaterialName); void applyTextureTransform(std::shared_ptr& material); - void applyMaterial(); + void applyMaterial(const TypedEntityPointer& entity); void deleteMaterial(const QUuid& oldParentID, const QString& oldParentMaterialName); NetworkMaterialResourcePointer _networkMaterial; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 88cc78b6b6..497294e45a 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -207,6 +207,18 @@ ShapeKey ShapeEntityRenderer::getShapeKey() { 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(mat->second.top().material); + if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { + return procedural->getBound(); + } + } + return Parent::getBound(); +} + void ShapeEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); Q_ASSERT(args->_batch); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 6061526f75..5bc61606ad 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -26,6 +26,7 @@ public: protected: ShapeKey getShapeKey() override; + Item::Bound getBound() override; private: virtual bool needsRenderUpdate() const override; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 6c12c6d019..565fb37781 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -3113,6 +3113,7 @@ std::function EntityTree::_getEntityObjectOperator = nul std::function EntityTree::_textSizeOperator = nullptr; std::function EntityTree::_areEntityClicksCapturedOperator = nullptr; std::function EntityTree::_emitScriptEventOperator = nullptr; +std::function EntityTree::_getUnscaledDimensionsForEntityIDOperator = nullptr; QObject* EntityTree::getEntityObject(const QUuid& id) { if (_getEntityObjectOperator) { @@ -3141,6 +3142,13 @@ void EntityTree::emitScriptEvent(const QUuid& id, const QVariant& message) { } } +glm::vec3 EntityTree::getUnscaledDimensionsForEntityID(const QUuid& id) { + if (_getUnscaledDimensionsForEntityIDOperator) { + return _getUnscaledDimensionsForEntityIDOperator(id); + } + return glm::vec3(1.0f); +} + void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender, MovingEntitiesOperator& moveOperator, bool force, bool tellServer) { // if the queryBox has changed, tell the entity-server diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 9108f8d8d2..c083493e99 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -271,6 +271,9 @@ public: static void setEmitScriptEventOperator(std::function emitScriptEventOperator) { _emitScriptEventOperator = emitScriptEventOperator; } static void emitScriptEvent(const QUuid& id, const QVariant& message); + static void setGetUnscaledDimensionsForEntityIDOperator(std::function getUnscaledDimensionsForEntityIDOperator) { _getUnscaledDimensionsForEntityIDOperator = getUnscaledDimensionsForEntityIDOperator; } + static glm::vec3 getUnscaledDimensionsForEntityID(const QUuid& id); + std::map getNamedPaths() const { return _namedPaths; } void updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender, @@ -386,6 +389,7 @@ private: static std::function _textSizeOperator; static std::function _areEntityClicksCapturedOperator; static std::function _emitScriptEventOperator; + static std::function _getUnscaledDimensionsForEntityIDOperator; std::vector _staleProxies; diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index 1a7c3c601b..22143e88ba 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -139,10 +139,10 @@ void MaterialEntityItem::debugDump() const { void MaterialEntityItem::setUnscaledDimensions(const glm::vec3& value) { _desiredDimensions = value; - if (_materialMappingMode == MaterialMappingMode::UV) { - EntityItem::setUnscaledDimensions(ENTITY_ITEM_DEFAULT_DIMENSIONS); - } else if (_materialMappingMode == MaterialMappingMode::PROJECTED) { + if (_hasVertexShader || _materialMappingMode == MaterialMappingMode::PROJECTED) { 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 aaCube = EntityItem::calculateInitialQueryAACube(success); // A Material entity's queryAACube contains its parent's queryAACube @@ -278,3 +285,16 @@ AACube MaterialEntityItem::calculateInitialQueryAACube(bool& success) { } 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::getUnscaledDimensionsForEntityID(getParentID())); + } else if (!hasVertexShader && prevHasVertexShader) { + setUnscaledDimensions(_desiredDimensions); + } +} \ No newline at end of file diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index 3f32486f0b..d8de8c3bc6 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -64,6 +64,8 @@ public: QString getParentMaterialName() const; void setParentMaterialName(const QString& parentMaterialName); + void setParentID(const QUuid& parentID) override; + glm::vec2 getMaterialMappingPos() const; void setMaterialMappingPos(const glm::vec2& materialMappingPos); glm::vec2 getMaterialMappingScale() const; @@ -73,6 +75,8 @@ public: AACube calculateInitialQueryAACube(bool& success) override; + void setHasVertexShader(bool hasVertexShader); + private: // 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: @@ -108,6 +112,8 @@ private: float _materialMappingRot { 0 }; QString _materialData; + bool _hasVertexShader { false }; + }; #endif // hifi_MaterialEntityItem_h diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 43c6b25dcb..22bfc3f1ad 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -29,6 +29,7 @@ Q_LOGGING_CATEGORY(proceduralLog, "hifi.gpu.procedural") // User-data parsing constants 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 URL_KEY = "shaderUrl"; 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) { return ((a.version == b.version) && (a.fragmentShaderUrl == b.fragmentShaderUrl) && + (a.vertexShaderUrl == b.vertexShaderUrl) && (a.uniforms == b.uniforms) && (a.channels == b.channels)); } @@ -101,9 +103,9 @@ void ProceduralData::parse(const QJsonObject& proceduralData) { } } - // Empty shader URL isn't valid - if (fragmentShaderUrl.isEmpty()) { - return; + { // Vertex shader URL + auto rawShaderUrl = proceduralData[VERTEX_URL_KEY].toString(); + vertexShaderUrl = DependencyManager::get()->normalizeURL(rawShaderUrl); } uniforms = proceduralData[UNIFORMS_KEY].toObject(); @@ -172,29 +174,57 @@ void Procedural::setProceduralData(const ProceduralData& proceduralData) { if (proceduralData.fragmentShaderUrl != _data.fragmentShaderUrl) { _data.fragmentShaderUrl = proceduralData.fragmentShaderUrl; - const auto& shaderUrl = _data.fragmentShaderUrl; _shaderDirty = true; _networkFragmentShader.reset(); _fragmentShaderPath.clear(); _fragmentShaderSource.clear(); - if (shaderUrl.isEmpty() || !shaderUrl.isValid()) { + if (!_data.fragmentShaderUrl.isValid()) { + qCWarning(proceduralLog) << "Invalid fragment shader URL: " << _data.fragmentShaderUrl; return; } - if (shaderUrl.isLocalFile()) { - if (!QFileInfo(shaderUrl.toLocalFile()).exists()) { + if (_data.fragmentShaderUrl.isLocalFile()) { + if (!QFileInfo(_data.fragmentShaderUrl.toLocalFile()).exists()) { + qCWarning(proceduralLog) << "Invalid fragment shader URL, missing local file: " << _data.fragmentShaderUrl; return; } - _fragmentShaderPath = shaderUrl.toLocalFile(); - } else if (shaderUrl.scheme() == URL_SCHEME_QRC) { - _fragmentShaderPath = ":" + shaderUrl.path(); + _fragmentShaderPath = _data.fragmentShaderUrl.toLocalFile(); + } else if (_data.fragmentShaderUrl.scheme() == URL_SCHEME_QRC) { + _fragmentShaderPath = ":" + _data.fragmentShaderUrl.path(); } 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; } @@ -213,8 +243,12 @@ bool Procedural::isReady() const { _fadeStartTime = usecTimestampNow(); } - // Do we have a network or local shader, and if so, is it loaded? - if (_fragmentShaderPath.isEmpty() && (!_networkFragmentShader || !_networkFragmentShader->isLoaded())) { + // We need to have at least one shader, and whichever ones we have need to be loaded + 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; } @@ -258,6 +292,20 @@ void Procedural::prepare(gpu::Batch& batch, _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) { _proceduralPipelines.clear(); } @@ -276,25 +324,42 @@ void Procedural::prepare(gpu::Batch& batch, 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[PROCEDURAL_VERSION] = "#define PROCEDURAL_V" + std::to_string(_data.version); - fragmentSource.replacements[PROCEDURAL_BLOCK] = _fragmentShaderSource.toStdString(); + fragmentSource.replacements[PROCEDURAL_VERSION] = versionDefine; + 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) if (!_data.uniforms.empty()) { - // First grab all the possible dialect/variant/Reflections - std::vector allReflections; + // First grab all the possible dialect/variant/reflections + std::vector allFragmentReflections; for (auto dialectIt = fragmentSource.dialectSources.begin(); dialectIt != fragmentSource.dialectSources.end(); ++dialectIt) { 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 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 int customSlot = procedural::slot::uniform::Custom; for (const auto& key : _data.uniforms.keys()) { 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; } ++customSlot; @@ -303,6 +368,7 @@ void Procedural::prepare(gpu::Batch& batch, // Leave this here for debugging //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 fragmentShader = gpu::Shader::createPixel(fragmentSource); @@ -453,6 +519,11 @@ glm::vec4 Procedural::getColor(const glm::vec4& entityColor) const { return entityColor; } +bool Procedural::hasVertexShader() const { + std::lock_guard lock(_mutex); + return !_data.vertexShaderUrl.isEmpty(); +} + void graphics::ProceduralMaterial::initializeProcedural() { _procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural); _procedural._vertexSourceSkinned = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural_deformed); diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index aac353bf7c..89f21218e6 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -36,6 +36,8 @@ const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 }; * The data used to define a Procedural shader material. * @typedef {object} ProceduralData * @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. * shaderUrl is an alias. * @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 uint8_t version { 0 }; QUrl fragmentShaderUrl; + QUrl vertexShaderUrl; QJsonObject uniforms; QJsonArray channels; }; @@ -110,6 +113,11 @@ public: void setIsFading(bool isFading) { _isFading = isFading; } void setDoesFade(bool doesFade) { _doesFade = doesFade; } + bool hasVertexShader() const; + void setBoundOperator(const std::function& boundOperator) { _boundOperator = boundOperator; } + bool hasBoundOperator() const { return (bool)_boundOperator; } + AABox getBound() { return _boundOperator(); } + gpu::Shader::Source _vertexSource; gpu::Shader::Source _vertexSourceSkinned; gpu::Shader::Source _vertexSourceSkinnedDQ; @@ -156,7 +164,11 @@ protected: uint64_t _firstCompile { 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 _fragmentShaderPath; uint64_t _fragmentShaderModified { 0 }; @@ -187,6 +199,9 @@ private: mutable bool _isFading { false }; bool _doesFade { true }; ProceduralProgramKey _prevKey; + + std::function _boundOperator { nullptr }; + mutable std::mutex _mutex; }; @@ -210,6 +225,7 @@ public: bool isFading() const { return _procedural.isFading(); } void setIsFading(bool isFading) { _procedural.setIsFading(isFading); } 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, const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) { _procedural.prepare(batch, position, size, orientation, created, key); @@ -217,6 +233,10 @@ public: void initializeProcedural(); + void setBoundOperator(const std::function& boundOperator) { _procedural.setBoundOperator(boundOperator); } + bool hasBoundOperator() const { return _procedural.hasBoundOperator(); } + AABox getBound() { return _procedural.getBound(); } + private: QString _proceduralString; Procedural _procedural; diff --git a/libraries/procedural/src/procedural/ProceduralCommon.slh b/libraries/procedural/src/procedural/ProceduralCommon.slh index 2915f096e6..e2344dc14e 100644 --- a/libraries/procedural/src/procedural/ProceduralCommon.slh +++ b/libraries/procedural/src/procedural/ProceduralCommon.slh @@ -60,6 +60,17 @@ LAYOUT_STD140(binding=PROCEDURAL_BUFFER_INPUTS) uniform standardInputsBuffer { #define iChannelResolution standardInputs.channelResolution #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 { vec3 normal; vec3 diffuse; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 6359c14896..fb1f400a70 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -110,6 +110,13 @@ ItemKey MeshPartPayload::getKey() 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(_drawMaterials.top().material); + if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { + return procedural->getBound(); + } + } return _worldBound; } @@ -175,6 +182,9 @@ void MeshPartPayload::render(RenderArgs* args) { if (!_drawMaterials.empty() && _drawMaterials.top().material && _drawMaterials.top().material->isProcedural() && _drawMaterials.top().material->isReady()) { + if (!(enableMaterialProceduralShaders && ENABLE_MATERIAL_PROCEDURAL_SHADERS)) { + return; + } auto procedural = std::static_pointer_cast(_drawMaterials.top().material); auto& schema = _drawMaterials.getSchemaBuffer().get(); glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); diff --git a/libraries/render-utils/src/simple_procedural.slv b/libraries/render-utils/src/simple_procedural.slv index a8d494f72d..70bce451d3 100644 --- a/libraries/render-utils/src/simple_procedural.slv +++ b/libraries/render-utils/src/simple_procedural.slv @@ -20,9 +20,9 @@ <@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@> <@include MeshDeformer.slh@> <@if HIFI_USE_DEFORMED@> - <$declareMeshDeformer(1, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> + <$declareMeshDeformer(1, 1, 1, _SCRIBE_NULL, 1)$> <@else@> - <$declareMeshDeformer(1, _SCRIBE_NULL, 1, 1, 1)$> + <$declareMeshDeformer(1, 1, 1, 1, 1)$> <@endif@> <$declareMeshDeformerActivation(1, 1)$> <@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_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) { vec4 positionMS = inPosition; 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@> - evalMeshDeformer(inPosition, positionMS, inNormal.xyz, normalMS, + evalMeshDeformer(inPosition, positionMS, inNormal.xyz, normalMS, inTangent.xyz, tangentMS, meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); <@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; _normalMS = normalMS; + _color = color; + _texCoord01 = vec4(texCoord0, 0.0, 0.0); TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, positionMS, _positionES, gl_Position)$> <$transformModelToWorldDir(cam, obj, normalMS, _normalWS)$> - - _color = color_sRGBAToLinear(inColor); - _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); } \ No newline at end of file From d54ca435545f04007916e9f4d4862eea0de73084 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Fri, 22 Nov 2019 00:37:27 -0800 Subject: [PATCH 02/16] properly implement alphaModes --- libraries/fbx/src/GLTFSerializer.cpp | 85 ++++++++++--------- libraries/fbx/src/GLTFSerializer.h | 20 ++--- libraries/graphics/src/graphics/Material.cpp | 3 +- .../src/graphics/MaterialTextures.slh | 17 ++-- libraries/hfm/src/hfm/HFM.h | 47 +++++----- .../render-utils/src/RenderPipelines.cpp | 4 +- libraries/render-utils/src/model.slf | 10 +-- 7 files changed, 94 insertions(+), 92 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 5d4daf53f7..34a610c921 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -225,18 +225,17 @@ int GLTFSerializer::getAccessorType(const QString& type) return GLTFAccessorType::SCALAR; } -int GLTFSerializer::getMaterialAlphaMode(const QString& type) -{ +graphics::MaterialKey::OpacityMapMode GLTFSerializer::getMaterialAlphaMode(const QString& type) { if (type == "OPAQUE") { - return GLTFMaterialAlphaMode::OPAQUE; + return graphics::MaterialKey::OPACITY_MAP_OPAQUE; } if (type == "MASK") { - return GLTFMaterialAlphaMode::MASK; + return graphics::MaterialKey::OPACITY_MAP_MASK; } 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) @@ -484,9 +483,9 @@ bool GLTFSerializer::addMaterial(const QJsonObject& object) { getIndexFromObject(object, "normalTexture", material.normalTexture, material.defined); getIndexFromObject(object, "occlusionTexture", material.occlusionTexture, material.defined); getBoolVal(object, "doubleSided", material.doubleSided, material.defined); - QString alphamode; - if (getStringVal(object, "alphaMode", alphamode, material.defined)) { - material.alphaMode = getMaterialAlphaMode(alphamode); + QString alphaMode; + if (getStringVal(object, "alphaMode", alphaMode, material.defined)) { + material.alphaMode = getMaterialAlphaMode(alphaMode); } getDoubleVal(object, "alphaCutoff", material.alphaCutoff, material.defined); QJsonObject jsMetallicRoughness; @@ -1764,62 +1763,68 @@ HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) { 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["emissiveFactor"] && material.emissiveFactor.size() == 3) { - glm::vec3 emissive = glm::vec3(material.emissiveFactor[0], - material.emissiveFactor[1], - material.emissiveFactor[2]); - fbxmat._material->setEmissive(emissive); + glm::vec3 emissive = glm::vec3(material.emissiveFactor[0], material.emissiveFactor[1], material.emissiveFactor[2]); + hfmMat._material->setEmissive(emissive); } if (material.defined["emissiveTexture"]) { - fbxmat.emissiveTexture = getHFMTexture(_file.textures[material.emissiveTexture]); - fbxmat.useEmissiveMap = true; + hfmMat.emissiveTexture = getHFMTexture(_file.textures[material.emissiveTexture]); + hfmMat.useEmissiveMap = true; } if (material.defined["normalTexture"]) { - fbxmat.normalTexture = getHFMTexture(_file.textures[material.normalTexture]); - fbxmat.useNormalMap = true; + hfmMat.normalTexture = getHFMTexture(_file.textures[material.normalTexture]); + hfmMat.useNormalMap = true; } if (material.defined["occlusionTexture"]) { - fbxmat.occlusionTexture = getHFMTexture(_file.textures[material.occlusionTexture]); - fbxmat.useOcclusionMap = true; + hfmMat.occlusionTexture = getHFMTexture(_file.textures[material.occlusionTexture]); + hfmMat.useOcclusionMap = true; } if (material.defined["pbrMetallicRoughness"]) { - fbxmat.isPBSMaterial = true; - + hfmMat.isPBSMaterial = true; + if (material.pbrMetallicRoughness.defined["metallicFactor"]) { - fbxmat.metallic = material.pbrMetallicRoughness.metallicFactor; + hfmMat.metallic = material.pbrMetallicRoughness.metallicFactor; } if (material.pbrMetallicRoughness.defined["baseColorTexture"]) { - fbxmat.opacityTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]); - fbxmat.albedoTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]); - fbxmat.useAlbedoMap = true; + hfmMat.opacityTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]); + hfmMat.albedoTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]); + hfmMat.useAlbedoMap = true; } if (material.pbrMetallicRoughness.defined["metallicRoughnessTexture"]) { - fbxmat.roughnessTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); - fbxmat.roughnessTexture.sourceChannel = image::ColorChannel::GREEN; - fbxmat.useRoughnessMap = true; - fbxmat.metallicTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); - fbxmat.metallicTexture.sourceChannel = image::ColorChannel::BLUE; - fbxmat.useMetallicMap = true; + hfmMat.roughnessTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); + hfmMat.roughnessTexture.sourceChannel = image::ColorChannel::GREEN; + hfmMat.useRoughnessMap = true; + hfmMat.metallicTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); + hfmMat.metallicTexture.sourceChannel = image::ColorChannel::BLUE; + hfmMat.useMetallicMap = true; } if (material.pbrMetallicRoughness.defined["roughnessFactor"]) { - fbxmat._material->setRoughness(material.pbrMetallicRoughness.roughnessFactor); + hfmMat._material->setRoughness(material.pbrMetallicRoughness.roughnessFactor); } if (material.pbrMetallicRoughness.defined["baseColorFactor"] && material.pbrMetallicRoughness.baseColorFactor.size() == 4) { - glm::vec3 dcolor = glm::vec3(material.pbrMetallicRoughness.baseColorFactor[0], - material.pbrMetallicRoughness.baseColorFactor[1], - material.pbrMetallicRoughness.baseColorFactor[2]); - fbxmat.diffuseColor = dcolor; - fbxmat._material->setAlbedo(dcolor); - fbxmat._material->setOpacity(material.pbrMetallicRoughness.baseColorFactor[3]); - } + glm::vec3 dcolor = + glm::vec3(material.pbrMetallicRoughness.baseColorFactor[0], material.pbrMetallicRoughness.baseColorFactor[1], + material.pbrMetallicRoughness.baseColorFactor[2]); + hfmMat.diffuseColor = dcolor; + hfmMat._material->setAlbedo(dcolor); + hfmMat._material->setOpacity(material.pbrMetallicRoughness.baseColorFactor[3]); + } } } diff --git a/libraries/fbx/src/GLTFSerializer.h b/libraries/fbx/src/GLTFSerializer.h index 4d72805863..b1020f7154 100755 --- a/libraries/fbx/src/GLTFSerializer.h +++ b/libraries/fbx/src/GLTFSerializer.h @@ -416,21 +416,13 @@ struct GLTFpbrMetallicRoughness { } }; -namespace GLTFMaterialAlphaMode { - enum Values { - OPAQUE = 0, - MASK, - BLEND - }; -}; - struct GLTFMaterial { QString name; QVector emissiveFactor; int emissiveTexture; int normalTexture; int occlusionTexture; - int alphaMode; + graphics::MaterialKey::OpacityMapMode alphaMode; double alphaCutoff; bool doubleSided; GLTFpbrMetallicRoughness pbrMetallicRoughness; @@ -451,6 +443,12 @@ struct GLTFMaterial { if (defined["emissiveFactor"]) { qCDebug(modelformat) << "emissiveFactor: " << emissiveFactor; } + if (defined["alphaMode"]) { + qCDebug(modelformat) << "alphaMode: " << alphaMode; + } + if (defined["alphaCutoff"]) { + qCDebug(modelformat) << "alphaCutoff: " << alphaCutoff; + } if (defined["pbrMetallicRoughness"]) { pbrMetallicRoughness.dump(); } @@ -800,7 +798,7 @@ private: 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 getAnimationSamplerInterpolation(const QString& interpolation); int getCameraType(const QString& type); @@ -854,7 +852,7 @@ private: bool doesResourceExist(const QString& url); - void setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material); + void setHFMMaterial(HFMMaterial& hfmMat, const GLTFMaterial& material); HFMTexture getHFMTexture(const GLTFTexture& texture); void glTFDebugDump(); void hfmDebugDump(const HFMModel& hfmModel); diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index d80c3adfbc..1b96ed433b 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -209,8 +209,7 @@ bool Material::resetOpacityMap() const { } } } - auto newious = _key.getOpacityMapMode(); - if (previous != newious) { + if (previous != _key.getOpacityMapMode()) { //opacity change detected for this material return true; } diff --git a/libraries/graphics/src/graphics/MaterialTextures.slh b/libraries/graphics/src/graphics/MaterialTextures.slh index 2a291e5d57..534e1ae869 100644 --- a/libraries/graphics/src/graphics/MaterialTextures.slh +++ b/libraries/graphics/src/graphics/MaterialTextures.slh @@ -214,22 +214,19 @@ vec3 fetchLightMap(vec2 uv) { } <@endfunc@> -<@func evalMaterialOpacityMask(fetchedOpacity, materialOpacityCutoff, opacity)@> +<@func evalMaterialOpacityMask(fetchedOpacity, materialOpacityCutoff, materialOpacity, matKey, opacity)@> { - // This path only valid for opaque or texel opaque material - <$opacity$> = step(<$materialOpacityCutoff$>, <$fetchedOpacity$>); + // This path only valid for opaque or texel opaque material + <$opacity$> = mix(<$materialOpacity$>, + step(<$materialOpacityCutoff$>, <$fetchedOpacity$>), + float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0)); } <@endfunc@> - -<@func evalMaterialOpacity(fetchedOpacity, materialOpacityCutoff, materialOpacity, matKey, opacity)@> +<@func evalMaterialOpacity(fetchedOpacity, materialOpacity, opacity)@> { // 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$>, - step(<$materialOpacityCutoff$>, <$fetchedOpacity$>), - float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0)) - * <$materialOpacity$>; + <$opacity$> = <$materialOpacity$> * <$fetchedOpacity$>; } <@endfunc@> diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index 888e562bca..7111ad2e65 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -173,24 +173,27 @@ public: void getTextureNames(QSet& textureList) const; void setMaxNumPixelsPerTexture(int maxNumPixels); - glm::vec3 diffuseColor{ 1.0f }; - float diffuseFactor{ 1.0f }; - glm::vec3 specularColor{ 0.02f }; - float specularFactor{ 1.0f }; + glm::vec3 diffuseColor { 1.0f }; + float diffuseFactor { 1.0f }; + glm::vec3 specularColor { 0.02f }; + float specularFactor { 1.0f }; - glm::vec3 emissiveColor{ 0.0f }; - float emissiveFactor{ 0.0f }; + glm::vec3 emissiveColor { 0.0f }; + float emissiveFactor { 0.0f }; - float shininess{ 23.0f }; - float opacity{ 1.0f }; + float shininess { 23.0f }; + float opacity { 1.0f }; - float metallic{ 0.0f }; - float roughness{ 1.0f }; - float emissiveIntensity{ 1.0f }; - float ambientFactor{ 1.0f }; + float metallic { 0.0f }; + float roughness { 1.0f }; + float emissiveIntensity { 1.0f }; + float ambientFactor { 1.0f }; float bumpMultiplier { 1.0f }; // TODO: to be implemented + graphics::MaterialKey::OpacityMapMode alphaMode { graphics::MaterialKey::OPACITY_MAP_BLEND }; + float alphaCutoff { 0.5f }; + QString materialID; QString name; QString shadingModel; @@ -207,19 +210,19 @@ public: Texture occlusionTexture; Texture scatteringTexture; 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 - bool useNormalMap{ false }; - bool useAlbedoMap{ false }; - bool useOpacityMap{ false }; - bool useRoughnessMap{ false }; - bool useSpecularMap{ false }; - bool useMetallicMap{ false }; - bool useEmissiveMap{ false }; - bool useOcclusionMap{ false }; + bool useNormalMap { false }; + bool useAlbedoMap { false }; + bool useOpacityMap { false }; + bool useRoughnessMap { false }; + bool useSpecularMap { false }; + bool useMetallicMap { false }; + bool useEmissiveMap { false }; + bool useOcclusionMap { false }; bool needTangentSpace() const; }; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 2b0d197819..ff2e3610c2 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -387,8 +387,10 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial std::call_once(once, [] { for (int i = 0; i < graphics::Material::NUM_TOTAL_FLAGS; i++) { // 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 && - i != graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT) { + i != graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT && + i != graphics::MaterialKey::OPACITY_MAP_MODE_BIT) { allFlags.insert(i); } } diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index bacc6b0ab1..229a6b1907 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -103,14 +103,13 @@ void main(void) { <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> <@if HIFI_USE_TRANSLUCENT@> - float cutoff = getMaterialOpacityCutoff(mat); float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, cutoff, opacity, matKey, opacity)$>; + <$evalMaterialOpacity(albedoTex.a, opacity, opacity)$>; <$discardInvisible(opacity)$>; <@else@> float cutoff = getMaterialOpacityCutoff(mat); float opacity = 1.0; - <$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity)$>; + <$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity, matKey, opacity)$>; <$discardTransparent(opacity)$>; <@endif@> @@ -155,14 +154,13 @@ void main(void) { <@endif@> <@if HIFI_USE_TRANSLUCENT@> - float cutoff = getMaterialOpacityCutoff(mat); float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, cutoff, opacity, matKey, opacity)$>; + <$evalMaterialOpacity(albedoTex.a, opacity, opacity)$>; <$discardInvisible(opacity)$>; <@else@> float cutoff = getMaterialOpacityCutoff(mat); float opacity = 1.0; - <$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity)$>; + <$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity, matKey, opacity)$>; <$discardTransparent(opacity)$>; <@endif@> From b66fa1d57a2ad79ca686d2b056f6f843d50ad251 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 24 Nov 2019 12:44:42 -0800 Subject: [PATCH 03/16] put back stepping in translucent case --- libraries/graphics/src/graphics/MaterialTextures.slh | 7 +++++-- libraries/render-utils/src/model.slf | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libraries/graphics/src/graphics/MaterialTextures.slh b/libraries/graphics/src/graphics/MaterialTextures.slh index 534e1ae869..cb83f7d9cf 100644 --- a/libraries/graphics/src/graphics/MaterialTextures.slh +++ b/libraries/graphics/src/graphics/MaterialTextures.slh @@ -223,10 +223,13 @@ vec3 fetchLightMap(vec2 uv) { } <@endfunc@> -<@func evalMaterialOpacity(fetchedOpacity, materialOpacity, opacity)@> +<@func evalMaterialOpacity(fetchedOpacity, materialOpacityCutoff, materialOpacity, matKey, opacity)@> { // This path only valid for transparent material - <$opacity$> = <$materialOpacity$> * <$fetchedOpacity$>; + <$opacity$> = mix(<$fetchedOpacity$>, + step(<$materialOpacityCutoff$>, <$fetchedOpacity$>), + float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0)) + * <$materialOpacity$>; } <@endfunc@> diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index 229a6b1907..a6cc82e335 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -103,8 +103,9 @@ void main(void) { <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> <@if HIFI_USE_TRANSLUCENT@> + float cutoff = getMaterialOpacityCutoff(mat); float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, opacity)$>; + <$evalMaterialOpacity(albedoTex.a, cutoff, opacity, matKey, opacity)$>; <$discardInvisible(opacity)$>; <@else@> float cutoff = getMaterialOpacityCutoff(mat); @@ -154,8 +155,9 @@ void main(void) { <@endif@> <@if HIFI_USE_TRANSLUCENT@> + float cutoff = getMaterialOpacityCutoff(mat); float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, opacity)$>; + <$evalMaterialOpacity(albedoTex.a, cutoff, opacity, matKey, opacity)$>; <$discardInvisible(opacity)$>; <@else@> float cutoff = getMaterialOpacityCutoff(mat); From 3fe395ca320b5a979dd31999c3987d8238e2e8b4 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Fri, 22 Nov 2019 00:37:27 -0800 Subject: [PATCH 04/16] properly implement alphaModes --- libraries/graphics/src/graphics/MaterialTextures.slh | 7 ++----- libraries/render-utils/src/model.slf | 6 ++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/libraries/graphics/src/graphics/MaterialTextures.slh b/libraries/graphics/src/graphics/MaterialTextures.slh index cb83f7d9cf..534e1ae869 100644 --- a/libraries/graphics/src/graphics/MaterialTextures.slh +++ b/libraries/graphics/src/graphics/MaterialTextures.slh @@ -223,13 +223,10 @@ vec3 fetchLightMap(vec2 uv) { } <@endfunc@> -<@func evalMaterialOpacity(fetchedOpacity, materialOpacityCutoff, materialOpacity, matKey, opacity)@> +<@func evalMaterialOpacity(fetchedOpacity, materialOpacity, opacity)@> { // This path only valid for transparent material - <$opacity$> = mix(<$fetchedOpacity$>, - step(<$materialOpacityCutoff$>, <$fetchedOpacity$>), - float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0)) - * <$materialOpacity$>; + <$opacity$> = <$materialOpacity$> * <$fetchedOpacity$>; } <@endfunc@> diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index a6cc82e335..229a6b1907 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -103,9 +103,8 @@ void main(void) { <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> <@if HIFI_USE_TRANSLUCENT@> - float cutoff = getMaterialOpacityCutoff(mat); float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, cutoff, opacity, matKey, opacity)$>; + <$evalMaterialOpacity(albedoTex.a, opacity, opacity)$>; <$discardInvisible(opacity)$>; <@else@> float cutoff = getMaterialOpacityCutoff(mat); @@ -155,9 +154,8 @@ void main(void) { <@endif@> <@if HIFI_USE_TRANSLUCENT@> - float cutoff = getMaterialOpacityCutoff(mat); float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, cutoff, opacity, matKey, opacity)$>; + <$evalMaterialOpacity(albedoTex.a, opacity, opacity)$>; <$discardInvisible(opacity)$>; <@else@> float cutoff = getMaterialOpacityCutoff(mat); From 59c67e559050478fabebaba677da0cd5e5b9d7cd Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 24 Nov 2019 12:44:42 -0800 Subject: [PATCH 05/16] put back stepping in translucent case --- libraries/graphics/src/graphics/MaterialTextures.slh | 7 +++++-- libraries/render-utils/src/model.slf | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libraries/graphics/src/graphics/MaterialTextures.slh b/libraries/graphics/src/graphics/MaterialTextures.slh index 534e1ae869..cb83f7d9cf 100644 --- a/libraries/graphics/src/graphics/MaterialTextures.slh +++ b/libraries/graphics/src/graphics/MaterialTextures.slh @@ -223,10 +223,13 @@ vec3 fetchLightMap(vec2 uv) { } <@endfunc@> -<@func evalMaterialOpacity(fetchedOpacity, materialOpacity, opacity)@> +<@func evalMaterialOpacity(fetchedOpacity, materialOpacityCutoff, materialOpacity, matKey, opacity)@> { // This path only valid for transparent material - <$opacity$> = <$materialOpacity$> * <$fetchedOpacity$>; + <$opacity$> = mix(<$fetchedOpacity$>, + step(<$materialOpacityCutoff$>, <$fetchedOpacity$>), + float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0)) + * <$materialOpacity$>; } <@endfunc@> diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index 229a6b1907..a6cc82e335 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -103,8 +103,9 @@ void main(void) { <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> <@if HIFI_USE_TRANSLUCENT@> + float cutoff = getMaterialOpacityCutoff(mat); float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, opacity)$>; + <$evalMaterialOpacity(albedoTex.a, cutoff, opacity, matKey, opacity)$>; <$discardInvisible(opacity)$>; <@else@> float cutoff = getMaterialOpacityCutoff(mat); @@ -154,8 +155,9 @@ void main(void) { <@endif@> <@if HIFI_USE_TRANSLUCENT@> + float cutoff = getMaterialOpacityCutoff(mat); float opacity = getMaterialOpacity(mat) * _color.a; - <$evalMaterialOpacity(albedoTex.a, opacity, opacity)$>; + <$evalMaterialOpacity(albedoTex.a, cutoff, opacity, matKey, opacity)$>; <$discardInvisible(opacity)$>; <@else@> float cutoff = getMaterialOpacityCutoff(mat); From e0a29d93676ffc5e6f13280ea7df58cd70a0c517 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Tue, 26 Nov 2019 14:48:43 -0800 Subject: [PATCH 06/16] material entities support cullFaceMode and support gltf doubleSided --- interface/src/graphics/WorldBox.cpp | 2 +- .../src/avatars-renderer/Avatar.cpp | 6 +- .../src/RenderableGizmoEntityItem.cpp | 2 +- .../src/RenderableLineEntityItem.cpp | 2 +- .../src/RenderableShapeEntityItem.cpp | 3 +- libraries/fbx/src/GLTFSerializer.cpp | 4 + .../src/graphics-scripting/Forward.h | 2 + .../GraphicsScriptingInterface.cpp | 5 + .../graphics-scripting/ScriptableModel.cpp | 3 + libraries/graphics/src/graphics/Material.cpp | 21 ++- libraries/graphics/src/graphics/Material.h | 20 +++ .../procedural/ProceduralMaterialCache.cpp | 24 +++- libraries/render-utils/src/GeometryCache.cpp | 121 ++++++++++-------- libraries/render-utils/src/GeometryCache.h | 21 +-- .../render-utils/src/MeshPartPayload.cpp | 6 + libraries/render-utils/src/Model.cpp | 2 +- .../render-utils/src/RenderPipelines.cpp | 78 +++++------ libraries/render/src/render/ShapePipeline.h | 51 +++++++- 18 files changed, 256 insertions(+), 117 deletions(-) diff --git a/interface/src/graphics/WorldBox.cpp b/interface/src/graphics/WorldBox.cpp index 648d6d3177..0e15d9da86 100644 --- a/interface/src/graphics/WorldBox.cpp +++ b/interface/src/graphics/WorldBox.cpp @@ -22,7 +22,7 @@ namespace render { PerformanceTimer perfTimer("worldBox"); auto& batch = *args->_batch; - DependencyManager::get()->bindSimpleProgram(batch, false, false, true, false, false, true, args->_renderMethod == Args::RenderMethod::FORWARD); + DependencyManager::get()->bindSimpleProgram(batch, false, false, false, false, true, args->_renderMethod == Args::RenderMethod::FORWARD); WorldBoxRenderData::renderWorldBox(args, batch); } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 9b8ce8cf34..8ceafbf5a1 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -791,7 +791,7 @@ void Avatar::render(RenderArgs* renderArgs) { pointerTransform.setTranslation(position); pointerTransform.setRotation(rotation); 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); } } @@ -815,7 +815,7 @@ void Avatar::render(RenderArgs* renderArgs) { pointerTransform.setTranslation(position); pointerTransform.setRotation(rotation); 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); } } @@ -1103,7 +1103,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const { PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderBevelCornersRect"); - DependencyManager::get()->bindSimpleProgram(batch, false, false, true, true, true, true, forward); + DependencyManager::get()->bindSimpleProgram(batch, false, false, true, true, true, forward); DependencyManager::get()->renderBevelCornersRect(batch, left, bottom, width, height, bevelDistance, backgroundColor, _nameRectGeometryID); } diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index a066107a15..9081d0727f 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -253,7 +253,7 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) { }); 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); diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index aaef0b3f7d..6e2be1b41e 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -50,7 +50,7 @@ void LineEntityRenderer::doRender(RenderArgs* args) { transform.setRotation(modelTransform.getRotation()); batch.setModelTransform(transform); if (_linePoints.size() > 1) { - DependencyManager::get()->bindSimpleProgram(batch, false, false, true, false, false, true, + DependencyManager::get()->bindSimpleProgram(batch, false, false, false, false, true, _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD); DependencyManager::get()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID); } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 497294e45a..d5a0e22199 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -200,6 +200,7 @@ ShapeKey ShapeEntityRenderer::getShapeKey() { if (drawMaterialKey.isUnlit()) { builder.withUnlit(); } + builder.withCullFaceMode(mat->second.getCullFaceMode()); } else if (pipelineType == Pipeline::PROCEDURAL) { builder.withOwnPipeline(); } @@ -263,7 +264,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { // FIXME, support instanced multi-shape rendering using multidraw indirect outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; 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) { geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline); } else { diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 34a610c921..e117e1f211 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1774,6 +1774,10 @@ void GLTFSerializer::setHFMMaterial(HFMMaterial& hfmMat, const GLTFMaterial& mat 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) { glm::vec3 emissive = glm::vec3(material.emissiveFactor[0], material.emissiveFactor[1], material.emissiveFactor[2]); hfmMat._material->setEmissive(emissive); diff --git a/libraries/graphics-scripting/src/graphics-scripting/Forward.h b/libraries/graphics-scripting/src/graphics-scripting/Forward.h index 9efaa0a90d..acef5a5bd4 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/Forward.h +++ b/libraries/graphics-scripting/src/graphics-scripting/Forward.h @@ -65,6 +65,7 @@ namespace scriptable { * @property {Mat4|string} texCoordTransform1 * @property {string} lightmapParams * @property {string} materialParams + * @property {string} cullFaceMode * @property {boolean} defaultFallthrough * @property {string} procedural */ @@ -99,6 +100,7 @@ namespace scriptable { QString lightMap; QString scatteringMap; std::array texCoordTransforms; + QString cullFaceMode; bool defaultFallthrough; std::unordered_map propertyFallthroughs; // not actually exposed to script diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index d76c1fcbd2..c0a2d4bf25 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -495,6 +495,11 @@ namespace scriptable { 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) { obj.setProperty("procedural", material.procedural); } diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp index 4a56db0d04..28cd49e7c4 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp @@ -45,6 +45,7 @@ scriptable::ScriptableMaterial& scriptable::ScriptableMaterial::operator=(const occlusionMap = material.occlusionMap; lightMap = material.lightMap; scatteringMap = material.scatteringMap; + cullFaceMode = material.cullFaceMode; } else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) { procedural = material.procedural; } @@ -131,6 +132,8 @@ scriptable::ScriptableMaterial::ScriptableMaterial(const graphics::MaterialPoint for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) { texCoordTransforms[i] = material->getTexCoordTransform(i); } + + cullFaceMode = QString(graphics::MaterialKey::getCullFaceModeName(material->getCullFaceMode()).c_str()); } else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) { procedural = material->getProceduralString(); } diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index 1b96ed433b..41cd319595 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -27,7 +27,7 @@ const float Material::DEFAULT_ROUGHNESS { 1.0f }; const float Material::DEFAULT_SCATTERING{ 0.0f }; const MaterialKey::OpacityMapMode Material::DEFAULT_OPACITY_MAP_MODE{ MaterialKey::OPACITY_MAP_OPAQUE }; 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) { 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; } +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_SHADER_SIMPLE { "hifi_shader_simple" }; @@ -67,6 +82,7 @@ Material::Material(const Material& material) : _texcoordTransforms(material._texcoordTransforms), _lightmapParams(material._lightmapParams), _materialParams(material._materialParams), + _cullFaceMode(material._cullFaceMode), _textureMaps(material._textureMaps), _defaultFallthrough(material._defaultFallthrough), _propertyFallthroughs(material._propertyFallthroughs) @@ -89,6 +105,7 @@ Material& Material::operator=(const Material& material) { _texcoordTransforms = material._texcoordTransforms; _lightmapParams = material._lightmapParams; _materialParams = material._materialParams; + _cullFaceMode = material._cullFaceMode; _textureMaps = material._textureMaps; _defaultFallthrough = material._defaultFallthrough; @@ -144,7 +161,7 @@ void Material::setOpacityMapMode(MaterialKey::OpacityMapMode opacityMapMode) { _key.setOpacityMapMode(opacityMapMode); } -MaterialKey::OpacityMapMode Material::getOpacityMapMode() const { +MaterialKey::OpacityMapMode Material::getOpacityMapMode() const { return _key.getOpacityMapMode(); } diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 48ab8151c5..7a411e5b2c 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -83,6 +83,16 @@ public: // find the enum value from a string, return true if match found 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 Flags _flags; @@ -349,6 +359,10 @@ public: void setOpacityCutoff(float 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); bool isUnlit() const { return _key.isUnlit(); } @@ -403,6 +417,7 @@ public: TEXCOORDTRANSFORM1, LIGHTMAP_PARAMS, MATERIAL_PARAMS, + CULL_FACE_MODE, NUM_TOTAL_FLAGS }; @@ -436,6 +451,7 @@ private: std::array _texcoordTransforms; glm::vec2 _lightmapParams { 0.0, 1.0 }; glm::vec2 _materialParams { 0.0, 1.0 }; + MaterialKey::CullFaceMode _cullFaceMode { DEFAULT_CULL_FACE_MODE }; TextureMaps _textureMaps; bool _defaultFallthrough { false }; @@ -524,6 +540,9 @@ public: graphics::MaterialKey getMaterialKey() const { return graphics::MaterialKey(_schemaBuffer.get()._key); } 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 setTexturesLoading(bool value) { _texturesLoading = value; } void setInitialized() { _initialized = true; } @@ -536,6 +555,7 @@ public: private: gpu::BufferView _schemaBuffer; + graphics::MaterialKey::CullFaceMode _cullFaceMode { graphics::Material::DEFAULT_CULL_FACE_MODE }; gpu::TextureTablePointer _textureTable { std::make_shared() }; bool _needsUpdate { false }; bool _texturesLoading { false }; diff --git a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp index b9611358e7..a97cb294b4 100644 --- a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp +++ b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp @@ -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 albedoMap * value for transparency. * "hifi_pbr" 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: * "OPACITY_MAP_OPAQUE" for ignoring the opacity map information. * "OPACITY_MAP_MASK" for using the opacity map as a mask, where only the texel greater than opacityCutoff are visible and rendered opaque. * "OPACITY_MAP_BLEND" 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 * when opacityMapMode is "OPACITY_MAP_MASK", range 0.01.0. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. + * @property {string} cullFaceMode - The mode defining which side of the geometry should be rendered. Values can be: + *
    + *
  • "CULL_NONE" for rendering both sides of the geometry.
  • + *
  • "CULL_FRONT" for culling the front faces of the geometry.
  • + *
  • "CULL_BACK" (the default) for culling the back faces of the geometry.
  • + *
+ * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. * @property {string} roughnessMap - The URL of the roughness texture image. You can use this or glossMap, but not * both. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. @@ -285,7 +292,20 @@ std::pair> NetworkMaterialResource } else if (value.isDouble()) { 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); if (value.isString() && value.toString() == FALLTHROUGH) { material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::SCATTERING_VAL_BIT); diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 997f87b8d6..ea66ac19ec 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -723,7 +723,7 @@ gpu::ShaderPointer GeometryCache::_forwardUnlitShader; gpu::ShaderPointer GeometryCache::_forwardSimpleFadeShader; gpu::ShaderPointer GeometryCache::_forwardUnlitFadeShader; -std::map, render::ShapePipelinePointer> GeometryCache::_shapePipelines; +std::map, render::ShapePipelinePointer> GeometryCache::_shapePipelines; GeometryCache::GeometryCache() : _nextID(0) { @@ -776,15 +776,18 @@ void GeometryCache::initializeShapePipelines() { bool transparent = i & 1; bool unlit = i & 2; 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, - bool unlit, bool depthBias, bool forward) { +render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool unlit, bool depthBias, bool forward, + graphics::MaterialKey::CullFaceMode cullFaceMode) { - return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false, true, forward), nullptr, + return std::make_shared(getSimplePipeline(textured, transparent, unlit, depthBias, false, true, forward, cullFaceMode), nullptr, [](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) { batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get()->getWhiteTexture()); DependencyManager::get()->setupKeyLightBatch(args, batch); @@ -792,12 +795,12 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool ); } -render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool culled, - bool unlit, bool depthBias, bool forward) { +render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool unlit, bool depthBias, bool forward, + graphics::MaterialKey::CullFaceMode cullFaceMode) { auto fadeEffect = DependencyManager::get(); auto fadeBatchSetter = fadeEffect->getBatchSetter(); auto fadeItemSetter = fadeEffect->getItemUniformSetter(); - return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true, true, forward), nullptr, + return std::make_shared(getSimplePipeline(textured, transparent, unlit, depthBias, true, true, forward, cullFaceMode), nullptr, [fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) { batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get()->getWhiteTexture()); fadeBatchSetter(shapePipeline, batch, args); @@ -2049,54 +2052,60 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo class SimpleProgramKey { public: enum FlagBit { - IS_TEXTURED_FLAG = 0, - IS_TRANSPARENT_FLAG, - IS_CULLED_FLAG, - IS_UNLIT_FLAG, - HAS_DEPTH_BIAS_FLAG, - IS_FADING_FLAG, - IS_ANTIALIASED_FLAG, - IS_FORWARD_FLAG, + IS_TEXTURED_BIT = 0, + IS_TRANSPARENT_BIT, + IS_UNLIT_BIT, + IS_DEPTH_BIASED_BIT, + IS_FADING_BIT, + IS_ANTIALIASED_BIT, + IS_FORWARD_BIT, + IS_CULL_FACE_NONE_BIT, // if neither of these are set, we're CULL_FACE_BACK + IS_CULL_FACE_FRONT_BIT, NUM_FLAGS, }; + typedef std::bitset Flags; - enum Flag { - IS_TEXTURED = (1 << IS_TEXTURED_FLAG), - IS_TRANSPARENT = (1 << IS_TRANSPARENT_FLAG), - IS_CULLED = (1 << IS_CULLED_FLAG), - IS_UNLIT = (1 << IS_UNLIT_FLAG), - HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG), - IS_FADING = (1 << IS_FADING_FLAG), - IS_ANTIALIASED = (1 << IS_ANTIALIASED_FLAG), - IS_FORWARD = (1 << IS_FORWARD_FLAG), - }; - 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); } + bool isTextured() const { return _flags[IS_TEXTURED_BIT]; } + bool isTransparent() const { return _flags[IS_TRANSPARENT_BIT]; } + bool isUnlit() const { return _flags[IS_UNLIT_BIT]; } + bool hasDepthBias() const { return _flags[IS_DEPTH_BIASED_BIT]; } + bool isFading() const { return _flags[IS_FADING_BIT]; } + bool isAntiAliased() const { return _flags[IS_ANTIALIASED_BIT]; } + bool isForward() const { return _flags[IS_FORWARD_BIT]; } + bool isCullFaceNone() const { return _flags[IS_CULL_FACE_NONE_BIT]; } + bool isCullFaceFront() const { return _flags[IS_CULL_FACE_FRONT_BIT]; } Flags _flags = 0; -#if defined(__clang__) - __attribute__((unused)) -#endif - short _spare = 0; // Padding - int getRaw() const { return *reinterpret_cast(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, - bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true, bool forward = false) { - _flags = (textured ? IS_TEXTURED : 0) | (transparent ? IS_TRANSPARENT : 0) | (culled ? IS_CULLED : 0) | - (unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0) | (fading ? IS_FADING : 0) | (isAntiAliased ? IS_ANTIALIASED : 0) | (forward ? IS_FORWARD : 0); + switch (cullFaceMode) { + case graphics::MaterialKey::CullFaceMode::CULL_NONE: + _flags.set(IS_CULL_FACE_NONE_BIT); + _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) {} @@ -2141,8 +2150,9 @@ gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent, bool return _webPipelines[{ transparent, forward }]; } -void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool isAntiAliased, bool forward) { - batch.setPipeline(getSimplePipeline(textured, transparent, culled, unlit, depthBiased, false, isAntiAliased, forward)); +void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool unlit, bool depthBiased, bool isAntiAliased, + 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 (!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) { - SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased, fading, isAntiAliased, forward }; +gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool unlit, bool depthBiased, bool fading, bool isAntiAliased, + bool forward, graphics::MaterialKey::CullFaceMode cullFaceMode) { + SimpleProgramKey config { textured, transparent, unlit, depthBiased, fading, isAntiAliased, forward, cullFaceMode }; // If the pipeline already exists, return it 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 auto state = std::make_shared(); - if (config.isCulled()) { - state->setCullMode(gpu::State::CULL_BACK); - } else { + if (config.isCullFaceNone()) { 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); if (config.hasDepthBias()) { diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index b474e6c712..179d49c076 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -162,18 +162,19 @@ public: static const int UNKNOWN_ID; // 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, - bool unlit = false, bool depthBias = false, bool isAntiAliased = true, bool forward = false); + void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool transparent = false, bool unlit = false, bool depthBias = false, + bool isAntiAliased = true, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK); // Get the pipeline to render static geometry - static gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true, - bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true, bool forward = false); + static gpu::PipelinePointer getSimplePipeline(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::CullFaceMode::CULL_BACK); void bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward); gpu::PipelinePointer getWebBrowserProgram(bool transparent, bool forward); static std::map, gpu::PipelinePointer> _webPipelines; 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 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 _forwardUnlitFadeShader; - static std::map, render::ShapePipelinePointer> _shapePipelines; + static std::map, render::ShapePipelinePointer> _shapePipelines; static QHash _simplePrograms; - static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool culled = true, - bool unlit = false, bool depthBias = false, bool forward = false); - static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool culled = true, - bool unlit = false, bool depthBias = false, bool forward = false); + static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool unlit = 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 unlit = false, + bool depthBias = false, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK); }; #endif // hifi_GeometryCache_h diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index fb1f400a70..947c53d546 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -143,6 +143,9 @@ ShapeKey MeshPartPayload::getShapeKey() const { if (drawMaterialKey.isUnlit()) { builder.withUnlit(); } + if (material) { + builder.withCullFaceMode(material->getCullFaceMode()); + } } return builder.build(); @@ -434,6 +437,9 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode pr if (isUnlit) { builder.withUnlit(); } + if (material) { + builder.withCullFaceMode(material->getCullFaceMode()); + } } _shapeKey = builder.build(); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3a2e450d4b..182bc535bf 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1040,7 +1040,7 @@ void Model::renderDebugMeshBoxes(gpu::Batch& batch, bool forward) { Transform meshToWorld(meshToWorldMatrix); batch.setModelTransform(meshToWorld); - DependencyManager::get()->bindSimpleProgram(batch, false, false, false, true, true, forward); + DependencyManager::get()->bindSimpleProgram(batch, false, false, true, true, forward, graphics::MaterialKey::CULL_NONE); for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) { for (auto &partTriangleSet : meshTriangleSets) { diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index ff2e3610c2..7f1ca4bd71 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -259,46 +259,44 @@ void addPlumberPipeline(ShapePlumber& plumber, gpu::ShaderPointer program = gpu::Shader::createProgram(programId); - for (int i = 0; i < 8; i++) { - bool isCulled = (i & 1); - bool isBiased = (i & 2); - bool isWireframed = (i & 4); + for (int i = 0; i < 4; i++) { + bool isBiased = (i & 1); + bool isWireframed = (i & 2); + for (int cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_NONE; cullFaceMode < graphics::MaterialKey::CullFaceMode::NUM_CULL_FACE_MODES; cullFaceMode++) { + auto state = std::make_shared(); + key.isTranslucent() ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state); - auto state = std::make_shared(); - key.isTranslucent() ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state); + // Depth test depends on transparency + 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 - 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); + ShapeKey::Builder builder(key); + builder.withCullFaceMode((graphics::MaterialKey::CullFaceMode)cullFaceMode); + state->setCullMode((gpu::State::CullMode)cullFaceMode); + if (isWireframed) { + builder.withWireframe(); + state->setFillMode(gpu::State::FILL_LINE); + } + if (isBiased) { + builder.withDepthBias(); + state->setDepthBias(1.0f); + state->setDepthBiasSlopeScale(1.0f); + } - ShapeKey::Builder builder(key); - if (!isCulled) { - builder.withoutCullFace(); + 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); } - 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); } } @@ -644,6 +642,12 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial wasSet = true; } break; + case graphics::Material::CULL_FACE_MODE: + if (!fallthrough) { + multiMaterial.setCullFaceMode(material->getCullFaceMode()); + wasSet = true; + } + break; default: break; } @@ -685,6 +689,8 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial case graphics::Material::MATERIAL_PARAMS: // these are initialized to the correct default values in Schema() break; + case graphics::Material::CULL_FACE_MODE: + multiMaterial.setCullFaceMode(graphics::Material::DEFAULT_CULL_FACE_MODE); case graphics::MaterialKey::ALBEDO_MAP_BIT: if (schemaKey.isAlbedoMap()) { drawMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, textureCache->getWhiteTexture()); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index cf41c85dd9..04b9919140 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -15,6 +15,7 @@ #include #include +#include #include "Args.h" @@ -34,8 +35,9 @@ public: DUAL_QUAT_SKINNED, DEPTH_BIAS, WIREFRAME, - NO_CULL_FACE, FADE, + CULL_FACE_NONE, // if neither of these are set, we're CULL_FACE_BACK + CULL_FACE_FRONT, OWN_PIPELINE, INVALID, @@ -81,9 +83,29 @@ public: Builder& withDualQuatSkinned() { _flags.set(DUAL_QUAT_SKINNED); return (*this); } Builder& withDepthBias() { _flags.set(DEPTH_BIAS); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } - Builder& withoutCullFace() { _flags.set(NO_CULL_FACE); return (*this); } Builder& withFade() { _flags.set(FADE); return (*this); } + Builder& 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& invalidate() { _flags.set(INVALID); return (*this); } @@ -137,8 +159,27 @@ public: Builder& withWireframe() { _flags.set(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& withoutCullFace() { _flags.set(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); } + 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; + } + _mask.set(CULL_FACE_NONE); + _mask.set(CULL_FACE_FRONT); + return (*this); + } Builder& withFade() { _flags.set(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 isDepthBiased() const { return _flags[DEPTH_BIAS]; } 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 hasOwnPipeline() const { return _flags[OWN_PIPELINE]; } From 398562321da5887d2d13edd20c4b271b2efc1be7 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 29 Apr 2019 11:07:36 -0700 Subject: [PATCH 07/16] fix wearables not disappearing with avatar --- .../src/avatars-renderer/Avatar.cpp | 19 ++++++++++++++++++- .../src/avatars-renderer/Avatar.h | 2 +- libraries/render/src/render/Item.cpp | 6 +++++- libraries/render/src/render/Item.h | 8 +++++++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 8ceafbf5a1..ce559a7729 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -2121,6 +2121,7 @@ void Avatar::updateAttachmentRenderIDs() { void Avatar::updateDescendantRenderIDs() { _subItemLock.withWriteLock([&] { + auto oldDescendantRenderIDs = _descendantRenderIDs; _descendantRenderIDs.clear(); auto entityTreeRenderer = DependencyManager::get(); EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; @@ -2135,13 +2136,29 @@ void Avatar::updateDescendantRenderIDs() { render::ItemIDs renderableSubItems; uint32_t numRenderableSubItems = renderer->metaFetchMetaSubItems(renderableSubItems); if (numRenderableSubItems > 0) { - _descendantRenderIDs.insert(_descendantRenderIDs.end(), renderableSubItems.begin(), renderableSubItems.end()); + for (auto& renderID : renderableSubItems) { + _descendantRenderIDs.insert(renderID); + oldDescendantRenderIDs.erase(renderID); + } } } } } }); }); + + render::Transaction transaction; + for (auto& oldDescendantRenderID : oldDescendantRenderIDs) { + transaction.updateItem(oldDescendantRenderID, [](render::PayloadProxyInterface& self) { + self.setOverrideSubMetaCulled(false); + }); + } + for (auto& descendantRenderIDs : _descendantRenderIDs) { + transaction.updateItem(descendantRenderIDs, [](render::PayloadProxyInterface& self) { + self.setOverrideSubMetaCulled(true); + }); + } + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); } }); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 031b2f1309..235a04f109 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -781,7 +781,7 @@ protected: void updateAttachmentRenderIDs(); render::ItemIDs _attachmentRenderIDs; void updateDescendantRenderIDs(); - render::ItemIDs _descendantRenderIDs; + render::ItemIDSet _descendantRenderIDs; uint32_t _lastAncestorChainRenderableVersion { 0 }; }; diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 532964777f..d5dde7f86b 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -123,7 +123,11 @@ namespace render { if (!payload) { return ItemKey::Builder::opaqueShape().withTypeMeta(); } - return payload->getKey(); + if (payload->overrideSubMetaCulled()) { + return ItemKey::Builder(payload->getKey()).withSubMetaCulled(); + } else { + return payload->getKey(); + } } template <> const ShapeKey shapeGetShapeKey(const PayloadProxyInterface::Pointer& payload) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 6b66e844c0..e28a88f6dd 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -614,7 +614,13 @@ public: virtual ShapeKey getShapeKey() = 0; virtual Item::Bound getBound() = 0; virtual void render(RenderArgs* args) = 0; - virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const = 0; + virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) = 0; + + bool overrideSubMetaCulled() const { return _overrideSubMetaCulled; } + void setOverrideSubMetaCulled(bool overrideSubMetaCulled) { _overrideSubMetaCulled = overrideSubMetaCulled; } + +protected: + bool _overrideSubMetaCulled { false }; }; template <> const ItemKey payloadGetKey(const PayloadProxyInterface::Pointer& payload); From 1736252f0de6ab85bb8f5f1df0bc6b0a9bc64416 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 30 Apr 2019 10:31:09 -0700 Subject: [PATCH 08/16] trying and failing to fix models --- .../src/avatars-renderer/Avatar.cpp | 35 +++++++++---------- .../src/avatars-renderer/Avatar.h | 3 +- .../src/RenderableEntityItem.cpp | 14 ++++---- .../src/RenderableEntityItem.h | 11 ++++++ .../src/RenderableMaterialEntityItem.cpp | 3 +- .../src/RenderableModelEntityItem.cpp | 12 ++++++- .../src/RenderableModelEntityItem.h | 1 + .../RenderableParticleEffectEntityItem.cpp | 14 +++++--- .../src/RenderablePolyLineEntityItem.cpp | 11 ++++-- .../src/RenderablePolyVoxEntityItem.cpp | 10 ++++++ .../src/RenderablePolyVoxEntityItem.h | 2 +- libraries/entities/src/EntityItem.cpp | 11 ++++++ libraries/entities/src/EntityItem.h | 5 ++- .../render-utils/src/MeshPartPayload.cpp | 8 +++++ libraries/render-utils/src/MeshPartPayload.h | 8 ++--- libraries/render-utils/src/Model.cpp | 16 ++++++++- libraries/render-utils/src/Model.h | 3 ++ libraries/render/src/render/Item.cpp | 6 +--- libraries/render/src/render/Item.h | 8 +---- 19 files changed, 126 insertions(+), 55 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index ce559a7729..868d49bb5c 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -2121,7 +2121,8 @@ void Avatar::updateAttachmentRenderIDs() { void Avatar::updateDescendantRenderIDs() { _subItemLock.withWriteLock([&] { - auto oldDescendantRenderIDs = _descendantRenderIDs; + auto oldRenderingDescendantEntityIDs = _renderingDescendantEntityIDs; + _renderingDescendantEntityIDs.clear(); _descendantRenderIDs.clear(); auto entityTreeRenderer = DependencyManager::get(); EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; @@ -2131,34 +2132,30 @@ void Avatar::updateDescendantRenderIDs() { if (object && object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); 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) { render::ItemIDs renderableSubItems; uint32_t numRenderableSubItems = renderer->metaFetchMetaSubItems(renderableSubItems); if (numRenderableSubItems > 0) { - for (auto& renderID : renderableSubItems) { - _descendantRenderIDs.insert(renderID); - oldDescendantRenderIDs.erase(renderID); - } + _descendantRenderIDs.insert(_descendantRenderIDs.end(), renderableSubItems.begin(), renderableSubItems.end()); } } } } }); - }); - render::Transaction transaction; - for (auto& oldDescendantRenderID : oldDescendantRenderIDs) { - transaction.updateItem(oldDescendantRenderID, [](render::PayloadProxyInterface& self) { - self.setOverrideSubMetaCulled(false); - }); - } - for (auto& descendantRenderIDs : _descendantRenderIDs) { - transaction.updateItem(descendantRenderIDs, [](render::PayloadProxyInterface& self) { - self.setOverrideSubMetaCulled(true); - }); - } - AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); + for (auto& oldRenderingDescendantEntityID : oldRenderingDescendantEntityIDs) { + auto entity = entityTree->findEntityByEntityItemID(oldRenderingDescendantEntityID); + if (entity) { + entity->setCullWithParent(false); + } + } + }); } }); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 235a04f109..6a740a793d 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -781,7 +781,8 @@ protected: void updateAttachmentRenderIDs(); render::ItemIDs _attachmentRenderIDs; void updateDescendantRenderIDs(); - render::ItemIDSet _descendantRenderIDs; + render::ItemIDs _descendantRenderIDs; + std::unordered_set _renderingDescendantEntityIDs; uint32_t _lastAncestorChainRenderableVersion { 0 }; }; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index fb3d2f1bf5..a1c5a5b432 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -168,19 +168,20 @@ render::hifi::Layer EntityRenderer::getHifiRenderLayer() const { } ItemKey EntityRenderer::getKey() { - ItemKey::Builder builder = ItemKey::Builder().withTypeShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); - + auto builder = ItemKey::Builder().withTypeShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); if (isTransparent()) { builder.withTransparent(); - } else if (_canCastShadow) { + } + + if (_canCastShadow) { builder.withShadowCaster(); } - if (!_visible) { - builder.withInvisible(); + if (_cullWithParent) { + builder.withSubMetaCulled(); } - return builder; + return builder.build(); } uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const { @@ -419,6 +420,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa setRenderLayer(entity->getRenderLayer()); setPrimitiveMode(entity->getPrimitiveMode()); _canCastShadow = entity->getCanCastShadow(); + setCullWithParent(entity->getCullWithParent()); _cauterized = entity->getCauterized(); entity->setNeedsRenderUpdate(false); }); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index d11f6dd6f4..227eb6a018 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -108,6 +108,16 @@ protected: virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; } virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; } virtual void setPrimitiveMode(PrimitiveMode value) { _primitiveMode = value; } + virtual void setCullWithParent(bool value) { _cullWithParent = value; } + + template + T withReadLockResult(const std::function& f) { + T result; + withReadLock([&] { + result = f(); + }); + return result; + } signals: void requestRenderUpdate(); @@ -130,6 +140,7 @@ protected: bool _visible { false }; bool _isVisibleInSecondaryCamera { false }; bool _canCastShadow { false }; + bool _cullWithParent { false }; RenderLayer _renderLayer { RenderLayer::WORLD }; PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; bool _cauterized { false }; diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index af121f2957..4c75a25962 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -210,8 +210,7 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo } ItemKey MaterialEntityRenderer::getKey() { - ItemKey::Builder builder; - builder.withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + auto builder = ItemKey::Builder().withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); if (!_visible) { builder.withInvisible(); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 1f2be0c488..1ea0d9d4c7 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1057,8 +1057,10 @@ ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Pare void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) { auto builder = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); - if (_model && _model->isGroupCulled()) { + if (!_cullWithParent && _model && _model->isGroupCulled()) { builder.withMetaCullGroup(); + } else if (_cullWithParent) { + builder.withoutSubMetaCulled(); } 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 void ModelEntityRenderer::doRender(RenderArgs* args) { DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender"); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index c32dad901f..0119c7bc26 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -164,6 +164,7 @@ protected: void setIsVisibleInSecondaryCamera(bool value) override; void setRenderLayer(RenderLayer value) override; void setPrimitiveMode(PrimitiveMode value) override; + void setCullWithParent(bool value) override; private: void animate(const TypedEntityPointer& entity); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index e3528e2291..f34eb85230 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -151,11 +151,17 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn ItemKey ParticleEffectEntityRenderer::getKey() { // FIXME: implement isTransparent() for particles and an opaque pipeline - if (_visible) { - return ItemKey::Builder::transparentShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); - } else { - return ItemKey::Builder().withInvisible().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()).build(); + auto builder = ItemKey::Builder::transparentShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + + if (!_visible) { + builder.withInvisible(); } + + if (_cullWithParent) { + builder.withSubMetaCulled(); + } + + return builder.build(); } ShapeKey ParticleEffectEntityRenderer::getShapeKey() { diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 9a762b3b3a..ae4654a21a 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -97,9 +97,14 @@ void PolyLineEntityRenderer::buildPipelines() { } ItemKey PolyLineEntityRenderer::getKey() { - return isTransparent() ? - ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()) : - ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + // FIXME: implement isTransparent() for polylines and an opaque pipeline + auto builder = ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + + if (_cullWithParent) { + builder.withSubMetaCulled(); + } + + return builder.build(); } ShapeKey PolyLineEntityRenderer::getShapeKey() { diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 853e36b45b..1555604604 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -1783,6 +1783,16 @@ PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) : _params = std::make_shared(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() { auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER); if (_primitiveMode == PrimitiveMode::LINES) { diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index c322959f86..825b4429cd 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -209,7 +209,7 @@ public: } protected: - virtual ItemKey getKey() override { return ItemKey::Builder::opaqueShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); } + virtual ItemKey getKey() override; virtual ShapeKey getShapeKey() override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 598ac17510..bbc9ff1991 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -3025,6 +3025,17 @@ void EntityItem::setCanCastShadow(bool value) { }); } +bool EntityItem::getCullWithParent() const { + return _cullWithParent; +} + +void EntityItem::setCullWithParent(bool value) { + if (_cullWithParent != value) { + _cullWithParent = value; + emit requestRenderUpdate(); + } +} + bool EntityItem::isChildOfMyAvatar() const { QUuid ancestorID = findAncestorOfType(NestableType::Avatar); return !ancestorID.isNull() && (ancestorID == Physics::getSessionUUID() || ancestorID == AVATAR_SELF_ID); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 3274379ee9..16ce9985bf 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -305,6 +305,9 @@ public: bool getCanCastShadow() const; void setCanCastShadow(bool value); + bool getCullWithParent() const; + void setCullWithParent(bool value); + void setCauterized(bool value); bool getCauterized() const; @@ -762,7 +765,7 @@ protected: QHash _grabActions; - mutable bool _needsRenderUpdate { false }; + bool _cullWithParent { false }; private: static std::function _getBillboardRotationOperator; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 947c53d546..d7983bbe50 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -102,6 +102,10 @@ void MeshPartPayload::updateKey(const render::ItemKey& key) { builder.withTransparent(); } + if (_cullWithParent) { + builder.withSubMetaCulled(); + } + _itemKey = builder.build(); } @@ -383,6 +387,10 @@ void ModelMeshPartPayload::updateKey(const render::ItemKey& key) { builder.withTransparent(); } + if (_cullWithParent) { + builder.withSubMetaCulled(); + } + _itemKey = builder.build(); } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 4d9510e4a2..e7415c6b8d 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -43,7 +43,7 @@ public: // Render Item interface virtual render::ItemKey getKey() const; virtual render::Item::Bound getBound() const; - virtual render::ShapeKey getShapeKey() const; // shape interface + virtual render::ShapeKey getShapeKey() const; virtual void render(RenderArgs* args); // ModelMeshPartPayload functions to perform render @@ -73,11 +73,11 @@ public: void addMaterial(graphics::MaterialLayer material); void removeMaterial(graphics::MaterialPointer material); - static bool enableMaterialProceduralShaders; + void setCullWithParent(bool value) { _cullWithParent = value; } protected: render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() }; - uint64_t _created; + bool _cullWithParent { false }; }; namespace render { @@ -106,7 +106,7 @@ public: void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform); // Render Item interface - render::ShapeKey getShapeKey() const override; // shape interface + render::ShapeKey getShapeKey() const override; void render(RenderArgs* args) override; void setShapeKey(bool invalidateShapeKey, PrimitiveMode primitiveMode, bool useDualQuaternionSkinning); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 182bc535bf..32e44c5cbf 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -154,7 +154,7 @@ void Model::setOffset(const glm::vec3& offset) { } void Model::calculateTextureInfo() { - if (!_hasCalculatedTextureInfo && isLoaded() && getGeometry()->areTexturesLoaded() && !_modelMeshRenderItemsMap.isEmpty()) { + if (!_hasCalculatedTextureInfo && isLoaded() && getGeometry()->areTexturesLoaded() && !_modelMeshRenderItems.isEmpty()) { size_t textureSize = 0; int textureCount = 0; bool allTexturesLoaded = true; @@ -960,6 +960,20 @@ void Model::setCauterized(bool cauterized, const render::ScenePointer& scene) { } } +void Model::setCullWithParent(bool cullWithParent) { + if (_cullWithParent != cullWithParent) { + _cullWithParent = cullWithParent; + + render::Transaction transaction; + foreach(auto item, _modelMeshRenderItemsMap.keys()) { + transaction.updateItem(item, [cullWithParent](ModelMeshPartPayload& data) { + data.setCullWithParent(cullWithParent); + }); + } + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); + } +} + const render::ItemKey Model::getRenderItemKeyGlobalFlags() const { return _renderItemKeyGlobalFlags; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 597fe552f7..b677861e9f 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -129,6 +129,8 @@ public: bool isCauterized() const { return _cauterized; } 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. const render::ItemKey getRenderItemKeyGlobalFlags() const; @@ -503,6 +505,7 @@ protected: // render::ItemKey _renderItemKeyGlobalFlags; bool _cauterized { false }; + bool _cullWithParent { false }; bool shouldInvalidatePayloadShapeKey(int meshIndex); diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index d5dde7f86b..532964777f 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -123,11 +123,7 @@ namespace render { if (!payload) { return ItemKey::Builder::opaqueShape().withTypeMeta(); } - if (payload->overrideSubMetaCulled()) { - return ItemKey::Builder(payload->getKey()).withSubMetaCulled(); - } else { - return payload->getKey(); - } + return payload->getKey(); } template <> const ShapeKey shapeGetShapeKey(const PayloadProxyInterface::Pointer& payload) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index e28a88f6dd..c94732eafe 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -615,12 +615,6 @@ public: virtual Item::Bound getBound() = 0; virtual void render(RenderArgs* args) = 0; virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) = 0; - - bool overrideSubMetaCulled() const { return _overrideSubMetaCulled; } - void setOverrideSubMetaCulled(bool overrideSubMetaCulled) { _overrideSubMetaCulled = overrideSubMetaCulled; } - -protected: - bool _overrideSubMetaCulled { false }; }; template <> const ItemKey payloadGetKey(const PayloadProxyInterface::Pointer& payload); @@ -631,7 +625,7 @@ template <> const ShapeKey shapeGetShapeKey(const PayloadProxyInterface::Pointer typedef Item::PayloadPointer PayloadPointer; -typedef std::vector< PayloadPointer > Payloads; +typedef std::vector Payloads; // A map of items by ShapeKey to optimize rendering pipeline assignments using ShapeBounds = std::unordered_map; From 615649534573520d643095ac1007ce46d068410d Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Tue, 26 Nov 2019 22:28:06 -0800 Subject: [PATCH 09/16] stupid, shadows still broken --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- libraries/render-utils/src/Model.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 1ea0d9d4c7..5fbbdfa0b8 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1060,7 +1060,7 @@ void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) { if (!_cullWithParent && _model && _model->isGroupCulled()) { builder.withMetaCullGroup(); } else if (_cullWithParent) { - builder.withoutSubMetaCulled(); + builder.withSubMetaCulled(); } if (didVisualGeometryRequestSucceed) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 32e44c5cbf..d8172112ff 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -965,9 +965,11 @@ void Model::setCullWithParent(bool cullWithParent) { _cullWithParent = cullWithParent; render::Transaction transaction; - foreach(auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [cullWithParent](ModelMeshPartPayload& data) { + auto renderItemsKey = _renderItemKeyGlobalFlags; + for(auto item : _modelMeshRenderItemIDs) { + transaction.updateItem(item, [cullWithParent, renderItemsKey](ModelMeshPartPayload& data) { data.setCullWithParent(cullWithParent); + data.updateKey(renderItemsKey); }); } AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); From 204c7a73914a4c340758d2478f367a9f69b272e6 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Thu, 5 Dec 2019 01:29:11 -0800 Subject: [PATCH 10/16] fix shadows!! --- .../src/RenderablePolyLineEntityItem.cpp | 7 +- .../render-utils/src/RenderShadowTask.cpp | 6 +- libraries/render/src/render/CullTask.cpp | 70 +------------------ libraries/render/src/render/CullTask.h | 28 +++----- .../src/render/RenderFetchCullSortTask.cpp | 2 +- 5 files changed, 20 insertions(+), 93 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index ae4654a21a..e75f8593d6 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -97,8 +97,11 @@ void PolyLineEntityRenderer::buildPipelines() { } ItemKey PolyLineEntityRenderer::getKey() { - // FIXME: implement isTransparent() for polylines and an opaque pipeline - auto builder = ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + auto builder = ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + + if (isTransparent()) { + builder.withTransparent(); + } if (_cullWithParent) { builder.withSubMetaCulled(); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 60e11f5301..fe005df2d4 100755 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -61,12 +61,12 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende const auto currentKeyLight = setupOutput.getN(4); // 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 shadowSelection = task.addJob("FetchShadowTree", fetchInput); - const auto selectionInputs = FilterSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying(); - const auto shadowItems = task.addJob("FilterShadowSelection", selectionInputs); + const auto selectionInputs = CullSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying(); + const auto shadowItems = task.addJob("FilterShadowSelection", selectionInputs, nullptr, true, RenderDetails::SHADOW); // 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. diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 5e5c6b4c6e..068d6f9851 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -172,7 +172,7 @@ void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inpu void CullSpatialSelection::configure(const Config& config) { _justFrozeFrustum = _justFrozeFrustum || (config.freezeFrustum && !_freezeFrustum); _freezeFrustum = config.freezeFrustum; - _skipCulling = config.skipCulling; + _overrideSkipCulling = config.skipCulling; } void CullSpatialSelection::run(const RenderContextPointer& renderContext, @@ -209,7 +209,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, // filter individually against the _filter // 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) - if (_skipCulling) { + if (_skipCulling || _overrideSkipCulling) { // inside & fit items: filter only, culling is disabled { PerformanceTimer perfTimer("insideFitItems"); @@ -444,69 +444,3 @@ void ApplyCullFunctorOnItemBounds::run(const RenderContextPointer& renderContext 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); - } - } - } - } -} diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h index 99ca7abe6c..e67edd6666 100644 --- a/libraries/render/src/render/CullTask.h +++ b/libraries/render/src/render/CullTask.h @@ -100,26 +100,25 @@ namespace render { }; class CullSpatialSelection { - bool _freezeFrustum{ false }; // initialized by Config - bool _justFrozeFrustum{ false }; - bool _skipCulling{ false }; - ViewFrustum _frozenFrustum; public: using Config = CullSpatialSelectionConfig; using Inputs = render::VaryingSet2; using JobModel = Job::ModelIO; - CullSpatialSelection(CullFunctor cullFunctor, RenderDetails::Type type) : - _cullFunctor{ cullFunctor }, + CullSpatialSelection(CullFunctor cullFunctor, bool skipCulling, RenderDetails::Type type) : + _cullFunctor(cullFunctor), + _skipCulling(skipCulling), _detailType(type) {} - CullSpatialSelection(CullFunctor cullFunctor) : - _cullFunctor{ cullFunctor } { - } - CullFunctor _cullFunctor; + bool _skipCulling { false }; 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 run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems); }; @@ -147,15 +146,6 @@ namespace render { }; - class FilterSpatialSelection { - public: - using Inputs = render::VaryingSet2; - using JobModel = Job::ModelIO; - - FilterSpatialSelection() {} - void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems); - }; - class ApplyCullFunctorOnItemBounds { public: using Inputs = render::VaryingSet2; diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index 6b1a57ed88..ebcf5a432b 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -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 spatialSelection = task.addJob("FetchSceneSelection", fetchInput); const auto cullInputs = CullSpatialSelection::Inputs(spatialSelection, spatialFilter).asVarying(); - const auto culledSpatialSelection = task.addJob("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM); + const auto culledSpatialSelection = task.addJob("CullSceneSelection", cullInputs, cullFunctor, false, RenderDetails::ITEM); // Layered objects are not culled const ItemFilter layeredFilter = ItemFilter::Builder::visibleWorldItems().withTagBits(tagBits, tagMask); From 1ef45b703c0b1dbca9bb5e63ce56138962bcf048 Mon Sep 17 00:00:00 2001 From: Maki Date: Tue, 19 Nov 2019 12:35:06 +0000 Subject: [PATCH 11/16] Added environment variables to change domain server ports Signed-off-by: Kasen IO --- libraries/networking/src/DomainHandler.h | 37 +++++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index fb18866001..a71be7be21 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -12,6 +12,8 @@ #ifndef hifi_DomainHandler_h #define hifi_DomainHandler_h +#include + #include #include #include @@ -30,10 +32,37 @@ #include "ReceivedMessage.h" #include "NetworkingConstants.h" -const unsigned short DEFAULT_DOMAIN_SERVER_PORT = 40102; -const unsigned short DEFAULT_DOMAIN_SERVER_DTLS_PORT = 40103; -const quint16 DOMAIN_SERVER_HTTP_PORT = 40100; -const quint16 DOMAIN_SERVER_HTTPS_PORT = 40101; +const unsigned short DEFAULT_DOMAIN_SERVER_PORT = + QProcessEnvironment::systemEnvironment() + .contains("HIFI_DOMAIN_SERVER_PORT") + ? QProcessEnvironment::systemEnvironment() + .value("HIFI_DOMAIN_SERVER_PORT") + .toShort() + : 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") + .toShort() + : 40103; + +const quint16 DOMAIN_SERVER_HTTP_PORT = + QProcessEnvironment::systemEnvironment() + .contains("HIFI_DOMAIN_SERVER_HTTP_PORT") + ? QProcessEnvironment::systemEnvironment() + .value("HIFI_DOMAIN_SERVER_HTTP_PORT") + .toShort() + : 40100; + +const quint16 DOMAIN_SERVER_HTTPS_PORT = + QProcessEnvironment::systemEnvironment() + .contains("HIFI_DOMAIN_SERVER_HTTPS_PORT") + ? QProcessEnvironment::systemEnvironment() + .value("HIFI_DOMAIN_SERVER_HTTPS_PORT") + .toShort() + : 40101; const int MAX_SILENT_DOMAIN_SERVER_CHECK_INS = 5; From a7851c9205940a60298bde76510e79d1e110e24b Mon Sep 17 00:00:00 2001 From: Maki Date: Wed, 20 Nov 2019 09:13:08 +0000 Subject: [PATCH 12/16] Fixed type conversions for environmental domain ports Signed-off-by: Kasen IO --- libraries/networking/src/DomainHandler.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index a71be7be21..505bbb94b5 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -37,7 +37,7 @@ const unsigned short DEFAULT_DOMAIN_SERVER_PORT = .contains("HIFI_DOMAIN_SERVER_PORT") ? QProcessEnvironment::systemEnvironment() .value("HIFI_DOMAIN_SERVER_PORT") - .toShort() + .toUShort() : 40102; const unsigned short DEFAULT_DOMAIN_SERVER_DTLS_PORT = @@ -45,7 +45,7 @@ const unsigned short DEFAULT_DOMAIN_SERVER_DTLS_PORT = .contains("HIFI_DOMAIN_SERVER_DTLS_PORT") ? QProcessEnvironment::systemEnvironment() .value("HIFI_DOMAIN_SERVER_DTLS_PORT") - .toShort() + .toUShort() : 40103; const quint16 DOMAIN_SERVER_HTTP_PORT = @@ -53,7 +53,7 @@ const quint16 DOMAIN_SERVER_HTTP_PORT = .contains("HIFI_DOMAIN_SERVER_HTTP_PORT") ? QProcessEnvironment::systemEnvironment() .value("HIFI_DOMAIN_SERVER_HTTP_PORT") - .toShort() + .toUInt() : 40100; const quint16 DOMAIN_SERVER_HTTPS_PORT = @@ -61,7 +61,7 @@ const quint16 DOMAIN_SERVER_HTTPS_PORT = .contains("HIFI_DOMAIN_SERVER_HTTPS_PORT") ? QProcessEnvironment::systemEnvironment() .value("HIFI_DOMAIN_SERVER_HTTPS_PORT") - .toShort() + .toUInt() : 40101; const int MAX_SILENT_DOMAIN_SERVER_CHECK_INS = 5; From 0bd5e15b47b4a2de8153b00083ef74661587db7b Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 11 Dec 2019 00:42:59 -0800 Subject: [PATCH 13/16] fix non-procedural material entity crash Signed-off-by: Kasen IO --- interface/src/Application.cpp | 2 +- .../src/RenderableMaterialEntityItem.cpp | 3 ++- libraries/entities/src/EntityTree.cpp | 8 ++++---- libraries/entities/src/EntityTree.h | 6 +++--- libraries/entities/src/MaterialEntityItem.cpp | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 492495808e..dd9a10a237 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2107,7 +2107,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } return false; }); - EntityTree::setGetUnscaledDimensionsForEntityIDOperator([this](const QUuid& id) { + EntityTree::setGetUnscaledDimensionsForIDOperator([this](const QUuid& id) { if (_aboutToQuit) { return glm::vec3(1.0f); } diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 4c75a25962..c1b024a478 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -395,7 +395,8 @@ void MaterialEntityRenderer::applyMaterial(const TypedEntityPointer& entity) { graphics::MaterialLayer materialLayer = graphics::MaterialLayer(material, _priority); - if (auto procedural = std::static_pointer_cast(material)) { + if (material->isProcedural()) { + auto procedural = std::static_pointer_cast(material); procedural->setBoundOperator([this] { return getBound(); }); entity->setHasVertexShader(procedural->hasVertexShader()); } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 565fb37781..41008625e8 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -3113,7 +3113,7 @@ std::function EntityTree::_getEntityObjectOperator = nul std::function EntityTree::_textSizeOperator = nullptr; std::function EntityTree::_areEntityClicksCapturedOperator = nullptr; std::function EntityTree::_emitScriptEventOperator = nullptr; -std::function EntityTree::_getUnscaledDimensionsForEntityIDOperator = nullptr; +std::function EntityTree::_getUnscaledDimensionsForIDOperator = nullptr; QObject* EntityTree::getEntityObject(const QUuid& id) { if (_getEntityObjectOperator) { @@ -3142,9 +3142,9 @@ void EntityTree::emitScriptEvent(const QUuid& id, const QVariant& message) { } } -glm::vec3 EntityTree::getUnscaledDimensionsForEntityID(const QUuid& id) { - if (_getUnscaledDimensionsForEntityIDOperator) { - return _getUnscaledDimensionsForEntityIDOperator(id); +glm::vec3 EntityTree::getUnscaledDimensionsForID(const QUuid& id) { + if (_getUnscaledDimensionsForIDOperator) { + return _getUnscaledDimensionsForIDOperator(id); } return glm::vec3(1.0f); } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index c083493e99..a0fcbd3244 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -271,8 +271,8 @@ public: static void setEmitScriptEventOperator(std::function emitScriptEventOperator) { _emitScriptEventOperator = emitScriptEventOperator; } static void emitScriptEvent(const QUuid& id, const QVariant& message); - static void setGetUnscaledDimensionsForEntityIDOperator(std::function getUnscaledDimensionsForEntityIDOperator) { _getUnscaledDimensionsForEntityIDOperator = getUnscaledDimensionsForEntityIDOperator; } - static glm::vec3 getUnscaledDimensionsForEntityID(const QUuid& id); + static void setGetUnscaledDimensionsForIDOperator(std::function getUnscaledDimensionsForIDOperator) { _getUnscaledDimensionsForIDOperator = getUnscaledDimensionsForIDOperator; } + static glm::vec3 getUnscaledDimensionsForID(const QUuid& id); std::map getNamedPaths() const { return _namedPaths; } @@ -389,7 +389,7 @@ private: static std::function _textSizeOperator; static std::function _areEntityClicksCapturedOperator; static std::function _emitScriptEventOperator; - static std::function _getUnscaledDimensionsForEntityIDOperator; + static std::function _getUnscaledDimensionsForIDOperator; std::vector _staleProxies; diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index 22143e88ba..73bebfc403 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -293,7 +293,7 @@ void MaterialEntityItem::setHasVertexShader(bool hasVertexShader) { if (hasVertexShader && !prevHasVertexShader) { setLocalPosition(glm::vec3(0.0f)); setLocalOrientation(glm::quat()); - setUnscaledDimensions(EntityTree::getUnscaledDimensionsForEntityID(getParentID())); + setUnscaledDimensions(EntityTree::getUnscaledDimensionsForID(getParentID())); } else if (!hasVertexShader && prevHasVertexShader) { setUnscaledDimensions(_desiredDimensions); } From 9839b23061534e3deb69108c0f463ab82ff0695d Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Fri, 13 Dec 2019 02:38:14 -0500 Subject: [PATCH 14/16] Made Sam's graphics patches work with 86 K2. --- libraries/entities/src/EntityItem.h | 3 +++ libraries/render-utils/src/MeshPartPayload.cpp | 2 +- libraries/render-utils/src/MeshPartPayload.h | 3 +++ libraries/render/src/render/Item.h | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 16ce9985bf..2c04614a1c 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -579,6 +579,7 @@ public: signals: void spaceUpdate(std::pair data); + void requestRenderUpdate(); protected: QHash _changeHandlers; @@ -766,6 +767,8 @@ protected: QHash _grabActions; bool _cullWithParent { false }; + + mutable bool _needsRenderUpdate { false }; private: static std::function _getBillboardRotationOperator; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index d7983bbe50..e82af5395f 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -189,7 +189,7 @@ void MeshPartPayload::render(RenderArgs* args) { if (!_drawMaterials.empty() && _drawMaterials.top().material && _drawMaterials.top().material->isProcedural() && _drawMaterials.top().material->isReady()) { - if (!(enableMaterialProceduralShaders && ENABLE_MATERIAL_PROCEDURAL_SHADERS)) { + if (!enableMaterialProceduralShaders) { return; } auto procedural = std::static_pointer_cast(_drawMaterials.top().material); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index e7415c6b8d..ee205bd778 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -75,9 +75,12 @@ public: void setCullWithParent(bool value) { _cullWithParent = value; } + static bool enableMaterialProceduralShaders; + protected: render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() }; bool _cullWithParent { false }; + uint64_t _created; }; namespace render { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index c94732eafe..3383101b5b 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -614,7 +614,7 @@ public: virtual ShapeKey getShapeKey() = 0; virtual Item::Bound getBound() = 0; virtual void render(RenderArgs* args) = 0; - virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) = 0; + virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const = 0; }; template <> const ItemKey payloadGetKey(const PayloadProxyInterface::Pointer& payload); From 1f01beba70a03f8e8017f7bdc3305f315637782b Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Fri, 13 Dec 2019 12:29:08 -0500 Subject: [PATCH 15/16] Fixed patch issues --- .../entities-renderer/src/RenderableEntityItem.cpp | 14 +++++++++----- libraries/entities/src/EntityItem.cpp | 6 +++--- libraries/entities/src/EntityItem.h | 1 - 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index a1c5a5b432..ae56a8fc47 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -168,12 +168,12 @@ render::hifi::Layer EntityRenderer::getHifiRenderLayer() const { } ItemKey EntityRenderer::getKey() { - auto builder = ItemKey::Builder().withTypeShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + ItemKey::Builder builder = + ItemKey::Builder().withTypeShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); + if (isTransparent()) { builder.withTransparent(); - } - - if (_canCastShadow) { + } else if (_canCastShadow) { builder.withShadowCaster(); } @@ -181,7 +181,11 @@ ItemKey EntityRenderer::getKey() { builder.withSubMetaCulled(); } - return builder.build(); + if (!_visible) { + builder.withInvisible(); + } + + return builder; } uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index bbc9ff1991..cc215d3528 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -3030,10 +3030,10 @@ bool EntityItem::getCullWithParent() const { } void EntityItem::setCullWithParent(bool value) { - if (_cullWithParent != value) { + withWriteLock([&] { + _needsRenderUpdate |= _cullWithParent != value; _cullWithParent = value; - emit requestRenderUpdate(); - } + }); } bool EntityItem::isChildOfMyAvatar() const { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 2c04614a1c..14b8b259cc 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -579,7 +579,6 @@ public: signals: void spaceUpdate(std::pair data); - void requestRenderUpdate(); protected: QHash _changeHandlers; From fd051445901f43c893b256328dec97ae5eaf6d80 Mon Sep 17 00:00:00 2001 From: Marcus Llewellyn Date: Tue, 17 Dec 2019 14:10:10 -0600 Subject: [PATCH 16/16] fix sdl2 on sam+domains branch --- cmake/ports/sdl2/CONTROL | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/ports/sdl2/CONTROL b/cmake/ports/sdl2/CONTROL index 3f96bc71f1..ec60fc09ba 100644 --- a/cmake/ports/sdl2/CONTROL +++ b/cmake/ports/sdl2/CONTROL @@ -1,6 +1,5 @@ Source: sdl2 Version: 2.0.10-2 -Homepage: https://github.com/SDL-Mirror/SDL Description: Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D. Feature: vulkan