From 9796ddd982480f662a73e5f16fff4c7e6f240ee1 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Thu, 26 Mar 2026 18:35:36 +0100 Subject: [PATCH] WebGPURenderer: Implement `WEBGL_multi_draw` fallback. (#33238) --- src/renderers/webgl-fallback/WebGLBackend.js | 22 +++++++++++++++---- .../webgl-fallback/nodes/GLSLNodeBuilder.js | 20 +++++++++++++++-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/renderers/webgl-fallback/WebGLBackend.js b/src/renderers/webgl-fallback/WebGLBackend.js index 55e155ecc09081..65484c52606625 100644 --- a/src/renderers/webgl-fallback/WebGLBackend.js +++ b/src/renderers/webgl-fallback/WebGLBackend.js @@ -991,14 +991,28 @@ class WebGLBackend extends Backend { * @param {number} firstVertex - The first vertex to render. * @param {number} vertexCount - The vertex count. * @param {number} instanceCount - The intance count. + * @param {WebGLProgram} programGPU - The raw WebGL shader program. */ - _draw( object, renderer, firstVertex, vertexCount, instanceCount ) { + _draw( object, renderer, firstVertex, vertexCount, instanceCount, programGPU ) { if ( object.isBatchedMesh ) { if ( this.hasFeature( 'WEBGL_multi_draw' ) === false ) { - warnOnce( 'WebGLBackend: WEBGL_multi_draw not supported.' ); + const { gl } = this; + + const drawIdLocation = gl.getUniformLocation( programGPU, 'nodeUniformDrawId' ); + + const starts = object._multiDrawStarts; + const counts = object._multiDrawCounts; + const drawCount = object._multiDrawCount; + + for ( let i = 0; i < drawCount; i ++ ) { + + gl.uniform1ui( drawIdLocation, i ); + renderer.render( starts[ i ], counts[ i ] ); + + } } else { @@ -1267,7 +1281,7 @@ class WebGLBackend extends Backend { state.bindBufferBase( gl.UNIFORM_BUFFER, cameraIndexBufferIndex, cameraData.indexesGPU[ i ] ); - this._draw( object, renderer, firstVertex, vertexCount, instanceCount ); + this._draw( object, renderer, firstVertex, vertexCount, instanceCount, programGPU ); } @@ -1278,7 +1292,7 @@ class WebGLBackend extends Backend { } else { - this._draw( object, renderer, firstVertex, vertexCount, instanceCount ); + this._draw( object, renderer, firstVertex, vertexCount, instanceCount, programGPU ); } diff --git a/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js b/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js index 974fba6112c02c..98fdf8702719f8 100644 --- a/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +++ b/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js @@ -1145,9 +1145,11 @@ ${ flowData.code } return 'uint( gl_DrawID )'; - } + } else { - return null; + return 'nodeUniformDrawId'; // fallback to uniform + + } } @@ -1556,6 +1558,20 @@ void main() { stageData.transforms = this.getTransforms( shaderStage ); stageData.flow = flow; + // fallbacks + + if ( shaderStage === 'vertex' ) { + + const ext = this.renderer.backend.extensions; + + if ( this.object.isBatchedMesh && ext.has( 'WEBGL_multi_draw' ) === false ) { + + stageData.uniforms += '\nuniform uint nodeUniformDrawId;\n'; + + } + + } + } if ( this.material !== null ) {