Skip to content

Commit

Permalink
BatchedMesh: add getColorAt and setColorAt (#28255)
Browse files Browse the repository at this point in the history
* BatchedMesh: add getColorAt and setColorAt

* pr fixes and suggestions

* bring back previous condition to recompile shader

* add colorSpace to DataTexture

* change instance to geometry in docs
  • Loading branch information
Kikedao committed May 17, 2024
1 parent de367cb commit 3b28707
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 3 deletions.
25 changes: 25 additions & 0 deletions docs/api/en/objects/BatchedMesh.html
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,19 @@ <h3>[method:this setCustomSort]( [param:Function sortFunction] )</h3>
in the list include a "z" field to perform a depth-ordered sort with.
</p>

<h3>
[method:undefined getColorAt]( [param:Integer index], [param:Color color] )
</h3>
<p>
[page:Integer index]: The index of a geometry. Values have to be in the
range [0, count].
</p>
<p>
[page:Color color]: This color object will be set to the color of the
defined geometry.
</p>
<p>Get the color of the defined geometry.</p>

<h3>
[method:Matrix4 getMatrixAt]( [param:Integer index], [param:Matrix4 matrix] )
</h3>
Expand All @@ -151,6 +164,18 @@ <h3>
</p>
<p>Get whether the given instance is marked as "visible" or not.</p>

<h3>
[method:undefined setColorAt]( [param:Integer index], [param:Color color] )
</h3>
<p>
[page:Integer index]: The index of a geometry. Values have to be in the
range [0, count].
</p>
<p>[page:Color color]: The color of a single geometry.</p>
<p>
Sets the given color to the defined geometry.
</p>

<h3>
[method:this setMatrixAt]( [param:Integer index], [param:Matrix4 matrix] )
</h3>
Expand Down
1 change: 1 addition & 0 deletions examples/jsm/renderers/common/RenderObject.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ export default class RenderObject {
if ( object.isBatchedMesh ) {

cacheKey += object._matricesTexture.uuid + ',';
cacheKey += object._colorsTexture.uuid + ',';

}

Expand Down
2 changes: 2 additions & 0 deletions src/core/Object3D.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
1 change: 1 addition & 0 deletions src/loaders/ObjectLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
75 changes: 75 additions & 0 deletions src/objects/BatchedMesh.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -160,6 +161,9 @@ class BatchedMesh extends Mesh {

this._initMatricesTexture();

// Local color per geometry by using data texture
this._colorsTexture = null;

}

_initMatricesTexture() {
Expand All @@ -182,6 +186,19 @@ class BatchedMesh extends Mesh {

}

_initColorsTexture() {

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 );
colorsTexture.colorSpace = ColorManagement.workingColorSpace;

this._colorsTexture = colorsTexture;

}

_initializeGeometry( reference ) {

const geometry = this.geometry;
Expand Down Expand Up @@ -746,6 +763,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;
Expand Down Expand Up @@ -886,6 +946,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;

}
Expand All @@ -897,6 +964,14 @@ class BatchedMesh extends Mesh {

this._matricesTexture.dispose();
this._matricesTexture = null;

if ( this._colorsTexture !== null ) {

this._colorsTexture.dispose();
this._colorsTexture = null;

}

return this;

}
Expand Down
16 changes: 16 additions & 0 deletions src/renderers/WebGLRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
15 changes: 15 additions & 0 deletions src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
`;
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 9 additions & 1 deletion src/renderers/shaders/ShaderChunk/color_vertex.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand All @@ -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
`;
3 changes: 2 additions & 1 deletion src/renderers/webgl/WebGLProgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -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' : '',
Expand Down Expand Up @@ -773,7 +774,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' : '',
Expand Down
3 changes: 3 additions & 0 deletions src/renderers/webgl/WebGLPrograms.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 3b28707

Please sign in to comment.