Clean house in material extensions.
- KHR_materials_common never had a real life in the glTF 2.0 world. One day we may see a new extension for Phong/Blinn/Lambert. - PBR_specular_glossiness is a poor fit for PBS StingRay (the only real source of PBR we have) and has no advantage over PBR_metallic_roughness. - The conversion we were doing for traditional materials to PBR made no sense. Revert to a very simple formula: diffuse -> baseColor, simple reasonable constants for metallic & roughness.
This commit is contained in:
parent
67bb9372d7
commit
7c0715c4ad
228
src/Raw2Gltf.cpp
228
src/Raw2Gltf.cpp
|
@ -624,13 +624,15 @@ ModelData *Raw2Gltf(
|
|||
float emissiveIntensity;
|
||||
|
||||
const Vec3f dielectric(0.04f, 0.04f, 0.04f);
|
||||
const float epsilon = 1e-6f;
|
||||
|
||||
// acquire the texture of a specific RawTextureUsage as *TextData, or nullptr if none exists
|
||||
auto simpleTex = [&](RawTextureUsage usage) -> std::shared_ptr<TextureData> {
|
||||
return (material.textures[usage] >= 0) ? getSimpleTexture(material.textures[usage], "simple") : nullptr;
|
||||
};
|
||||
|
||||
TextureData *normalTexture = simpleTex(RAW_TEXTURE_USAGE_NORMAL).get();
|
||||
TextureData *emissiveTexture = simpleTex(RAW_TEXTURE_USAGE_EMISSIVE).get();
|
||||
|
||||
// acquire derived texture of two RawTextureUsage as *TextData, or nullptr if neither exists
|
||||
auto merge2Tex = [&](
|
||||
const std::string tag,
|
||||
|
@ -658,19 +660,6 @@ ModelData *Raw2Gltf(
|
|||
combine, tag, outputHasAlpha);
|
||||
};
|
||||
|
||||
auto getMaxComponent = [&](const Vec3f &color) {
|
||||
return fmax(color.x, fmax(color.y, color.z));
|
||||
};
|
||||
auto getPerceivedBrightness = [&](const Vec3f &color) {
|
||||
return sqrt(0.299 * color.x * color.x + 0.587 * color.y * color.y + 0.114 * color.z * color.z);
|
||||
};
|
||||
auto toVec3f = [&](const pixel &pix) -> const Vec3f {
|
||||
return Vec3f(pix[0], pix[1], pix[2]);
|
||||
};
|
||||
auto toVec4f = [&](const pixel &pix) -> const Vec4f {
|
||||
return Vec4f(pix[0], pix[1], pix[2], pix[3]);
|
||||
};
|
||||
|
||||
std::shared_ptr<PBRMetallicRoughness> pbrMetRough;
|
||||
if (options.usePBRMetRough) {
|
||||
// albedo is a basic texture, no merging needed
|
||||
|
@ -701,212 +690,25 @@ ModelData *Raw2Gltf(
|
|||
/**
|
||||
* Traditional FBX Material -> PBR Met/Rough glTF.
|
||||
*
|
||||
* Diffuse channel is used as base colour.
|
||||
* Diffuse channel is used as base colour. Simple constants for metallic and roughness.
|
||||
*/
|
||||
const RawTraditionalMatProps *props = ((RawTraditionalMatProps *) material.info.get());
|
||||
diffuseFactor = props->diffuseFactor;
|
||||
// TODO: make configurable on the command line, or do a better job guessing from other, supplied params
|
||||
if (material.info->shadingModel == RAW_SHADING_MODEL_LAMBERT) {
|
||||
metallic = 0.6f;
|
||||
roughness = 1.0f;
|
||||
} else {
|
||||
metallic = 0.2f;
|
||||
roughness = 0.8f;
|
||||
} else {
|
||||
metallic = 0.4f;
|
||||
roughness = 0.6f;
|
||||
}
|
||||
auto solveMetallic = [&](float pDiff, float pSpec, float oneMinusSpecularStrength)
|
||||
{
|
||||
if (pSpec < dielectric.x) {
|
||||
return 0.0;
|
||||
}
|
||||
baseColorTex = simpleTex(RAW_TEXTURE_USAGE_DIFFUSE);
|
||||
|
||||
float a = dielectric.x;
|
||||
float b = pDiff * oneMinusSpecularStrength / (1 - dielectric.x) + pSpec - 2 * dielectric.x;
|
||||
float c = dielectric.x - pSpec;
|
||||
float D = fmax(b * b - 4 * a * c, 0);
|
||||
return fmax(0.0, fmin(1.0, (-b + sqrt(D)) / (2 * a)));
|
||||
};
|
||||
metRoughTex = merge3Tex("rough_met",
|
||||
RAW_TEXTURE_USAGE_SPECULAR, RAW_TEXTURE_USAGE_SHININESS, RAW_TEXTURE_USAGE_DIFFUSE,
|
||||
[&](const std::vector<const pixel *> pixels) -> pixel {
|
||||
const Vec3f specular = Vec3f(0.4f, 0.4f, 0.4f) +
|
||||
0.2f * (pixels[0] ? toVec3f(*pixels[0]) : props->specularFactor);
|
||||
float shininess = pixels[1] ? (*pixels[1])[0] : props->shininess;
|
||||
const Vec4f diffuse = pixels[2] ? toVec4f(*pixels[2]) : props->diffuseFactor;
|
||||
|
||||
float pixelMet = solveMetallic(
|
||||
getPerceivedBrightness(diffuse.xyz()),
|
||||
getPerceivedBrightness(specular),
|
||||
1 - getMaxComponent(specular));
|
||||
float pixelRough = 1 - shininess;
|
||||
|
||||
return { 0, pixelRough, pixelMet, 0 };
|
||||
}, false);
|
||||
if (material.textures[RAW_TEXTURE_USAGE_DIFFUSE] >= 0) {
|
||||
const RawTexture &diffuseTex = raw.GetTexture(material.textures[RAW_TEXTURE_USAGE_DIFFUSE]);
|
||||
baseColorTex = merge2Tex("base_col", RAW_TEXTURE_USAGE_DIFFUSE, RAW_TEXTURE_USAGE_SPECULAR,
|
||||
[&](const std::vector<const pixel *> pixels) -> pixel {
|
||||
const Vec4f diffuse = pixels[0] ? toVec4f(*pixels[0]) : props->diffuseFactor;
|
||||
const Vec3f specular = Vec3f(0.4f, 0.4f, 0.4f) +
|
||||
0.2f * (pixels[1] ? toVec3f(*pixels[1]) : props->specularFactor);
|
||||
|
||||
float oneMinus = 1 - getMaxComponent(specular);
|
||||
|
||||
float pixelMet = solveMetallic(
|
||||
getPerceivedBrightness(diffuse.xyz()),
|
||||
getPerceivedBrightness(specular),
|
||||
oneMinus);
|
||||
|
||||
Vec3f fromDiffuse = diffuse.xyz() * (oneMinus / (1.0f - dielectric.x) / fmax(1.0f - pixelMet, epsilon));
|
||||
Vec3f fromSpecular = specular - dielectric * (1.0f - pixelMet) * (1.0f / fmax(pixelMet, epsilon));
|
||||
Vec3f baseColor = Vec3f::Lerp(fromDiffuse, fromSpecular, pixelMet * pixelMet);
|
||||
|
||||
return { baseColor[0], baseColor[1], baseColor[2], diffuse[3] };
|
||||
}, diffuseTex.occlusion == RAW_TEXTURE_OCCLUSION_TRANSPARENT);
|
||||
}
|
||||
emissiveFactor = props->emissiveFactor;
|
||||
emissiveIntensity = 1.0f;
|
||||
}
|
||||
pbrMetRough.reset(new PBRMetallicRoughness(baseColorTex.get(), metRoughTex.get(), diffuseFactor, metallic, roughness));
|
||||
}
|
||||
|
||||
std::shared_ptr<PBRSpecularGlossiness> pbrSpecGloss;
|
||||
if (options.usePBRSpecGloss) {
|
||||
Vec4f diffuseFactor;
|
||||
Vec3f specularFactor;
|
||||
float glossiness;
|
||||
std::shared_ptr<TextureData> specGlossTex;
|
||||
std::shared_ptr<TextureData> diffuseTex;
|
||||
|
||||
const Vec3f dielectric(0.04f, 0.04f, 0.04f);
|
||||
const float epsilon = 1e-6f;
|
||||
if (material.info->shadingModel == RAW_SHADING_MODEL_PBR_MET_ROUGH) {
|
||||
/**
|
||||
* PBR FBX Material -> PBR Spec/Gloss glTF.
|
||||
*
|
||||
* TODO: A complete mess. Low priority.
|
||||
*/
|
||||
RawMetRoughMatProps *props = (RawMetRoughMatProps *) material.info.get();
|
||||
// we can estimate spec/gloss from met/rough by between Vec4f(0.04, 0.04, 0.04) and baseColor
|
||||
// according to metalness, and then taking gloss to be the inverse of roughness
|
||||
specGlossTex = merge3Tex("specgloss",
|
||||
RAW_TEXTURE_USAGE_ALBEDO, RAW_TEXTURE_USAGE_METALLIC, RAW_TEXTURE_USAGE_ROUGHNESS,
|
||||
[&](const std::vector<const pixel *> pixels) -> pixel {
|
||||
Vec3f baseColor(1.0f);
|
||||
if (pixels[0]) {
|
||||
baseColor.x = (*pixels[0])[0];
|
||||
baseColor.y = (*pixels[0])[1];
|
||||
baseColor.z = (*pixels[0])[2];
|
||||
}
|
||||
float metallic = pixels[1] ? (*pixels[1])[0] : 1.0f;
|
||||
float roughness = pixels[2] ? (*pixels[2])[0] : 1.0f;
|
||||
Vec3f spec = Vec3f::Lerp(dielectric, baseColor, metallic);
|
||||
return { spec[0], spec[1], spec[2], 1.0f - roughness };
|
||||
}, false);
|
||||
diffuseTex = merge2Tex("albedo",
|
||||
RAW_TEXTURE_USAGE_ALBEDO, RAW_TEXTURE_USAGE_METALLIC,
|
||||
[&](const std::vector<const pixel *> pixels) -> pixel {
|
||||
Vec3f baseColor(1.0f);
|
||||
float alpha = 1.0f;
|
||||
if (pixels[0]) {
|
||||
baseColor[0] = (*pixels[0])[0];
|
||||
baseColor[1] = (*pixels[0])[1];
|
||||
baseColor[2] = (*pixels[0])[2];
|
||||
alpha = (*pixels[0])[3];
|
||||
}
|
||||
float metallic = pixels[1] ? (*pixels[1])[0] : 1.0f;
|
||||
Vec3f spec = Vec3f::Lerp(dielectric, baseColor, metallic);
|
||||
float maxSpecComp = fmax(fmax(spec.x, spec.y), spec.z);
|
||||
// attenuate baseColor to get specgloss-compliant diffuse; for details consult
|
||||
// https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_pbrSpecularGlossiness
|
||||
Vec3f diffuse = baseColor * (1 - dielectric[0]) * (1 - metallic) * fmax(1.0f - maxSpecComp, epsilon);
|
||||
return { diffuse[0], diffuse[1], diffuse[2], alpha };
|
||||
}, true);
|
||||
diffuseFactor = props->diffuseFactor;
|
||||
specularFactor = Vec3f::Lerp(dielectric, props->diffuseFactor.xyz(), props->metallic);
|
||||
glossiness = 1.0f - props->roughness;
|
||||
|
||||
} else {
|
||||
/**
|
||||
* Traditional FBX Material -> PBR Spec/Gloss glTF.
|
||||
*
|
||||
* TODO: A complete mess. Low priority.
|
||||
*/
|
||||
// TODO: this section a ludicrous over-simplifictation; we can surely do better.
|
||||
const RawTraditionalMatProps *props = ((RawTraditionalMatProps *) material.info.get());
|
||||
specGlossTex = merge2Tex("specgloss",
|
||||
RAW_TEXTURE_USAGE_SPECULAR, RAW_TEXTURE_USAGE_SHININESS,
|
||||
[&](const std::vector<const pixel *> pixels) -> pixel {
|
||||
const auto &spec = *(pixels[0]);
|
||||
const auto &shine = *(pixels[1]);
|
||||
return { spec[0], spec[1], spec[2], shine[0] };
|
||||
}, false);
|
||||
diffuseTex = simpleTex(RAW_TEXTURE_USAGE_DIFFUSE);
|
||||
diffuseFactor = props->diffuseFactor;
|
||||
specularFactor = props->specularFactor;
|
||||
glossiness = props->shininess;
|
||||
}
|
||||
|
||||
pbrSpecGloss.reset(
|
||||
new PBRSpecularGlossiness(
|
||||
diffuseTex.get(), diffuseFactor, specGlossTex.get(), specularFactor, glossiness));
|
||||
}
|
||||
|
||||
TextureData *normalTexture = simpleTex(RAW_TEXTURE_USAGE_NORMAL).get();
|
||||
TextureData *emissiveTexture = simpleTex(RAW_TEXTURE_USAGE_EMISSIVE).get();
|
||||
|
||||
std::shared_ptr<KHRCommonMats> khrComMat;
|
||||
if (options.useKHRMatCom) {
|
||||
float shininess;
|
||||
Vec3f ambientFactor, specularFactor;
|
||||
Vec4f diffuseFactor;
|
||||
std::shared_ptr<TextureData> diffuseTex;
|
||||
auto type = KHRCommonMats::MaterialType::Constant;
|
||||
|
||||
if (material.info->shadingModel == RAW_SHADING_MODEL_PBR_MET_ROUGH) {
|
||||
/**
|
||||
* PBR FBX Material -> KHR Common Materials glTF.
|
||||
*
|
||||
* TODO: We can use the specularFactor calculation below to generate a reasonable specular map, too.
|
||||
*/
|
||||
const RawMetRoughMatProps *props = (RawMetRoughMatProps *) material.info.get();
|
||||
shininess = 1.0f - props->roughness;
|
||||
ambientFactor = Vec3f(0.0f, 0.0f, 0.0f);
|
||||
diffuseTex = simpleTex(RAW_TEXTURE_USAGE_ALBEDO);
|
||||
diffuseFactor = props->diffuseFactor;
|
||||
specularFactor = Vec3f::Lerp(Vec3f(0.04f, 0.04f, 0.04f), props->diffuseFactor.xyz(), props->metallic);
|
||||
// render as Phong if there's any specularity, otherwise Lambert
|
||||
type = (specularFactor.LengthSquared() > 1e-4) ?
|
||||
KHRCommonMats::MaterialType::Phong : KHRCommonMats::MaterialType::Lambert;
|
||||
// TODO: convert textures
|
||||
|
||||
} else {
|
||||
/**
|
||||
* Traditional FBX Material -> KHR Common Materials glTF.
|
||||
*
|
||||
* Should be in good shape. Essentially pass-through.
|
||||
*/
|
||||
const RawTraditionalMatProps *props = (RawTraditionalMatProps *) material.info.get();
|
||||
shininess = props->shininess;
|
||||
ambientFactor = props->ambientFactor;
|
||||
diffuseTex = simpleTex(RAW_TEXTURE_USAGE_DIFFUSE);
|
||||
diffuseFactor = props->diffuseFactor;
|
||||
specularFactor = props->specularFactor;
|
||||
|
||||
if (material.info->shadingModel == RAW_SHADING_MODEL_LAMBERT) {
|
||||
type = KHRCommonMats::MaterialType::Lambert;
|
||||
} else if (material.info->shadingModel == RAW_SHADING_MODEL_BLINN) {
|
||||
type = KHRCommonMats::MaterialType::Blinn;
|
||||
} else if (material.info->shadingModel == RAW_SHADING_MODEL_PHONG) {
|
||||
type = KHRCommonMats::MaterialType::Phong;
|
||||
}
|
||||
}
|
||||
khrComMat.reset(
|
||||
new KHRCommonMats(type,
|
||||
simpleTex(RAW_TEXTURE_USAGE_SHININESS).get(), shininess,
|
||||
simpleTex(RAW_TEXTURE_USAGE_AMBIENT).get(), ambientFactor,
|
||||
diffuseTex.get(), diffuseFactor,
|
||||
simpleTex(RAW_TEXTURE_USAGE_SPECULAR).get(), specularFactor));
|
||||
}
|
||||
|
||||
std::shared_ptr<KHRCmnUnlitMaterial> khrCmnUnlitMat;
|
||||
if (options.useKHRMatUnlit) {
|
||||
|
@ -938,7 +740,7 @@ ModelData *Raw2Gltf(
|
|||
material.name, isTransparent,
|
||||
normalTexture, emissiveTexture,
|
||||
emissiveFactor * emissiveIntensity,
|
||||
khrComMat, khrCmnUnlitMat, pbrMetRough, pbrSpecGloss));
|
||||
khrCmnUnlitMat, pbrMetRough));
|
||||
materialsByName[materialHash(material)] = mData;
|
||||
}
|
||||
|
||||
|
@ -1209,21 +1011,9 @@ ModelData *Raw2Gltf(
|
|||
|
||||
{
|
||||
std::vector<std::string> extensionsUsed, extensionsRequired;
|
||||
if (options.useKHRMatCom) {
|
||||
extensionsUsed.push_back(KHR_MATERIALS_COMMON);
|
||||
if (!options.usePBRSpecGloss && !options.usePBRMetRough) {
|
||||
extensionsRequired.push_back(KHR_MATERIALS_COMMON);
|
||||
}
|
||||
}
|
||||
if (options.useKHRMatUnlit) {
|
||||
extensionsUsed.push_back(KHR_MATERIALS_CMN_UNLIT);
|
||||
}
|
||||
if (options.usePBRSpecGloss) {
|
||||
extensionsUsed.push_back(KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS);
|
||||
if (!options.useKHRMatCom && !options.usePBRMetRough) {
|
||||
extensionsRequired.push_back(KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS);
|
||||
}
|
||||
}
|
||||
if (options.useDraco) {
|
||||
extensionsUsed.push_back(KHR_DRACO_MESH_COMPRESSION);
|
||||
extensionsRequired.push_back(KHR_DRACO_MESH_COMPRESSION);
|
||||
|
|
|
@ -28,12 +28,10 @@ using json = nlohmann::basic_json<workaround_fifo_map>;
|
|||
#include "FBX2glTF.h"
|
||||
#include "RawModel.h"
|
||||
|
||||
static const std::string KHR_DRACO_MESH_COMPRESSION = "KHR_draco_mesh_compression";
|
||||
static const std::string KHR_MATERIALS_COMMON = "KHR_materials_common";
|
||||
static const std::string KHR_MATERIALS_CMN_UNLIT = "KHR_materials_unlit";
|
||||
static const std::string KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS = "KHR_materials_pbrSpecularGlossiness";
|
||||
const std::string KHR_DRACO_MESH_COMPRESSION = "KHR_draco_mesh_compression";
|
||||
const std::string KHR_MATERIALS_CMN_UNLIT = "KHR_materials_unlit";
|
||||
|
||||
static const std::string extBufferFilename = "buffer.bin";
|
||||
const std::string extBufferFilename = "buffer.bin";
|
||||
|
||||
struct ComponentType {
|
||||
// OpenGL Datatype enums
|
||||
|
@ -52,8 +50,8 @@ struct ComponentType {
|
|||
const unsigned int size;
|
||||
};
|
||||
|
||||
static const ComponentType CT_USHORT = {ComponentType::GL_UNSIGNED_SHORT, 2};
|
||||
static const ComponentType CT_FLOAT = {ComponentType::GL_FLOAT, 4};
|
||||
const ComponentType CT_USHORT = {ComponentType::GL_UNSIGNED_SHORT, 2};
|
||||
const ComponentType CT_FLOAT = {ComponentType::GL_FLOAT, 4};
|
||||
|
||||
// Map our low-level data types for glTF output
|
||||
struct GLType {
|
||||
|
@ -101,16 +99,16 @@ struct GLType {
|
|||
const std::string dataType;
|
||||
};
|
||||
|
||||
static const GLType GLT_FLOAT = {CT_FLOAT, 1, "SCALAR"};
|
||||
static const GLType GLT_USHORT = {CT_USHORT, 1, "SCALAR"};
|
||||
static const GLType GLT_VEC2F = {CT_FLOAT, 2, "VEC2"};
|
||||
static const GLType GLT_VEC3F = {CT_FLOAT, 3, "VEC3"};
|
||||
static const GLType GLT_VEC4F = {CT_FLOAT, 4, "VEC4"};
|
||||
static const GLType GLT_VEC4I = {CT_USHORT, 4, "VEC4"};
|
||||
static const GLType GLT_MAT2F = {CT_USHORT, 4, "MAT2"};
|
||||
static const GLType GLT_MAT3F = {CT_USHORT, 9, "MAT3"};
|
||||
static const GLType GLT_MAT4F = {CT_FLOAT, 16, "MAT4"};
|
||||
static const GLType GLT_QUATF = {CT_FLOAT, 4, "VEC4"};
|
||||
const GLType GLT_FLOAT = {CT_FLOAT, 1, "SCALAR"};
|
||||
const GLType GLT_USHORT = {CT_USHORT, 1, "SCALAR"};
|
||||
const GLType GLT_VEC2F = {CT_FLOAT, 2, "VEC2"};
|
||||
const GLType GLT_VEC3F = {CT_FLOAT, 3, "VEC3"};
|
||||
const GLType GLT_VEC4F = {CT_FLOAT, 4, "VEC4"};
|
||||
const GLType GLT_VEC4I = {CT_USHORT, 4, "VEC4"};
|
||||
const GLType GLT_MAT2F = {CT_USHORT, 4, "MAT2"};
|
||||
const GLType GLT_MAT3F = {CT_USHORT, 9, "MAT3"};
|
||||
const GLType GLT_MAT4F = {CT_FLOAT, 16, "MAT4"};
|
||||
const GLType GLT_QUATF = {CT_FLOAT, 4, "VEC4"};
|
||||
|
||||
/**
|
||||
* The base of any indexed glTF entity.
|
||||
|
|
|
@ -337,6 +337,8 @@ void RawModel::TransformGeometry(ComputeNormalsOption normals)
|
|||
case BROKEN:
|
||||
case ALWAYS:
|
||||
size_t computedNormalsCount = this->CalculateNormals(normals == ComputeNormalsOption::BROKEN);
|
||||
vertexAttributes |= RAW_VERTEX_ATTRIBUTE_NORMAL;
|
||||
|
||||
if (verboseOutput) {
|
||||
if (normals == ComputeNormalsOption::BROKEN) {
|
||||
fmt::printf("Repaired %lu empty normals.\n", computedNormalsCount);
|
||||
|
@ -572,13 +574,18 @@ Vec3f RawModel::getFaceNormal(int verts[3]) const
|
|||
|
||||
const Vec3f e0 = vertices[verts[(index + 1) % 3]].position - vertices[verts[index]].position;
|
||||
const Vec3f e1 = vertices[verts[(index + 2) % 3]].position - vertices[verts[index]].position;
|
||||
|
||||
auto result = Vec3f::CrossProduct(e0, e1);
|
||||
if (result.LengthSquared() < FLT_MIN) {
|
||||
if (e0.LengthSquared() < FLT_MIN || e1.LengthSquared() < FLT_MIN) {
|
||||
return Vec3f { 0.0f };
|
||||
}
|
||||
result.Normalize();
|
||||
return result;
|
||||
auto result = Vec3f::CrossProduct(e0, e1);
|
||||
auto resultLengthSquared = result.LengthSquared();
|
||||
if (resultLengthSquared < FLT_MIN) {
|
||||
return Vec3f { 0.0f };
|
||||
}
|
||||
float edgeDot = std::max(-1.0f, std::min(1.0f, Vec3f::DotProduct(e0, e1)));
|
||||
float angle = acos(edgeDot);
|
||||
float area = resultLengthSquared / 2.0f;
|
||||
return result.Normalized() * angle * area;
|
||||
}
|
||||
|
||||
size_t RawModel::CalculateNormals(bool onlyBroken)
|
||||
|
|
|
@ -42,14 +42,10 @@ struct GltfOptions
|
|||
bool embedResources { false };
|
||||
/** Whether to use KHR_draco_mesh_compression to minimize static geometry size. */
|
||||
bool useDraco { false };
|
||||
/** Whether to use KHR_materials_common to extend materials definitions. */
|
||||
bool useKHRMatCom { false };
|
||||
/** Whether to use KHR_materials_unlit to extend materials definitions. */
|
||||
bool useKHRMatUnlit { false };
|
||||
/** Whether to populate the pbrMetallicRoughness substruct in materials. */
|
||||
bool usePBRMetRough { false };
|
||||
/** Whether to use KHR_materials_pbrSpecularGlossiness to extend material definitions. */
|
||||
bool usePBRSpecGloss { false };
|
||||
/** Whether to include blend shape normals, if present according to the SDK. */
|
||||
bool useBlendShapeNormals { false };
|
||||
/** Whether to include blend shape tangents, if present according to the SDK. */
|
||||
|
|
|
@ -27,72 +27,6 @@ void to_json(json &j, const Tex &data) {
|
|||
};
|
||||
}
|
||||
|
||||
static inline Vec4f toRGBA(const Vec3f &colour, float alpha = 1) {
|
||||
return { colour[0], colour[1], colour[2], alpha };
|
||||
};
|
||||
|
||||
KHRCommonMats::KHRCommonMats(
|
||||
MaterialType type,
|
||||
const TextureData *shininessTexture, float shininess,
|
||||
const TextureData *ambientTexture, const Vec3f &ambientFactor,
|
||||
const TextureData *diffuseTexture, const Vec4f &diffuseFactor,
|
||||
const TextureData *specularTexture, const Vec3f &specularFactor)
|
||||
: type(type),
|
||||
shininessTexture(Tex::ref(shininessTexture)),
|
||||
shininess(shininess),
|
||||
ambientTexture(Tex::ref(ambientTexture)),
|
||||
ambientFactor(ambientFactor),
|
||||
diffuseTexture(Tex::ref(diffuseTexture)),
|
||||
diffuseFactor(diffuseFactor),
|
||||
specularTexture(Tex::ref(specularTexture)),
|
||||
specularFactor(specularFactor)
|
||||
{
|
||||
}
|
||||
|
||||
std::string KHRCommonMats::typeDesc(MaterialType type)
|
||||
{
|
||||
switch (type) {
|
||||
case Blinn:
|
||||
return "commonBlinn";
|
||||
case Phong:
|
||||
return "commonPhong";
|
||||
case Lambert:
|
||||
return "commonLambert";
|
||||
case Constant:
|
||||
return "commonConstant";
|
||||
}
|
||||
}
|
||||
|
||||
void to_json(json &j, const KHRCommonMats &d)
|
||||
{
|
||||
j = {{"type", KHRCommonMats::typeDesc(d.type)}};
|
||||
|
||||
if (d.shininessTexture != nullptr) {
|
||||
j["shininessTexture"] = *d.shininessTexture;
|
||||
}
|
||||
if (d.shininess != 0) {
|
||||
j["shininess"] = d.shininess;
|
||||
}
|
||||
if (d.ambientTexture != nullptr) {
|
||||
j["ambientTexture"] = *d.ambientTexture;
|
||||
}
|
||||
if (d.ambientFactor.LengthSquared() > 0) {
|
||||
j["ambientFactor"] = toStdVec(toRGBA(d.ambientFactor));
|
||||
}
|
||||
if (d.diffuseTexture != nullptr) {
|
||||
j["diffuseTexture"] = *d.diffuseTexture;
|
||||
}
|
||||
if (d.diffuseFactor.LengthSquared() > 0) {
|
||||
j["diffuseFactor"] = toStdVec(d.diffuseFactor);
|
||||
}
|
||||
if (d.specularTexture != nullptr) {
|
||||
j["specularTexture"] = *d.specularTexture;
|
||||
}
|
||||
if (d.specularFactor.LengthSquared() > 0) {
|
||||
j["specularFactor"] = toStdVec(toRGBA(d.specularFactor));
|
||||
}
|
||||
}
|
||||
|
||||
KHRCmnUnlitMaterial::KHRCmnUnlitMaterial()
|
||||
{
|
||||
}
|
||||
|
@ -102,38 +36,6 @@ void to_json(json &j, const KHRCmnUnlitMaterial &d)
|
|||
j = json({});
|
||||
}
|
||||
|
||||
PBRSpecularGlossiness::PBRSpecularGlossiness(
|
||||
const TextureData *diffuseTexture, const Vec4f &diffuseFactor,
|
||||
const TextureData *specularGlossinessTexture, const Vec3f &specularFactor,
|
||||
float glossinessFactor)
|
||||
: diffuseTexture(Tex::ref(diffuseTexture)),
|
||||
diffuseFactor(diffuseFactor),
|
||||
specularGlossinessTexture(Tex::ref(specularGlossinessTexture)),
|
||||
specularFactor(specularFactor),
|
||||
glossinessFactor(glossinessFactor)
|
||||
{
|
||||
}
|
||||
|
||||
void to_json(json &j, const PBRSpecularGlossiness &d)
|
||||
{
|
||||
j = {};
|
||||
if (d.diffuseTexture != nullptr) {
|
||||
j["diffuseTexture"] = *d.diffuseTexture;
|
||||
}
|
||||
if (d.diffuseFactor.LengthSquared() > 0) {
|
||||
j["diffuseFactor"] = toStdVec(d.diffuseFactor);
|
||||
}
|
||||
if (d.specularGlossinessTexture != nullptr) {
|
||||
j["specularGlossinessTexture"] = *d.specularGlossinessTexture;
|
||||
}
|
||||
if (d.specularFactor.LengthSquared() > 0) {
|
||||
j["specularFactor"] = toStdVec(d.specularFactor);
|
||||
}
|
||||
if (d.glossinessFactor != 0) {
|
||||
j["glossinessFactor"] = d.glossinessFactor;
|
||||
}
|
||||
}
|
||||
|
||||
PBRMetallicRoughness::PBRMetallicRoughness(
|
||||
const TextureData *baseColorTexture, const TextureData *metRoughTexture,
|
||||
const Vec4f &baseColorFactor, float metallic, float roughness)
|
||||
|
@ -169,20 +71,16 @@ void to_json(json &j, const PBRMetallicRoughness &d)
|
|||
MaterialData::MaterialData(
|
||||
std::string name, bool isTransparent, const TextureData *normalTexture,
|
||||
const TextureData *emissiveTexture, const Vec3f & emissiveFactor,
|
||||
std::shared_ptr<KHRCommonMats> const khrCommonMats,
|
||||
std::shared_ptr<KHRCmnUnlitMaterial> const khrCmnConstantMaterial,
|
||||
std::shared_ptr<PBRMetallicRoughness> const pbrMetallicRoughness,
|
||||
std::shared_ptr<PBRSpecularGlossiness> const pbrSpecularGlossiness)
|
||||
std::shared_ptr<PBRMetallicRoughness> const pbrMetallicRoughness)
|
||||
: Holdable(),
|
||||
name(std::move(name)),
|
||||
isTransparent(isTransparent),
|
||||
normalTexture(Tex::ref(normalTexture)),
|
||||
emissiveTexture(Tex::ref(emissiveTexture)),
|
||||
emissiveFactor(std::move(emissiveFactor)),
|
||||
khrCommonMats(khrCommonMats),
|
||||
emissiveFactor(emissiveFactor),
|
||||
khrCmnConstantMaterial(khrCmnConstantMaterial),
|
||||
pbrMetallicRoughness(pbrMetallicRoughness),
|
||||
pbrSpecularGlossiness(pbrSpecularGlossiness) {}
|
||||
pbrMetallicRoughness(pbrMetallicRoughness) {}
|
||||
|
||||
json MaterialData::serialize() const
|
||||
{
|
||||
|
@ -203,18 +101,9 @@ json MaterialData::serialize() const
|
|||
if (pbrMetallicRoughness != nullptr) {
|
||||
result["pbrMetallicRoughness"] = *pbrMetallicRoughness;
|
||||
}
|
||||
if (khrCommonMats != nullptr || khrCmnConstantMaterial != nullptr || pbrSpecularGlossiness != nullptr) {
|
||||
if (khrCmnConstantMaterial != nullptr) {
|
||||
json extensions = { };
|
||||
if (khrCommonMats != nullptr) {
|
||||
extensions[KHR_MATERIALS_COMMON] = *khrCommonMats;
|
||||
}
|
||||
if (khrCmnConstantMaterial != nullptr) {
|
||||
extensions[KHR_MATERIALS_CMN_UNLIT] = *khrCmnConstantMaterial;
|
||||
}
|
||||
if (pbrSpecularGlossiness != nullptr) {
|
||||
extensions[KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS] = *pbrSpecularGlossiness;
|
||||
}
|
||||
|
||||
extensions[KHR_MATERIALS_CMN_UNLIT] = *khrCmnConstantMaterial;
|
||||
result["extensions"] = extensions;
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -23,55 +23,11 @@ struct Tex
|
|||
const uint32_t texCoord;
|
||||
};
|
||||
|
||||
struct KHRCommonMats
|
||||
{
|
||||
enum MaterialType
|
||||
{
|
||||
Blinn,
|
||||
Phong,
|
||||
Lambert,
|
||||
Constant,
|
||||
};
|
||||
|
||||
KHRCommonMats(
|
||||
MaterialType type,
|
||||
const TextureData *shininessTexture, float shininess,
|
||||
const TextureData *ambientTexture, const Vec3f &ambientFactor,
|
||||
const TextureData *diffuseTexture, const Vec4f &diffuseFactor,
|
||||
const TextureData *specularTexture, const Vec3f &specularFactor);
|
||||
|
||||
static std::string typeDesc(MaterialType type);
|
||||
|
||||
const MaterialType type;
|
||||
const std::unique_ptr<Tex> shininessTexture;
|
||||
const float shininess;
|
||||
const std::unique_ptr<Tex> ambientTexture;
|
||||
const Vec3f ambientFactor;
|
||||
const std::unique_ptr<Tex> diffuseTexture;
|
||||
const Vec4f diffuseFactor;
|
||||
const std::unique_ptr<Tex> specularTexture;
|
||||
const Vec3f specularFactor;
|
||||
};
|
||||
|
||||
struct KHRCmnUnlitMaterial
|
||||
{
|
||||
KHRCmnUnlitMaterial();
|
||||
};
|
||||
|
||||
struct PBRSpecularGlossiness
|
||||
{
|
||||
PBRSpecularGlossiness(
|
||||
const TextureData *diffuseTexture, const Vec4f &diffuseFactor,
|
||||
const TextureData *specularGlossinessTexture,
|
||||
const Vec3f &specularFactor, float glossinessFactor);
|
||||
|
||||
std::unique_ptr<Tex> diffuseTexture;
|
||||
const Vec4f diffuseFactor;
|
||||
std::unique_ptr<Tex> specularGlossinessTexture;
|
||||
const Vec3f specularFactor;
|
||||
const float glossinessFactor;
|
||||
};
|
||||
|
||||
struct PBRMetallicRoughness
|
||||
{
|
||||
PBRMetallicRoughness(
|
||||
|
@ -90,10 +46,8 @@ struct MaterialData : Holdable
|
|||
MaterialData(
|
||||
std::string name, bool isTransparent, const TextureData *normalTexture,
|
||||
const TextureData *emissiveTexture, const Vec3f &emissiveFactor,
|
||||
std::shared_ptr<KHRCommonMats> const khrCommonMats,
|
||||
std::shared_ptr<KHRCmnUnlitMaterial> const khrCmnConstantMaterial,
|
||||
std::shared_ptr<PBRMetallicRoughness> const pbrMetallicRoughness,
|
||||
std::shared_ptr<PBRSpecularGlossiness> const pbrSpecularGlossiness);
|
||||
std::shared_ptr<PBRMetallicRoughness> const pbrMetallicRoughness);
|
||||
|
||||
json serialize() const override;
|
||||
|
||||
|
@ -103,16 +57,12 @@ struct MaterialData : Holdable
|
|||
const std::unique_ptr<const Tex> emissiveTexture;
|
||||
const Vec3f emissiveFactor;
|
||||
|
||||
const std::shared_ptr<const KHRCommonMats> khrCommonMats;
|
||||
const std::shared_ptr<const KHRCmnUnlitMaterial> khrCmnConstantMaterial;
|
||||
const std::shared_ptr<const KHRCmnUnlitMaterial> khrCmnConstantMaterial;
|
||||
const std::shared_ptr<const PBRMetallicRoughness> pbrMetallicRoughness;
|
||||
const std::shared_ptr<const PBRSpecularGlossiness> pbrSpecularGlossiness;
|
||||
};
|
||||
|
||||
void to_json(json &j, const Tex &data);
|
||||
void to_json(json &j, const KHRCommonMats &d);
|
||||
void to_json(json &j, const KHRCmnUnlitMaterial &d);
|
||||
void to_json(json &j, const PBRSpecularGlossiness &d);
|
||||
void to_json(json &j, const PBRMetallicRoughness &d);
|
||||
|
||||
#endif //FBX2GLTF_MATERIALDATA_H
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "utils/String_Utils.h"
|
||||
#include "utils/File_Utils.h"
|
||||
#include "Fbx2Raw.h"
|
||||
#include "RawModel.h"
|
||||
#include "Raw2Gltf.h"
|
||||
|
||||
bool verboseOutput = false;
|
||||
|
@ -70,12 +69,6 @@ int main(int argc, char *argv[])
|
|||
(
|
||||
"khr-materials-unlit", "Use KHR_materials_unlit extension to specify Unlit shader.",
|
||||
cxxopts::value<bool>(gltfOptions.useKHRMatUnlit))
|
||||
(
|
||||
"khr-materials-common", "(WIP) Use KHR_materials_common extensions to specify Lambert/Blinn/Phong shaders.",
|
||||
cxxopts::value<bool>(gltfOptions.useKHRMatCom))
|
||||
(
|
||||
"pbr-specular-glossiness", "(WIP) Experimentally fill in the KHR_materials_pbrSpecularGlossiness extension.",
|
||||
cxxopts::value<bool>(gltfOptions.usePBRSpecGloss))
|
||||
(
|
||||
"blend-shape-normals", "Include blend shape normals, if reported present by the FBX SDK.",
|
||||
cxxopts::value<bool>(gltfOptions.useBlendShapeNormals))
|
||||
|
@ -125,7 +118,7 @@ Copyright (c) 2016-2017 Oculus VR, LLC.
|
|||
verboseOutput = true;
|
||||
}
|
||||
|
||||
if (!gltfOptions.useKHRMatUnlit && !gltfOptions.useKHRMatCom && !gltfOptions.usePBRSpecGloss && !gltfOptions.usePBRMetRough) {
|
||||
if (!gltfOptions.useKHRMatUnlit && !gltfOptions.usePBRMetRough) {
|
||||
if (verboseOutput) {
|
||||
fmt::printf("Defaulting to --pbr-metallic-roughness material support.\n");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue