From 68b754fc0c20465be00dbe8006b6b7774b1a93dd Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 12 Sep 2019 17:01:16 -0700 Subject: [PATCH] Changes driven by the alpha mode --- .../src/graphics-scripting/Forward.h | 1 + .../GraphicsScriptingInterface.cpp | 6 +- .../graphics-scripting/ScriptableModel.cpp | 2 + libraries/graphics/src/graphics/Material.cpp | 25 +++++-- libraries/graphics/src/graphics/Material.h | 67 +++++++++++++++---- libraries/graphics/src/graphics/Material.slh | 10 +-- .../src/graphics/MaterialTextures.slh | 7 ++ .../render-utils/src/RenderPipelines.cpp | 1 + libraries/render-utils/src/model.slf | 18 +++-- 9 files changed, 103 insertions(+), 34 deletions(-) diff --git a/libraries/graphics-scripting/src/graphics-scripting/Forward.h b/libraries/graphics-scripting/src/graphics-scripting/Forward.h index 6fa7362e84..c74c1c09bf 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/Forward.h +++ b/libraries/graphics-scripting/src/graphics-scripting/Forward.h @@ -79,6 +79,7 @@ namespace scriptable { float roughness; float metallic; float scattering; + float alphaCutoff; bool unlit; glm::vec3 emissive; glm::vec3 albedo; diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index a271affe49..02083af932 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -382,7 +382,8 @@ namespace scriptable { if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::SCATTERING_VAL_BIT)) { obj.setProperty("scattering", FALLTHROUGH); - } else if (material.key.isScattering()) { + } + else if (material.key.isScattering()) { obj.setProperty("scattering", material.scattering); } @@ -428,8 +429,11 @@ namespace scriptable { if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OPACITY_MASK_MAP_BIT)) { obj.setProperty("opacityMapMode", FALLTHROUGH); + obj.setProperty("alphaCutoff", FALLTHROUGH); } else if (material.key.isGlossy()) { obj.setProperty("opacityMapMode", material.opacityMode); + + obj.setProperty("alphaCutoff", material.alphaCutoff); } if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OCCLUSION_MAP_BIT)) { diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp index 071272a382..a81f17f254 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp @@ -26,6 +26,7 @@ scriptable::ScriptableMaterial& scriptable::ScriptableMaterial::operator=(const roughness = material.roughness; metallic = material.metallic; scattering = material.scattering; + alphaCutoff = material.alphaCutoff; unlit = material.unlit; emissive = material.emissive; albedo = material.albedo; @@ -63,6 +64,7 @@ scriptable::ScriptableMaterial::ScriptableMaterial(const graphics::MaterialPoint roughness = material->getRoughness(); metallic = material->getMetallic(); scattering = material->getScattering(); + alphaCutoff = material->getAlphaCutoff(); unlit = material->isUnlit(); emissive = material->getEmissive(); albedo = material->getAlbedo(); diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index 6be8ec5f68..d18ad4b74e 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -22,7 +22,8 @@ const float Material::DEFAULT_OPACITY { 1.0f }; const float Material::DEFAULT_ALBEDO { 0.5f }; const float Material::DEFAULT_METALLIC { 0.0f }; const float Material::DEFAULT_ROUGHNESS { 1.0f }; -const float Material::DEFAULT_SCATTERING { 0.0f }; +const float Material::DEFAULT_SCATTERING{ 0.0f }; +const float Material::DEFAULT_ALPHA_CUTOFF { 0.5f }; Material::Material() { for (int i = 0; i < NUM_TOTAL_FLAGS; i++) { @@ -40,6 +41,7 @@ Material::Material(const Material& material) : _roughness(material._roughness), _metallic(material._metallic), _scattering(material._scattering), + _alphaCutoff(material._alphaCutoff), _texcoordTransforms(material._texcoordTransforms), _lightmapParams(material._lightmapParams), _materialParams(material._materialParams), @@ -50,7 +52,7 @@ Material::Material(const Material& material) : } Material& Material::operator=(const Material& material) { - QMutexLocker locker(&_textureMapsMutex); + std::lock_guard locker(_textureMapsMutex); _name = material._name; _model = material._model; @@ -61,6 +63,7 @@ Material& Material::operator=(const Material& material) { _roughness = material._roughness; _metallic = material._metallic; _scattering = material._scattering; + _alphaCutoff = material._alphaCutoff; _texcoordTransforms = material._texcoordTransforms; _lightmapParams = material._lightmapParams; _materialParams = material._materialParams; @@ -109,8 +112,22 @@ void Material::setScattering(float scattering) { _scattering = scattering; } +void Material::setAlphaCutoff(float alphaCutoff) { + alphaCutoff = glm::clamp(alphaCutoff, 0.0f, 1.0f); + // _key.setAlphaCutoff(alphaCutoff != DEFAULT_ALPHA_CUTOFF); + _alphaCutoff = alphaCutoff; +} + +void Material::setAlphaMapMode(MaterialKey::AlphaMapMode alphaMode) { + _key.setAlphaMapMode(alphaMode); +} + +MaterialKey::AlphaMapMode Material::getAlphaMapMode() const { + return _key.getAlphaMapMode(); +} + void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) { - QMutexLocker locker(&_textureMapsMutex); + std::lock_guard locker(_textureMapsMutex); if (textureMap) { _key.setMapChannel(channel, true); @@ -166,7 +183,7 @@ void Material::resetOpacityMap() const { } const TextureMapPointer Material::getTextureMap(MapChannel channel) const { - QMutexLocker locker(&_textureMapsMutex); + std::lock_guard locker(_textureMapsMutex); auto result = _textureMaps.find(channel); if (result != _textureMaps.end()) { diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 25601c5743..500eab9a39 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -11,8 +11,7 @@ #ifndef hifi_model_Material_h #define hifi_model_Material_h -#include - +#include #include #include #include @@ -73,6 +72,12 @@ public: NUM_MAP_CHANNELS, }; + enum AlphaMapMode { + ALPHA_MAP_OPAQUE = 0, + ALPHA_MAP_MASK, + ALPHA_MAP_BLEND, + }; + // The signature is the Flags Flags _flags; @@ -104,6 +109,23 @@ public: Builder& withTranslucentMap() { _flags.set(OPACITY_TRANSLUCENT_MAP_BIT); return (*this); } Builder& withMaskMap() { _flags.set(OPACITY_MASK_MAP_BIT); return (*this); } + Builder& withAlphaMapMode(AlphaMapMode mode) { + switch (mode) { + case ALPHA_MAP_OPAQUE: + _flags.reset(OPACITY_TRANSLUCENT_MAP_BIT); + _flags.reset(OPACITY_MASK_MAP_BIT); + break; + case ALPHA_MAP_MASK: + _flags.reset(OPACITY_TRANSLUCENT_MAP_BIT); + _flags.set(OPACITY_MASK_MAP_BIT); + break; + case ALPHA_MAP_BLEND: + _flags.set(OPACITY_TRANSLUCENT_MAP_BIT); + _flags.reset(OPACITY_MASK_MAP_BIT); + break; + }; + return (*this); + } Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); } Builder& withOcclusionMap() { _flags.set(OCCLUSION_MAP_BIT); return (*this); } @@ -171,6 +193,25 @@ public: // Translucency and Opacity Heuristics are combining several flags: + void setAlphaMapMode(AlphaMapMode mode) { + switch (mode) { + case ALPHA_MAP_OPAQUE: + _flags.reset(OPACITY_TRANSLUCENT_MAP_BIT); + _flags.reset(OPACITY_MASK_MAP_BIT); + break; + case ALPHA_MAP_MASK: + _flags.reset(OPACITY_TRANSLUCENT_MAP_BIT); + _flags.set(OPACITY_MASK_MAP_BIT); + break; + case ALPHA_MAP_BLEND: + _flags.set(OPACITY_TRANSLUCENT_MAP_BIT); + _flags.reset(OPACITY_MASK_MAP_BIT); + break; + }; + } + AlphaMapMode getAlphaMapMode() const { return (_flags[OPACITY_MASK_MAP_BIT] ? ALPHA_MAP_MASK : (_flags[OPACITY_TRANSLUCENT_MAP_BIT] ? ALPHA_MAP_BLEND : ALPHA_MAP_OPAQUE)); } + + bool isTranslucent() const { return isTranslucentFactor() || isTranslucentMap(); } bool isOpaque() const { return !isTranslucent(); } bool isSurfaceOpaque() const { return isOpaque() && !isOpacityMaskMap(); } @@ -283,6 +324,13 @@ public: void setOpacity(float opacity); float getOpacity() const { return _opacity; } + void setAlphaMapMode(MaterialKey::AlphaMapMode alphaMode); + MaterialKey::AlphaMapMode getAlphaMapMode() const; + + static const float DEFAULT_ALPHA_CUTOFF; + void setAlphaCutoff(float alphaCutoff); + float getAlphaCutoff() const { return _alphaCutoff; } + void setUnlit(bool value); bool isUnlit() const { return _key.isUnlit(); } @@ -357,6 +405,7 @@ private: float _roughness { DEFAULT_ROUGHNESS }; float _metallic { DEFAULT_METALLIC }; float _scattering { DEFAULT_SCATTERING }; + float _alphaCutoff { DEFAULT_ALPHA_CUTOFF }; std::array _texcoordTransforms; glm::vec2 _lightmapParams { 0.0, 1.0 }; glm::vec2 _materialParams { 0.0, 1.0 }; @@ -365,7 +414,7 @@ private: bool _defaultFallthrough { false }; std::unordered_map _propertyFallthroughs { NUM_TOTAL_FLAGS }; - mutable QMutex _textureMapsMutex { QMutex::Recursive }; + mutable std::recursive_mutex _textureMapsMutex; }; typedef std::shared_ptr MaterialPointer; @@ -425,18 +474,8 @@ public: float _metallic { Material::DEFAULT_METALLIC }; // Not Metallic float _scattering { Material::DEFAULT_SCATTERING }; // Scattering info -#if defined(__clang__) - __attribute__((unused)) -#endif - glm::vec2 _spare { 0.0f }; // Padding - + float _alphaCutoff { Material::DEFAULT_ALPHA_CUTOFF }; // Alpha cutoff applyed when using alphaMa as Mask uint32_t _key { 0 }; // a copy of the materialKey -#if defined(__clang__) - __attribute__((unused)) -#endif - glm::vec3 _spare2 { 0.0f }; - - // for alignment beauty, Material size == Mat4x4 // Texture Coord Transform Array glm::mat4 _texcoordTransforms[Material::NUM_TEXCOORD_TRANSFORMS]; diff --git a/libraries/graphics/src/graphics/Material.slh b/libraries/graphics/src/graphics/Material.slh index dfd4a8eec4..8ebf66417c 100644 --- a/libraries/graphics/src/graphics/Material.slh +++ b/libraries/graphics/src/graphics/Material.slh @@ -49,8 +49,7 @@ struct TexMapArray { struct Material { vec4 _emissiveOpacity; vec4 _albedoRoughness; - vec4 _metallicScatteringSpare2; - vec4 _keySpare3; + vec4 _metallicScatteringAlphaCutoffKey; }; LAYOUT_STD140(binding=GRAPHICS_BUFFER_MATERIAL) uniform materialBuffer { @@ -72,10 +71,11 @@ vec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; } float getMaterialRoughness(Material m) { return m._albedoRoughness.a; } float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); } -float getMaterialMetallic(Material m) { return m._metallicScatteringSpare2.x; } -float getMaterialScattering(Material m) { return m._metallicScatteringSpare2.y; } +float getMaterialMetallic(Material m) { return m._metallicScatteringAlphaCutoffKey.x; } +float getMaterialScattering(Material m) { return m._metallicScatteringAlphaCutoffKey.y; } +float getMaterialAlphaCutoff(Material m) { return m._metallicScatteringAlphaCutoffKey.z; } -BITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._keySpare3.x); } +BITFIELD getMaterialKey(Material m) { return floatBitsToInt(m._metallicScatteringAlphaCutoffKey.w); } const BITFIELD EMISSIVE_VAL_BIT = 0x00000001; const BITFIELD UNLIT_VAL_BIT = 0x00000002; diff --git a/libraries/graphics/src/graphics/MaterialTextures.slh b/libraries/graphics/src/graphics/MaterialTextures.slh index 278057b01a..93b90cc591 100644 --- a/libraries/graphics/src/graphics/MaterialTextures.slh +++ b/libraries/graphics/src/graphics/MaterialTextures.slh @@ -214,6 +214,13 @@ vec3 fetchLightMap(vec2 uv) { } <@endfunc@> +<@func evalMaterialOpacityMask(fetchedOpacity, materialAlphaCutoff, opacity)@> +{ + <$opacity$> = step(<$materialAlphaCutoff$>, <$fetchedOpacity$>); +} +<@endfunc@> + + <@func evalMaterialOpacity(fetchedOpacity, materialOpacity, matKey, opacity)@> { const float OPACITY_MASK_THRESHOLD = 0.5; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index d0ebe167f9..14ceb4f9be 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -486,6 +486,7 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial schemaKey.setAlbedoMap(true); schemaKey.setOpacityMaskMap(material->getKey().isOpacityMaskMap()); schemaKey.setTranslucentMap(material->getKey().isTranslucentMap()); + schema._alphaCutoff = material->getAlphaCutoff(); } break; case graphics::MaterialKey::METALLIC_MAP_BIT: diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index 3e4711dac8..2d9cb6c654 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -104,13 +104,12 @@ void main(void) { <@if HIFI_USE_TRANSLUCENT@> float opacity = getMaterialOpacity(mat) * _color.a; - <@else@> - float opacity = 1.0; - <@endif@> <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <@if HIFI_USE_TRANSLUCENT@> <$discardInvisible(opacity)$>; <@else@> + float cutoff = getMaterialAlphaCutoff(mat); + float opacity = 1.0; + <$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity)$>; <$discardTransparent(opacity)$>; <@endif@> @@ -156,14 +155,13 @@ void main(void) { <@if HIFI_USE_TRANSLUCENT@> float opacity = getMaterialOpacity(mat) * _color.a; - <@else@> - float opacity = 1.0; - <@endif@> <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; - <@if HIFI_USE_TRANSLUCENT@> - <$discardInvisible(opacity)$>; + <$discardInvisible(opacity)$>; <@else@> - <$discardTransparent(opacity)$>; + float cutoff = getMaterialAlphaCutoff(mat); + float opacity = 1.0; + <$evalMaterialOpacityMask(albedoTex.a, cutoff, opacity)$>; + <$discardTransparent(opacity)$>; <@endif@> vec3 albedo = getMaterialAlbedo(mat);