Pārlūkot izejas kodu

InstancingMesh: Added per instance color support

Mr.doob 5 gadi atpakaļ
vecāks
revīzija
e4dfea2672

+ 13 - 0
src/objects/InstancedMesh.js

@@ -14,6 +14,7 @@ function InstancedMesh( geometry, material, count ) {
 	Mesh.call( this, geometry, material );
 
 	this.instanceMatrix = new BufferAttribute( new Float32Array( count * 16 ), 16 );
+	this.instanceColor = null;
 
 	this.count = count;
 
@@ -38,6 +39,18 @@ InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
 
 	},
 
+	setColorAt: function ( index, color ) {
+
+		if ( this.instanceColor === null ) {
+
+			this.instanceColor = new BufferAttribute( new Float32Array( this.count * 3 ), 3 );
+
+		}
+
+		color.toArray( this.instanceColor.array, index * 3 );
+
+	},
+
 	getMatrixAt: function ( index, matrix ) {
 
 		matrix.fromArray( this.instanceMatrix.array, index * 16 );

+ 1 - 1
src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js

@@ -1,5 +1,5 @@
 export default /* glsl */`
-#ifdef USE_COLOR
+#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )
 
 	varying vec3 vColor;
 

+ 13 - 1
src/renderers/shaders/ShaderChunk/color_vertex.glsl.js

@@ -1,7 +1,19 @@
 export default /* glsl */`
+#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )
+
+	vColor = vec3( 1.0 );
+
+#endif
+
 #ifdef USE_COLOR
 
-	vColor.xyz = color.xyz;
+	vColor.xyz *= color.xyz;
+
+#endif
+
+#ifdef USE_INSTANCING_COLOR
+
+	vColor.xyz *= instanceColor.xyz;
 
 #endif
 `;

+ 17 - 0
src/renderers/webgl/WebGLBindingStates.js

@@ -402,6 +402,23 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) {
 					gl.vertexAttribPointer( programAttribute + 2, 4, type, false, 64, 32 );
 					gl.vertexAttribPointer( programAttribute + 3, 4, type, false, 64, 48 );
 
+				} else if ( name === 'instanceColor' ) {
+
+					const attribute = attributes.get( object.instanceColor );
+
+					// TODO Attribute may not be available on context restore
+
+					if ( attribute === undefined ) continue;
+
+					const buffer = attribute.buffer;
+					const type = attribute.type;
+
+					enableAttributeAndDivisor( programAttribute, 1 );
+
+					gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
+
+					gl.vertexAttribPointer( programAttribute, 3, type, false, 12, 0 );
+
 				} else if ( materialDefaultAttributeValues !== undefined ) {
 
 					const value = materialDefaultAttributeValues[ name ];

+ 6 - 0
src/renderers/webgl/WebGLObjects.js

@@ -29,6 +29,12 @@ function WebGLObjects( gl, geometries, attributes, info ) {
 
 			attributes.update( object.instanceMatrix, gl.ARRAY_BUFFER );
 
+			if ( object.instanceColor !== null ) {
+
+				attributes.update( object.instanceColor, gl.ARRAY_BUFFER );
+
+			}
+
 		}
 
 		return buffergeometry;

+ 10 - 2
src/renderers/webgl/WebGLProgram.js

@@ -444,6 +444,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 			customDefines,
 
 			parameters.instancing ? '#define USE_INSTANCING' : '',
+			parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
+
 			parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
 
 			'#define GAMMA_FACTOR ' + gammaFactorDefine,
@@ -506,7 +508,13 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 
 			'#ifdef USE_INSTANCING',
 
-			' attribute mat4 instanceMatrix;',
+			'	attribute mat4 instanceMatrix;',
+
+			'#endif',
+
+			'#ifdef USE_INSTANCING_COLOR',
+
+			'	attribute vec3 instanceColor;',
 
 			'#endif',
 
@@ -604,7 +612,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 			parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
 
 			parameters.vertexTangents ? '#define USE_TANGENT' : '',
-			parameters.vertexColors ? '#define USE_COLOR' : '',
+			parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
 			parameters.vertexUvs ? '#define USE_UV' : '',
 			parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
 

+ 2 - 1
src/renderers/webgl/WebGLPrograms.js

@@ -34,7 +34,7 @@ function WebGLPrograms( renderer, extensions, capabilities, bindingStates ) {
 	};
 
 	const parameterNames = [
-		"precision", "isWebGL2", "supportsVertexTextures", "outputEncoding", "instancing",
+		"precision", "isWebGL2", "supportsVertexTextures", "outputEncoding", "instancing", "instancingColor",
 		"map", "mapEncoding", "matcap", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding", "envMapCubeUV",
 		"lightMap", "lightMapEncoding", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "tangentSpaceNormalMap", "clearcoatMap", "clearcoatRoughnessMap", "clearcoatNormalMap", "displacementMap", "specularMap",
 		"roughnessMap", "metalnessMap", "gradientMap",
@@ -169,6 +169,7 @@ function WebGLPrograms( renderer, extensions, capabilities, bindingStates ) {
 			precision: precision,
 
 			instancing: object.isInstancedMesh === true,
+			instancingColor: object.isInstancedMesh === true && object.instanceColor !== null,
 
 			supportsVertexTextures: vertexTextures,
 			outputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding,