Skip to content

Commit 9d91428

Browse files
vanruescgkjohnson
andauthored
BatchedMesh: Enable per-instance opacity (#32725)
Co-authored-by: Garrett Johnson <garrett.kjohnson@gmail.com>
1 parent be02a54 commit 9d91428

File tree

9 files changed

+90
-56
lines changed

9 files changed

+90
-56
lines changed
-81.6 KB
Loading

examples/webgl_mesh_batch.html

Lines changed: 72 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
let stats, gui, guiStatsEl;
4141
let camera, controls, scene, renderer;
42-
let geometries, mesh, material;
42+
let geometries, mesh;
4343
const ids = [];
4444
const matrix = new THREE.Matrix4();
4545

@@ -64,9 +64,9 @@
6464
count: 256,
6565
dynamic: 16,
6666

67+
transparent: true,
6768
sortObjects: true,
6869
perObjectFrustumCulled: true,
69-
opacity: 1,
7070
useCustomSort: true,
7171
};
7272

@@ -103,32 +103,68 @@
103103

104104
}
105105

106-
function initGeometries() {
106+
function randomizeColor( color ) {
107107

108-
geometries = [
109-
new THREE.ConeGeometry( 1.0, 2.0 ),
110-
new THREE.BoxGeometry( 2.0, 2.0, 2.0 ),
111-
new THREE.SphereGeometry( 1.0, 16, 8 ),
112-
];
108+
return color.setHSL( Math.random() * 0.5, 0.6, 0.5 );
113109

114110
}
115111

116-
function createMaterial() {
112+
function randomizeAlpha() {
113+
114+
// make ~20% of all objects transparent
115+
return Math.random() > 0.8 ? 0.5 : 1.0;
116+
117+
}
118+
119+
function initGeometries() {
117120

118-
if ( ! material ) {
121+
const cone = new THREE.ConeGeometry( 1.0, 2.0 );
122+
const box = new THREE.BoxGeometry( 2.0, 2.0, 2.0 );
123+
const sphere = new THREE.SphereGeometry( 1.0, 16, 8 );
119124

120-
material = new THREE.MeshNormalMaterial();
125+
geometries = [ cone, box, sphere ];
126+
127+
for ( const geometry of geometries ) {
128+
129+
// add vertex colors for testing
130+
const count = geometry.getAttribute( 'position' ).count;
131+
const attribute = new THREE.BufferAttribute( new Float32Array( count * 3 ), 3 );
132+
geometry.setAttribute( 'color', attribute );
133+
134+
for ( let i = 0, l = attribute.array.length; i < l; ++ i ) {
135+
136+
attribute.array[ i ] = 1.0;
137+
138+
}
121139

122140
}
123141

124-
return material;
142+
}
143+
144+
function createMaterial() {
145+
146+
return new THREE.MeshPhongMaterial( {
147+
vertexColors: true,
148+
transparent: api.transparent,
149+
depthWrite: ! api.transparent
150+
} );
125151

126152
}
127153

128154
function cleanup() {
129155

130156
if ( mesh ) {
131157

158+
mesh.traverse( node => {
159+
160+
if ( node instanceof THREE.Mesh ) {
161+
162+
node.material.dispose();
163+
164+
}
165+
166+
} );
167+
132168
mesh.parent.remove( mesh );
133169

134170
if ( mesh.dispose ) {
@@ -160,10 +196,13 @@
160196
function initRegularMesh() {
161197

162198
mesh = new THREE.Group();
163-
const material = createMaterial();
164199

165200
for ( let i = 0; i < api.count; i ++ ) {
166201

202+
const material = createMaterial();
203+
randomizeColor( material.color );
204+
material.opacity = randomizeAlpha();
205+
167206
const child = new THREE.Mesh( geometries[ i % geometries.length ], material );
168207
randomizeMatrix( child.matrix );
169208
child.matrix.decompose( child.position, child.quaternion, child.scale );
@@ -184,6 +223,8 @@
184223

185224
const euler = new THREE.Euler();
186225
const matrix = new THREE.Matrix4();
226+
const color = new THREE.Color();
227+
const colorWithAlpha = new THREE.Vector4();
187228
mesh = new THREE.BatchedMesh( geometryCount, vertexCount, indexCount, createMaterial() );
188229
mesh.userData.rotationSpeeds = [];
189230

@@ -200,8 +241,12 @@
200241

201242
for ( let i = 0; i < api.count; i ++ ) {
202243

244+
randomizeColor( color );
245+
colorWithAlpha.set( color.r, color.g, color.b, randomizeAlpha() );
246+
203247
const id = mesh.addInstance( geometryIds[ i % geometryIds.length ] );
204248
mesh.setMatrixAt( id, randomizeMatrix( matrix ) );
249+
mesh.setColorAt( id, colorWithAlpha );
205250

206251
const rotationMatrix = new THREE.Matrix4();
207252
rotationMatrix.makeRotationFromEuler( randomizeRotationSpeed( euler ) );
@@ -244,6 +289,13 @@
244289
controls.autoRotate = true;
245290
controls.autoRotateSpeed = 1.0;
246291

292+
// light
293+
294+
const ambientLight = new THREE.AmbientLight( 0xffffff, 2 );
295+
const directionalLight = new THREE.DirectionalLight( 0xffffff, 2 );
296+
directionalLight.position.set( 1, 1, 1 );
297+
scene.add( directionalLight, ambientLight );
298+
247299
// stats
248300

249301
stats = new Stats();
@@ -255,24 +307,20 @@
255307
gui.add( api, 'count', 1, MAX_GEOMETRY_COUNT ).step( 1 ).onChange( initMesh );
256308
gui.add( api, 'dynamic', 0, MAX_GEOMETRY_COUNT ).step( 1 );
257309
gui.add( api, 'method', Method ).onChange( initMesh );
258-
gui.add( api, 'opacity', 0, 1 ).onChange( v => {
259-
260-
if ( v < 1 ) {
261310

262-
material.transparent = true;
263-
material.depthWrite = false;
311+
gui.add( api, 'transparent' ).onChange( v => mesh.traverse( node => {
264312

265-
} else {
313+
if ( node instanceof THREE.Mesh ) {
266314

267-
material.transparent = false;
268-
material.depthWrite = true;
315+
const material = node.material;
316+
material.transparent = v;
317+
material.depthWrite = ! v;
318+
material.needsUpdate = true;
269319

270320
}
271321

272-
material.opacity = v;
273-
material.needsUpdate = true;
322+
} ) );
274323

275-
} );
276324
gui.add( api, 'sortObjects' );
277325
gui.add( api, 'perObjectFrustumCulled' );
278326
gui.add( api, 'useCustomSort' );

src/objects/BatchedMesh.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,7 @@ class BatchedMesh extends Mesh {
11031103
* Sets the given color to the defined instance.
11041104
*
11051105
* @param {number} instanceId - The ID of an instance to set the color of.
1106-
* @param {Color} color - The color to set the instance to.
1106+
* @param {Color|Vector4} color - The color to set the instance to. Use a `Vector4` to also define alpha.
11071107
* @return {BatchedMesh} A reference to this batched mesh.
11081108
*/
11091109
setColorAt( instanceId, color ) {
@@ -1127,8 +1127,8 @@ class BatchedMesh extends Mesh {
11271127
* Returns the color of the defined instance.
11281128
*
11291129
* @param {number} instanceId - The ID of an instance to get the color of.
1130-
* @param {Color} color - The target object that is used to store the method's result.
1131-
* @return {Color} The instance's color.
1130+
* @param {Color|Vector4} color - The target object that is used to store the method's result.
1131+
* @return {Color|Vector4} The instance's color. Use a `Vector4` to also retrieve alpha.
11321132
*/
11331133
getColorAt( instanceId, color ) {
11341134

src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ export default /* glsl */`
3535
#ifdef USE_BATCHING_COLOR
3636
3737
uniform sampler2D batchingColorTexture;
38-
vec3 getBatchingColor( const in float i ) {
38+
vec4 getBatchingColor( const in float i ) {
3939
4040
int size = textureSize( batchingColorTexture, 0 ).x;
4141
int j = int( i );
4242
int x = j % size;
4343
int y = j / size;
44-
return texelFetch( batchingColorTexture, ivec2( x, y ), 0 ).rgb;
44+
return texelFetch( batchingColorTexture, ivec2( x, y ), 0 );
4545
4646
}
4747
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
export default /* glsl */`
2-
#if defined( USE_COLOR_ALPHA )
2+
#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA )
33
44
diffuseColor *= vColor;
55
6-
#elif defined( USE_COLOR )
7-
8-
diffuseColor.rgb *= vColor;
9-
106
#endif
117
`;
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
export default /* glsl */`
2-
#if defined( USE_COLOR_ALPHA )
2+
#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA )
33
44
varying vec4 vColor;
55
6-
#elif defined( USE_COLOR )
7-
8-
varying vec3 vColor;
9-
106
#endif
117
`;
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
export default /* glsl */`
2-
#if defined( USE_COLOR_ALPHA )
2+
#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )
33
44
varying vec4 vColor;
55
6-
#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )
7-
8-
varying vec3 vColor;
9-
106
#endif
117
`;
Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,29 @@
11
export default /* glsl */`
2-
#if defined( USE_COLOR_ALPHA )
2+
#if defined( USE_COLOR ) || defined( USE_COLOR_ALPHA ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )
33
44
vColor = vec4( 1.0 );
55
6-
#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )
7-
8-
vColor = vec3( 1.0 );
9-
106
#endif
117
12-
#ifdef USE_COLOR
8+
#ifdef USE_COLOR_ALPHA
139
1410
vColor *= color;
1511
12+
#elif defined( USE_COLOR )
13+
14+
vColor.rgb *= color;
15+
1616
#endif
1717
1818
#ifdef USE_INSTANCING_COLOR
1919
20-
vColor.xyz *= instanceColor.xyz;
20+
vColor.rgb *= instanceColor.rgb;
2121
2222
#endif
2323
2424
#ifdef USE_BATCHING_COLOR
2525
26-
vec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );
27-
28-
vColor.xyz *= batchingColor.xyz;
26+
vColor *= getBatchingColor( getIndirectIndex( gl_DrawID ) );
2927
3028
#endif
3129
`;

src/renderers/webgl/WebGLProgram.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -732,8 +732,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
732732
parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
733733

734734
parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '',
735-
parameters.vertexColors || parameters.instancingColor || parameters.batchingColor ? '#define USE_COLOR' : '',
736-
parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
735+
parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
736+
parameters.vertexAlphas || parameters.batchingColor ? '#define USE_COLOR_ALPHA' : '',
737737
parameters.vertexUv1s ? '#define USE_UV1' : '',
738738
parameters.vertexUv2s ? '#define USE_UV2' : '',
739739
parameters.vertexUv3s ? '#define USE_UV3' : '',

0 commit comments

Comments
 (0)