git.s-ol.nu ~forks/DiligentTools / 5841036
GLTFLoader: reworked material to load material attribs in a shader-friendly format assiduous 1 year, 1 month ago
2 changed file(s) with 94 addition(s) and 80 deletion(s). Raw diff Collapse all Expand all
6464
6565 struct Material
6666 {
67 Material() noexcept {}
67 Material() noexcept
68 {
69 TextureIds.fill(-1);
70 }
71
72 enum PBR_WORKFLOW
73 {
74 PBR_WORKFLOW_METALL_ROUGH = 0,
75 PBR_WORKFLOW_SPEC_GLOSS
76 };
77
78 // Material attributes packed in a shader-friendly format
79 struct ShaderAttribs
80 {
81 float4 BaseColorFactor = float4{1, 1, 1, 1};
82 float4 EmissiveFactor = float4{1, 1, 1, 1};
83 float4 SpecularFactor = float4{1, 1, 1, 1};
84
85 int Workflow = PBR_WORKFLOW_METALL_ROUGH;
86 float BaseColorUVSelector = -1;
87 float PhysicalDescriptorUVSelector = -1;
88 float NormalUVSelector = -1;
89
90 float OcclusionUVSelector = -1;
91 float EmissiveUVSelector = -1;
92 float MetallicFactor = 1;
93 float RoughnessFactor = 1;
94
95 // When texture atlas is used, UV scale and bias applied to
96 // each texture coordinate set
97 float4 BaseColorUVScaleBias = float4{1, 1, 0, 0};
98 float4 PhysicalDescriptorUVScaleBias = float4{1, 1, 0, 0};
99 float4 NormalUVScaleBias = float4{1, 1, 0, 0};
100 float4 OcclusionUVScaleBias = float4{1, 1, 0, 0};
101 float4 EmissiveUVScaleBias = float4{1, 1, 0, 0};
102
103 int UseAlphaMask = 0;
104 float AlphaCutoff = 0.5f;
105 float Dummy0;
106 float Dummy1;
107 };
108 static_assert(sizeof(ShaderAttribs) % 16 == 0, "ShaderAttribs struct must be 16-byte aligned");
109 ShaderAttribs Attribs;
68110
69111 enum ALPHA_MODE
70112 {
76118
77119 bool DoubleSided = false;
78120
79 float AlphaCutoff = 1.0f;
80 float MetallicFactor = 1.0f;
81 float RoughnessFactor = 1.0f;
82
83 float4 BaseColorFactor = float4{1, 1, 1, 1};
84 float4 EmissiveFactor = float4{1, 1, 1, 1};
85 float4 DiffuseFactor = float4{1, 1, 1, 1};
86 float4 SpecularFactor = float4{1, 1, 1, 1};
87
88 struct TextureAttribs
89 {
90 // Texture index in Model.Textures array
91 Int16 Index = -1;
92
93 // Texture coordinates set (UV0 / UV1)
94 Uint8 CoordSet = 0;
95
96 void SetIndex(int Idx)
97 {
98 // clang-format off
99 DEV_CHECK_ERR(Idx >= static_cast<int>(std::numeric_limits<decltype(Index)>::min()) &&
100 Idx <= static_cast<int>(std::numeric_limits<decltype(Index)>::max()),
101 "Texture index (", Idx, ") is out of representable range");
102 // clang-format on
103 Index = static_cast<decltype(Index)>(Idx);
104 }
105
106 void SetCoordSet(int Set)
107 {
108 // clang-format off
109 DEV_CHECK_ERR(Set >= static_cast<int>(std::numeric_limits<decltype(CoordSet)>::min()) &&
110 Set <= static_cast<int>(std::numeric_limits<decltype(CoordSet)>::max()),
111 "Texture coordinate set (", Set, ") is out of representable range");
112 // clang-format on
113 CoordSet = static_cast<decltype(CoordSet)>(Set);
114 }
115 };
116121 enum TEXTURE_ID
117122 {
123 // Base color for metallic-roughness workflow or
124 // diffuse color for specular-glossinees workflow
118125 TEXTURE_ID_BASE_COLOR = 0,
119 TEXTURE_ID_METALL_ROUGHNESS,
126
127 // Metallic-roughness or specular-glossinees map
128 TEXTURE_ID_PHYSICAL_DESC,
129
120130 TEXTURE_ID_NORMAL_MAP,
121131 TEXTURE_ID_OCCLUSION,
122132 TEXTURE_ID_EMISSIVE,
123 TEXTURE_ID_SPEC_GLOSS,
124 TEXTURE_ID_DIFFUSE,
125133 TEXTURE_ID_NUM_TEXTURES
126134 };
127 std::array<TextureAttribs, TEXTURE_ID_NUM_TEXTURES> Textures;
128
129 enum class PbrWorkflow
130 {
131 MetallicRoughness,
132 SpecularGlossiness
133 };
134 PbrWorkflow workflow = PbrWorkflow::MetallicRoughness;
135 // Texture indices in Model.Textures array
136 std::array<int, TEXTURE_ID_NUM_TEXTURES> TextureIds = {};
135137 };
136138
137139
10031003 struct TextureParameterInfo
10041004 {
10051005 const Material::TEXTURE_ID TextureId;
1006 float& UVSelector;
1007 float4& UVScaleBias;
10061008 const char* const TextureName;
10071009 const tinygltf::ParameterMap& Params;
10081010 };
10091011 // clang-format off
10101012 std::array<TextureParameterInfo, 5> TextureParams =
10111013 {
1012 TextureParameterInfo{Material::TEXTURE_ID_BASE_COLOR, "baseColorTexture", gltf_mat.values},
1013 TextureParameterInfo{Material::TEXTURE_ID_METALL_ROUGHNESS, "metallicRoughnessTexture", gltf_mat.values},
1014 TextureParameterInfo{Material::TEXTURE_ID_NORMAL_MAP, "normalTexture", gltf_mat.additionalValues},
1015 TextureParameterInfo{Material::TEXTURE_ID_OCCLUSION, "occlusionTexture", gltf_mat.additionalValues},
1016 TextureParameterInfo{Material::TEXTURE_ID_EMISSIVE, "emissiveTexture", gltf_mat.additionalValues}
1014 TextureParameterInfo{Material::TEXTURE_ID_BASE_COLOR, Mat.Attribs.BaseColorUVSelector, Mat.Attribs.BaseColorUVScaleBias, "baseColorTexture", gltf_mat.values},
1015 TextureParameterInfo{Material::TEXTURE_ID_PHYSICAL_DESC, Mat.Attribs.PhysicalDescriptorUVSelector, Mat.Attribs.PhysicalDescriptorUVScaleBias, "metallicRoughnessTexture", gltf_mat.values},
1016 TextureParameterInfo{Material::TEXTURE_ID_NORMAL_MAP, Mat.Attribs.NormalUVSelector, Mat.Attribs.NormalUVScaleBias, "normalTexture", gltf_mat.additionalValues},
1017 TextureParameterInfo{Material::TEXTURE_ID_OCCLUSION, Mat.Attribs.OcclusionUVSelector, Mat.Attribs.OcclusionUVScaleBias, "occlusionTexture", gltf_mat.additionalValues},
1018 TextureParameterInfo{Material::TEXTURE_ID_EMISSIVE, Mat.Attribs.EmissiveUVSelector, Mat.Attribs.EmissiveUVScaleBias, "emissiveTexture", gltf_mat.additionalValues}
10171019 };
10181020 // clang-format on
10191021
10221024 auto tex_it = Param.Params.find(Param.TextureName);
10231025 if (tex_it != Param.Params.end())
10241026 {
1025 auto& TexInfo = Mat.Textures[Param.TextureId];
1026 TexInfo.SetIndex(tex_it->second.TextureIndex());
1027 TexInfo.SetCoordSet(tex_it->second.TextureTexCoord());
1027 Mat.TextureIds[Param.TextureId] = tex_it->second.TextureIndex();
1028 Param.UVSelector = static_cast<float>(tex_it->second.TextureTexCoord());
10281029 }
10291030 }
10301031
10361037 Factor = static_cast<float>(it->second.Factor());
10371038 }
10381039 };
1039 ReadFactor(Mat.RoughnessFactor, gltf_mat.values, "roughnessFactor");
1040 ReadFactor(Mat.MetallicFactor, gltf_mat.values, "metallicFactor");
1040 ReadFactor(Mat.Attribs.RoughnessFactor, gltf_mat.values, "roughnessFactor");
1041 ReadFactor(Mat.Attribs.MetallicFactor, gltf_mat.values, "metallicFactor");
10411042
10421043 auto ReadColorFactor = [](float4& Factor, const tinygltf::ParameterMap& Params, const char* Name) //
10431044 {
10481049 }
10491050 };
10501051
1051 ReadColorFactor(Mat.BaseColorFactor, gltf_mat.values, "baseColorFactor");
1052 ReadColorFactor(Mat.EmissiveFactor, gltf_mat.additionalValues, "emissiveFactor");
1052 ReadColorFactor(Mat.Attribs.BaseColorFactor, gltf_mat.values, "baseColorFactor");
1053 ReadColorFactor(Mat.Attribs.EmissiveFactor, gltf_mat.additionalValues, "emissiveFactor");
10531054
10541055 {
10551056 auto alpha_mode_it = gltf_mat.additionalValues.find("alphaMode");
10621063 }
10631064 if (param.string_value == "MASK")
10641065 {
1065 Mat.AlphaCutoff = 0.5f;
1066 Mat.AlphaMode = Material::ALPHAMODE_MASK;
1067 }
1068 }
1069 }
1070
1071 ReadFactor(Mat.AlphaCutoff, gltf_mat.additionalValues, "alphaCutoff");
1066 Mat.AlphaMode = Material::ALPHAMODE_MASK;
1067
1068 Mat.Attribs.UseAlphaMask = 1;
1069 Mat.Attribs.AlphaCutoff = 0.5f;
1070 }
1071 }
1072 }
1073
1074 ReadFactor(Mat.Attribs.AlphaCutoff, gltf_mat.additionalValues, "alphaCutoff");
10721075
10731076 {
10741077 auto double_sided_it = gltf_mat.additionalValues.find("doubleSided");
10781081 }
10791082 }
10801083
1084 Mat.Attribs.Workflow = Material::PBR_WORKFLOW_METALL_ROUGH;
1085
10811086 // Extensions
10821087 // @TODO: Find out if there is a nicer way of reading these properties with recent tinygltf headers
10831088 {
10891094 auto index = ext_it->second.Get("specularGlossinessTexture").Get("index");
10901095 auto texCoordSet = ext_it->second.Get("specularGlossinessTexture").Get("texCoord");
10911096
1092 auto& TexInfo = Mat.Textures[Material::TEXTURE_ID_SPEC_GLOSS];
1093 TexInfo.SetIndex(index.Get<int>());
1094 TexInfo.SetCoordSet(texCoordSet.Get<int>());
1095
1096 Mat.workflow = Material::PbrWorkflow::SpecularGlossiness;
1097 Mat.TextureIds[Material::TEXTURE_ID_PHYSICAL_DESC] = index.Get<int>();
1098 Mat.Attribs.PhysicalDescriptorUVSelector = static_cast<float>(texCoordSet.Get<int>());
1099
1100 Mat.Attribs.Workflow = Material::PBR_WORKFLOW_SPEC_GLOSS;
10971101 }
10981102
10991103 if (ext_it->second.Has("diffuseTexture"))
11011105 auto index = ext_it->second.Get("diffuseTexture").Get("index");
11021106 auto texCoordSet = ext_it->second.Get("diffuseTexture").Get("texCoord");
11031107
1104 auto& TexInfo = Mat.Textures[Material::TEXTURE_ID_DIFFUSE];
1105 TexInfo.SetIndex(index.Get<int>());
1106 TexInfo.SetCoordSet(texCoordSet.Get<int>());
1108 Mat.TextureIds[Material::TEXTURE_ID_BASE_COLOR] = index.Get<int>();
1109 Mat.Attribs.BaseColorUVSelector = static_cast<float>(texCoordSet.Get<int>());
11071110 }
11081111
11091112 if (ext_it->second.Has("diffuseFactor"))
11111114 auto factor = ext_it->second.Get("diffuseFactor");
11121115 for (uint32_t i = 0; i < factor.ArrayLen(); i++)
11131116 {
1114 const auto val = factor.Get(i);
1115 Mat.DiffuseFactor[i] = val.IsNumber() ? (float)val.Get<double>() : (float)val.Get<int>();
1117 const auto val = factor.Get(i);
1118 Mat.Attribs.BaseColorFactor[i] =
1119 val.IsNumber() ? (float)val.Get<double>() : (float)val.Get<int>();
11161120 }
11171121 }
11181122
11211125 auto factor = ext_it->second.Get("specularFactor");
11221126 for (uint32_t i = 0; i < factor.ArrayLen(); i++)
11231127 {
1124 const auto val = factor.Get(i);
1125 Mat.SpecularFactor[i] = val.IsNumber() ? (float)val.Get<double>() : (float)val.Get<int>();
1128 const auto val = factor.Get(i);
1129 Mat.Attribs.SpecularFactor[i] =
1130 val.IsNumber() ? (float)val.Get<double>() : (float)val.Get<int>();
11261131 }
11271132 }
11281133 }
1134 }
1135
1136 for (const auto& Param : TextureParams)
1137 {
1138 auto TexIndex = Mat.TextureIds[Param.TextureId];
1139 if (TexIndex >= 0)
1140 Param.UVScaleBias = GetUVScaleBias(TexIndex);
11291141 }
11301142
11311143 Materials.push_back(Mat);