diff --git a/src/objects/BatchedMesh.js b/src/objects/BatchedMesh.js index 4e33f27754713e..5dca90f30f6de1 100644 --- a/src/objects/BatchedMesh.js +++ b/src/objects/BatchedMesh.js @@ -1513,7 +1513,19 @@ class BatchedMesh extends Mesh { // the indexed version of the multi draw function requires specifying the start // offset in bytes. const index = geometry.getIndex(); - const bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT; + let bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT; + + + // the "wireframe" attribute implicitly creates a line attribute in the renderer, which is double + // the vertices to draw (3 lines per triangle) so we multiply the draw counts / starts and make + // assumptions about the index buffer byte size. + let multiDrawMultiplier = 1; + if ( material.wireframe ) { + + multiDrawMultiplier = 2; + bytesPerElement = geometry.attributes.position.count > 65535 ? 4 : 2; + + } const instanceInfo = this._instanceInfo; const multiDrawStarts = this._multiDrawStarts; @@ -1594,8 +1606,8 @@ class BatchedMesh extends Mesh { for ( let i = 0, l = list.length; i < l; i ++ ) { const item = list[ i ]; - multiDrawStarts[ multiDrawCount ] = item.start * bytesPerElement; - multiDrawCounts[ multiDrawCount ] = item.count; + multiDrawStarts[ multiDrawCount ] = item.start * bytesPerElement * multiDrawMultiplier; + multiDrawCounts[ multiDrawCount ] = item.count * multiDrawMultiplier; indirectArray[ multiDrawCount ] = item.index; multiDrawCount ++; @@ -1625,8 +1637,8 @@ class BatchedMesh extends Mesh { if ( ! culled ) { const geometryInfo = geometryInfoList[ geometryId ]; - multiDrawStarts[ multiDrawCount ] = geometryInfo.start * bytesPerElement; - multiDrawCounts[ multiDrawCount ] = geometryInfo.count; + multiDrawStarts[ multiDrawCount ] = geometryInfo.start * bytesPerElement * multiDrawMultiplier; + multiDrawCounts[ multiDrawCount ] = geometryInfo.count * multiDrawMultiplier; indirectArray[ multiDrawCount ] = i; multiDrawCount ++; diff --git a/src/renderers/common/Geometries.js b/src/renderers/common/Geometries.js index edac9a4fa1082b..eb332c41588292 100644 --- a/src/renderers/common/Geometries.js +++ b/src/renderers/common/Geometries.js @@ -1,6 +1,5 @@ import DataMap from './DataMap.js'; import { AttributeType } from './Constants.js'; -import { arrayNeedsUint32 } from '../../utils.js'; import { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute.js'; @@ -77,7 +76,7 @@ function getWireframeIndex( geometry ) { } - const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); + const attribute = new ( geometryPosition.count >= 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); attribute.version = getWireframeVersion( geometry ); attribute.__id = getWireframeId( geometry ); diff --git a/src/renderers/webgl/WebGLGeometries.js b/src/renderers/webgl/WebGLGeometries.js index c28d0feacd47cf..d89b220b9345c5 100644 --- a/src/renderers/webgl/WebGLGeometries.js +++ b/src/renderers/webgl/WebGLGeometries.js @@ -1,5 +1,4 @@ import { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute.js'; -import { arrayNeedsUint32 } from '../../utils.js'; function WebGLGeometries( gl, attributes, info, bindingStates ) { @@ -85,6 +84,12 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) { const geometryPosition = geometry.attributes.position; let version = 0; + if ( geometryPosition === undefined ) { + + return; + + } + if ( geometryIndex !== null ) { const array = geometryIndex.array; @@ -100,7 +105,7 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) { } - } else if ( geometryPosition !== undefined ) { + } else { const array = geometryPosition.array; version = geometryPosition.version; @@ -115,13 +120,11 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) { } - } else { - - return; - } - const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); + // check whether a 32 bit or 16 bit buffer is required to store the indices + // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 + const attribute = new ( geometryPosition.count >= 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); attribute.version = version; // Updating index buffer in VAO now. See WebGLBindingStates diff --git a/src/renderers/webgpu/WebGPUBackend.js b/src/renderers/webgpu/WebGPUBackend.js index 224b2782e6121d..9370928ff49c02 100644 --- a/src/renderers/webgpu/WebGPUBackend.js +++ b/src/renderers/webgpu/WebGPUBackend.js @@ -1596,6 +1596,14 @@ class WebGPUBackend extends Backend { } + let bytesPerElement = ( hasIndex === true ) ? index.array.BYTES_PER_ELEMENT : 1; + + if ( material.wireframe ) { + + bytesPerElement = object.geometry.attributes.position.count > 65535 ? 4 : 2; + + } + for ( let i = 0; i < drawCount; i ++ ) { const count = drawInstances ? drawInstances[ i ] : 1; @@ -1603,7 +1611,7 @@ class WebGPUBackend extends Backend { if ( hasIndex === true ) { - passEncoderGPU.drawIndexed( counts[ i ], count, starts[ i ] / index.array.BYTES_PER_ELEMENT, 0, firstInstance ); + passEncoderGPU.drawIndexed( counts[ i ], count, starts[ i ] / bytesPerElement, 0, firstInstance ); } else {