Browse Source

Enable mat2/3/4 attribute in shader (#16141)

* Enable mat2/3/4 in shader

* Clean up instanceMatrix and instanceColor WebGL handlings
Takahiro 4 years ago
parent
commit
19359e3aef

+ 2 - 2
docs/api/en/objects/InstancedMesh.html

@@ -51,13 +51,13 @@
 			If you need more instances than the original count value, you have to create a new [name].
 			If you need more instances than the original count value, you have to create a new [name].
 		</p>
 		</p>
 
 
-		<h3>[property:BufferAttribute instanceColor]</h3>
+		<h3>[property:InstancedBufferAttribute instanceColor]</h3>
 		<p>
 		<p>
 			Represents the colors of all instances. *null* by default.
 			Represents the colors of all instances. *null* by default.
 			You have to set its [page:BufferAttribute.needsUpdate needsUpdate] flag to true if you modify instanced data via [page:.setColorAt]().
 			You have to set its [page:BufferAttribute.needsUpdate needsUpdate] flag to true if you modify instanced data via [page:.setColorAt]().
 		</p>
 		</p>
 
 
-		<h3>[property:BufferAttribute instanceMatrix]</h3>
+		<h3>[property:InstancedBufferAttribute instanceMatrix]</h3>
 		<p>
 		<p>
 			Represents the local transformation of all instances.
 			Represents the local transformation of all instances.
 			You have to set its [page:BufferAttribute.needsUpdate needsUpdate] flag to true if you modify instanced data via [page:.setMatrixAt]().
 			You have to set its [page:BufferAttribute.needsUpdate needsUpdate] flag to true if you modify instanced data via [page:.setMatrixAt]().

+ 2 - 2
docs/api/zh/objects/InstancedMesh.html

@@ -49,13 +49,13 @@
 			如果你需要比原先的数量更多的实例数量,你需要创建一个新的[name]。
 			如果你需要比原先的数量更多的实例数量,你需要创建一个新的[name]。
 		</p>
 		</p>
 
 
-		<h3>[property:BufferAttribute instanceColor]</h3>
+		<h3>[property:InstancedBufferAttribute instanceColor]</h3>
 		<p>
 		<p>
 			Represents the colors of all instances. *null* by default.
 			Represents the colors of all instances. *null* by default.
 			You have to set its [page:BufferAttribute.needsUpdate needsUpdate] flag to true if you modify instanced data via [page:.setColorAt]().
 			You have to set its [page:BufferAttribute.needsUpdate needsUpdate] flag to true if you modify instanced data via [page:.setColorAt]().
 		</p>
 		</p>
 
 
-		<h3>[property:BufferAttribute instanceMatrix]</h3>
+		<h3>[property:InstancedBufferAttribute instanceMatrix]</h3>
 		<p>
 		<p>
 			表示所有实例的本地变换。
 			表示所有实例的本地变换。
 			如果你要通过 [page:.setMatrixAt]() 来修改实例数据,你必须将它的 [page:BufferAttribute.needsUpdate needsUpdate] 标识为 true 。
 			如果你要通过 [page:.setMatrixAt]() 来修改实例数据,你必须将它的 [page:BufferAttribute.needsUpdate needsUpdate] 标识为 true 。

+ 3 - 3
src/loaders/ObjectLoader.js

@@ -18,7 +18,7 @@ import {
 	LinearMipmapNearestFilter,
 	LinearMipmapNearestFilter,
 	LinearMipmapLinearFilter
 	LinearMipmapLinearFilter
 } from '../constants.js';
 } from '../constants.js';
-import { BufferAttribute } from '../core/BufferAttribute.js';
+import { InstancedBufferAttribute } from '../core/InstancedBufferAttribute.js';
 import { Color } from '../math/Color.js';
 import { Color } from '../math/Color.js';
 import { Object3D } from '../core/Object3D.js';
 import { Object3D } from '../core/Object3D.js';
 import { Group } from '../objects/Group.js';
 import { Group } from '../objects/Group.js';
@@ -908,8 +908,8 @@ class ObjectLoader extends Loader {
 				const instanceColor = data.instanceColor;
 				const instanceColor = data.instanceColor;
 
 
 				object = new InstancedMesh( geometry, material, count );
 				object = new InstancedMesh( geometry, material, count );
-				object.instanceMatrix = new BufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
-				if ( instanceColor !== undefined ) object.instanceColor = new BufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize );
+				object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
+				if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize );
 
 
 				break;
 				break;
 
 

+ 3 - 3
src/objects/InstancedMesh.js

@@ -1,4 +1,4 @@
-import { BufferAttribute } from '../core/BufferAttribute.js';
+import { InstancedBufferAttribute } from '../core/InstancedBufferAttribute.js';
 import { Mesh } from './Mesh.js';
 import { Mesh } from './Mesh.js';
 import { Matrix4 } from '../math/Matrix4.js';
 import { Matrix4 } from '../math/Matrix4.js';
 
 
@@ -15,7 +15,7 @@ class InstancedMesh extends Mesh {
 
 
 		super( geometry, material );
 		super( geometry, material );
 
 
-		this.instanceMatrix = new BufferAttribute( new Float32Array( count * 16 ), 16 );
+		this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 );
 		this.instanceColor = null;
 		this.instanceColor = null;
 
 
 		this.count = count;
 		this.count = count;
@@ -95,7 +95,7 @@ class InstancedMesh extends Mesh {
 
 
 		if ( this.instanceColor === null ) {
 		if ( this.instanceColor === null ) {
 
 
-			this.instanceColor = new BufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ), 3 );
+			this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ), 3 );
 
 
 		}
 		}
 
 

+ 8 - 8
src/renderers/WebGLRenderer.js

@@ -687,8 +687,8 @@ function WebGLRenderer( parameters = {} ) {
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
 
 
-			bindingStates.enableAttribute( programAttributes.position );
-			_gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 );
+			bindingStates.enableAttribute( programAttributes.position.location );
+			_gl.vertexAttribPointer( programAttributes.position.location, 3, _gl.FLOAT, false, 0, 0 );
 
 
 		}
 		}
 
 
@@ -697,8 +697,8 @@ function WebGLRenderer( parameters = {} ) {
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal );
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
 
 
-			bindingStates.enableAttribute( programAttributes.normal );
-			_gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 );
+			bindingStates.enableAttribute( programAttributes.normal.location );
+			_gl.vertexAttribPointer( programAttributes.normal.location, 3, _gl.FLOAT, false, 0, 0 );
 
 
 		}
 		}
 
 
@@ -707,8 +707,8 @@ function WebGLRenderer( parameters = {} ) {
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
 
 
-			bindingStates.enableAttribute( programAttributes.uv );
-			_gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 );
+			bindingStates.enableAttribute( programAttributes.uv.location );
+			_gl.vertexAttribPointer( programAttributes.uv.location, 2, _gl.FLOAT, false, 0, 0 );
 
 
 		}
 		}
 
 
@@ -717,8 +717,8 @@ function WebGLRenderer( parameters = {} ) {
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
 
 
-			bindingStates.enableAttribute( programAttributes.color );
-			_gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 );
+			bindingStates.enableAttribute( programAttributes.color.location );
+			_gl.vertexAttribPointer( programAttributes.color.location, 3, _gl.FLOAT, false, 0, 0 );
 
 
 		}
 		}
 
 

+ 58 - 51
src/renderers/webgl/WebGLBindingStates.js

@@ -322,9 +322,16 @@
 
 
 			const programAttribute = programAttributes[ name ];
 			const programAttribute = programAttributes[ name ];
 
 
-			if ( programAttribute >= 0 ) {
+			if ( programAttribute.location >= 0 ) {
 
 
-				const geometryAttribute = geometryAttributes[ name ];
+				let geometryAttribute = geometryAttributes[ name ];
+
+				if ( geometryAttribute === undefined ) {
+
+					if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix;
+					if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor;
+
+				}
 
 
 				if ( geometryAttribute !== undefined ) {
 				if ( geometryAttribute !== undefined ) {
 
 
@@ -349,85 +356,85 @@
 
 
 						if ( data && data.isInstancedInterleavedBuffer ) {
 						if ( data && data.isInstancedInterleavedBuffer ) {
 
 
-							enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
-
-							if ( geometry._maxInstanceCount === undefined ) {
+							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
 
 
-								geometry._maxInstanceCount = data.meshPerAttribute * data.count;
+								enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute );
 
 
 							}
 							}
 
 
-						} else {
-
-							enableAttribute( programAttribute );
+							if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
 
 
-						}
+								geometry._maxInstanceCount = data.meshPerAttribute * data.count;
 
 
-						gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
-						vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
+							}
 
 
-					} else {
+						} else {
 
 
-						if ( geometryAttribute.isInstancedBufferAttribute ) {
+							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
 
 
-							enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
+								enableAttribute( programAttribute.location + i );
 
 
-							if ( geometry._maxInstanceCount === undefined ) {
+							}
 
 
-								geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
+						}
 
 
-							}
+						gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
 
 
-						} else {
+						for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
 
 
-							enableAttribute( programAttribute );
+							vertexAttribPointer(
+								programAttribute.location + i,
+								size / programAttribute.locationSize,
+								type,
+								normalized,
+								stride * bytesPerElement,
+								( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement
+							);
 
 
 						}
 						}
 
 
-						gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
-						vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );
+					} else {
 
 
-					}
+						if ( geometryAttribute.isInstancedBufferAttribute ) {
 
 
-				} else if ( name === 'instanceMatrix' ) {
+							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
 
 
-					const attribute = attributes.get( object.instanceMatrix );
+								enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute );
 
 
-					// TODO Attribute may not be available on context restore
+							}
 
 
-					if ( attribute === undefined ) continue;
+							if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
 
 
-					const buffer = attribute.buffer;
-					const type = attribute.type;
+								geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
 
 
-					enableAttributeAndDivisor( programAttribute + 0, 1 );
-					enableAttributeAndDivisor( programAttribute + 1, 1 );
-					enableAttributeAndDivisor( programAttribute + 2, 1 );
-					enableAttributeAndDivisor( programAttribute + 3, 1 );
+							}
 
 
-					gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
+						} else {
 
 
-					gl.vertexAttribPointer( programAttribute + 0, 4, type, false, 64, 0 );
-					gl.vertexAttribPointer( programAttribute + 1, 4, type, false, 64, 16 );
-					gl.vertexAttribPointer( programAttribute + 2, 4, type, false, 64, 32 );
-					gl.vertexAttribPointer( programAttribute + 3, 4, type, false, 64, 48 );
+							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
 
 
-				} else if ( name === 'instanceColor' ) {
+								enableAttribute( programAttribute.location + i );
 
 
-					const attribute = attributes.get( object.instanceColor );
+							}
 
 
-					// TODO Attribute may not be available on context restore
+						}
 
 
-					if ( attribute === undefined ) continue;
+						gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
 
 
-					const buffer = attribute.buffer;
-					const type = attribute.type;
+						for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
 
 
-					enableAttributeAndDivisor( programAttribute, 1 );
+							vertexAttribPointer(
+								programAttribute.location + i,
+								size / programAttribute.locationSize,
+								type,
+								normalized,
+								size * bytesPerElement,
+								( size / programAttribute.locationSize ) * i * bytesPerElement
+							);
 
 
-					gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
+						}
 
 
-					gl.vertexAttribPointer( programAttribute, 3, type, false, 12, 0 );
+					}
 
 
 				} else if ( materialDefaultAttributeValues !== undefined ) {
 				} else if ( materialDefaultAttributeValues !== undefined ) {
 
 
@@ -438,19 +445,19 @@
 						switch ( value.length ) {
 						switch ( value.length ) {
 
 
 							case 2:
 							case 2:
-								gl.vertexAttrib2fv( programAttribute, value );
+								gl.vertexAttrib2fv( programAttribute.location, value );
 								break;
 								break;
 
 
 							case 3:
 							case 3:
-								gl.vertexAttrib3fv( programAttribute, value );
+								gl.vertexAttrib3fv( programAttribute.location, value );
 								break;
 								break;
 
 
 							case 4:
 							case 4:
-								gl.vertexAttrib4fv( programAttribute, value );
+								gl.vertexAttrib4fv( programAttribute.location, value );
 								break;
 								break;
 
 
 							default:
 							default:
-								gl.vertexAttrib1fv( programAttribute, value );
+								gl.vertexAttrib1fv( programAttribute.location, value );
 
 
 						}
 						}
 
 

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

@@ -153,9 +153,18 @@ function fetchAttributeLocations( gl, program ) {
 		const info = gl.getActiveAttrib( program, i );
 		const info = gl.getActiveAttrib( program, i );
 		const name = info.name;
 		const name = info.name;
 
 
+		let locationSize = 1;
+		if ( info.type === gl.FLOAT_MAT2 ) locationSize = 2;
+		if ( info.type === gl.FLOAT_MAT3 ) locationSize = 3;
+		if ( info.type === gl.FLOAT_MAT4 ) locationSize = 4;
+
 		// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
 		// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
 
 
-		attributes[ name ] = gl.getAttribLocation( program, name );
+		attributes[ name ] = {
+			type: info.type,
+			location: gl.getAttribLocation( program, name ),
+			locationSize: locationSize
+		};
 
 
 	}
 	}
 
 

+ 3 - 0
utils/build/rollup.config.js

@@ -125,6 +125,9 @@ export function glconstants() {
 		FRAGMENT_SHADER: 35632,
 		FRAGMENT_SHADER: 35632,
 		MAX_VERTEX_TEXTURE_IMAGE_UNITS: 35660,
 		MAX_VERTEX_TEXTURE_IMAGE_UNITS: 35660,
 		MAX_COMBINED_TEXTURE_IMAGE_UNITS: 35661,
 		MAX_COMBINED_TEXTURE_IMAGE_UNITS: 35661,
+		FLOAT_MAT2: 35674,
+		FLOAT_MAT3: 35675,
+		FLOAT_MAT4: 35676,
 		COMPILE_STATUS: 35713,
 		COMPILE_STATUS: 35713,
 		LINK_STATUS: 35714,
 		LINK_STATUS: 35714,
 		VALIDATE_STATUS: 35715,
 		VALIDATE_STATUS: 35715,