Browse Source

Trade: MaterialTextureSwizzle::GA for normal maps and related utils.

Things are getting complicated, heh.
pull/459/head
Vladimír Vondruš 6 years ago
parent
commit
9c00efa7e0
  1. 38
      doc/snippets/MagnumTrade.glsl
  2. 7
      src/Magnum/Trade/MaterialData.cpp
  3. 35
      src/Magnum/Trade/MaterialData.h
  4. 13
      src/Magnum/Trade/Test/MaterialDataTest.cpp

38
doc/snippets/MagnumTrade.glsl

@ -0,0 +1,38 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/* [unpackTwoChannelNormal] */
/* Assumes (1, y, 1, x) or (x, y, <anything>, 1) */
vec3 unpackTwoChannelNormal(vec4 packed) {
packed.x *= packed.w;
/* reconstruct Z */
vec3 normal;
normal.xy = packed.xy*2.0 - 1.0;
normal.z = sqrt(max(0.0, 1.0 - dot(normal.xy,
normal.xy)));
return normal;
}
/* [unpackTwoChannelNormal] */

7
src/Magnum/Trade/MaterialData.cpp

@ -65,6 +65,13 @@ constexpr struct {
} }
UnsignedInt materialTextureSwizzleComponentCount(const MaterialTextureSwizzle swizzle) {
return (UnsignedInt(swizzle) & 0xff000000u ? 1 : 0) +
(UnsignedInt(swizzle) & 0x00ff0000u ? 1 : 0) +
(UnsignedInt(swizzle) & 0x0000ff00u ? 1 : 0) +
(UnsignedInt(swizzle) & 0x000000ffu ? 1 : 0);
}
std::size_t materialAttributeTypeSize(const MaterialAttributeType type) { std::size_t materialAttributeTypeSize(const MaterialAttributeType type) {
switch(type) { switch(type) {
case MaterialAttributeType::Bool: case MaterialAttributeType::Bool:

35
src/Magnum/Trade/MaterialData.h

@ -613,10 +613,22 @@ enum class MaterialAttribute: UnsignedInt {
* not present, @ref MaterialTextureSwizzle::RGB is assumed. * not present, @ref MaterialTextureSwizzle::RGB is assumed.
* *
* If the texture is just two-component, the remaining component is * If the texture is just two-component, the remaining component is
* implicit and calculated as @f$ z = \sqrt{1 - x^2 - y^2} @f$. * implicit and calculated as @f$ z = \sqrt{1 - x^2 - y^2} @f$. In order to
* account for numeric issues and avoid negative values under the square
* root, it's commonly done as @f$ z = \sqrt{\max(0, 1 - x^2 - y^2)} @f$.
* Additionally, to mitigate artifacts when storing normal texture in a
* compressed format, @ref MaterialTextureSwizzle::GA may get used instead
* of @ref MaterialTextureSwizzle::RG.
*
* Shader code that is able to reconstruct a XYZ normal from both RG and GA
* variants assuming constant values in other channels ([source](https://github.com/KhronosGroup/glTF/issues/1682#issuecomment-557880407)):
*
* @snippet MagnumTrade.glsl unpackTwoChannelNormal
*
* @see @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture(), * @see @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture(),
* @ref PbrMetallicRoughnessMaterialData::normalTextureSwizzle(), * @ref PbrMetallicRoughnessMaterialData::normalTextureSwizzle(),
* @ref PbrSpecularGlossinessMaterialData::normalTextureSwizzle() * @ref PbrSpecularGlossinessMaterialData::normalTextureSwizzle(),
* @ref materialTextureSwizzleComponentCount()
*/ */
NormalTextureSwizzle, NormalTextureSwizzle,
@ -842,6 +854,7 @@ MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialAttribute value);
@m_since_latest @m_since_latest
See @ref MaterialData for more information. See @ref MaterialData for more information.
@see @ref materialTextureSwizzleComponentCount()
*/ */
enum class MaterialTextureSwizzle: UnsignedInt { enum class MaterialTextureSwizzle: UnsignedInt {
/** Red component */ /** Red component */
@ -862,6 +875,16 @@ enum class MaterialTextureSwizzle: UnsignedInt {
/** Green and blue component */ /** Green and blue component */
GB = Utility::Endianness::fourCC('G', 'B', '\0', '\0'), GB = Utility::Endianness::fourCC('G', 'B', '\0', '\0'),
/**
* Green and alpha component. May get used to mitigate artifacts when
* storing two independent channels (such as two-channel normal maps) in
* compressed texture formats --- these commonly have separately compressed
* RGB and alpha, with green channel having the most precision of the RGB
* triplet.
* @see @ref MaterialAttribute::NormalTextureSwizzle
*/
GA = Utility::Endianness::fourCC('G', 'A', '\0', '\0'),
/** Blue and alpha component */ /** Blue and alpha component */
BA = Utility::Endianness::fourCC('B', 'A', '\0', '\0'), BA = Utility::Endianness::fourCC('B', 'A', '\0', '\0'),
@ -875,6 +898,14 @@ enum class MaterialTextureSwizzle: UnsignedInt {
RGBA = Utility::Endianness::fourCC('R', 'G', 'B', 'A'), RGBA = Utility::Endianness::fourCC('R', 'G', 'B', 'A'),
}; };
/**
@brief Component count in a material texture swizzle
@m_since_latest
Returns for example @cpp 2 @ce for @ref MaterialTextureSwizzle::GA.
*/
MAGNUM_TRADE_EXPORT UnsignedInt materialTextureSwizzleComponentCount(MaterialTextureSwizzle swizzle);
/** /**
@debugoperatorenum{MaterialTextureSwizzle} @debugoperatorenum{MaterialTextureSwizzle}
@m_since_latest @m_since_latest

13
src/Magnum/Trade/Test/MaterialDataTest.cpp

@ -46,6 +46,7 @@ class MaterialDataTest: public TestSuite::Tester {
public: public:
explicit MaterialDataTest(); explicit MaterialDataTest();
void textureSwizzleComponentCount();
void attributeTypeSize(); void attributeTypeSize();
void attributeTypeSizeInvalid(); void attributeTypeSizeInvalid();
@ -217,7 +218,9 @@ class MaterialDataTest: public TestSuite::Tester {
}; };
MaterialDataTest::MaterialDataTest() { MaterialDataTest::MaterialDataTest() {
addTests({&MaterialDataTest::attributeTypeSize, addTests({&MaterialDataTest::textureSwizzleComponentCount,
&MaterialDataTest::attributeTypeSize,
&MaterialDataTest::attributeTypeSizeInvalid, &MaterialDataTest::attributeTypeSizeInvalid,
&MaterialDataTest::attributeMap, &MaterialDataTest::attributeMap,
&MaterialDataTest::layerMap, &MaterialDataTest::layerMap,
@ -417,6 +420,14 @@ MaterialDataTest::MaterialDataTest() {
using namespace Containers::Literals; using namespace Containers::Literals;
using namespace Math::Literals; using namespace Math::Literals;
void MaterialDataTest::textureSwizzleComponentCount() {
CORRADE_COMPARE(materialTextureSwizzleComponentCount(MaterialTextureSwizzle::B), 1);
CORRADE_COMPARE(materialTextureSwizzleComponentCount(MaterialTextureSwizzle::RG), 2);
CORRADE_COMPARE(materialTextureSwizzleComponentCount(MaterialTextureSwizzle::GA), 2);
CORRADE_COMPARE(materialTextureSwizzleComponentCount(MaterialTextureSwizzle::GBA), 3);
CORRADE_COMPARE(materialTextureSwizzleComponentCount(MaterialTextureSwizzle::RGBA), 4);
}
void MaterialDataTest::attributeTypeSize() { void MaterialDataTest::attributeTypeSize() {
CORRADE_COMPARE(materialAttributeTypeSize(MaterialAttributeType::Bool), 1); CORRADE_COMPARE(materialAttributeTypeSize(MaterialAttributeType::Bool), 1);
CORRADE_COMPARE(materialAttributeTypeSize(MaterialAttributeType::Deg), 4); CORRADE_COMPARE(materialAttributeTypeSize(MaterialAttributeType::Deg), 4);

Loading…
Cancel
Save