Skip to content

Commit

Permalink
Use fallback textures for base color when no diffuse is given
Browse files Browse the repository at this point in the history
  • Loading branch information
javagl committed Feb 9, 2024
1 parent adcfeff commit fe58a4b
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 68 deletions.
137 changes: 69 additions & 68 deletions lib/updateVersion.js
Original file line number Diff line number Diff line change
Expand Up @@ -1084,87 +1084,88 @@ function convertTechniquesToPbr(gltf, options) {
removeExtension(gltf, "KHR_blend");
}

function assignAsBaseColor(material, baseColor) {
if (defined(baseColor)) {
if (isVec4(baseColor)) {
material.pbrMetallicRoughness.baseColorFactor = srgbToLinear(baseColor);
} else if (isTexture(baseColor)) {
material.pbrMetallicRoughness.baseColorTexture = baseColor;
}
}
}

function assignAsEmissive(material, emissive) {
if (defined(emissive)) {
if (isVec4(emissive)) {
material.emissiveFactor = emissive.slice(0, 3);
} else if (isTexture(emissive)) {
material.emissiveTexture = emissive;
}
}
}

function convertMaterialsCommonToPbr(gltf) {
// Future work: convert KHR_materials_common lights to KHR_lights_punctual
ForEach.material(gltf, function (material) {
const materialsCommon = defaultValue(
material.extensions,
defaultValue.EMPTY_OBJECT,
).KHR_materials_common;
if (!defined(materialsCommon)) {
// Nothing to do
return;
}

if (defined(materialsCommon)) {
const technique = materialsCommon.technique;
if (technique === "CONSTANT") {
// Add the KHR_materials_unlit extension
addExtensionsUsed(gltf, "KHR_materials_unlit");
material.extensions = defined(material.extensions)
? material.extensions
: {};
material.extensions["KHR_materials_unlit"] = {};
}

const values = defined(materialsCommon.values)
? materialsCommon.values
const values = defaultValue(materialsCommon.values, {});
const ambient = values.ambient;
const diffuse = values.diffuse;
const emission = values.emission;
const transparency = values.transparency;

// These actually exist on the extension object, not the values object despite what's shown in the spec
const doubleSided = materialsCommon.doubleSided;
const transparent = materialsCommon.transparent;

// Ignore specular and shininess for now because the conversion to PBR
// isn't straightforward and depends on the technique
initializePbrMaterial(material);

const technique = materialsCommon.technique;
if (technique === "CONSTANT") {
// Add the KHR_materials_unlit extension
addExtensionsUsed(gltf, "KHR_materials_unlit");
material.extensions = defined(material.extensions)
? material.extensions
: {};
material.extensions["KHR_materials_unlit"] = {};

const ambient = values.ambient;
const diffuse = values.diffuse;
const emission = values.emission;
const transparency = values.transparency;

// These actually exist on the extension object, not the values object despite what's shown in the spec
const doubleSided = materialsCommon.doubleSided;
const transparent = materialsCommon.transparent;

// Ignore specular and shininess for now because the conversion to PBR
// isn't straightforward and depends on the technique
initializePbrMaterial(material);

if (defined(ambient)) {
if (isVec4(ambient)) {
material.emissiveFactor = ambient.slice(0, 3);
} else if (isTexture(ambient)) {
material.emissiveTexture = ambient;
}
}

if (defined(diffuse)) {
if (isVec4(diffuse)) {
material.pbrMetallicRoughness.baseColorFactor = srgbToLinear(diffuse);
} else if (isTexture(diffuse)) {
material.pbrMetallicRoughness.baseColorTexture = diffuse;
}
}

if (defined(doubleSided)) {
material.doubleSided = doubleSided;
}

if (defined(emission)) {
if (isVec4(emission)) {
material.emissiveFactor = emission.slice(0, 3);
} else if (isTexture(emission)) {
material.emissiveTexture = emission;
}
}

if (defined(transparency)) {
if (defined(material.pbrMetallicRoughness.baseColorFactor)) {
material.pbrMetallicRoughness.baseColorFactor[3] *= transparency;
} else {
material.pbrMetallicRoughness.baseColorFactor = [
1,
1,
1,
transparency,
];
}
}
// The CONSTANT technique does not support 'diffuse', so
// assign either the 'emission' or the 'ambient' as the
// base color
assignAsBaseColor(material, emission);
assignAsBaseColor(material, ambient);
} else {
// Assign the 'diffuse' as the base color, and
// the 'ambient' or 'emissive' as the emissive
// part if they are present.
assignAsBaseColor(material, diffuse);
assignAsEmissive(material, ambient);
assignAsEmissive(material, emission);
}

if (defined(transparent)) {
material.alphaMode = transparent ? "BLEND" : "OPAQUE";
if (defined(doubleSided)) {
material.doubleSided = doubleSided;
}
if (defined(transparency)) {
if (defined(material.pbrMetallicRoughness.baseColorFactor)) {
material.pbrMetallicRoughness.baseColorFactor[3] *= transparency;
} else {
material.pbrMetallicRoughness.baseColorFactor = [1, 1, 1, transparency];
}
}
if (defined(transparent)) {
material.alphaMode = transparent ? "BLEND" : "OPAQUE";
}
});

removeExtension(gltf, "KHR_materials_common");
Expand Down
21 changes: 21 additions & 0 deletions specs/lib/updateVersionSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,27 @@ describe("updateVersion", () => {
expect(gltf.extensionsUsed.indexOf("KHR_materials_unlit") !== -1);
});

it("updates glTF 1.0 with KHR_materials_common with CONSTANT technique to PBR materials using emissive as the base color texture when diffuse is not present", async () => {
const gltf = fsExtra.readJsonSync(gltf1MaterialsCommonTextured);
await readResources(gltf, {
resourceDirectory: path.dirname(gltf1MaterialsCommonTextured),
});

const materialsCommon =
gltf.materials["Effect-Texture"].extensions.KHR_materials_common;
// Move the 'diffuse' texture definition into 'emission', and expect
// this to show up as the base color texture after the update
materialsCommon.values.emission = materialsCommon.values.diffuse;
delete materialsCommon.values.diffuse;
materialsCommon.technique = "CONSTANT";
updateVersion(gltf);

const material = gltf.materials[0];
expect(material.pbrMetallicRoughness.baseColorTexture).toBeDefined();
expect(material.extensions.KHR_materials_unlit).toBeDefined();
expect(gltf.extensionsUsed.indexOf("KHR_materials_unlit") !== -1);
});

it("updates glTF 1.0 with KHR_materials_common with other values to PBR materials", async () => {
const gltf = fsExtra.readJsonSync(gltf1MaterialsCommon);
await readResources(gltf, {
Expand Down

0 comments on commit fe58a4b

Please sign in to comment.