Fix for when specular and diffuse reference the same texture

This commit is contained in:
Sean Lilley 2019-10-26 19:03:32 -04:00
parent 8fa5bf9d24
commit d912e28571
10 changed files with 126 additions and 17 deletions

View File

@ -237,11 +237,10 @@ function addTexture(gltf, texture) {
function getTexture(gltf, texture) { function getTexture(gltf, texture) {
let textureIndex; let textureIndex;
const name = texture.name; const images = gltf.images;
const textures = gltf.textures; const length = images.length;
const length = textures.length;
for (let i = 0; i < length; ++i) { for (let i = 0; i < length; ++i) {
if (textures[i].name === name) { if (images[i].extras._obj2gltf === texture) {
textureIndex = i; textureIndex = i;
break; break;
} }

View File

@ -8,6 +8,7 @@ const readLines = require('./readLines');
const Texture = require('./Texture'); const Texture = require('./Texture');
const CesiumMath = Cesium.Math; const CesiumMath = Cesium.Math;
const clone = Cesium.clone;
const combine = Cesium.combine; const combine = Cesium.combine;
const defaultValue = Cesium.defaultValue; const defaultValue = Cesium.defaultValue;
const defined = Cesium.defined; const defined = Cesium.defined;
@ -178,13 +179,30 @@ function loadMtl(mtlPath, options) {
material.ambientTexture = undefined; material.ambientTexture = undefined;
} }
loadMaterialTexture(material, 'diffuseTexture', diffuseAlphaTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); const textureNames = ['diffuseTexture', 'ambientTexture', 'emissiveTexture', 'specularTexture', 'specularShininessTexture', 'normalTexture', 'alphaTexture'];
loadMaterialTexture(material, 'ambientTexture', ambientTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); const textureOptions = [diffuseAlphaTextureOptions, ambientTextureOptions, emissiveTextureOptions, specularTextureOptions, specularShinessTextureOptions, normalTextureOptions, alphaTextureOptions];
loadMaterialTexture(material, 'emissiveTexture', emissiveTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options);
loadMaterialTexture(material, 'specularTexture', specularTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); const sharedOptions = {};
loadMaterialTexture(material, 'specularShininessTexture', specularShinessTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); textureNames.forEach(function(name, index) {
loadMaterialTexture(material, 'normalTexture', normalTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); const texturePath = material[name];
loadMaterialTexture(material, 'alphaTexture', alphaTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); const originalOptions = textureOptions[index];
if (defined(texturePath) && defined(originalOptions)) {
if (!defined(sharedOptions[texturePath])) {
sharedOptions[texturePath] = clone(originalOptions);
}
const options = sharedOptions[texturePath];
options.checkTransparency = options.checkTransparency || originalOptions.checkTransparency;
options.decode = options.decode || originalOptions.decode;
options.keepSource = options.keepSource || !originalOptions.decode || !originalOptions.checkTransparency;
}
});
textureNames.forEach(function(name) {
const texturePath = material[name];
if (defined(texturePath)) {
loadMaterialTexture(material, name, sharedOptions[texturePath], mtlDirectory, texturePromiseMap, texturePromises, options);
}
});
} }
return readLines(mtlPath, parseLine) return readLines(mtlPath, parseLine)

View File

@ -19,6 +19,7 @@ module.exports = loadTexture;
* @param {Object} [options] An object with the following properties: * @param {Object} [options] An object with the following properties:
* @param {Boolean} [options.checkTransparency=false] Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel. * @param {Boolean} [options.checkTransparency=false] Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel.
* @param {Boolean} [options.decode=false] Whether to decode the texture. * @param {Boolean} [options.decode=false] Whether to decode the texture.
* @param {Boolean} [options.keepSource=false] Whether to keep the source image contents in memory.
* @returns {Promise} A promise resolving to a Texture object. * @returns {Promise} A promise resolving to a Texture object.
* *
* @private * @private
@ -27,6 +28,7 @@ function loadTexture(texturePath, options) {
options = defaultValue(options, {}); options = defaultValue(options, {});
options.checkTransparency = defaultValue(options.checkTransparency, false); options.checkTransparency = defaultValue(options.checkTransparency, false);
options.decode = defaultValue(options.decode, false); options.decode = defaultValue(options.decode, false);
options.keepSource = defaultValue(options.keepSource, false);
return fsExtra.readFile(texturePath) return fsExtra.readFile(texturePath)
.then(function(source) { .then(function(source) {
@ -46,7 +48,10 @@ function loadTexture(texturePath, options) {
} }
if (defined(decodePromise)) { if (defined(decodePromise)) {
return decodePromise.thenReturn(texture); return decodePromise
.then(function() {
return texture;
});
} }
return texture; return texture;
@ -109,7 +114,9 @@ function decodePng(texture, options) {
texture.pixels = decodedResults.data; texture.pixels = decodedResults.data;
texture.width = decodedResults.width; texture.width = decodedResults.width;
texture.height = decodedResults.height; texture.height = decodedResults.height;
texture.source = undefined; // Unload resources if (!options.keepSource) {
texture.source = undefined; // Unload resources
}
} }
}); });
} }
@ -122,6 +129,8 @@ function decodeJpeg(texture, options) {
texture.pixels = decodedResults.data; texture.pixels = decodedResults.data;
texture.width = decodedResults.width; texture.width = decodedResults.width;
texture.height = decodedResults.height; texture.height = decodedResults.height;
texture.source = undefined; // Unload resources if (!options.keepSource) {
texture.source = undefined; // Unload resources
}
} }
} }

View File

@ -0,0 +1,14 @@
# Blender MTL File: 'box.blend'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd cesium.png
map_Ke cesium.png

View File

@ -1,6 +1,6 @@
# Blender v2.78 (sub 0) OBJ File: 'box.blend' # Blender v2.78 (sub 0) OBJ File: 'box.blend'
# www.blender.org # www.blender.org
mtllib box-diffuse-ambient-same.mtl mtllib box-shared-textures-2.mtl
o Cube o Cube
v -1.000000 -1.000000 1.000000 v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000 v -1.000000 1.000000 1.000000

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -12,3 +12,4 @@ d 1.000000
illum 2 illum 2
map_Kd cesium.png map_Kd cesium.png
map_Ka cesium.png map_Ka cesium.png
map_Ks cesium.png

View File

@ -0,0 +1,46 @@
# Blender v2.78 (sub 0) OBJ File: 'box.blend'
# www.blender.org
mtllib box-shared-textures.mtl
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Material
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9/3 8/10/3 6/11/3 5/12/3
f 5/13/4 6/14/4 2/15/4 1/16/4
f 3/5/5 7/17/5 5/18/5 1/16/5
f 8/19/6 4/6/6 2/15/6 6/20/6

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -15,7 +15,8 @@ const externalMaterialPath = 'specs/data/box-external-resources/box-external-res
const resourcesInRootMaterialPath = 'specs/data/box-resources-in-root/box-resources-in-root.mtl'; const resourcesInRootMaterialPath = 'specs/data/box-resources-in-root/box-resources-in-root.mtl';
const externalInRootMaterialPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.mtl'; const externalInRootMaterialPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.mtl';
const transparentMaterialPath = 'specs/data/box-transparent/box-transparent.mtl'; const transparentMaterialPath = 'specs/data/box-transparent/box-transparent.mtl';
const diffuseAmbientSameMaterialPath = 'specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.mtl'; const sharedTexturesMaterialPath = 'specs/data/box-shared-textures/box-shared-textures.mtl';
const sharedTexturesMaterial2Path = 'specs/data/box-shared-textures-2/box-shared-textures-2.mtl';
const diffuseTexturePath = 'specs/data/box-textured/cesium.png'; const diffuseTexturePath = 'specs/data/box-textured/cesium.png';
const transparentDiffuseTexturePath = 'specs/data/box-complex-material/diffuse.png'; const transparentDiffuseTexturePath = 'specs/data/box-complex-material/diffuse.png';
@ -204,7 +205,7 @@ describe('loadMtl', () => {
}); });
it('ambient texture is ignored if it is the same as the diffuse texture', async () => { it('ambient texture is ignored if it is the same as the diffuse texture', async () => {
const materials = await loadMtl(diffuseAmbientSameMaterialPath, options); const materials = await loadMtl(sharedTexturesMaterialPath, options);
expect(materials.length).toBe(1); expect(materials.length).toBe(1);
const material = materials[0]; const material = materials[0];
const pbr = material.pbrMetallicRoughness; const pbr = material.pbrMetallicRoughness;
@ -212,6 +213,27 @@ describe('loadMtl', () => {
expect(pbr.occlusionTexture).toBeUndefined(); expect(pbr.occlusionTexture).toBeUndefined();
}); });
it('texture referenced by specular is decoded', async () => {
const materials = await loadMtl(sharedTexturesMaterialPath, options);
expect(materials.length).toBe(1);
const material = materials[0];
const pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture.pixels).toBeDefined();
expect(pbr.baseColorTexture.source).toBeDefined();
expect(pbr.metallicRoughnessTexture.pixels).toBeDefined();
expect(pbr.metallicRoughnessTexture.source).toBeUndefined();
});
it('texture referenced by diffuse and emission is not decoded', async() => {
const materials = await loadMtl(sharedTexturesMaterial2Path, options);
expect(materials.length).toBe(1);
const material = materials[0];
const pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBe(material.emissiveTexture);
expect(pbr.baseColorTexture.pixels).toBeUndefined();
expect(pbr.baseColorTexture.source).toBeDefined();
});
describe('metallicRoughness', () => { describe('metallicRoughness', () => {
it('creates default material', () => { it('creates default material', () => {
const material = loadMtl._createMaterial(undefined, options); const material = loadMtl._createMaterial(undefined, options);