diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index c9ff8e681b..855a5965ad 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -147,11 +147,12 @@ bool NetworkGeometry::isLoadedWithTextures() const { (material->lightmapTexture && !material->lightmapTexture->isLoaded())) { return false; } - if (material->albedoTexture && material->albedoTexture->getGPUTexture()) { + if (material->useAlbedoMapOpacity && material->albedoTexture && material->albedoTexture->getGPUTexture()) { + material->_material->setTextureMap(model::MaterialKey::ALBEDO_MAP, material->_material->getTextureMap(model::MaterialKey::ALBEDO_MAP)); // Reset the materialKey transparentTexture key only, as it is albedoTexture-dependent const auto& usage = material->albedoTexture->getGPUTexture()->getUsage(); bool isTransparentTexture = usage.isAlpha() && !usage.isAlphaMask(); - material->_material->setTransparentTexture(isTransparentTexture); + // material->_material->setTransparentTexture(isTransparentTexture); // FIXME: Materials with *some* transparent textures seem to give all *other* textures alphas of 0. _hasTransparentTextures = isTransparentTexture && _hasTransparentTextures; } @@ -376,9 +377,21 @@ static NetworkMaterial* buildNetworkMaterial(NetworkGeometry* geometry, const FB auto albedoMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.albedoTexture, DEFAULT_TEXTURE, networkMaterial->albedoTexture, networkMaterial->albedoTextureName); albedoMap->setTextureTransform(material.albedoTexture.transform); + + if (!material.opacityTexture.filename.isEmpty()) { + if (material.albedoTexture.filename == material.opacityTexture.filename) { + // Best case scenario, just indicating that the albedo map contains transparency + networkMaterial->useAlbedoMapOpacity; + albedoMap->setUseAlphaChannel(true); + } else { + // Opacity Map is different from the Abledo map, not supported + } + } + material._material->setTextureMap(model::MaterialKey::ALBEDO_MAP, albedoMap); } + if (!material.normalTexture.filename.isEmpty()) { auto normalMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.normalTexture, (material.normalTexture.isBumpmap ? BUMP_TEXTURE : NORMAL_TEXTURE), diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 7f01bdafaa..b172bb70b4 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -199,6 +199,7 @@ public: QSharedPointer<NetworkTexture> occlusionTexture; QString lightmapTextureName; QSharedPointer<NetworkTexture> lightmapTexture; + bool useAlbedoMapOpacity{ false }; }; diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index 306867c204..21fdab59a3 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -51,7 +51,7 @@ void Material::setEmissive(const Color& emissive, bool isSRGB) { } void Material::setOpacity(float opacity) { - _key.setTransparent((opacity < 1.0f)); + _key.setTransparentFactor((opacity < 1.0f)); _schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong(); _schemaBuffer.edit<Schema>()._opacity = opacity; } @@ -80,19 +80,52 @@ void Material::setMetallic(float metallic) { _schemaBuffer.edit<Schema>()._metallic = metallic; } -void Material::setTransparentTexture(bool isTransparent) { - _key.setTransparentTexture(isTransparent); - _schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong(); -} void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) { if (textureMap) { _key.setMapChannel(channel, (true)); + + if (channel == MaterialKey::ALBEDO_MAP) { + if (textureMap->useAlphaChannel()) { + if (textureMap->isDefined()) { + if (textureMap->getTextureView().isValid()) { + auto usage = textureMap->getTextureView()._texture->getUsage(); + if (usage.isAlpha()) { + // Texture has alpha, is nut just a mask or a true transparent channel + if (!usage.isAlphaMask()) { + _key.setOpacityMaskMap(true); + _key.setTransparentMap(false); + } else { + _key.setOpacityMaskMap(false); + _key.setTransparentMap(true); + } + } + } + } + } + } + _schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong(); _textureMaps[channel] = textureMap; } else { _key.setMapChannel(channel, (false)); + + if (channel == MaterialKey::ALBEDO_MAP) { + _key.setOpacityMaskMap(false); + _key.setTransparentMap(false); + } + _schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong(); _textureMaps.erase(channel); } } + + +const TextureMapPointer Material::getTextureMap(MapChannel channel) const { + auto result = _textureMaps.find(channel); + if (result != _textureMaps.end()) { + return (result->second); + } else { + return TextureMapPointer(); + } +} \ No newline at end of file diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index 078fc6499a..0cef46f788 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -31,14 +31,14 @@ public: ALBEDO_VAL_BIT, METALLIC_VAL_BIT, GLOSSY_VAL_BIT, - TRANSPARENT_VAL_BIT, - TRANSPARENT_TEX_VAL_BIT, + OPACITY_VAL_BIT, EMISSIVE_MAP_BIT, ALBEDO_MAP_BIT, + OPACITY_MASK_MAP_BIT, // OPacity Map and Opacity MASK map are mutually exclusive + OPACITY_TRANSPARENT_MAP_BIT, METALLIC_MAP_BIT, ROUGHNESS_MAP_BIT, - TRANSPARENT_MAP_BIT, NORMAL_MAP_BIT, OCCLUSION_MAP_BIT, LIGHTMAP_MAP_BIT, @@ -52,7 +52,6 @@ public: ALBEDO_MAP, METALLIC_MAP, ROUGHNESS_MAP, - TRANSPARENT_MAP, NORMAL_MAP, OCCLUSION_MAP, LIGHTMAP_MAP, @@ -77,13 +76,15 @@ public: Builder& withAlbedo() { _flags.set(ALBEDO_VAL_BIT); return (*this); } Builder& withMetallic() { _flags.set(METALLIC_VAL_BIT); return (*this); } Builder& withGlossy() { _flags.set(GLOSSY_VAL_BIT); return (*this); } - Builder& withTransparent() { _flags.set(TRANSPARENT_VAL_BIT); return (*this); } + Builder& withOpacity() { _flags.set(OPACITY_VAL_BIT); return (*this); } Builder& withEmissiveMap() { _flags.set(EMISSIVE_MAP_BIT); return (*this); } Builder& withAlbedoMap() { _flags.set(ALBEDO_MAP_BIT); return (*this); } Builder& withMetallicMap() { _flags.set(METALLIC_MAP_BIT); return (*this); } Builder& withRoughnessMap() { _flags.set(ROUGHNESS_MAP_BIT); return (*this); } - Builder& withTransparentMap() { _flags.set(TRANSPARENT_MAP_BIT); return (*this); } + + Builder& withTransparentMap() { _flags.set(OPACITY_TRANSPARENT_MAP_BIT); return (*this); } + Builder& withMaskMap() { _flags.set(OPACITY_MASK_MAP_BIT); return (*this); } Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); } Builder& withOcclusionMap() { _flags.set(OCCLUSION_MAP_BIT); return (*this); } @@ -102,9 +103,6 @@ public: void setAlbedo(bool value) { _flags.set(ALBEDO_VAL_BIT, value); } bool isAlbedo() const { return _flags[ALBEDO_VAL_BIT]; } - void setTransparentTexture(bool value) { _flags.set(TRANSPARENT_TEX_VAL_BIT, value); } - bool isTransparentTexture() const { return _flags[TRANSPARENT_TEX_VAL_BIT]; } - void setAlbedoMap(bool value) { _flags.set(ALBEDO_MAP_BIT, value); } bool isAlbedoMap() const { return _flags[ALBEDO_MAP_BIT]; } @@ -121,13 +119,16 @@ public: void setRoughnessMap(bool value) { _flags.set(ROUGHNESS_MAP_BIT, value); } bool isRoughnessMap() const { return _flags[ROUGHNESS_MAP_BIT]; } - void setTransparent(bool value) { _flags.set(TRANSPARENT_VAL_BIT, value); } - bool isTransparent() const { return _flags[TRANSPARENT_VAL_BIT]; } - bool isOpaque() const { return !_flags[TRANSPARENT_VAL_BIT]; } + void setTransparentFactor(bool value) { _flags.set(OPACITY_VAL_BIT, value); } + bool isTransparentFactor() const { return _flags[OPACITY_VAL_BIT]; } + bool isOpaqueFactor() const { return !_flags[OPACITY_VAL_BIT]; } - void setTransparentMap(bool value) { _flags.set(TRANSPARENT_MAP_BIT, value); } - bool isTransparentMap() const { return _flags[TRANSPARENT_MAP_BIT]; } + void setTransparentMap(bool value) { _flags.set(OPACITY_TRANSPARENT_MAP_BIT, value); } + bool isTransparentMap() const { return _flags[OPACITY_TRANSPARENT_MAP_BIT]; } + void setOpacityMaskMap(bool value) { _flags.set(OPACITY_MASK_MAP_BIT, value); } + bool isOpacityMaskMap() const { return _flags[OPACITY_MASK_MAP_BIT]; } + void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); } bool isNormalMap() const { return _flags[NORMAL_MAP_BIT]; } @@ -168,9 +169,6 @@ public: Builder& withoutAlbedo() { _value.reset(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); } Builder& withAlbedo() { _value.set(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); } - Builder& withoutTransparentTexture() { _value.reset(MaterialKey::TRANSPARENT_TEX_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_TEX_VAL_BIT); return (*this); } - Builder& withTransparentTexture() { _value.set(MaterialKey::TRANSPARENT_TEX_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_TEX_VAL_BIT); return (*this); } - Builder& withoutAlbedoMap() { _value.reset(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT); return (*this); } Builder& withAlbedoMap() { _value.set(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT); return (*this); } @@ -186,11 +184,15 @@ public: Builder& withoutRoughnessMap() { _value.reset(MaterialKey::ROUGHNESS_MAP_BIT); _mask.set(MaterialKey::ROUGHNESS_MAP_BIT); return (*this); } Builder& withRoughnessMap() { _value.set(MaterialKey::ROUGHNESS_MAP_BIT); _mask.set(MaterialKey::ROUGHNESS_MAP_BIT); return (*this); } - Builder& withoutTransparent() { _value.reset(MaterialKey::TRANSPARENT_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_VAL_BIT); return (*this); } - Builder& withTransparent() { _value.set(MaterialKey::TRANSPARENT_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_VAL_BIT); return (*this); } + Builder& withoutTransparentFactor() { _value.reset(MaterialKey::OPACITY_VAL_BIT); _mask.set(MaterialKey::OPACITY_VAL_BIT); return (*this); } + Builder& withTransparentFactor() { _value.set(MaterialKey::OPACITY_VAL_BIT); _mask.set(MaterialKey::OPACITY_VAL_BIT); return (*this); } + Builder& withOpaqueFactor() { return withoutTransparentFactor(); } - Builder& withoutTransparentMap() { _value.reset(MaterialKey::TRANSPARENT_MAP_BIT); _mask.set(MaterialKey::TRANSPARENT_MAP_BIT); return (*this); } - Builder& withTransparentMap() { _value.set(MaterialKey::TRANSPARENT_MAP_BIT); _mask.set(MaterialKey::TRANSPARENT_MAP_BIT); return (*this); } + Builder& withoutTransparentMap() { _value.reset(MaterialKey::OPACITY_TRANSPARENT_MAP_BIT); _mask.set(MaterialKey::OPACITY_TRANSPARENT_MAP_BIT); return (*this); } + Builder& withTransparentMap() { _value.set(MaterialKey::OPACITY_TRANSPARENT_MAP_BIT); _mask.set(MaterialKey::OPACITY_TRANSPARENT_MAP_BIT); return (*this); } + + Builder& withoutMaskMap() { _value.reset(MaterialKey::OPACITY_MASK_MAP_BIT); _mask.set(MaterialKey::OPACITY_MASK_MAP_BIT); return (*this); } + Builder& withMaskMap() { _value.set(MaterialKey::OPACITY_MASK_MAP_BIT); _mask.set(MaterialKey::OPACITY_MASK_MAP_BIT); return (*this); } Builder& withoutNormalMap() { _value.reset(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); } Builder& withNormalMap() { _value.set(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); } @@ -202,7 +204,7 @@ public: Builder& withLightmapMap() { _value.set(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); } // Convenient standard keys that we will keep on using all over the place - static MaterialFilter opaqueAlbedo() { return Builder().withAlbedo().withoutTransparent().build(); } + static MaterialFilter opaqueAlbedo() { return Builder().withAlbedo().withOpaqueFactor().build(); } }; // Item Filter operator testing if a key pass the filter @@ -255,7 +257,6 @@ public: void setRoughness(float roughness); float getRoughness() const { return _schemaBuffer.get<Schema>()._roughness; } - void setTransparentTexture(bool isTransparent); // Schema to access the attribute values of the material class Schema { @@ -283,6 +284,7 @@ public: // The texture map to channel association void setTextureMap(MapChannel channel, const TextureMapPointer& textureMap); const TextureMaps& getTextureMaps() const { return _textureMaps; } + const TextureMapPointer getTextureMap(MapChannel channel) const; // conversion from legacy material properties to PBR equivalent static float shininessToRoughness(float shininess) { return 1.0f - shininess / 100.0f; } diff --git a/libraries/model/src/model/TextureMap.h b/libraries/model/src/model/TextureMap.h index 228adb25e6..e845aebb81 100755 --- a/libraries/model/src/model/TextureMap.h +++ b/libraries/model/src/model/TextureMap.h @@ -56,6 +56,9 @@ public: void setTextureTransform(const Transform& texcoordTransform); const Transform& getTextureTransform() const { return _texcoordTransform; } + void setUseAlphaChannel(bool useAlpha) { _useAlphaChannel = useAlpha; } + bool useAlphaChannel() const { return _useAlphaChannel; } + void setLightmapOffsetScale(float offset, float scale); const glm::vec2& getLightmapOffsetScale() const { return _lightmapOffsetScale; } @@ -64,6 +67,8 @@ protected: Transform _texcoordTransform; glm::vec2 _lightmapOffsetScale{ 0.0f, 1.0f }; + + bool _useAlphaChannel{ false }; }; typedef std::shared_ptr< TextureMap > TextureMapPointer; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 4ae5b4532a..2e66fe43f2 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -81,7 +81,7 @@ ItemKey MeshPartPayload::getKey() const { if (_drawMaterial) { auto matKey = _drawMaterial->getKey(); - if (matKey.isTransparent() || matKey.isTransparentTexture() || matKey.isTransparentMap()) { + if (matKey.isTransparentFactor() || matKey.isTransparentMap()) { builder.withTransparent(); } } @@ -100,7 +100,7 @@ ShapeKey MeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; - if (drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentTexture() || drawMaterialKey.isTransparentMap()) { + if (drawMaterialKey.isTransparentFactor() || drawMaterialKey.isTransparentMap()) { builder.withTranslucent(); } if (drawMaterialKey.isNormalMap()) { @@ -365,7 +365,7 @@ ItemKey ModelMeshPartPayload::getKey() const { if (_drawMaterial) { auto matKey = _drawMaterial->getKey(); - if (matKey.isTransparent() || matKey.isTransparentTexture() || matKey.isTransparentMap()) { + if (matKey.isTransparentFactor() || matKey.isTransparentMap()) { builder.withTransparent(); } } @@ -413,7 +413,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { } bool isTranslucent = - drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentTexture() || drawMaterialKey.isTransparentMap(); + drawMaterialKey.isTransparentFactor() || drawMaterialKey.isTransparentMap(); bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); bool hasSpecular = drawMaterialKey.isMetallicMap(); bool hasLightmap = drawMaterialKey.isLightmapMap();