From f9edbcdd2453fc223af29e66b8af97d20f138668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 11 Aug 2020 17:22:00 +0200 Subject: [PATCH] Trade: rework metallic/roughness packing. Turns out glTF doesn't actually put metalness into R and roughness into G, even though the naming suggests that. This was done originally, but then they changed that in order to be compatible with UE4 and allow for a more efficient storage of an occlusion map. Because this feels extremely arbitrary, the docs have added rationale for each of the packing variants, and I'm also renaming the packed attribute and checks to imply the red channel isn't used. --- doc/snippets/MagnumTrade.cpp | 22 ++-- .../materialAttributeProperties.hpp | 2 +- src/Magnum/Trade/MaterialData.h | 61 +++++----- .../PbrMetallicRoughnessMaterialData.cpp | 26 ++--- .../Trade/PbrMetallicRoughnessMaterialData.h | 91 +++++++++------ src/Magnum/Trade/Test/MaterialDataTest.cpp | 104 ++++++++++-------- 6 files changed, 175 insertions(+), 131 deletions(-) diff --git a/doc/snippets/MagnumTrade.cpp b/doc/snippets/MagnumTrade.cpp index 5306b5bb5..61eb9b3c5 100644 --- a/doc/snippets/MagnumTrade.cpp +++ b/doc/snippets/MagnumTrade.cpp @@ -310,24 +310,26 @@ if(data.types() & Trade::MaterialType::PbrSpecularGlossiness) { { /* [MaterialData-usage-packing] */ -Trade::PbrMetallicRoughnessMaterialData data = DOXYGEN_IGNORE(Trade::PbrMetallicRoughnessMaterialData{{}, {}}); +Trade::PbrSpecularGlossinessMaterialData data = DOXYGEN_IGNORE(Trade::PbrSpecularGlossinessMaterialData{{}, {}}); /* Use a shader that accepts a single packed metallic/roughness texture. Querying any texture attributes will give the same values for both metalness and roughness. */ -if(data.hasMetallicRoughnessTexture()) { - UnsignedInt metallicRoughness = data.metalnessTexture(); +if(data.hasSpecularGlossinessTexture()) { + UnsignedInt specularGlossiness = data.specularTexture(); - DOXYGEN_IGNORE(static_cast(metallicRoughness);) + DOXYGEN_IGNORE(static_cast(specularGlossiness);) /* Supply texture channels separately */ } else { - UnsignedInt metalness = data.metalnessTexture(); - UnsignedInt roughness = data.roughnessTexture(); - Trade::MaterialTextureSwizzle metalnessSwizzle = data.metalnessTextureSwizzle(); - Trade::MaterialTextureSwizzle roughnessSwizzle = data.roughnessTextureSwizzle(); + UnsignedInt specular = data.specularTexture(); + UnsignedInt glossiness = data.glossinessTexture(); + Trade::MaterialTextureSwizzle specularSwizzle = + data.specularTextureSwizzle(); + Trade::MaterialTextureSwizzle glossinessSwizzle = + data.glossinessTextureSwizzle(); - DOXYGEN_IGNORE(static_cast(metalness), static_cast(roughness), static_cast(metalnessSwizzle), static_cast(roughnessSwizzle);) + DOXYGEN_IGNORE(static_cast(specular), static_cast(glossiness), static_cast(specularSwizzle), static_cast(glossinessSwizzle);) } /* [MaterialData-usage-packing] */ } @@ -413,7 +415,7 @@ Trade::MaterialData data{ Trade::MaterialType::PbrMetallicRoughness|Trade::MaterialType::PbrClearCoat, { {Trade::MaterialAttribute::BaseColor, 0xffcc33_srgbf}, - {Trade::MaterialAttribute::MetallicRoughnessTexture, 0u}, + {Trade::MaterialAttribute::NoneRoughnessMetallicTexture, 0u}, {Trade::MaterialLayer::ClearCoat}, {Trade::MaterialAttribute::LayerFactorTexture, 1u}, diff --git a/src/Magnum/Trade/Implementation/materialAttributeProperties.hpp b/src/Magnum/Trade/Implementation/materialAttributeProperties.hpp index 9e42b5725..306440a91 100644 --- a/src/Magnum/Trade/Implementation/materialAttributeProperties.hpp +++ b/src/Magnum/Trade/Implementation/materialAttributeProperties.hpp @@ -57,7 +57,7 @@ _c(RoughnessTexture,UnsignedInt) _ct(RoughnessTextureSwizzle,TextureSwizzle,MaterialTextureSwizzle) _c(RoughnessTextureMatrix,Matrix3x3) _c(RoughnessTextureCoordinates,UnsignedInt) -_c(MetallicRoughnessTexture,UnsignedInt) +_c(NoneRoughnessMetallicTexture,UnsignedInt) _c(Glossiness,Float) _c(GlossinessTexture,UnsignedInt) _ct(GlossinessTextureSwizzle,TextureSwizzle,MaterialTextureSwizzle) diff --git a/src/Magnum/Trade/MaterialData.h b/src/Magnum/Trade/MaterialData.h index 1928e31f1..ecfa2701e 100644 --- a/src/Magnum/Trade/MaterialData.h +++ b/src/Magnum/Trade/MaterialData.h @@ -356,7 +356,7 @@ enum class MaterialAttribute: UnsignedInt { * @ref MaterialAttributeType::Float. * * If @ref MaterialAttribute::MetalnessTexture or - * @ref MaterialAttribute::MetallicRoughnessTexture is present as well, + * @ref MaterialAttribute::NoneRoughnessMetallicTexture is present as well, * these two are multiplied together. * @see @ref PbrMetallicRoughnessMaterialData::metalness() */ @@ -368,9 +368,9 @@ enum class MaterialAttribute: UnsignedInt { * * If @ref MaterialAttribute::Metalness is present as well, these two are * multiplied together. Can be alternatively supplied as a packed - * @ref MaterialAttribute::MetallicRoughnessTexture. + * @ref MaterialAttribute::NoneRoughnessMetallicTexture. * @see @ref PbrMetallicRoughnessMaterialData::hasMetalnessTexture(), - * @ref PbrMetallicRoughnessMaterialData::hasMetallicRoughnessTexture(), + * @ref PbrMetallicRoughnessMaterialData::hasNoneRoughnessMetallicTexture(), * @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), * @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture() * @ref PbrMetallicRoughnessMaterialData::metalnessTexture() @@ -385,9 +385,10 @@ enum class MaterialAttribute: UnsignedInt { * @ref MaterialAttribute::MetalnessTexture together with other maps in a * single texture. A single-channel swizzle value is expected. If not * present, @ref MaterialTextureSwizzle::R is assumed. Does not apply to - * @ref MaterialAttribute::MetallicRoughnessTexture --- in that case, the - * metalness is implicitly in the red channel regardless of this attribute. - * @see @ref PbrMetallicRoughnessMaterialData::hasMetallicRoughnessTexture(), + * @ref MaterialAttribute::NoneRoughnessMetallicTexture --- in that case, + * the metalness is implicitly in the red channel regardless of this + * attribute. + * @see @ref PbrMetallicRoughnessMaterialData::hasNoneRoughnessMetallicTexture(), * @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), * @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture() * @ref PbrMetallicRoughnessMaterialData::metalnessTextureSwizzle() @@ -419,7 +420,7 @@ enum class MaterialAttribute: UnsignedInt { * @ref MaterialAttributeType::Float. * * If @ref MaterialAttribute::RoughnessTexture or - * @ref MaterialAttribute::MetallicRoughnessTexture is present as well, + * @ref MaterialAttribute::NoneRoughnessMetallicTexture is present as well, * these two are multiplied together. * @see @ref PbrMetallicRoughnessMaterialData::roughness() */ @@ -431,9 +432,9 @@ enum class MaterialAttribute: UnsignedInt { * * If @ref MaterialAttribute::Roughness is present as well, these two are * multiplied together. Can be alternatively supplied as a packed - * @ref MaterialAttribute::MetallicRoughnessTexture. + * @ref MaterialAttribute::NoneRoughnessMetallicTexture. * @see @ref PbrMetallicRoughnessMaterialData::hasRoughnessTexture(), - * @ref PbrMetallicRoughnessMaterialData::hasMetallicRoughnessTexture(), + * @ref PbrMetallicRoughnessMaterialData::hasNoneRoughnessMetallicTexture(), * @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), * @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture() * @ref PbrMetallicRoughnessMaterialData::roughnessTexture() @@ -448,10 +449,10 @@ enum class MaterialAttribute: UnsignedInt { * @ref MaterialAttribute::RoughnessTexture together with other maps in a * single texture. A single-channel swizzle value is expected. If not * present, @ref MaterialTextureSwizzle::R is assumed. Does not apply to - * @ref MaterialAttribute::MetallicRoughnessTexture --- in that case, the - * metalness is implicitly in the green channel regardless of this + * @ref MaterialAttribute::NoneRoughnessMetallicTexture --- in that case, + * the metalness is implicitly in the green channel regardless of this * attribute. - * @see @ref PbrMetallicRoughnessMaterialData::hasMetallicRoughnessTexture(), + * @see @ref PbrMetallicRoughnessMaterialData::hasNoneRoughnessMetallicTexture(), * @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), * @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture() * @ref PbrMetallicRoughnessMaterialData::roughnessTextureSwizzle() @@ -479,32 +480,36 @@ enum class MaterialAttribute: UnsignedInt { RoughnessTextureCoordinates, /** - * Combined metallic/roughness texture index for PBR metallic/roughness - * materials with metalness in the red channel and roughness in the green + * Combined roughness/metallic texture index for PBR metallic/roughness + * materials with metalness in the blue channel and roughness in the green * channel, @ref MaterialAttributeType::UnsignedInt. * * If @ref MaterialAttribute::Metalness / @ref MaterialAttribute::Roughness - * is present as well, these two are multiplied together. Can be - * alternatively specified as a pair of @ref MaterialAttribute::MetalnessTexture - * / @ref MaterialAttribute::RoughnessTexture attributes together with - * @ref MaterialAttribute::MetalnessTextureSwizzle set to - * @ref MaterialTextureSwizzle::R (or omitted, since that's the default) - * and @ref MaterialAttribute::RoughnessTextureSwizzle set to - * @ref MaterialTextureSwizzle::G. Texture transformation and coordinate + * is present as well, these two are multiplied together. + * + * This is a convenience alias to simplify representation of glTF and UE4 + * materials, which is where this packing is used ([rationale](https://github.com/KhronosGroup/glTF/issues/857)). + * This packing (and other variants) can be alternatively specified as a + * pair of @ref MaterialAttribute::RoughnessTexture / + * @ref MaterialAttribute::MetalnessTexture attributes together with + * @ref MaterialAttribute::RoughnessTextureSwizzle set to + * @ref MaterialTextureSwizzle::G + * and @ref MaterialAttribute::MetalnessTextureSwizzle set to + * @ref MaterialTextureSwizzle::B. Texture transformation and coordinate * set, if needed, have to be specified either using the global * @ref MaterialAttribute::TextureMatrix and * @ref MaterialAttribute::TextureCoordinates attributes or the per-texture - * @ref MaterialAttribute::MetalnessTextureMatrix, * @ref MaterialAttribute::RoughnessTextureMatrix, - * @ref MaterialAttribute::MetalnessTextureCoordinates and - * @ref MaterialAttribute::RoughnessTextureCoordinates variants. - * @see @ref PbrMetallicRoughnessMaterialData::hasMetallicRoughnessTexture(), + * @ref MaterialAttribute::MetalnessTextureMatrix, + * @ref MaterialAttribute::RoughnessTextureCoordinates and + * @ref MaterialAttribute::MetalnessTextureCoordinates variants. + * @see @ref PbrMetallicRoughnessMaterialData::hasNoneRoughnessMetallicTexture(), * @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), * @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture() * @ref PbrMetallicRoughnessMaterialData::metalnessTexture(), * @ref PbrMetallicRoughnessMaterialData::roughnessTexture() */ - MetallicRoughnessTexture, + NoneRoughnessMetallicTexture, /* DiffuseColor, DiffuseTexture, DiffuseTextureMatrix, DiffuseTextureCoordinates, SpecularColor, SpecularTexture, @@ -1441,8 +1446,8 @@ various @ref MaterialTextureSwizzle attributes such as @ref MaterialAttribute::MetalnessTextureSwizzle. While this provides an almost endless variability, real-world textures are in just a few common packing schemes. For convenience these have dedicated attributes such as -@ref MaterialAttribute::MetallicRoughnessTexture and can also be checked for -with for example @ref PbrMetallicRoughnessMaterialData::hasMetallicRoughnessTexture(): +@ref MaterialAttribute::SpecularGlossinessTexture and can also be checked +for with for example @ref PbrSpecularGlossinessMaterialData::hasSpecularGlossinessTexture(): @snippet MagnumTrade.cpp MaterialData-usage-packing diff --git a/src/Magnum/Trade/PbrMetallicRoughnessMaterialData.cpp b/src/Magnum/Trade/PbrMetallicRoughnessMaterialData.cpp index 3655b118c..d22ba4c23 100644 --- a/src/Magnum/Trade/PbrMetallicRoughnessMaterialData.cpp +++ b/src/Magnum/Trade/PbrMetallicRoughnessMaterialData.cpp @@ -34,22 +34,22 @@ using namespace Math::Literals; bool PbrMetallicRoughnessMaterialData::hasMetalnessTexture() const { return hasAttribute(MaterialAttribute::MetalnessTexture) || - hasAttribute(MaterialAttribute::MetallicRoughnessTexture); + hasAttribute(MaterialAttribute::NoneRoughnessMetallicTexture); } bool PbrMetallicRoughnessMaterialData::hasRoughnessTexture() const { return hasAttribute(MaterialAttribute::RoughnessTexture) || - hasAttribute(MaterialAttribute::MetallicRoughnessTexture); + hasAttribute(MaterialAttribute::NoneRoughnessMetallicTexture); } -bool PbrMetallicRoughnessMaterialData::hasMetallicRoughnessTexture() const { - return (hasAttribute(MaterialAttribute::MetallicRoughnessTexture) || +bool PbrMetallicRoughnessMaterialData::hasNoneRoughnessMetallicTexture() const { + return (hasAttribute(MaterialAttribute::NoneRoughnessMetallicTexture) || (hasAttribute(MaterialAttribute::MetalnessTexture) && hasAttribute(MaterialAttribute::RoughnessTexture) && - metalnessTextureSwizzle() == MaterialTextureSwizzle::R && - roughnessTextureSwizzle() == MaterialTextureSwizzle::G)) && - metalnessTextureMatrix() == roughnessTextureMatrix() && - metalnessTextureCoordinates() == roughnessTextureCoordinates(); + roughnessTextureSwizzle() == MaterialTextureSwizzle::G && + metalnessTextureSwizzle() == MaterialTextureSwizzle::B)) && + roughnessTextureMatrix() == metalnessTextureMatrix() && + roughnessTextureCoordinates() == metalnessTextureCoordinates(); } bool PbrMetallicRoughnessMaterialData::hasRoughnessMetallicOcclusionTexture() const { @@ -156,7 +156,7 @@ UnsignedInt PbrMetallicRoughnessMaterialData::metalnessTexture() const { would be misleading as it can be also MetallicRoughnessTexture */ CORRADE_ASSERT(hasMetalnessTexture(), "Trade::PbrMetallicRoughnessMaterialData::metalnessTexture(): the material doesn't have a metalness texture", {}); - if(Containers::Optional value = tryAttribute(MaterialAttribute::MetallicRoughnessTexture)) + if(Containers::Optional value = tryAttribute(MaterialAttribute::NoneRoughnessMetallicTexture)) return *value; return attribute(MaterialAttribute::MetalnessTexture); } @@ -164,8 +164,8 @@ UnsignedInt PbrMetallicRoughnessMaterialData::metalnessTexture() const { MaterialTextureSwizzle PbrMetallicRoughnessMaterialData::metalnessTextureSwizzle() const { CORRADE_ASSERT(hasMetalnessTexture(), "Trade::PbrMetallicRoughnessMaterialData::metalnessTextureSwizzle(): the material doesn't have a metalness texture", {}); - if(hasAttribute(MaterialAttribute::MetallicRoughnessTexture)) - return MaterialTextureSwizzle::R; + if(hasAttribute(MaterialAttribute::NoneRoughnessMetallicTexture)) + return MaterialTextureSwizzle::B; return attributeOr(MaterialAttribute::MetalnessTextureSwizzle, MaterialTextureSwizzle::R); } @@ -194,7 +194,7 @@ UnsignedInt PbrMetallicRoughnessMaterialData::roughnessTexture() const { would be misleading as it can be also MetallicRoughnessTexture */ CORRADE_ASSERT(hasRoughnessTexture(), "Trade::PbrMetallicRoughnessMaterialData::roughnessTexture(): the material doesn't have a roughness texture", {}); - if(Containers::Optional value = tryAttribute(MaterialAttribute::MetallicRoughnessTexture)) + if(Containers::Optional value = tryAttribute(MaterialAttribute::NoneRoughnessMetallicTexture)) return *value; return attribute(MaterialAttribute::RoughnessTexture); } @@ -202,7 +202,7 @@ UnsignedInt PbrMetallicRoughnessMaterialData::roughnessTexture() const { MaterialTextureSwizzle PbrMetallicRoughnessMaterialData::roughnessTextureSwizzle() const { CORRADE_ASSERT(hasRoughnessTexture(), "Trade::PbrMetallicRoughnessMaterialData::roughnessTextureSwizzle(): the material doesn't have a roughness texture", {}); - if(hasAttribute(MaterialAttribute::MetallicRoughnessTexture)) + if(hasAttribute(MaterialAttribute::NoneRoughnessMetallicTexture)) return MaterialTextureSwizzle::G; return attributeOr(MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::R); } diff --git a/src/Magnum/Trade/PbrMetallicRoughnessMaterialData.h b/src/Magnum/Trade/PbrMetallicRoughnessMaterialData.h index def41bfaf..6723660e9 100644 --- a/src/Magnum/Trade/PbrMetallicRoughnessMaterialData.h +++ b/src/Magnum/Trade/PbrMetallicRoughnessMaterialData.h @@ -60,9 +60,9 @@ class MAGNUM_TRADE_EXPORT PbrMetallicRoughnessMaterialData: public MaterialData * * Returns @cpp true @ce if any of the * @ref MaterialAttribute::MetalnessTexture or - * @ref MaterialAttribute::MetallicRoughnessTexture attributes is + * @ref MaterialAttribute::NoneRoughnessMetallicTexture attributes is * present, @cpp false @ce otherwise. - * @see @ref hasRoughnessTexture(), @ref hasMetallicRoughnessTexture() + * @see @ref hasRoughnessTexture(), @ref hasNoneRoughnessMetallicTexture() */ bool hasMetalnessTexture() const; @@ -71,41 +71,48 @@ class MAGNUM_TRADE_EXPORT PbrMetallicRoughnessMaterialData: public MaterialData * * Returns @cpp true @ce if any of the * @ref MaterialAttribute::RoughnessTexture or - * @ref MaterialAttribute::MetallicRoughnessTexture attributes is + * @ref MaterialAttribute::NoneRoughnessMetallicTexture attributes is * present, @cpp false @ce otherwise. - * @see @ref hasMetalnessTexture(), @ref hasMetallicRoughnessTexture() + * @see @ref hasMetalnessTexture(), @ref hasNoneRoughnessMetallicTexture() */ bool hasRoughnessTexture() const; /** - * @brief Whether the material has a combined metallic/roughness texture + * @brief Whether the material has a combined roughness/metallic texture * * Returns @cpp true @ce if either the - * @ref MaterialAttribute::MetallicRoughnessTexture attribute is - * present or both @ref MaterialAttribute::MetalnessTexture and - * @ref MaterialAttribute::RoughnessTexture are present, point to - * the same texture ID, @ref MaterialAttribute::MetalnessTextureSwizzle - * is set to @ref MaterialTextureSwizzle::R (or omitted, in which case - * it's the default) and @ref MaterialAttribute::RoughnessTextureSwizzle - * is set to @ref MaterialTextureSwizzle::G, and ddditionally - * @ref MaterialAttribute::MetalnessTextureMatrix and - * @ref MaterialAttribute::RoughnessTextureMatrix are both either not + * @ref MaterialAttribute::NoneRoughnessMetallicTexture attribute is + * present or both @ref MaterialAttribute::RoughnessTexture and + * @ref MaterialAttribute::MetalnessTexture are present, point to the + * same texture ID, @ref MaterialAttribute::RoughnessTextureSwizzle is + * set to @ref MaterialTextureSwizzle::G and + * @ref MaterialAttribute::MetalnessTextureSwizzle is set to + * @ref MaterialTextureSwizzle::B, and ddditionally + * @ref MaterialAttribute::RoughnessTextureMatrix and + * @ref MaterialAttribute::MetalnessTextureMatrix are both either not * present or have the same value, and - * @ref MaterialAttribute::MetalnessTextureCoordinates and - * @ref MaterialAttribute::RoughnessTextureCoordinates are both either + * @ref MaterialAttribute::RoughnessTextureCoordinates and + * @ref MaterialAttribute::MetalnessTextureCoordinates are both either * not present or have the same value; @cpp false @ce otherwise. * * In other words, if this function returns @cpp true @ce, - * @ref metalnessTexture(), @ref metalnessTextureMatrix() and - * @ref metalnessTextureCoordinates() return values common for both + * @ref roughnessTexture(), @ref roughnessTextureMatrix() and + * @ref roughnessTextureCoordinates() return values common for both * metalness and roughness texture, and the two are packed together - * with metalness occupying the R channel and roughness the G channel. + * with roughness occupying the G channel and metalness the B channel. + * This packing is common in glTF metallic/roughness materials, which + * in turn is compatible with how UE4 assets are usually packed. + * Original rationale for this [can be seen here](https://github.com/KhronosGroup/glTF/issues/857). + * + * The red and alpha channels are ignored and can be repurposed for + * other maps such as occlusion or transmission. This check is a subset + * of @ref hasOcclusionRoughnessMetallicTexture() --- if that function + * returns @cpp true @ce, this will return @cpp true @ce as well. * @see @ref hasMetalnessTexture(), @ref hasRoughnessTexture(), - * @ref hasOcclusionRoughnessMetallicTexture(), * @ref hasRoughnessMetallicOcclusionTexture(), * @ref hasNormalRoughnessMetallicTexture() */ - bool hasMetallicRoughnessTexture() const; + bool hasNoneRoughnessMetallicTexture() const; /** * @brief Whether the material has a combined occlusion/roughness/metallic texture @@ -133,9 +140,19 @@ class MAGNUM_TRADE_EXPORT PbrMetallicRoughnessMaterialData: public MaterialData * @ref occlusionTextureCoordinates() return values common for * occlusion, roughness and metalness textures, and the three are * packed together with occlusion occupying the R channel, roughness - * the G channel and metalness the B channel. + * the G channel and metalness the B channel. This packing is common in + * glTF metallic/roughness materials, which in turn is compatible with + * how UE4 assets are usually packed. Original rationale for this [can + * be seen here](https://github.com/KhronosGroup/glTF/issues/857), + * there's also a [MSFT_packing_occlusionRoughnessMetallic](https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Vendor/MSFT_packing_occlusionRoughnessMetallic/README.md) + * glTF extension using this packing in a more explicit way. + * + * The alpha channel is ignored and can be repurposed for other maps + * such as transmission. This check is a superset of + * @ref hasNoneRoughnessMetallicTexture() --- if this function returns + * @cpp true @ce, that one will return @cpp true @ce as well. * @see @ref hasMetalnessTexture(), @ref hasRoughnessTexture(), - * @ref hasMetallicRoughnessTexture(), + * @ref hasNoneRoughnessMetallicTexture(), * @ref hasRoughnessMetallicOcclusionTexture(), * @ref hasNormalRoughnessMetallicTexture() */ @@ -167,9 +184,14 @@ class MAGNUM_TRADE_EXPORT PbrMetallicRoughnessMaterialData: public MaterialData * @ref roughnessTextureCoordinates() return values common for * roughness, metalness and occlusion textures, and the three are * packed together with roughness occupying the R channel, metalness - * the G channel and occlusion the B channel. + * the G channel and occlusion the B channel. This check is present in + * order to provide support for the [MSFT_packing_occlusionRoughnessMetallic](https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Vendor/MSFT_packing_occlusionRoughnessMetallic/README.md) + * glTF extension. + * + * The alpha channel is ignored and can be repurposed for other maps + * such as transmission. * @see @ref hasMetalnessTexture(), @ref hasRoughnessTexture(), - * @ref hasMetallicRoughnessTexture(), + * @ref hasNoneRoughnessMetallicTexture(), * @ref hasOcclusionRoughnessMetallicTexture(), * @ref hasNormalRoughnessMetallicTexture() */ @@ -201,9 +223,12 @@ class MAGNUM_TRADE_EXPORT PbrMetallicRoughnessMaterialData: public MaterialData * @ref normalTextureCoordinates() return values common for normal, * roughness and metalness textures, and the three are packed together * with normals occupying the RG channel, roughness the B channel and - * metalness the A channel. + * metalness the A channel. This check is present in order to provide + * support for the [MSFT_packing_normalRoughnessMetallic](https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Vendor/MSFT_packing_normalRoughnessMetallic/README.md) + * glTF extension. + * * @see @ref hasMetalnessTexture(), @ref hasRoughnessTexture(), - * @ref hasMetallicRoughnessTexture(), + * @ref hasNoneRoughnessMetallicTexture(), * @ref hasRoughnessMetallicOcclusionTexture(), * @ref hasOcclusionRoughnessMetallicTexture() */ @@ -297,8 +322,8 @@ class MAGNUM_TRADE_EXPORT PbrMetallicRoughnessMaterialData: public MaterialData * @brief Metalness texture ID * * Available only if either @ref MaterialAttribute::MetalnessTexture or - * @ref MaterialAttribute::MetallicRoughnessTexture is present. Meant - * to be multiplied with @ref metalness(). + * @ref MaterialAttribute::NoneRoughnessMetallicTexture is present. + * Meant to be multiplied with @ref metalness(). * @see @ref hasMetalnessTexture(), @ref AbstractImporter::texture() */ UnsignedInt metalnessTexture() const; @@ -306,8 +331,8 @@ class MAGNUM_TRADE_EXPORT PbrMetallicRoughnessMaterialData: public MaterialData /** * @brief Metalness texture swizzle * - * If @ref MaterialAttribute::MetallicRoughnessTexture is present, - * returns always @ref MaterialTextureSwizzle::R. Otherwise returns the + * If @ref MaterialAttribute::NoneRoughnessMetallicTexture is present, + * returns always @ref MaterialTextureSwizzle::B. Otherwise returns the * @ref MaterialAttribute::MetalnessTextureSwizzle attribute, or * @ref MaterialTextureSwizzle::R, if it's not present. Available only * if the material has a metalness texture. @@ -353,7 +378,7 @@ class MAGNUM_TRADE_EXPORT PbrMetallicRoughnessMaterialData: public MaterialData * @brief Roughness texture ID * * Available only if either @ref MaterialAttribute::RoughnessTexture or - * @ref MaterialAttribute::MetallicRoughnessTexture is present. Meant + * @ref MaterialAttribute::NoneRoughnessMetallicTexture is present. Meant * to be multiplied with @ref roughness(). * @see @ref hasRoughnessTexture(), @ref AbstractImporter::texture() */ @@ -362,7 +387,7 @@ class MAGNUM_TRADE_EXPORT PbrMetallicRoughnessMaterialData: public MaterialData /** * @brief Roughness texture swizzle * - * If @ref MaterialAttribute::MetallicRoughnessTexture is present, + * If @ref MaterialAttribute::NoneRoughnessMetallicTexture is present, * returns always @ref MaterialTextureSwizzle::G. Otherwise returns the * @ref MaterialAttribute::RoughnessTextureSwizzle attribute, or * @ref MaterialTextureSwizzle::R, if it's not present. Available only diff --git a/src/Magnum/Trade/Test/MaterialDataTest.cpp b/src/Magnum/Trade/Test/MaterialDataTest.cpp index 2dff7a542..6c6e2bd45 100644 --- a/src/Magnum/Trade/Test/MaterialDataTest.cpp +++ b/src/Magnum/Trade/Test/MaterialDataTest.cpp @@ -2679,7 +2679,7 @@ void MaterialDataTest::pbrMetallicRoughnessAccess() { CORRADE_VERIFY(!data.hasMetalnessTexture()); CORRADE_VERIFY(!data.hasRoughnessTexture()); - CORRADE_VERIFY(!data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); CORRADE_VERIFY(!data.hasRoughnessMetallicOcclusionTexture()); CORRADE_VERIFY(!data.hasOcclusionRoughnessMetallicTexture()); CORRADE_VERIFY(!data.hasNormalRoughnessMetallicTexture()); @@ -2700,7 +2700,7 @@ void MaterialDataTest::pbrMetallicRoughnessAccessDefaults() { CORRADE_VERIFY(!data.hasMetalnessTexture()); CORRADE_VERIFY(!data.hasRoughnessTexture()); - CORRADE_VERIFY(!data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); CORRADE_VERIFY(!data.hasRoughnessMetallicOcclusionTexture()); CORRADE_VERIFY(!data.hasOcclusionRoughnessMetallicTexture()); CORRADE_VERIFY(!data.hasNormalRoughnessMetallicTexture()); @@ -2747,7 +2747,7 @@ void MaterialDataTest::pbrMetallicRoughnessAccessTextured() { CORRADE_VERIFY(data.hasMetalnessTexture()); CORRADE_VERIFY(data.hasRoughnessTexture()); - CORRADE_VERIFY(!data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); CORRADE_VERIFY(!data.hasRoughnessMetallicOcclusionTexture()); CORRADE_VERIFY(!data.hasOcclusionRoughnessMetallicTexture()); CORRADE_VERIFY(!data.hasNormalRoughnessMetallicTexture()); @@ -2797,7 +2797,7 @@ void MaterialDataTest::pbrMetallicRoughnessAccessTexturedDefaults() { CORRADE_VERIFY(data.hasMetalnessTexture()); CORRADE_VERIFY(data.hasRoughnessTexture()); - CORRADE_VERIFY(!data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); CORRADE_VERIFY(!data.hasRoughnessMetallicOcclusionTexture()); CORRADE_VERIFY(!data.hasOcclusionRoughnessMetallicTexture()); CORRADE_VERIFY(!data.hasNormalRoughnessMetallicTexture()); @@ -2868,63 +2868,63 @@ void MaterialDataTest::pbrMetallicRoughnessAccessTexturedImplicitPackedMetallicR /* Just the texture ID, the rest is implicit */ { PbrMetallicRoughnessMaterialData data{{}, { - {MaterialAttribute::MetallicRoughnessTexture, 2u}, + {MaterialAttribute::NoneRoughnessMetallicTexture, 2u}, }}; - CORRADE_VERIFY(data.hasMetallicRoughnessTexture()); - CORRADE_COMPARE(data.metalnessTexture(), 2); - CORRADE_COMPARE(data.metalnessTextureSwizzle(), MaterialTextureSwizzle::R); - CORRADE_COMPARE(data.metalnessTextureMatrix(), Matrix3{}); - CORRADE_COMPARE(data.metalnessTextureCoordinates(), 0); + CORRADE_VERIFY(data.hasNoneRoughnessMetallicTexture()); CORRADE_COMPARE(data.roughnessTexture(), 2); CORRADE_COMPARE(data.roughnessTextureSwizzle(), MaterialTextureSwizzle::G); CORRADE_COMPARE(data.roughnessTextureMatrix(), Matrix3{}); CORRADE_COMPARE(data.roughnessTextureCoordinates(), 0); + CORRADE_COMPARE(data.metalnessTexture(), 2); + CORRADE_COMPARE(data.metalnessTextureSwizzle(), MaterialTextureSwizzle::B); + CORRADE_COMPARE(data.metalnessTextureMatrix(), Matrix3{}); + CORRADE_COMPARE(data.metalnessTextureCoordinates(), 0); /* Explicit parameters for everything, but all the same */ } { PbrMetallicRoughnessMaterialData data{{}, { - {MaterialAttribute::MetallicRoughnessTexture, 2u}, - {MaterialAttribute::MetalnessTextureMatrix, Matrix3::scaling({0.5f, 0.5f})}, - {MaterialAttribute::MetalnessTextureSwizzle, MaterialTextureSwizzle::R}, - {MaterialAttribute::MetalnessTextureCoordinates, 3u}, + {MaterialAttribute::NoneRoughnessMetallicTexture, 2u}, {MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::G}, {MaterialAttribute::RoughnessTextureMatrix, Matrix3::scaling({0.5f, 0.5f})}, - {MaterialAttribute::RoughnessTextureCoordinates, 3u} + {MaterialAttribute::RoughnessTextureCoordinates, 3u}, + {MaterialAttribute::MetalnessTextureMatrix, Matrix3::scaling({0.5f, 0.5f})}, + {MaterialAttribute::MetalnessTextureSwizzle, MaterialTextureSwizzle::B}, + {MaterialAttribute::MetalnessTextureCoordinates, 3u} }}; - CORRADE_VERIFY(data.hasMetallicRoughnessTexture()); - CORRADE_COMPARE(data.metalnessTexture(), 2); - CORRADE_COMPARE(data.metalnessTextureSwizzle(), MaterialTextureSwizzle::R); - CORRADE_COMPARE(data.metalnessTextureMatrix(), Matrix3::scaling({0.5f, 0.5f})); - CORRADE_COMPARE(data.metalnessTextureCoordinates(), 3); + CORRADE_VERIFY(data.hasNoneRoughnessMetallicTexture()); CORRADE_COMPARE(data.roughnessTexture(), 2); CORRADE_COMPARE(data.roughnessTextureSwizzle(), MaterialTextureSwizzle::G); CORRADE_COMPARE(data.roughnessTextureMatrix(), Matrix3::scaling({0.5f, 0.5f})); CORRADE_COMPARE(data.roughnessTextureCoordinates(), 3); + CORRADE_COMPARE(data.metalnessTexture(), 2); + CORRADE_COMPARE(data.metalnessTextureSwizzle(), MaterialTextureSwizzle::B); + CORRADE_COMPARE(data.metalnessTextureMatrix(), Matrix3::scaling({0.5f, 0.5f})); + CORRADE_COMPARE(data.metalnessTextureCoordinates(), 3); /* Swizzle is ignored when the combined texture is specified, so this is fine */ } { PbrMetallicRoughnessMaterialData data{{}, { - {MaterialAttribute::MetallicRoughnessTexture, 2u}, - {MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::B}, + {MaterialAttribute::NoneRoughnessMetallicTexture, 2u}, + {MaterialAttribute::MetalnessTextureSwizzle, MaterialTextureSwizzle::G}, }}; - CORRADE_VERIFY(data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(data.hasNoneRoughnessMetallicTexture()); /* Unexpected texture matrix */ } { PbrMetallicRoughnessMaterialData data{{}, { - {MaterialAttribute::MetallicRoughnessTexture, 2u}, + {MaterialAttribute::NoneRoughnessMetallicTexture, 2u}, {MaterialAttribute::MetalnessTextureMatrix, Matrix3::scaling({0.5f, 1.0f})}, }}; - CORRADE_VERIFY(!data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); /* Unexpected texture coordinates */ } { PbrMetallicRoughnessMaterialData data{{}, { - {MaterialAttribute::MetallicRoughnessTexture, 2u}, + {MaterialAttribute::NoneRoughnessMetallicTexture, 2u}, {MaterialAttribute::RoughnessTextureCoordinates, 1u}, }}; - CORRADE_VERIFY(!data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); } } @@ -2932,62 +2932,66 @@ void MaterialDataTest::pbrMetallicRoughnessAccessTexturedExplicitPackedMetallicR /* Just the texture IDs and swizzles, the rest is implicit */ { PbrMetallicRoughnessMaterialData data{{}, { - {MaterialAttribute::MetalnessTexture, 2u}, {MaterialAttribute::RoughnessTexture, 2u}, - {MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::G} + {MaterialAttribute::MetalnessTexture, 2u}, + {MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::G}, + {MaterialAttribute::MetalnessTextureSwizzle, MaterialTextureSwizzle::B} }}; - CORRADE_VERIFY(data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(data.hasNoneRoughnessMetallicTexture()); /* Explicit parameters for everything, but all the same */ } { PbrMetallicRoughnessMaterialData data{{}, { - {MaterialAttribute::MetalnessTexture, 2u}, - {MaterialAttribute::MetalnessTextureMatrix, Matrix3::scaling({0.5f, 0.5f})}, - {MaterialAttribute::MetalnessTextureSwizzle, MaterialTextureSwizzle::R}, - {MaterialAttribute::MetalnessTextureCoordinates, 3u}, {MaterialAttribute::RoughnessTexture, 2u}, {MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::G}, {MaterialAttribute::RoughnessTextureMatrix, Matrix3::scaling({0.5f, 0.5f})}, - {MaterialAttribute::RoughnessTextureCoordinates, 3u} + {MaterialAttribute::RoughnessTextureCoordinates, 3u}, + {MaterialAttribute::MetalnessTexture, 2u}, + {MaterialAttribute::MetalnessTextureMatrix, Matrix3::scaling({0.5f, 0.5f})}, + {MaterialAttribute::MetalnessTextureSwizzle, MaterialTextureSwizzle::B}, + {MaterialAttribute::MetalnessTextureCoordinates, 3u} }}; - CORRADE_VERIFY(data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(data.hasNoneRoughnessMetallicTexture()); /* One texture missing */ } { PbrMetallicRoughnessMaterialData data{{}, { {MaterialAttribute::RoughnessTexture, 2u}, - {MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::B}, + {MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::G}, }}; - CORRADE_VERIFY(!data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); /* Unexpected swizzle */ } { PbrMetallicRoughnessMaterialData data{{}, { - {MaterialAttribute::MetalnessTexture, 2u}, {MaterialAttribute::RoughnessTexture, 2u}, - {MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::B}, + {MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::R}, + {MaterialAttribute::MetalnessTexture, 2u}, + {MaterialAttribute::MetalnessTextureSwizzle, MaterialTextureSwizzle::B}, }}; - CORRADE_VERIFY(!data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); /* Unexpected texture matrix */ } { PbrMetallicRoughnessMaterialData data{{}, { - {MaterialAttribute::MetalnessTexture, 2u}, - {MaterialAttribute::MetalnessTextureMatrix, Matrix3::scaling({0.5f, 1.0f})}, {MaterialAttribute::RoughnessTexture, 2u}, {MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::G}, + {MaterialAttribute::MetalnessTexture, 2u}, + {MaterialAttribute::MetalnessTextureSwizzle, MaterialTextureSwizzle::B}, + {MaterialAttribute::MetalnessTextureMatrix, Matrix3::scaling({0.5f, 1.0f})}, }}; - CORRADE_VERIFY(!data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); /* Unexpected texture coordinates */ } { PbrMetallicRoughnessMaterialData data{{}, { - {MaterialAttribute::MetalnessTexture, 2u}, {MaterialAttribute::RoughnessTexture, 2u}, {MaterialAttribute::RoughnessTextureSwizzle, MaterialTextureSwizzle::G}, {MaterialAttribute::RoughnessTextureCoordinates, 1u}, + {MaterialAttribute::MetalnessTexture, 2u}, + {MaterialAttribute::MetalnessTextureSwizzle, MaterialTextureSwizzle::B}, }}; - CORRADE_VERIFY(!data.hasMetallicRoughnessTexture()); + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); } } @@ -3002,6 +3006,8 @@ void MaterialDataTest::pbrMetallicRoughnessAccessTexturedExplicitPackedRoughness {MaterialAttribute::OcclusionTextureSwizzle, MaterialTextureSwizzle::B}, }}; CORRADE_VERIFY(data.hasRoughnessMetallicOcclusionTexture()); + /* This isn't a superset */ + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); /* Explicit parameters for everything, but all the same */ } { @@ -3020,6 +3026,8 @@ void MaterialDataTest::pbrMetallicRoughnessAccessTexturedExplicitPackedRoughness {MaterialAttribute::OcclusionTextureCoordinates, 3u} }}; CORRADE_VERIFY(data.hasRoughnessMetallicOcclusionTexture()); + /* This isn't a superset */ + CORRADE_VERIFY(!data.hasNoneRoughnessMetallicTexture()); /* One texture missing */ } { @@ -3080,6 +3088,8 @@ void MaterialDataTest::pbrMetallicRoughnessAccessTexturedExplicitPackedOcclusion {MaterialAttribute::MetalnessTextureSwizzle, MaterialTextureSwizzle::B}, }}; CORRADE_VERIFY(data.hasOcclusionRoughnessMetallicTexture()); + /* This is a superset */ + CORRADE_VERIFY(data.hasNoneRoughnessMetallicTexture()); /* Explicit parameters for everything, but all the same */ } { @@ -3098,6 +3108,8 @@ void MaterialDataTest::pbrMetallicRoughnessAccessTexturedExplicitPackedOcclusion {MaterialAttribute::MetalnessTextureCoordinates, 3u} }}; CORRADE_VERIFY(data.hasOcclusionRoughnessMetallicTexture()); + /* This is a superset */ + CORRADE_VERIFY(data.hasNoneRoughnessMetallicTexture()); /* One texture missing */ } {