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 );