diff --git a/examples/jsm/physics/JoltPhysics.js b/examples/jsm/physics/JoltPhysics.js index 2cc09dcf1e18cb..e406a2385341a8 100644 --- a/examples/jsm/physics/JoltPhysics.js +++ b/examples/jsm/physics/JoltPhysics.js @@ -77,7 +77,7 @@ async function JoltPhysics() { if ( Jolt === null ) { - const { default: initJolt } = await import( `${JOLT_PATH}` ); + const { default: initJolt } = await import( JOLT_PATH /* @vite-ignore */ ); Jolt = await initJolt(); } diff --git a/examples/jsm/physics/RapierPhysics.js b/examples/jsm/physics/RapierPhysics.js index 7a952151ae805e..dbd6424c4e2a90 100644 --- a/examples/jsm/physics/RapierPhysics.js +++ b/examples/jsm/physics/RapierPhysics.js @@ -97,7 +97,7 @@ async function RapierPhysics() { if ( RAPIER === null ) { - RAPIER = await import( `${RAPIER_PATH}` ); + RAPIER = await import( RAPIER_PATH /* @vite-ignore */ ); await RAPIER.init(); } diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 4c523e3259e96f..625f890c0daa28 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -446,7 +446,7 @@ class WebGLRenderer { attributes = new WebGLAttributes( _gl ); bindingStates = new WebGLBindingStates( _gl, attributes ); geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); - objects = new WebGLObjects( _gl, geometries, attributes, info ); + objects = new WebGLObjects( _gl, geometries, attributes, bindingStates, info ); morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); clipping = new WebGLClipping( properties ); programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); diff --git a/src/renderers/webgl/WebGLBindingStates.js b/src/renderers/webgl/WebGLBindingStates.js index d63aeb7f35281a..fa11e53527f8e1 100644 --- a/src/renderers/webgl/WebGLBindingStates.js +++ b/src/renderers/webgl/WebGLBindingStates.js @@ -14,7 +14,7 @@ function WebGLBindingStates( gl, attributes ) { let updateBuffers = false; - const state = getBindingState( geometry, program, material ); + const state = getBindingState( object, geometry, program, material ); if ( currentState !== state ) { @@ -67,16 +67,28 @@ function WebGLBindingStates( gl, attributes ) { } - function getBindingState( geometry, program, material ) { + function getBindingState( object, geometry, program, material ) { const wireframe = ( material.wireframe === true ); - let programMap = bindingStates[ geometry.id ]; + let objectMap = bindingStates[ geometry.id ]; + + if ( objectMap === undefined ) { + + objectMap = {}; + bindingStates[ geometry.id ] = objectMap; + + } + + // Each InstancedMesh requires unique binding states because it contains instanced attributes. + const objectId = ( object.isInstancedMesh === true ) ? object.id : 0; + + let programMap = objectMap[ objectId ]; if ( programMap === undefined ) { programMap = {}; - bindingStates[ geometry.id ] = programMap; + objectMap[ objectId ] = programMap; } @@ -477,21 +489,27 @@ function WebGLBindingStates( gl, attributes ) { for ( const geometryId in bindingStates ) { - const programMap = bindingStates[ geometryId ]; + const objectMap = bindingStates[ geometryId ]; - for ( const programId in programMap ) { + for ( const objectId in objectMap ) { - const stateMap = programMap[ programId ]; + const programMap = objectMap[ objectId ]; - for ( const wireframe in stateMap ) { + for ( const programId in programMap ) { - deleteVertexArrayObject( stateMap[ wireframe ].object ); + const stateMap = programMap[ programId ]; - delete stateMap[ wireframe ]; + for ( const wireframe in stateMap ) { - } + deleteVertexArrayObject( stateMap[ wireframe ].object ); - delete programMap[ programId ]; + delete stateMap[ wireframe ]; + + } + + delete programMap[ programId ]; + + } } @@ -505,21 +523,27 @@ function WebGLBindingStates( gl, attributes ) { if ( bindingStates[ geometry.id ] === undefined ) return; - const programMap = bindingStates[ geometry.id ]; + const objectMap = bindingStates[ geometry.id ]; - for ( const programId in programMap ) { + for ( const objectId in objectMap ) { - const stateMap = programMap[ programId ]; + const programMap = objectMap[ objectId ]; - for ( const wireframe in stateMap ) { + for ( const programId in programMap ) { - deleteVertexArrayObject( stateMap[ wireframe ].object ); + const stateMap = programMap[ programId ]; - delete stateMap[ wireframe ]; + for ( const wireframe in stateMap ) { - } + deleteVertexArrayObject( stateMap[ wireframe ].object ); - delete programMap[ programId ]; + delete stateMap[ wireframe ]; + + } + + delete programMap[ programId ]; + + } } @@ -531,26 +555,73 @@ function WebGLBindingStates( gl, attributes ) { for ( const geometryId in bindingStates ) { - const programMap = bindingStates[ geometryId ]; + const objectMap = bindingStates[ geometryId ]; + + for ( const objectId in objectMap ) { + + const programMap = objectMap[ objectId ]; + + if ( programMap[ program.id ] === undefined ) continue; + + const stateMap = programMap[ program.id ]; + + for ( const wireframe in stateMap ) { + + deleteVertexArrayObject( stateMap[ wireframe ].object ); + + delete stateMap[ wireframe ]; + + } + + delete programMap[ program.id ]; + + } + + } + + } + + function releaseStatesOfObject( object ) { + + for ( const geometryId in bindingStates ) { + + const objectMap = bindingStates[ geometryId ]; - if ( programMap[ program.id ] === undefined ) continue; + const objectId = ( object.isInstancedMesh === true ) ? object.id : 0; - const stateMap = programMap[ program.id ]; + const programMap = objectMap[ objectId ]; - for ( const wireframe in stateMap ) { + if ( programMap === undefined ) continue; - deleteVertexArrayObject( stateMap[ wireframe ].object ); + for ( const programId in programMap ) { - delete stateMap[ wireframe ]; + const stateMap = programMap[ programId ]; + + for ( const wireframe in stateMap ) { + + deleteVertexArrayObject( stateMap[ wireframe ].object ); + + delete stateMap[ wireframe ]; + + } + + delete programMap[ programId ]; } - delete programMap[ program.id ]; + delete objectMap[ objectId ]; + + if ( Object.keys( objectMap ).length === 0 ) { + + delete bindingStates[ geometryId ]; + + } } } + function reset() { resetDefaultState(); @@ -580,6 +651,7 @@ function WebGLBindingStates( gl, attributes ) { resetDefaultState: resetDefaultState, dispose: dispose, releaseStatesOfGeometry: releaseStatesOfGeometry, + releaseStatesOfObject: releaseStatesOfObject, releaseStatesOfProgram: releaseStatesOfProgram, initAttributes: initAttributes, diff --git a/src/renderers/webgl/WebGLObjects.js b/src/renderers/webgl/WebGLObjects.js index dd00338013fd75..d35eda6cd0a57e 100644 --- a/src/renderers/webgl/WebGLObjects.js +++ b/src/renderers/webgl/WebGLObjects.js @@ -1,4 +1,4 @@ -function WebGLObjects( gl, geometries, attributes, info ) { +function WebGLObjects( gl, geometries, attributes, bindingStates, info ) { let updateMap = new WeakMap(); @@ -73,6 +73,8 @@ function WebGLObjects( gl, geometries, attributes, info ) { instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose ); + bindingStates.releaseStatesOfObject( instancedMesh ); + attributes.remove( instancedMesh.instanceMatrix ); if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor );