diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index 21fdab59a3..5f5c93eb61 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.setTransparentFactor((opacity < 1.0f)); + _key.setTranslucentFactor((opacity < 1.0f)); _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); _schemaBuffer.edit()._opacity = opacity; } @@ -94,10 +94,10 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur // Texture has alpha, is nut just a mask or a true transparent channel if (!usage.isAlphaMask()) { _key.setOpacityMaskMap(true); - _key.setTransparentMap(false); + _key.setTranslucentMap(false); } else { _key.setOpacityMaskMap(false); - _key.setTransparentMap(true); + _key.setTranslucentMap(true); } } } @@ -112,7 +112,7 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur if (channel == MaterialKey::ALBEDO_MAP) { _key.setOpacityMaskMap(false); - _key.setTransparentMap(false); + _key.setTranslucentMap(false); } _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index f590b73b85..2527c8e1e1 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -76,14 +76,14 @@ 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& withOpacity() { _flags.set(OPACITY_VAL_BIT); return (*this); } + Builder& withTranslucentFactor() { _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(OPACITY_TRANSLUCENT_MAP_BIT); return (*this); } + Builder& withTranslucentMap() { _flags.set(OPACITY_TRANSLUCENT_MAP_BIT); return (*this); } Builder& withMaskMap() { _flags.set(OPACITY_MASK_MAP_BIT); return (*this); } Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); } @@ -122,8 +122,8 @@ public: void setTranslucentFactor(bool value) { _flags.set(OPACITY_VAL_BIT, value); } bool isTranslucentFactor() const { return _flags[OPACITY_VAL_BIT]; } - void setTransparentMap(bool value) { _flags.set(OPACITY_TRANSLUCENT_MAP_BIT, value); } - bool isOpacityMap() const { return _flags[OPACITY_TRANSLUCENT_MAP_BIT]; } + void setTranslucentMap(bool value) { _flags.set(OPACITY_TRANSLUCENT_MAP_BIT, value); } + bool isTranslucentMap() const { return _flags[OPACITY_TRANSLUCENT_MAP_BIT]; } void setOpacityMaskMap(bool value) { _flags.set(OPACITY_MASK_MAP_BIT, value); } bool isOpacityMaskMap() const { return _flags[OPACITY_MASK_MAP_BIT]; } @@ -140,6 +140,12 @@ public: void setMapChannel(MapChannel channel, bool value) { _flags.set(EMISSIVE_MAP_BIT + channel, value); } bool isMapChannel(MapChannel channel) const { return _flags[EMISSIVE_MAP_BIT + channel]; } + + // Translucency and Opacity Heuristics are combining several flags: + bool isTranslucent() const { return isTranslucentFactor() || isTranslucentMap(); } + bool isOpaque() const { return !isTranslucent(); } + bool isSurfaceOpaque() const { return isOpaque() && !isOpacityMaskMap(); } + bool isTexelOpaque() const { return isOpaque() && isOpacityMaskMap(); } }; @@ -183,12 +189,11 @@ 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& 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& withoutTranslucentFactor() { _value.reset(MaterialKey::OPACITY_VAL_BIT); _mask.set(MaterialKey::OPACITY_VAL_BIT); return (*this); } + Builder& withTranslucentFactor() { _value.set(MaterialKey::OPACITY_VAL_BIT); _mask.set(MaterialKey::OPACITY_VAL_BIT); return (*this); } - Builder& withoutTransparentMap() { _value.reset(MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT); _mask.set(MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT); return (*this); } - Builder& withTransparentMap() { _value.set(MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT); _mask.set(MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT); return (*this); } + Builder& withoutTranslucentMap() { _value.reset(MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT); _mask.set(MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT); return (*this); } + Builder& withTranslucentMap() { _value.set(MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT); _mask.set(MaterialKey::OPACITY_TRANSLUCENT_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); } @@ -203,7 +208,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().withOpaqueFactor().build(); } + static MaterialFilter opaqueAlbedo() { return Builder().withAlbedo().withoutTranslucentFactor().build(); } }; // Item Filter operator testing if a key pass the filter diff --git a/libraries/model/src/model/Material.slh b/libraries/model/src/model/Material.slh index da185ddf0b..e8c9d3d6bc 100644 --- a/libraries/model/src/model/Material.slh +++ b/libraries/model/src/model/Material.slh @@ -43,17 +43,17 @@ const int EMISSIVE_VAL_BIT = 0x00000001; const int ALBEDO_VAL_BIT = 0x00000002; const int METALLIC_VAL_BIT = 0x00000004; const int GLOSSY_VAL_BIT = 0x00000008; -const int TRANSPARENT_VAL_BIT = 0x00000010; -const int TRANSPARENT_TEX_VAL_BIT = 0x00000020; +const int OPACITY_VAL_BIT = 0x00000010; -const int EMISSIVE_MAP_BIT = 0x00000040; -const int ALBEDO_MAP_BIT = 0x00000080; -const int METALLIC_MAP_BIT = 0x00000100; -const int ROUGHNESS_MAP_BIT = 0x00000200; -const int TRANSPARENT_MAP_BIT = 0x00000400; -const int NORMAL_MAP_BIT = 0x00000800; -const int OCCLUSION_MAP_BIT = 0x00001000; +const int EMISSIVE_MAP_BIT = 0x00000020; +const int ALBEDO_MAP_BIT = 0x00000040; +const int OPACITY_MASK_MAP_BIT = 0x00000080; +const int OPACITY_TRANSLUCENT_MAP_BIT = 0x00000100; +const int METALLIC_MAP_BIT = 0x00000200; +const int ROUGHNESS_MAP_BIT = 0x00000400; +const int NORMAL_MAP_BIT = 0x00001000; +const int OCCLUSION_MAP_BIT = 0x00002000; +const int LIGHTMAP_MAP_BIT = 0x00004000; -const int LIGHTMAP_MAP_BIT = 0x00002000; <@endif@> diff --git a/libraries/render-utils/src/MaterialTextures.slh b/libraries/render-utils/src/MaterialTextures.slh index 8904ae34b2..ef8c30a97f 100644 --- a/libraries/render-utils/src/MaterialTextures.slh +++ b/libraries/render-utils/src/MaterialTextures.slh @@ -59,7 +59,7 @@ float fetchOcclusionMap(vec2 uv) { <@func fetchMaterialTextures(matKey, texcoord0, albedo, roughness, normal, metallic, emissive, occlusion)@> <@if albedo@> - vec4 <$albedo$> = (((<$matKey$> & ALBEDO_MAP_BIT) != 0) ? fetchAlbedoMap(<$texcoord0$>) : vec4(1.0)); + vec4 <$albedo$> = (((<$matKey$> & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(<$texcoord0$>) : vec4(1.0)); <@endif@> <@if roughness@> float <$roughness$> = (((<$matKey$> & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(<$texcoord0$>) : 1.0); @@ -112,6 +112,23 @@ vec3 fetchLightmapMap(vec2 uv) { } <@endfunc@> +<@func evalMaterialOpacity(fetchedOpacity, materialOpacity, matKey, opacity)@> +{ + const float OPACITY_MASK_THRESHOLD = 0.5; + <$opacity$> = (((<$matKey$> & (OPACITY_TRANSLUCENCY_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ? + (((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, <$fetchedOpacity$>) : <$fetchedOpacity$>) : + 1.0) * <$materialOpacity$>; +} +<@endfunc@> + +<@func $discardTransparent(opacity)@> +{ + if (<$opacity$> < 1.0) { + discard; + } +} +<@endfunc@> + <@func evalMaterialRoughness(fetchedRoughness, materialRoughness, matKey, roughness)@> { <$roughness$> = (((<$matKey$> & ROUGHNESS_MAP_BIT) != 0) ? <$fetchedRoughness$> : <$materialRoughness$>); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 2e66fe43f2..aca9774221 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.isTransparentFactor() || matKey.isTransparentMap()) { + if (matKey.isTranslucentFactor() || matKey.isTranslucentMap()) { builder.withTransparent(); } } @@ -100,7 +100,7 @@ ShapeKey MeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; - if (drawMaterialKey.isTransparentFactor() || drawMaterialKey.isTransparentMap()) { + if (drawMaterialKey.isTranslucent()) { builder.withTranslucent(); } if (drawMaterialKey.isNormalMap()) { @@ -365,7 +365,7 @@ ItemKey ModelMeshPartPayload::getKey() const { if (_drawMaterial) { auto matKey = _drawMaterial->getKey(); - if (matKey.isTransparentFactor() || matKey.isTransparentMap()) { + if (matKey.isTranslucent()) { builder.withTransparent(); } } @@ -412,8 +412,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { drawMaterialKey = _drawMaterial->getKey(); } - bool isTranslucent = - drawMaterialKey.isTransparentFactor() || drawMaterialKey.isTransparentMap(); + bool isTranslucent = drawMaterialKey.isTranslucent(); bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); bool hasSpecular = drawMaterialKey.isMetallicMap(); bool hasLightmap = drawMaterialKey.isLightmapMap(); diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index c9ca6d9eb7..ddfd83d1d4 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -29,6 +29,10 @@ void main(void) { int matKey = getMaterialKey(mat); <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex, occlusionTex)$> + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$discardTransparent(opacity)$>; + vec3 albedo = getMaterialAlbedo(mat); <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; albedo *= _color; @@ -41,7 +45,7 @@ void main(void) { packDeferredFragment( normalize(_normal.xyz), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), + opacity, albedo, roughness, getMaterialMetallic(mat), diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index a584427005..10ae6ee880 100755 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -30,6 +30,10 @@ void main(void) { int matKey = getMaterialKey(mat); <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, occlusionTex)$> + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$discardTransparent(opacity)$>; + vec3 albedo = getMaterialAlbedo(mat); <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; albedo *= _color; @@ -45,7 +49,7 @@ void main(void) { packDeferredFragment( viewNormal, - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), + opacity, albedo, roughness, getMaterialMetallic(mat), diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf index cf461db7ef..2529596818 100755 --- a/libraries/render-utils/src/model_normal_specular_map.slf +++ b/libraries/render-utils/src/model_normal_specular_map.slf @@ -30,6 +30,10 @@ void main(void) { int matKey = getMaterialKey(mat); <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, occlusionTex)$> + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$discardTransparent(opacity)$>; + vec3 albedo = getMaterialAlbedo(mat); <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; albedo *= _color; @@ -49,7 +53,7 @@ void main(void) { packDeferredFragment( normalize(viewNormal.xyz), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), + opacity, albedo, roughness, metallic, diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf index 32e5823430..9b2f4ae640 100755 --- a/libraries/render-utils/src/model_specular_map.slf +++ b/libraries/render-utils/src/model_specular_map.slf @@ -30,6 +30,10 @@ void main(void) { int matKey = getMaterialKey(mat); <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, occlusionTex)$> + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$discardTransparent(opacity)$>; + vec3 albedo = getMaterialAlbedo(mat); <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; albedo *= _color; @@ -45,7 +49,7 @@ void main(void) { packDeferredFragment( normalize(_normal), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), + opacity, albedo, roughness, metallic, diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index b99b5c8a2a..12a7b9299f 100755 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -36,6 +36,10 @@ void main(void) { int matKey = getMaterialKey(mat); <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex, occlusionTex)$> + float opacity = getMaterialOpacity(mat) * _alpha; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$discardTransparent(opacity)$>; + vec3 albedo = getMaterialAlbedo(mat); <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; albedo *= _color; @@ -52,8 +56,6 @@ void main(void) { vec3 fragPosition = _position.xyz; vec3 fragNormal = normalize(_normal); - float fragOpacity = getMaterialOpacity(mat) * albedoTex.a * _alpha; - TransformCamera cam = getTransformCamera(); _fragColor = vec4(evalAmbientSphereGlobalColor( @@ -66,5 +68,5 @@ void main(void) { metallic, emissive, roughness), - fragOpacity); + opacity); }