Skip to content

Commit 0319a2a

Browse files
authored
WebGLRenderer: Add initial support for multi draw BatchedMesh (#27111)
* Add support for multi draw * Fix multidraw
1 parent 6d7566e commit 0319a2a

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed

examples/jsm/objects/BatchedMesh.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ class BatchedMesh extends Mesh {
113113

114114
this._geometryInitialized = false;
115115
this._geometryCount = 0;
116+
this._multiDrawCounts = null;
117+
this._multiDrawStarts = null;
118+
this._multiDrawCount = 0;
116119

117120
// Local matrix per geometry by using data texture
118121
// @TODO: Support uniform parameter per geometry
@@ -240,6 +243,8 @@ class BatchedMesh extends Mesh {
240243
geometry.setAttribute( ID_ATTR_NAME, new BufferAttribute( idArray, 1 ) );
241244

242245
this._geometryInitialized = true;
246+
this._multiDrawCounts = new Int32Array( maxGeometryCount );
247+
this._multiDrawStarts = new Int32Array( maxGeometryCount );
243248

244249
}
245250

@@ -436,7 +441,7 @@ class BatchedMesh extends Mesh {
436441
// add the reserved range and draw range objects
437442
reservedRanges.push( reservedRange );
438443
drawRanges.push( {
439-
start: hasIndex ? reservedRange.indexStart * 3 : reservedRange.vertexStart * 3,
444+
start: hasIndex ? reservedRange.indexStart : reservedRange.vertexStart,
440445
count: - 1
441446
} );
442447

@@ -541,7 +546,7 @@ class BatchedMesh extends Mesh {
541546
// set drawRange count
542547
const drawRange = this._drawRanges[ id ];
543548
const posAttr = geometry.getAttribute( 'position' );
544-
drawRange.count = hasIndex ? srcIndex.count * 3 : posAttr.count * 3;
549+
drawRange.count = hasIndex ? srcIndex.count : posAttr.count;
545550

546551
return id;
547552

@@ -705,8 +710,36 @@ class BatchedMesh extends Mesh {
705710

706711
material.defines.BATCHING = true;
707712

713+
// the indexed version of the multi draw function requires specifying the start
714+
// offset in bytes.
715+
const index = _geometry.getIndex();
716+
const bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT;
717+
718+
const visible = this._visible;
719+
const multiDrawStarts = this._multiDrawStarts;
720+
const multiDrawCounts = this._multiDrawCounts;
721+
const drawRanges = this._drawRanges;
722+
723+
let count = 0;
724+
for ( let i = 0, l = visible.length; i < l; i ++ ) {
725+
726+
if ( visible[ i ] ) {
727+
728+
const range = drawRanges[ i ];
729+
multiDrawStarts[ count ] = range.start * bytesPerElement;
730+
multiDrawCounts[ count ] = range.count;
731+
count ++;
732+
733+
}
734+
735+
}
736+
737+
this._multiDrawCount = count;
738+
708739
// @TODO: Implement frustum culling for each geometry
709740

741+
// @TODO: Implement geometry sorting for transparent and opaque materials
742+
710743
}
711744

712745
onAfterRender( _renderer, _scene, _camera, _geometry, material/*, _group*/ ) {

src/renderers/WebGLRenderer.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,11 @@ class WebGLRenderer {
896896

897897
}
898898

899-
if ( object.isInstancedMesh ) {
899+
if ( object.isBatchedMesh ) {
900+
901+
renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount );
902+
903+
} else if ( object.isInstancedMesh ) {
900904

901905
renderer.renderInstances( drawStart, drawCount, object.count );
902906

src/renderers/webgl/WebGLBufferRenderer.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,37 @@ function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
4949

5050
}
5151

52+
function renderMultiDraw( starts, counts, drawCount ) {
53+
54+
if ( drawCount === 0 ) return;
55+
56+
const extension = extensions.get( 'WEBGL_multi_draw' );
57+
if ( extension === null ) {
58+
59+
console.error( 'THREE.WebGLBufferRenderer: using THREE.BatchedMesh but hardware does not support extension WEBGL_multi_draw.' );
60+
return;
61+
62+
}
63+
64+
extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount );
65+
66+
let elementCount = 0;
67+
for ( let i = 0; i < drawCount; i ++ ) {
68+
69+
elementCount += counts[ i ];
70+
71+
}
72+
73+
info.update( elementCount, mode, 1 );
74+
75+
}
76+
5277
//
5378

5479
this.setMode = setMode;
5580
this.render = render;
5681
this.renderInstances = renderInstances;
82+
this.renderMultiDraw = renderMultiDraw;
5783

5884
}
5985

src/renderers/webgl/WebGLIndexedBufferRenderer.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,38 @@ function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
5858

5959
}
6060

61+
function renderMultiDraw( starts, counts, drawCount ) {
62+
63+
if ( drawCount === 0 ) return;
64+
65+
const extension = extensions.get( 'WEBGL_multi_draw' );
66+
if ( extension === null ) {
67+
68+
console.error( 'THREE.WebGLBufferRenderer: using THREE.BatchedMesh but hardware does not support extension WEBGL_multi_draw.' );
69+
return;
70+
71+
}
72+
73+
extension.multiDrawElementsWEBGL( mode, counts, 0, type, starts, 0, drawCount );
74+
75+
let elementCount = 0;
76+
for ( let i = 0; i < drawCount; i ++ ) {
77+
78+
elementCount += counts[ i ];
79+
80+
}
81+
82+
info.update( elementCount, mode, 1 );
83+
84+
}
85+
6186
//
6287

6388
this.setMode = setMode;
6489
this.setIndex = setIndex;
6590
this.render = render;
6691
this.renderInstances = renderInstances;
92+
this.renderMultiDraw = renderMultiDraw;
6793

6894
}
6995

0 commit comments

Comments
 (0)