Skip to content

Commit decc02e

Browse files
authored
Allow InstancedMesh provide a unique ID for WebGLBindingStates (mrdoob#32556)
1 parent e796263 commit decc02e

File tree

3 files changed

+103
-29
lines changed

3 files changed

+103
-29
lines changed

src/renderers/WebGLRenderer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ class WebGLRenderer {
446446
attributes = new WebGLAttributes( _gl );
447447
bindingStates = new WebGLBindingStates( _gl, attributes );
448448
geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
449-
objects = new WebGLObjects( _gl, geometries, attributes, info );
449+
objects = new WebGLObjects( _gl, geometries, attributes, bindingStates, info );
450450
morphtargets = new WebGLMorphtargets( _gl, capabilities, textures );
451451
clipping = new WebGLClipping( properties );
452452
programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping );

src/renderers/webgl/WebGLBindingStates.js

Lines changed: 99 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function WebGLBindingStates( gl, attributes ) {
1414

1515
let updateBuffers = false;
1616

17-
const state = getBindingState( geometry, program, material );
17+
const state = getBindingState( object, geometry, program, material );
1818

1919
if ( currentState !== state ) {
2020

@@ -67,16 +67,28 @@ function WebGLBindingStates( gl, attributes ) {
6767

6868
}
6969

70-
function getBindingState( geometry, program, material ) {
70+
function getBindingState( object, geometry, program, material ) {
7171

7272
const wireframe = ( material.wireframe === true );
7373

74-
let programMap = bindingStates[ geometry.id ];
74+
let objectMap = bindingStates[ geometry.id ];
75+
76+
if ( objectMap === undefined ) {
77+
78+
objectMap = {};
79+
bindingStates[ geometry.id ] = objectMap;
80+
81+
}
82+
83+
// Each InstancedMesh requires unique binding states because it contains instanced attributes.
84+
const objectId = ( object.isInstancedMesh === true ) ? object.id : 0;
85+
86+
let programMap = objectMap[ objectId ];
7587

7688
if ( programMap === undefined ) {
7789

7890
programMap = {};
79-
bindingStates[ geometry.id ] = programMap;
91+
objectMap[ objectId ] = programMap;
8092

8193
}
8294

@@ -477,21 +489,27 @@ function WebGLBindingStates( gl, attributes ) {
477489

478490
for ( const geometryId in bindingStates ) {
479491

480-
const programMap = bindingStates[ geometryId ];
492+
const objectMap = bindingStates[ geometryId ];
481493

482-
for ( const programId in programMap ) {
494+
for ( const objectId in objectMap ) {
483495

484-
const stateMap = programMap[ programId ];
496+
const programMap = objectMap[ objectId ];
485497

486-
for ( const wireframe in stateMap ) {
498+
for ( const programId in programMap ) {
487499

488-
deleteVertexArrayObject( stateMap[ wireframe ].object );
500+
const stateMap = programMap[ programId ];
489501

490-
delete stateMap[ wireframe ];
502+
for ( const wireframe in stateMap ) {
491503

492-
}
504+
deleteVertexArrayObject( stateMap[ wireframe ].object );
493505

494-
delete programMap[ programId ];
506+
delete stateMap[ wireframe ];
507+
508+
}
509+
510+
delete programMap[ programId ];
511+
512+
}
495513

496514
}
497515

@@ -505,21 +523,27 @@ function WebGLBindingStates( gl, attributes ) {
505523

506524
if ( bindingStates[ geometry.id ] === undefined ) return;
507525

508-
const programMap = bindingStates[ geometry.id ];
526+
const objectMap = bindingStates[ geometry.id ];
509527

510-
for ( const programId in programMap ) {
528+
for ( const objectId in objectMap ) {
511529

512-
const stateMap = programMap[ programId ];
530+
const programMap = objectMap[ objectId ];
513531

514-
for ( const wireframe in stateMap ) {
532+
for ( const programId in programMap ) {
515533

516-
deleteVertexArrayObject( stateMap[ wireframe ].object );
534+
const stateMap = programMap[ programId ];
517535

518-
delete stateMap[ wireframe ];
536+
for ( const wireframe in stateMap ) {
519537

520-
}
538+
deleteVertexArrayObject( stateMap[ wireframe ].object );
521539

522-
delete programMap[ programId ];
540+
delete stateMap[ wireframe ];
541+
542+
}
543+
544+
delete programMap[ programId ];
545+
546+
}
523547

524548
}
525549

@@ -531,26 +555,73 @@ function WebGLBindingStates( gl, attributes ) {
531555

532556
for ( const geometryId in bindingStates ) {
533557

534-
const programMap = bindingStates[ geometryId ];
558+
const objectMap = bindingStates[ geometryId ];
559+
560+
for ( const objectId in objectMap ) {
561+
562+
const programMap = objectMap[ objectId ];
563+
564+
if ( programMap[ program.id ] === undefined ) continue;
565+
566+
const stateMap = programMap[ program.id ];
567+
568+
for ( const wireframe in stateMap ) {
569+
570+
deleteVertexArrayObject( stateMap[ wireframe ].object );
571+
572+
delete stateMap[ wireframe ];
573+
574+
}
575+
576+
delete programMap[ program.id ];
577+
578+
}
579+
580+
}
581+
582+
}
583+
584+
function releaseStatesOfObject( object ) {
585+
586+
for ( const geometryId in bindingStates ) {
587+
588+
const objectMap = bindingStates[ geometryId ];
535589

536-
if ( programMap[ program.id ] === undefined ) continue;
590+
const objectId = ( object.isInstancedMesh === true ) ? object.id : 0;
537591

538-
const stateMap = programMap[ program.id ];
592+
const programMap = objectMap[ objectId ];
539593

540-
for ( const wireframe in stateMap ) {
594+
if ( programMap === undefined ) continue;
541595

542-
deleteVertexArrayObject( stateMap[ wireframe ].object );
596+
for ( const programId in programMap ) {
543597

544-
delete stateMap[ wireframe ];
598+
const stateMap = programMap[ programId ];
599+
600+
for ( const wireframe in stateMap ) {
601+
602+
deleteVertexArrayObject( stateMap[ wireframe ].object );
603+
604+
delete stateMap[ wireframe ];
605+
606+
}
607+
608+
delete programMap[ programId ];
545609

546610
}
547611

548-
delete programMap[ program.id ];
612+
delete objectMap[ objectId ];
613+
614+
if ( Object.keys( objectMap ).length === 0 ) {
615+
616+
delete bindingStates[ geometryId ];
617+
618+
}
549619

550620
}
551621

552622
}
553623

624+
554625
function reset() {
555626

556627
resetDefaultState();
@@ -580,6 +651,7 @@ function WebGLBindingStates( gl, attributes ) {
580651
resetDefaultState: resetDefaultState,
581652
dispose: dispose,
582653
releaseStatesOfGeometry: releaseStatesOfGeometry,
654+
releaseStatesOfObject: releaseStatesOfObject,
583655
releaseStatesOfProgram: releaseStatesOfProgram,
584656

585657
initAttributes: initAttributes,

src/renderers/webgl/WebGLObjects.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
function WebGLObjects( gl, geometries, attributes, info ) {
1+
function WebGLObjects( gl, geometries, attributes, bindingStates, info ) {
22

33
let updateMap = new WeakMap();
44

@@ -73,6 +73,8 @@ function WebGLObjects( gl, geometries, attributes, info ) {
7373

7474
instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose );
7575

76+
bindingStates.releaseStatesOfObject( instancedMesh );
77+
7678
attributes.remove( instancedMesh.instanceMatrix );
7779

7880
if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor );

0 commit comments

Comments
 (0)