From 3b173f09aea7cecfec41b47a6bb7a06fc0c189fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quique=20Mar=C3=ADn=20Richelet?= Date: Wed, 1 May 2024 20:00:42 +0200 Subject: [PATCH 1/5] BatchedMesh: add getColorAt and setColorAt --- docs/api/en/objects/BatchedMesh.html | 25 ++++++ examples/jsm/renderers/common/RenderObject.js | 1 + src/core/Object3D.js | 2 + src/loaders/ObjectLoader.js | 1 + src/objects/BatchedMesh.js | 80 +++++++++++++++++++ src/renderers/WebGLRenderer.js | 16 ++++ .../ShaderChunk/batching_pars_vertex.glsl.js | 15 ++++ .../ShaderChunk/color_pars_vertex.glsl.js | 2 +- .../shaders/ShaderChunk/color_vertex.glsl.js | 10 ++- src/renderers/webgl/WebGLProgram.js | 3 +- src/renderers/webgl/WebGLPrograms.js | 3 + 11 files changed, 155 insertions(+), 3 deletions(-) diff --git a/docs/api/en/objects/BatchedMesh.html b/docs/api/en/objects/BatchedMesh.html index 8c0a095b7e520e..b25285a689b329 100644 --- a/docs/api/en/objects/BatchedMesh.html +++ b/docs/api/en/objects/BatchedMesh.html @@ -129,6 +129,19 @@

[method:this setCustomSort]( [param:Function sortFunction] )

in the list include a "z" field to perform a depth-ordered sort with.

+

+ [method:undefined getColorAt]( [param:Integer index], [param:Color color] ) +

+

+ [page:Integer index]: The index of an instance. Values have to be in the + range [0, count]. +

+

+ [page:Color color]: This color object will be set to the color of the + defined instance. +

+

Get the color of the defined instance.

+

[method:Matrix4 getMatrixAt]( [param:Integer index], [param:Matrix4 matrix] )

@@ -151,6 +164,18 @@

Get whether the given instance is marked as "visible" or not.

+

+ [method:undefined setColorAt]( [param:Integer index], [param:Color color] ) +

+

+ [page:Integer index]: The index of an instance. Values have to be in the + range [0, count]. +

+

[page:Color color]: The color of a single instance.

+

+ Sets the given color to the defined instance. +

+

[method:this setMatrixAt]( [param:Integer index], [param:Matrix4 matrix] )

diff --git a/examples/jsm/renderers/common/RenderObject.js b/examples/jsm/renderers/common/RenderObject.js index 4628c2fe5edfb7..7d8bdbf5d796e9 100644 --- a/examples/jsm/renderers/common/RenderObject.js +++ b/examples/jsm/renderers/common/RenderObject.js @@ -225,6 +225,7 @@ export default class RenderObject { if ( object.isBatchedMesh ) { cacheKey += object._matricesTexture.uuid + ','; + cacheKey += object._colorsTexture.uuid + ','; } diff --git a/src/core/Object3D.js b/src/core/Object3D.js index 6f47db133e62c5..a317d6e2f99187 100644 --- a/src/core/Object3D.js +++ b/src/core/Object3D.js @@ -761,6 +761,8 @@ class Object3D extends EventDispatcher { object.matricesTexture = this._matricesTexture.toJSON( meta ); + if ( this.colorsTexture !== null ) object.colorsTexture = this.colorsTexture.toJSON( meta ); + if ( this.boundingSphere !== null ) { object.boundingSphere = { diff --git a/src/loaders/ObjectLoader.js b/src/loaders/ObjectLoader.js index d430386baac682..73d8afc8d68592 100644 --- a/src/loaders/ObjectLoader.js +++ b/src/loaders/ObjectLoader.js @@ -946,6 +946,7 @@ class ObjectLoader extends Loader { object._geometryCount = data.geometryCount; object._matricesTexture = getTexture( data.matricesTexture.uuid ); + if ( data.colorsTexture !== undefined ) object.colorsTexture = getTexture( data.colorsTexture.uuid ); break; diff --git a/src/objects/BatchedMesh.js b/src/objects/BatchedMesh.js index 89e549476f2710..c9449a3e7c3026 100644 --- a/src/objects/BatchedMesh.js +++ b/src/objects/BatchedMesh.js @@ -160,6 +160,9 @@ class BatchedMesh extends Mesh { this._initMatricesTexture(); + // Local color per geometry by using data texture + this.colorsTexture = null; + } _initMatricesTexture() { @@ -182,6 +185,25 @@ class BatchedMesh extends Mesh { } + _initColorsTexture() { + + // layout (1 color = 1 pixel) + // RGBA (=> column1) + // with 8x8 pixel texture max 64 matrices * 1 pixel = (8 * 8) + // 16x16 pixel texture max 256 matrices * 1 pixel = (16 * 16) + // 32x32 pixel texture max 1024 matrices * 1 pixel = (32 * 32) + // 64x64 pixel texture max 4096 matrices * 1 pixel = (64 * 64) + + let size = Math.sqrt( this._maxGeometryCount ); // 1 pixel needed for 1 color + size = Math.ceil( size ); + + const colorsArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel + const colorsTexture = new DataTexture( colorsArray, size, size, RGBAFormat, FloatType ); + + this.colorsTexture = colorsTexture; + + } + _initializeGeometry( reference ) { const geometry = this.geometry; @@ -746,6 +768,49 @@ class BatchedMesh extends Mesh { } + setColorAt( geometryId, color ) { + + if ( this.colorsTexture === null ) { + + this._initColorsTexture(); + + } + + // @TODO: Map geometryId to index of the arrays because + // optimize() can make geometryId mismatch the index + + const active = this._active; + const colorsTexture = this.colorsTexture; + const colorsArray = this.colorsTexture.image.data; + const geometryCount = this._geometryCount; + if ( geometryId >= geometryCount || active[ geometryId ] === false ) { + + return this; + + } + + color.toArray( colorsArray, geometryId * 4 ); + colorsTexture.needsUpdate = true; + + return this; + + } + + getColorAt( geometryId, color ) { + + const active = this._active; + const colorsArray = this.colorsTexture.image.data; + const geometryCount = this._geometryCount; + if ( geometryId >= geometryCount || active[ geometryId ] === false ) { + + return null; + + } + + return color.fromArray( colorsArray, geometryId * 4 ); + + } + setVisibleAt( geometryId, value ) { const visibility = this._visibility; @@ -886,6 +951,13 @@ class BatchedMesh extends Mesh { this._matricesTexture = source._matricesTexture.clone(); this._matricesTexture.image.data = this._matricesTexture.image.slice(); + if ( this.colorsTexture !== null ) { + + this.colorsTexture = source.colorsTexture.clone(); + this.colorsTexture.image.data = this.colorsTexture.image.slice(); + + } + return this; } @@ -897,6 +969,14 @@ class BatchedMesh extends Mesh { this._matricesTexture.dispose(); this._matricesTexture = null; + + if ( this.colorsTexture !== null ) { + + this.colorsTexture.dispose(); + this.colorsTexture = null; + + } + return this; } diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 6fe5a52fa19f08..e67e41f79168bf 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -1716,6 +1716,7 @@ class WebGLRenderer { materialProperties.outputColorSpace = parameters.outputColorSpace; materialProperties.batching = parameters.batching; + materialProperties.batchingColor = parameters.batchingColor; materialProperties.instancing = parameters.instancing; materialProperties.instancingColor = parameters.instancingColor; materialProperties.instancingMorph = parameters.instancingMorph; @@ -1805,6 +1806,14 @@ class WebGLRenderer { needsProgramChange = true; + } else if ( object.isBatchedMesh && materialProperties.batchingColor === true && object.colorTexture === null ) { + + needsProgramChange = true; + + } else if ( object.isBatchedMesh && materialProperties.batchingColor === false && object.colorTexture !== null ) { + + needsProgramChange = true; + } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { needsProgramChange = true; @@ -1997,6 +2006,13 @@ class WebGLRenderer { p_uniforms.setOptional( _gl, object, 'batchingTexture' ); p_uniforms.setValue( _gl, 'batchingTexture', object._matricesTexture, textures ); + p_uniforms.setOptional( _gl, object, 'batchingColorTexture' ); + if ( object.colorsTexture !== null ) { + + p_uniforms.setValue( _gl, 'batchingColorTexture', object.colorsTexture, textures ); + + } + } const morphAttributes = geometry.morphAttributes; diff --git a/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js index fb602a0f7d8804..89c7829b61ab7f 100644 --- a/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js +++ b/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js @@ -16,4 +16,19 @@ export default /* glsl */` } #endif + +#ifdef USE_BATCHING_COLOR + + uniform sampler2D batchingColorTexture; + vec3 getBatchingColor( const in float i ) { + + int size = textureSize( batchingColorTexture, 0 ).x; + int j = int( i ); + int x = j % size; + int y = j / size; + return texelFetch( batchingColorTexture, ivec2( x, y ), 0 ).rgb; + + } + +#endif `; diff --git a/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js index 80c4934d555ee1..944eedf9bf7c0e 100644 --- a/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js +++ b/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js @@ -3,7 +3,7 @@ export default /* glsl */` varying vec4 vColor; -#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) +#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) varying vec3 vColor; diff --git a/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js index b288b7c472c0fb..daf7164e60cb79 100644 --- a/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js +++ b/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js @@ -3,7 +3,7 @@ export default /* glsl */` vColor = vec4( 1.0 ); -#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) +#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) vColor = vec3( 1.0 ); @@ -19,5 +19,13 @@ export default /* glsl */` vColor.xyz *= instanceColor.xyz; +#endif + +#ifdef USE_BATCHING_COLOR + + vec3 batchingColor = getBatchingColor( batchId ); + + vColor.xyz *= batchingColor.xyz; + #endif `; diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index cfccc448bfb3ae..b133801128fd93 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -522,6 +522,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.extensionClipCullDistance ? '#define USE_CLIP_DISTANCE' : '', parameters.batching ? '#define USE_BATCHING' : '', + parameters.batchingColor ? '#define USE_BATCHING_COLOR' : '', parameters.instancing ? '#define USE_INSTANCING' : '', parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', parameters.instancingMorph ? '#define USE_INSTANCING_MORPH' : '', @@ -799,7 +800,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', - parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', + parameters.vertexColors || parameters.instancingColor || parameters.batchingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUv1s ? '#define USE_UV1' : '', parameters.vertexUv2s ? '#define USE_UV2' : '', diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js index f4701d9006314d..7884fd5222b110 100644 --- a/src/renderers/webgl/WebGLPrograms.js +++ b/src/renderers/webgl/WebGLPrograms.js @@ -192,6 +192,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities precision: precision, batching: IS_BATCHEDMESH, + batchingColor: IS_BATCHEDMESH && object.colorsTexture !== null, instancing: IS_INSTANCEDMESH, instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null, @@ -510,6 +511,8 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 19 ); if ( parameters.dispersion ) _programLayers.enable( 20 ); + if ( parameters.batchingColor ) + _programLayers.enable( 21 ); array.push( _programLayers.mask ); _programLayers.disableAll(); From 45c34a104ad57e30fe31b69f7bc43b993954ccbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quique=20Mar=C3=ADn=20Richelet?= Date: Fri, 10 May 2024 13:40:09 +0200 Subject: [PATCH 2/5] pr fixes and suggestions --- src/core/Object3D.js | 2 +- src/loaders/ObjectLoader.js | 2 +- src/objects/BatchedMesh.js | 33 +++++++++++----------------- src/renderers/WebGLRenderer.js | 8 +++---- src/renderers/webgl/WebGLPrograms.js | 2 +- 5 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/core/Object3D.js b/src/core/Object3D.js index a317d6e2f99187..9cd4a5486b20e2 100644 --- a/src/core/Object3D.js +++ b/src/core/Object3D.js @@ -761,7 +761,7 @@ class Object3D extends EventDispatcher { object.matricesTexture = this._matricesTexture.toJSON( meta ); - if ( this.colorsTexture !== null ) object.colorsTexture = this.colorsTexture.toJSON( meta ); + if ( this._colorsTexture !== null ) object.colorsTexture = this._colorsTexture.toJSON( meta ); if ( this.boundingSphere !== null ) { diff --git a/src/loaders/ObjectLoader.js b/src/loaders/ObjectLoader.js index 73d8afc8d68592..4f34700d8de848 100644 --- a/src/loaders/ObjectLoader.js +++ b/src/loaders/ObjectLoader.js @@ -946,7 +946,7 @@ class ObjectLoader extends Loader { object._geometryCount = data.geometryCount; object._matricesTexture = getTexture( data.matricesTexture.uuid ); - if ( data.colorsTexture !== undefined ) object.colorsTexture = getTexture( data.colorsTexture.uuid ); + if ( data.colorsTexture !== undefined ) object._colorsTexture = getTexture( data.colorsTexture.uuid ); break; diff --git a/src/objects/BatchedMesh.js b/src/objects/BatchedMesh.js index c9449a3e7c3026..4aead42e32ba64 100644 --- a/src/objects/BatchedMesh.js +++ b/src/objects/BatchedMesh.js @@ -161,7 +161,7 @@ class BatchedMesh extends Mesh { this._initMatricesTexture(); // Local color per geometry by using data texture - this.colorsTexture = null; + this._colorsTexture = null; } @@ -187,20 +187,13 @@ class BatchedMesh extends Mesh { _initColorsTexture() { - // layout (1 color = 1 pixel) - // RGBA (=> column1) - // with 8x8 pixel texture max 64 matrices * 1 pixel = (8 * 8) - // 16x16 pixel texture max 256 matrices * 1 pixel = (16 * 16) - // 32x32 pixel texture max 1024 matrices * 1 pixel = (32 * 32) - // 64x64 pixel texture max 4096 matrices * 1 pixel = (64 * 64) - - let size = Math.sqrt( this._maxGeometryCount ); // 1 pixel needed for 1 color + let size = Math.sqrt( this._maxGeometryCount ); size = Math.ceil( size ); const colorsArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel const colorsTexture = new DataTexture( colorsArray, size, size, RGBAFormat, FloatType ); - this.colorsTexture = colorsTexture; + this._colorsTexture = colorsTexture; } @@ -770,7 +763,7 @@ class BatchedMesh extends Mesh { setColorAt( geometryId, color ) { - if ( this.colorsTexture === null ) { + if ( this._colorsTexture === null ) { this._initColorsTexture(); @@ -780,8 +773,8 @@ class BatchedMesh extends Mesh { // optimize() can make geometryId mismatch the index const active = this._active; - const colorsTexture = this.colorsTexture; - const colorsArray = this.colorsTexture.image.data; + const colorsTexture = this._colorsTexture; + const colorsArray = this._colorsTexture.image.data; const geometryCount = this._geometryCount; if ( geometryId >= geometryCount || active[ geometryId ] === false ) { @@ -799,7 +792,7 @@ class BatchedMesh extends Mesh { getColorAt( geometryId, color ) { const active = this._active; - const colorsArray = this.colorsTexture.image.data; + const colorsArray = this._colorsTexture.image.data; const geometryCount = this._geometryCount; if ( geometryId >= geometryCount || active[ geometryId ] === false ) { @@ -951,10 +944,10 @@ class BatchedMesh extends Mesh { this._matricesTexture = source._matricesTexture.clone(); this._matricesTexture.image.data = this._matricesTexture.image.slice(); - if ( this.colorsTexture !== null ) { + if ( this._colorsTexture !== null ) { - this.colorsTexture = source.colorsTexture.clone(); - this.colorsTexture.image.data = this.colorsTexture.image.slice(); + this._colorsTexture = source._colorsTexture.clone(); + this._colorsTexture.image.data = this._colorsTexture.image.slice(); } @@ -970,10 +963,10 @@ class BatchedMesh extends Mesh { this._matricesTexture.dispose(); this._matricesTexture = null; - if ( this.colorsTexture !== null ) { + if ( this._colorsTexture !== null ) { - this.colorsTexture.dispose(); - this.colorsTexture = null; + this._colorsTexture.dispose(); + this._colorsTexture = null; } diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 1d027de266a2a4..adab872fccaae9 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -1806,11 +1806,11 @@ class WebGLRenderer { needsProgramChange = true; - } else if ( object.isBatchedMesh && materialProperties.batchingColor === true && object.colorTexture === null ) { + } else if ( object.isBatchedMesh && materialProperties.batchingColor === true ) { needsProgramChange = true; - } else if ( object.isBatchedMesh && materialProperties.batchingColor === false && object.colorTexture !== null ) { + } else if ( object.isBatchedMesh && materialProperties.batchingColor === false ) { needsProgramChange = true; @@ -2007,9 +2007,9 @@ class WebGLRenderer { p_uniforms.setValue( _gl, 'batchingTexture', object._matricesTexture, textures ); p_uniforms.setOptional( _gl, object, 'batchingColorTexture' ); - if ( object.colorsTexture !== null ) { + if ( object._colorsTexture !== null ) { - p_uniforms.setValue( _gl, 'batchingColorTexture', object.colorsTexture, textures ); + p_uniforms.setValue( _gl, 'batchingColorTexture', object._colorsTexture, textures ); } diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js index 7884fd5222b110..82a19b766e4aa4 100644 --- a/src/renderers/webgl/WebGLPrograms.js +++ b/src/renderers/webgl/WebGLPrograms.js @@ -192,7 +192,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities precision: precision, batching: IS_BATCHEDMESH, - batchingColor: IS_BATCHEDMESH && object.colorsTexture !== null, + batchingColor: IS_BATCHEDMESH && object._colorsTexture !== null, instancing: IS_INSTANCEDMESH, instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null, From 9e5eaf0f3445fc16a0f21b116f6cc8295cd545c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quique=20Mar=C3=ADn=20Richelet?= Date: Mon, 13 May 2024 10:11:41 +0200 Subject: [PATCH 3/5] bring back previous condition to recompile shader --- src/renderers/WebGLRenderer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index adab872fccaae9..e43ba7233626ef 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -1806,11 +1806,11 @@ class WebGLRenderer { needsProgramChange = true; - } else if ( object.isBatchedMesh && materialProperties.batchingColor === true ) { + } else if ( object.isBatchedMesh && materialProperties.batchingColor === true && object.colorTexture === null ) { needsProgramChange = true; - } else if ( object.isBatchedMesh && materialProperties.batchingColor === false ) { + } else if ( object.isBatchedMesh && materialProperties.batchingColor === false && object.colorTexture !== null ) { needsProgramChange = true; From cffc52d41e01e8319f0920d576c43721e70bd20e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quique=20Mar=C3=ADn=20Richelet?= Date: Thu, 16 May 2024 16:49:19 +0200 Subject: [PATCH 4/5] add colorSpace to DataTexture --- src/objects/BatchedMesh.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/objects/BatchedMesh.js b/src/objects/BatchedMesh.js index 4aead42e32ba64..8f09bd4f6a3812 100644 --- a/src/objects/BatchedMesh.js +++ b/src/objects/BatchedMesh.js @@ -5,6 +5,7 @@ import { FloatType } from '../constants.js'; import { Matrix4 } from '../math/Matrix4.js'; import { Mesh } from './Mesh.js'; import { RGBAFormat } from '../constants.js'; +import { ColorManagement } from '../math/ColorManagement.js'; import { Box3 } from '../math/Box3.js'; import { Sphere } from '../math/Sphere.js'; import { Frustum } from '../math/Frustum.js'; @@ -192,6 +193,7 @@ class BatchedMesh extends Mesh { const colorsArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel const colorsTexture = new DataTexture( colorsArray, size, size, RGBAFormat, FloatType ); + colorsTexture.colorSpace = ColorManagement.workingColorSpace; this._colorsTexture = colorsTexture; From 957152d647746aea9ce30ead5f52182aa006982f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quique=20Mar=C3=ADn=20Richelet?= Date: Thu, 16 May 2024 16:58:12 +0200 Subject: [PATCH 5/5] change instance to geometry in docs --- docs/api/en/objects/BatchedMesh.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/api/en/objects/BatchedMesh.html b/docs/api/en/objects/BatchedMesh.html index b25285a689b329..bd2c2aae607944 100644 --- a/docs/api/en/objects/BatchedMesh.html +++ b/docs/api/en/objects/BatchedMesh.html @@ -133,14 +133,14 @@

[method:undefined getColorAt]( [param:Integer index], [param:Color color] )

- [page:Integer index]: The index of an instance. Values have to be in the + [page:Integer index]: The index of a geometry. Values have to be in the range [0, count].

[page:Color color]: This color object will be set to the color of the - defined instance. + defined geometry.

-

Get the color of the defined instance.

+

Get the color of the defined geometry.

[method:Matrix4 getMatrixAt]( [param:Integer index], [param:Matrix4 matrix] ) @@ -168,12 +168,12 @@

[method:undefined setColorAt]( [param:Integer index], [param:Color color] )

- [page:Integer index]: The index of an instance. Values have to be in the + [page:Integer index]: The index of a geometry. Values have to be in the range [0, count].

-

[page:Color color]: The color of a single instance.

+

[page:Color color]: The color of a single geometry.

- Sets the given color to the defined instance. + Sets the given color to the defined geometry.