diff --git a/examples/files.json b/examples/files.json index 31f706f8f73475..8e16304e663f92 100644 --- a/examples/files.json +++ b/examples/files.json @@ -345,6 +345,7 @@ "webgpu_loader_gltf_transmission", "webgpu_loader_materialx", "webgpu_materials", + "webgpu_materials_arrays", "webgpu_materials_basic", "webgpu_materials_displacementmap", "webgpu_materials_envmaps", diff --git a/examples/screenshots/webgpu_materials_arrays.jpg b/examples/screenshots/webgpu_materials_arrays.jpg new file mode 100644 index 00000000000000..4021cdb71cb370 Binary files /dev/null and b/examples/screenshots/webgpu_materials_arrays.jpg differ diff --git a/examples/tags.json b/examples/tags.json index 0c457fd8bfbc79..df979dbfff3107 100644 --- a/examples/tags.json +++ b/examples/tags.json @@ -126,6 +126,7 @@ "webgpu_materials_lightmap": [ "shadow" ], "webgpu_materials_sss": [ "subsurface scattering", "derivatives", "translucency" ], "webgpu_materials_transmission": [ "alpha" ], + "webgpu_materials_arrays": [ "webgpu", "geometry", "groups", "array" ], "webgpu_mirror": [ "reflection" ], "webgpu_multiple_rendertargets": [ "mrt" ], "webgpu_multiple_rendertargets_readback": [ "mrt" ], diff --git a/examples/webgpu_materials_arrays.html b/examples/webgpu_materials_arrays.html new file mode 100644 index 00000000000000..05139154daf8cf --- /dev/null +++ b/examples/webgpu_materials_arrays.html @@ -0,0 +1,173 @@ + + + + three.js webgpu - materials arrays and geometry groups + + + + + + +
+ three.js - WebGPU Materials Arrays and Geometry Groups
+
+ + + + + + + diff --git a/src/renderers/common/Renderer.js b/src/renderers/common/Renderer.js index adc41149095aa5..f30c41b228946f 100644 --- a/src/renderers/common/Renderer.js +++ b/src/renderers/common/Renderer.js @@ -1570,7 +1570,8 @@ class Renderer { _renderObjectDirect( object, material, scene, camera, lightsNode, group, passId ) { const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, passId ); - renderObject.drawRange = group || object.geometry.drawRange; + renderObject.drawRange = object.geometry.drawRange; + renderObject.group = group; // diff --git a/src/renderers/webgl-fallback/WebGLBackend.js b/src/renderers/webgl-fallback/WebGLBackend.js index d2e030a00a1c80..b17fa7a776c9ac 100644 --- a/src/renderers/webgl-fallback/WebGLBackend.js +++ b/src/renderers/webgl-fallback/WebGLBackend.js @@ -637,7 +637,6 @@ class WebGLBackend extends Backend { const geometry = renderObject.geometry; const drawRange = renderObject.drawRange; - const firstVertex = drawRange.start; // @@ -669,6 +668,7 @@ class WebGLBackend extends Backend { } // + let rangeFactor = 1; const renderer = this.bufferRenderer; @@ -683,6 +683,8 @@ class WebGLBackend extends Backend { state.setLineWidth( material.wireframeLinewidth * this.renderer.getPixelRatio() ); renderer.mode = gl.LINES; + rangeFactor = 2; + } else { renderer.mode = gl.TRIANGLES; @@ -693,28 +695,51 @@ class WebGLBackend extends Backend { // + const group = renderObject.group; - let count; renderer.object = object; + + let firstVertex = drawRange.start * rangeFactor; + let lastVertex = ( drawRange.start + drawRange.count ) * rangeFactor; + + if ( group !== null ) { + + firstVertex = Math.max( firstVertex, group.start * rangeFactor ); + lastVertex = Math.min( lastVertex, ( group.start + group.count ) * rangeFactor ); + + } + if ( index !== null ) { const indexData = this.get( index ); - const indexCount = ( drawRange.count !== Infinity ) ? drawRange.count : index.count; + const indexCount = index.count; renderer.index = index.count; renderer.type = indexData.type; - count = indexCount; + firstVertex = Math.max( firstVertex, 0 ); + lastVertex = Math.min( lastVertex, indexCount ); } else { renderer.index = 0; - const vertexCount = ( drawRange.count !== Infinity ) ? drawRange.count : geometry.attributes.position.count; + const vertexCount = geometry.attributes.position.count; + + firstVertex = Math.max( firstVertex, 0 ); + lastVertex = Math.min( lastVertex, vertexCount ); + + } + + const count = lastVertex - firstVertex; + + if ( count < 0 || count === Infinity ) return; + + if ( index !== null ) { - count = vertexCount; + firstVertex *= index.array.BYTES_PER_ELEMENT; } diff --git a/src/renderers/webgpu/WebGPUBackend.js b/src/renderers/webgpu/WebGPUBackend.js index 2077f19ed6027d..db364c260ce977 100644 --- a/src/renderers/webgpu/WebGPUBackend.js +++ b/src/renderers/webgpu/WebGPUBackend.js @@ -829,7 +829,7 @@ class WebGPUBackend extends Backend { draw( renderObject, info ) { - const { object, geometry, context, pipeline } = renderObject; + const { object, material, geometry, context, pipeline, group } = renderObject; const bindings = renderObject.getBindings(); const renderContextData = this.get( context ); const pipelineGPU = this.get( pipeline ).pipeline; @@ -930,7 +930,26 @@ class WebGPUBackend extends Backend { // draw const drawRange = renderObject.drawRange; - const firstVertex = drawRange.start; + + let rangeFactor = 1; + + if ( material.wireframe === true && ! object.isPoints && ! object.isLineSegments && ! object.isLine && ! object.isLineLoop ) { + + rangeFactor = 2; + + } + + let firstVertex = drawRange.start * rangeFactor; + let lastVertex = ( drawRange.start + drawRange.count ) * rangeFactor; + + if ( group !== null ) { + + firstVertex = Math.max( firstVertex, group.start * rangeFactor ); + lastVertex = Math.min( lastVertex, ( group.start + group.count ) * rangeFactor ); + + } + + const instanceCount = this.getInstanceCount( renderObject ); if ( instanceCount === 0 ) return; @@ -955,18 +974,32 @@ class WebGPUBackend extends Backend { } else if ( hasIndex === true ) { - const indexCount = ( drawRange.count !== Infinity ) ? drawRange.count : index.count; + const indexCount = index.count; + + firstVertex = Math.max( firstVertex, 0 ); + lastVertex = Math.min( lastVertex, indexCount ); + + const count = lastVertex - firstVertex; - passEncoderGPU.drawIndexed( indexCount, instanceCount, firstVertex, 0, 0 ); + if ( count < 0 || count === Infinity ) return; + + passEncoderGPU.drawIndexed( count, instanceCount, firstVertex, 0, 0 ); info.update( object, indexCount, instanceCount ); } else { const positionAttribute = geometry.attributes.position; - const vertexCount = ( drawRange.count !== Infinity ) ? drawRange.count : positionAttribute.count; + const vertexCount = positionAttribute.count; + + firstVertex = Math.max( firstVertex, 0 ); + lastVertex = Math.min( lastVertex, vertexCount ); + + const count = lastVertex - firstVertex; + + if ( count < 0 || count === Infinity ) return; - passEncoderGPU.draw( vertexCount, instanceCount, firstVertex, 0 ); + passEncoderGPU.draw( count, instanceCount, firstVertex, 0 ); info.update( object, vertexCount, instanceCount );