diff --git a/src/uniforms/MaterialsTexture.js b/src/uniforms/MaterialsTexture.js index 4d46c263e..3a9bf9888 100644 --- a/src/uniforms/MaterialsTexture.js +++ b/src/uniforms/MaterialsTexture.js @@ -1,4 +1,5 @@ import { DataTexture, RGBAFormat, ClampToEdgeWrapping, FloatType, FrontSide, BackSide, DoubleSide } from 'three'; +import { reduceTexturesToUniqueSources } from './utils.js'; const MATERIAL_PIXELS = 45; const MATERIAL_STRIDE = MATERIAL_PIXELS * 4; @@ -58,7 +59,16 @@ export class MaterialsTexture extends DataTexture { function getTexture( material, key, def = - 1 ) { - return key in material ? textures.indexOf( material[ key ] ) : def; + if ( key in material && material[ key ] ) { + + const source = material[ key ].source; + return uniqueTextures.findIndex( tex => tex.source === source ); + + } else { + + return def; + + } } @@ -140,6 +150,9 @@ export class MaterialsTexture extends DataTexture { const dimension = Math.ceil( Math.sqrt( pixelCount ) ); const { threeCompatibilityTransforms, image } = this; + // get the list of textures with unique sources + const uniqueTextures = reduceTexturesToUniqueSources( textures ); + if ( image.width !== dimension ) { this.dispose(); @@ -170,9 +183,9 @@ export class MaterialsTexture extends DataTexture { // sample 1 // metalness & roughness floatArray[ index ++ ] = getField( m, 'metalness', 0.0 ); - floatArray[ index ++ ] = textures.indexOf( m.metalnessMap ); + floatArray[ index ++ ] = uniqueTextures.indexOf( m.metalnessMap ); floatArray[ index ++ ] = getField( m, 'roughness', 0.0 ); - floatArray[ index ++ ] = textures.indexOf( m.roughnessMap ); + floatArray[ index ++ ] = uniqueTextures.indexOf( m.roughnessMap ); // sample 2 // transmission & emissiveIntensity diff --git a/src/uniforms/RenderTarget2DArray.js b/src/uniforms/RenderTarget2DArray.js index 66f7711bf..7dc7efa85 100644 --- a/src/uniforms/RenderTarget2DArray.js +++ b/src/uniforms/RenderTarget2DArray.js @@ -9,6 +9,7 @@ import { NoToneMapping, } from 'three'; import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js'; +import { reduceTexturesToUniqueSources } from './utils.js'; const prevColor = new Color(); export class RenderTarget2DArray extends WebGLArrayRenderTarget { @@ -37,6 +38,9 @@ export class RenderTarget2DArray extends WebGLArrayRenderTarget { setTextures( renderer, width, height, textures ) { + // get the list of textures with unique sources + const uniqueTextures = reduceTexturesToUniqueSources( textures ); + // save previous renderer state const prevRenderTarget = renderer.getRenderTarget(); const prevToneMapping = renderer.toneMapping; @@ -45,7 +49,7 @@ export class RenderTarget2DArray extends WebGLArrayRenderTarget { // resize the render target and ensure we don't have an empty texture // render target depth must be >= 1 to avoid unbound texture error on android devices - const depth = textures.length || 1; + const depth = uniqueTextures.length || 1; this.setSize( width, height, depth ); renderer.setClearColor( 0, 0 ); renderer.toneMapping = NoToneMapping; @@ -54,7 +58,7 @@ export class RenderTarget2DArray extends WebGLArrayRenderTarget { const fsQuad = this.fsQuad; for ( let i = 0, l = depth; i < l; i ++ ) { - const texture = textures[ i ]; + const texture = uniqueTextures[ i ]; if ( texture ) { // revert to default texture transform before rendering diff --git a/src/uniforms/utils.js b/src/uniforms/utils.js new file mode 100644 index 000000000..ec378b64c --- /dev/null +++ b/src/uniforms/utils.js @@ -0,0 +1,21 @@ +// reduce the set of textures to just those with a unique source while retaining +// the order of the textures. +export function reduceTexturesToUniqueSources( textures ) { + + const sourceSet = new Set(); + const result = []; + for ( let i = 0, l = textures.length; i < l; i ++ ) { + + const tex = textures[ i ]; + if ( ! sourceSet.has( tex.source ) ) { + + sourceSet.add( tex.source ); + result.push( tex ); + + } + + } + + return result; + +}