Skip to content

Commit c99fd4b

Browse files
AssetLoader: preserve GLTF specular-glossiness materials
1 parent 7b8555d commit c99fd4b

3 files changed

Lines changed: 124 additions & 0 deletions

File tree

AssetLoader/interface/GLTFLoader.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ struct Material
196196
float AlphaCutoff = 0.5f;
197197
float MetallicFactor = 1;
198198

199+
// Roughness factor for metallic-roughness workflow and glossiness factor
200+
// for specular-glossiness workflow.
199201
float RoughnessFactor = 1;
200202
float OcclusionFactor = 1;
201203
float ClearcoatFactor = 0;

AssetLoader/src/GLTFLoader.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,10 +1513,32 @@ Material LoadMaterial(const tinygltf::Model& gltf_model,
15131513
Mat.Attribs.Workflow = Material::PBR_WORKFLOW_SPEC_GLOSS;
15141514

15151515
const tinygltf::Value& SpecGlossExt = ext_it->second;
1516+
1517+
// KHR_materials_pbrSpecularGlossiness replaces the core
1518+
// metallic-roughness representation. Reset aliased core values so
1519+
// that optional extension properties use their own defaults rather
1520+
// than the fallback representation intended for clients that do not
1521+
// support the extension.
1522+
Mat.Attribs.BaseColorFactor = float4{1, 1, 1, 1};
1523+
Mat.Attribs.SpecularFactor = float3{1, 1, 1};
1524+
Mat.Attribs.RoughnessFactor = 1; // Glossiness factor in this workflow.
1525+
1526+
auto ResetTexture = [&](const char* Name) {
1527+
const int TextureAttribIdx = LoadCtx.GetTextureAttributeIndex(Name);
1528+
if (TextureAttribIdx >= 0)
1529+
{
1530+
MatBuilder.SetTextureId(TextureAttribIdx, -1);
1531+
MatBuilder.GetTextureAttrib(TextureAttribIdx) = {};
1532+
}
1533+
};
1534+
ResetTexture(BaseColorTextureName);
1535+
ResetTexture(MetallicRoughnessTextureName);
1536+
15161537
LoadExtensionTexture(gltf_model, LoadCtx, SpecGlossExt, MatBuilder, SpecularGlossinessTextureName);
15171538
LoadExtensionTexture(gltf_model, LoadCtx, SpecGlossExt, MatBuilder, DiffuseTextureName);
15181539
LoadExtensionParameter(SpecGlossExt, "diffuseFactor", Mat.Attribs.BaseColorFactor);
15191540
LoadExtensionParameter(SpecGlossExt, "specularFactor", Mat.Attribs.SpecularFactor);
1541+
LoadExtensionParameter(SpecGlossExt, "glossinessFactor", Mat.Attribs.RoughnessFactor);
15201542
}
15211543
}
15221544

Tests/DiligentToolsTest/src/GLTFLoaderTest.cpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include "Image.h"
3333

34+
#include <initializer_list>
3435
#include <utility>
3536

3637
namespace Diligent
@@ -67,6 +68,31 @@ tinygltf::Texture CreateDDSTexture(int Source)
6768
return Texture;
6869
}
6970

71+
tinygltf::Value MakeNumberArray(std::initializer_list<double> Values)
72+
{
73+
tinygltf::Value::Array Array;
74+
Array.reserve(Values.size());
75+
for (double Value : Values)
76+
Array.emplace_back(Value);
77+
return tinygltf::Value{std::move(Array)};
78+
}
79+
80+
tinygltf::Value MakeTextureInfo(int TextureIndex, int TexCoord)
81+
{
82+
tinygltf::Value::Object TextureInfo;
83+
TextureInfo.emplace("index", tinygltf::Value{TextureIndex});
84+
TextureInfo.emplace("texCoord", tinygltf::Value{TexCoord});
85+
return tinygltf::Value{std::move(TextureInfo)};
86+
}
87+
88+
tinygltf::Parameter MakeCoreTextureParameter(int TextureIndex, int TexCoord)
89+
{
90+
tinygltf::Parameter Parameter;
91+
Parameter.json_double_value.emplace("index", TextureIndex);
92+
Parameter.json_double_value.emplace("texCoord", TexCoord);
93+
return Parameter;
94+
}
95+
7096
TEST(Tools_GLTFLoader, MSFTTextureDDSUsesRawDDSImageData)
7197
{
7298
tinygltf::Image DDSImage;
@@ -102,4 +128,78 @@ TEST(Tools_GLTFLoader, MSFTTextureDDSRejectsNonDDSImageData)
102128
EXPECT_EQ(GLTF::MSFTTextureDDS::GetSource(Texture, Model), -1);
103129
}
104130

131+
TEST(Tools_GLTFLoader, SpecularGlossinessLoadsFactors)
132+
{
133+
tinygltf::Value::Object Extension;
134+
Extension.emplace("diffuseFactor", MakeNumberArray({0.1, 0.2, 0.3, 0.4}));
135+
Extension.emplace("specularFactor", MakeNumberArray({0.5, 0.6, 0.7}));
136+
Extension.emplace("glossinessFactor", tinygltf::Value{0.8});
137+
138+
tinygltf::Material Source;
139+
Source.extensions.emplace("KHR_materials_pbrSpecularGlossiness",
140+
tinygltf::Value{std::move(Extension)});
141+
142+
const GLTF::Material Material = GLTF::LoadMaterial(tinygltf::Model{}, Source);
143+
EXPECT_EQ(Material.Attribs.Workflow, GLTF::Material::PBR_WORKFLOW_SPEC_GLOSS);
144+
EXPECT_FLOAT_EQ(Material.Attribs.BaseColorFactor.x, 0.1f);
145+
EXPECT_FLOAT_EQ(Material.Attribs.BaseColorFactor.y, 0.2f);
146+
EXPECT_FLOAT_EQ(Material.Attribs.BaseColorFactor.z, 0.3f);
147+
EXPECT_FLOAT_EQ(Material.Attribs.BaseColorFactor.w, 0.4f);
148+
EXPECT_FLOAT_EQ(Material.Attribs.SpecularFactor.x, 0.5f);
149+
EXPECT_FLOAT_EQ(Material.Attribs.SpecularFactor.y, 0.6f);
150+
EXPECT_FLOAT_EQ(Material.Attribs.SpecularFactor.z, 0.7f);
151+
EXPECT_FLOAT_EQ(Material.Attribs.RoughnessFactor, 0.8f);
152+
}
153+
154+
TEST(Tools_GLTFLoader, SpecularGlossinessUsesExtensionDefaultsInsteadOfCoreFallback)
155+
{
156+
tinygltf::Material Source;
157+
158+
tinygltf::Parameter BaseColorFactor;
159+
BaseColorFactor.number_array = {0.1, 0.2, 0.3, 0.4};
160+
Source.values.emplace("baseColorFactor", std::move(BaseColorFactor));
161+
162+
tinygltf::Parameter RoughnessFactor;
163+
RoughnessFactor.number_value = 0.25;
164+
Source.values.emplace("roughnessFactor", std::move(RoughnessFactor));
165+
166+
Source.values.emplace(GLTF::BaseColorTextureName, MakeCoreTextureParameter(0, 1));
167+
Source.values.emplace(GLTF::MetallicRoughnessTextureName, MakeCoreTextureParameter(1, 1));
168+
Source.extensions.emplace("KHR_materials_pbrSpecularGlossiness",
169+
tinygltf::Value{tinygltf::Value::Object{}});
170+
171+
tinygltf::Model Model;
172+
Model.textures.resize(2);
173+
174+
const GLTF::Material Material = GLTF::LoadMaterial(Model, Source);
175+
EXPECT_EQ(Material.Attribs.Workflow, GLTF::Material::PBR_WORKFLOW_SPEC_GLOSS);
176+
EXPECT_EQ(Material.Attribs.BaseColorFactor, (float4{1, 1, 1, 1}));
177+
EXPECT_EQ(Material.Attribs.SpecularFactor, (float3{1, 1, 1}));
178+
EXPECT_FLOAT_EQ(Material.Attribs.RoughnessFactor, 1.f);
179+
EXPECT_EQ(Material.GetTextureId(GLTF::DefaultDiffuseTextureAttribId), -1);
180+
EXPECT_EQ(Material.GetTextureId(GLTF::DefaultSpecularGlossinessTextureAttibId), -1);
181+
}
182+
183+
TEST(Tools_GLTFLoader, SpecularGlossinessTexturesOverrideAliasedCoreTextures)
184+
{
185+
tinygltf::Value::Object Extension;
186+
Extension.emplace(GLTF::DiffuseTextureName, MakeTextureInfo(2, 1));
187+
Extension.emplace(GLTF::SpecularGlossinessTextureName, MakeTextureInfo(3, 2));
188+
189+
tinygltf::Material Source;
190+
Source.values.emplace(GLTF::BaseColorTextureName, MakeCoreTextureParameter(0, 0));
191+
Source.values.emplace(GLTF::MetallicRoughnessTextureName, MakeCoreTextureParameter(1, 0));
192+
Source.extensions.emplace("KHR_materials_pbrSpecularGlossiness",
193+
tinygltf::Value{std::move(Extension)});
194+
195+
tinygltf::Model Model;
196+
Model.textures.resize(4);
197+
198+
const GLTF::Material Material = GLTF::LoadMaterial(Model, Source);
199+
EXPECT_EQ(Material.GetTextureId(GLTF::DefaultDiffuseTextureAttribId), 2);
200+
EXPECT_EQ(Material.GetTextureAttrib(GLTF::DefaultDiffuseTextureAttribId).GetUVSelector(), 1);
201+
EXPECT_EQ(Material.GetTextureId(GLTF::DefaultSpecularGlossinessTextureAttibId), 3);
202+
EXPECT_EQ(Material.GetTextureAttrib(GLTF::DefaultSpecularGlossinessTextureAttibId).GetUVSelector(), 2);
203+
}
204+
105205
} // namespace

0 commit comments

Comments
 (0)