mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
102.3k stars 35.36k forks source link

[GLTFLoader]: cache gltf texture which have same source, sampler and extensions but different textureIndex #22037

Closed deepkolos closed 3 years ago

deepkolos commented 3 years ago

Problem

using the same normalMap texture bewteen diffrent material in blender

blend file: https://github.com/deepkolos/lazy-gltf-loader/blob/main/examples/banzi2.blend

图片

but the exported gltf file will look like this

gltf flile: https://github.com/deepkolos/lazy-gltf-loader/blob/main/examples/banzi2/banzi2.gltf

{
  ...
  "textures" : [
      {
          "sampler" : 0,
          "source" : 0
      },
      {
          "sampler" : 0,
          "source" : 1
      },
      {
          "sampler" : 0,
          "source" : 2
      },
      {
          "sampler" : 0,
          "source" : 3
      },
      {
          "sampler" : 0,
          "source" : 1
      },
      {
          "sampler" : 0,
          "source" : 2
      }
  ],
  ...
}

which means it will create duplicated texture with same source, sampler and extensions, upload duplicated texture to WebGL memory.

Solution

update texture cache key

/**
* Requests the specified dependency asynchronously, with caching.
* @param {string} type
* @param {number} index
* @return {Promise<Object3D|Material|THREE.Texture|AnimationClip|ArrayBuffer|Object>}
*/
getDependency( type, index ) {

  let cacheKey = type + ':' + index;

  // maping same source, sampler and extensions to the same texture
  if ( type == 'texture' ) {

    const textureDef = this.json.textures[index];
    cacheKey = type + ':' + textureDef.sampler + ':' + textureDef.source + ':' + JSON.stringify( textureDef.extensions );

  }

  let dependency = this.cache.get( cacheKey );
  ...
}
deepkolos commented 3 years ago

duplicated #21559

deepkolos commented 3 years ago

but the current GLTFLoader solution may not consider texture's extensions, so i think the solution i provided is better, which can cover ktx2, basis,compressed-texture with fallback or other texture extension with custom loadTexture funciton and not cache inside

the test page is here

https://deepkolos.github.io/lazy-gltf-loader/examples/texture-test.html

图片

deepkolos commented 3 years ago

maybe it is a common case that cache doesn't care about extensions. in this case, loadTexture, maybe so does other like loadMesh, loadBufferView, loadMaterial

donmccurdy commented 3 years ago

See https://github.com/mrdoob/three.js/pull/22038#issuecomment-867349612 — I think I would prefer to consider this a bug in the exporting software, rather than trying to detect deeply duplicated resources in a file.