浏览代码

Support all Typed Array datatypes in bufferAttribute (#8618)

* merge bufferAttributeTypes with dev

* else if

* serialize the normalized flag

* update docs

* remove support for DataView as BufferAttribute source. This is to specific purpose, and geometry using this will break in too many other methods

* reimplement the DataView as a BufferAttribute data source

* try to warn when bufferAttribute contains a DataView and cannot be read

* Changed too many `warn` to `error`

* Code quality update in BufferAttribute datatype selection

* support load and save of normalized flag in BufferAttribute

* Check for DataView attribute buffers

* mend

* Revert "mend"

This reverts commit 1b4c87687d10fdaefd5007b98019b25d33c492e1.

* try to fix after --ammend causes conflicts

* working on cleaning this all up

* More whitespace cleanup

* more code style cleanup

* strike OBE comment

* more spacing cleanup
rchadwic 9 年之前
父节点
当前提交
26d1c78088

+ 8 - 3
docs/api/core/BufferAttribute.html

@@ -15,17 +15,17 @@
 		</div>
 
 		<h2>Constructor</h2>
-		<h3>[name]([page:TypedArray array], [page:Integer itemSize])</h3>
+		<h3>[name]([page:TypedArray array], [page:Integer itemSize], [page:Boolean normalized])</h3>
 		<div>
 		Instantiates this attribute with data from the associated buffer.
-		itemSize gives the number of values of the array that should be associated with a particular vertex.
+		itemSize gives the number of values of the array that should be associated with a particular vertex. normalized indicates how the underlying data in the buffer maps to the values in the GLSL shader code. 
 		</div>
 
 		<h2>Properties</h2>
 
 		<h3>[property:TypedArray array]</h3>
 		<div>
-		Stores the data associated with this attribute. This element should have <code>itemSize * numVertices</code> elements, where numVertices is the number of vertices in the associated [page:BufferGeometry geometry].
+		Stores the data associated with this attribute. This element should have <code>itemSize * numVertices</code> elements, where numVertices is the number of vertices in the associated [page:BufferGeometry geometry].  [page:TypedArray array] can be an instance of UInt8Array, Int8Array, UInt16Array, Int16Array, or Float32Array.
 		</div>
 
 		<h3>[property:Integer itemSize]</h3>
@@ -44,6 +44,11 @@
 		Flag to indicate that this attribute has changed and should be re-send to the GPU. Set this to true when you modify the value of the array.
 		</div>
 
+		<h3>[property:Boolean normalized]</h3>
+		<div>
+		Indicates how the underlying data in the buffer maps to the values in the GLSL code. For instance, if [page:TypedArray array] is an instance of UInt16Array, and [page:Boolean normalized] is true, the values 0 - +65535 in the array data will be mapped to 0.0f - +1.0f in the GLSL attribute. An Int16Array (signed) would map from -32767 - +32767  to -1.0f - +1.0f. If [page:Boolean normalized] is false, the values will be converted to floats which contain the exact value, i.e. 32767 becomes 32767.0f.
+		</div>
+
 		<h3>[property:Integer version]</h3>
 		<div>
 		A version number, incremented every time the needsUpdate property is set to true.

+ 264 - 0
examples/webgl_buffergeometry_bufferDataTypes.html

@@ -0,0 +1,264 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - buffergeometry - uint</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				color: #cccccc;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+
+				background-color: #050505;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px; width: 100%;
+				padding: 5px;
+			}
+
+			a {
+				color: #0080ff;
+			}
+
+		</style>
+	</head>
+	<body>
+
+		<div id="container"></div>
+		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> webgl - buffergeometry - BufferAttributeTypes</div>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var container, stats;
+
+			var camera, scene, renderer;
+
+			var mesh;
+
+			init();
+			animate();
+
+			function init() {
+
+				container = document.getElementById( 'container' );
+
+				//
+
+				camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 3500 );
+				camera.position.z = 2750;
+
+				scene = new THREE.Scene();
+				scene.fog = new THREE.Fog( 0x050505, 2000, 3500 );
+
+				//
+
+				scene.add( new THREE.AmbientLight( 0x444444 ) );
+
+				var light1 = new THREE.DirectionalLight( 0xffffff, 0.5 );
+				light1.position.set( 1, 1, 1 );
+				scene.add( light1 );
+
+				var light2 = new THREE.DirectionalLight( 0xffffff, 1.5 );
+				light2.position.set( 0, -1, 0 );
+				scene.add( light2 );
+
+				//
+
+				var triangles = 500000;
+
+				var geometry = new THREE.BufferGeometry();
+
+				var indices = new Uint32Array( triangles * 3 );
+
+				for ( var i = 0; i < indices.length; i ++ ) {
+
+					indices[ i ] = i;
+
+				}
+
+				var positions = new Float32Array( triangles * 3 * 3 );
+				var normals = new Int16Array( triangles * 3 * 3 );
+				var colors = new Uint8Array( triangles * 3 * 3 );
+
+				var color = new THREE.Color();
+
+				var n = 800, n2 = n/2;	// triangles spread in the cube
+				var d = 12, d2 = d/2;	// individual triangle size
+
+				var pA = new THREE.Vector3();
+				var pB = new THREE.Vector3();
+				var pC = new THREE.Vector3();
+
+				var cb = new THREE.Vector3();
+				var ab = new THREE.Vector3();
+
+				for ( var i = 0; i < positions.length; i += 9 ) {
+
+					// positions
+
+					var x = Math.random() * n - n2;
+					var y = Math.random() * n - n2;
+					var z = Math.random() * n - n2;
+
+					var ax = x + Math.random() * d - d2;
+					var ay = y + Math.random() * d - d2;
+					var az = z + Math.random() * d - d2;
+
+					var bx = x + Math.random() * d - d2;
+					var by = y + Math.random() * d - d2;
+					var bz = z + Math.random() * d - d2;
+
+					var cx = x + Math.random() * d - d2;
+					var cy = y + Math.random() * d - d2;
+					var cz = z + Math.random() * d - d2;
+
+					positions[ i ]     = ax;
+					positions[ i + 1 ] = ay;
+					positions[ i + 2 ] = az;
+
+					positions[ i + 3 ] = bx;
+					positions[ i + 4 ] = by;
+					positions[ i + 5 ] = bz;
+
+					positions[ i + 6 ] = cx;
+					positions[ i + 7 ] = cy;
+					positions[ i + 8 ] = cz;
+
+					// flat face normals
+
+					pA.set( ax, ay, az );
+					pB.set( bx, by, bz );
+					pC.set( cx, cy, cz );
+
+					cb.subVectors( pC, pB );
+					ab.subVectors( pA, pB );
+					cb.cross( ab );
+
+					cb.normalize();
+
+					var nx = cb.x;
+					var ny = cb.y;
+					var nz = cb.z;
+
+					normals[ i ]     = nx * 32767;
+					normals[ i + 1 ] = ny * 32767;
+					normals[ i + 2 ] = nz * 32767;
+
+					normals[ i + 3 ] = nx * 32767;
+					normals[ i + 4 ] = ny * 32767;
+					normals[ i + 5 ] = nz * 32767;
+
+					normals[ i + 6 ] = nx * 32767;
+					normals[ i + 7 ] = ny * 32767;
+					normals[ i + 8 ] = nz * 32767;
+
+					// colors
+
+					var vx = ( x / n ) + 0.5;
+					var vy = ( y / n ) + 0.5;
+					var vz = ( z / n ) + 0.5;
+
+					color.setRGB( vx, vy, vz );
+
+					colors[ i ]     = color.r * 255;
+					colors[ i + 1 ] = color.g * 255;
+					colors[ i + 2 ] = color.b * 255;
+
+					colors[ i + 3 ] = color.r * 255;
+					colors[ i + 4 ] = color.g * 255;
+					colors[ i + 5 ] = color.b * 255;
+
+					colors[ i + 6 ] = color.r * 255;
+					colors[ i + 7 ] = color.g * 255;
+					colors[ i + 8 ] = color.b * 255;
+
+				}
+
+				geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
+				geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+				geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3, true ) );
+				geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3, true ) );
+
+				geometry.computeBoundingSphere();
+
+				var material = new THREE.MeshPhongMaterial( {
+					color: 0xaaaaaa, specular: 0xffffff, shininess: 250,
+					side: THREE.DoubleSide, vertexColors: THREE.VertexColors
+				} );
+
+				mesh = new THREE.Mesh( geometry, material );
+				scene.add( mesh );
+
+				//
+
+				renderer = new THREE.WebGLRenderer( { antialias: false } );
+				renderer.setClearColor( scene.fog.color );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				renderer.gammaInput = true;
+				renderer.gammaOutput = true;
+
+				container.appendChild( renderer.domElement );
+
+				//
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+
+				var time = Date.now() * 0.001;
+
+				mesh.rotation.x = time * 0.25;
+				mesh.rotation.y = time * 0.5;
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+
+	</body>
+</html>

+ 2 - 1
src/core/BufferAttribute.js

@@ -2,7 +2,7 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
-THREE.BufferAttribute = function ( array, itemSize ) {
+THREE.BufferAttribute = function ( array, itemSize, normalized ) {
 
 	this.uuid = THREE.Math.generateUUID();
 
@@ -13,6 +13,7 @@ THREE.BufferAttribute = function ( array, itemSize ) {
 	this.updateRange = { offset: 0, count: - 1 };
 
 	this.version = 0;
+	this.normalized = normalized ? true : false;
 
 };
 

+ 2 - 1
src/core/BufferGeometry.js

@@ -918,7 +918,8 @@ THREE.BufferGeometry.prototype = {
 			data.data.attributes[ key ] = {
 				itemSize: attribute.itemSize,
 				type: attribute.array.constructor.name,
-				array: array
+				array: array,
+				normalized: attribute.normalized
 			};
 
 		}

+ 2 - 2
src/loaders/BufferGeometryLoader.js

@@ -56,8 +56,8 @@ THREE.BufferGeometryLoader.prototype = {
 
 			var attribute = attributes[ key ];
 			var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
-
-			geometry.addAttribute( key, new THREE.BufferAttribute( typedArray, attribute.itemSize ) );
+			var normalized = attribute.normalized || false;
+			geometry.addAttribute( key, new THREE.BufferAttribute( typedArray, attribute.itemSize , normalized) );
 
 		}
 

+ 44 - 17
src/renderers/WebGLRenderer.js

@@ -831,8 +831,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
-		//
-
 		var index = geometry.index;
 		var position = geometry.attributes.position;
 
@@ -867,8 +865,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
-		//
-
 		var dataStart = 0;
 		var dataCount = Infinity;
 
@@ -1000,6 +996,48 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( geometryAttribute !== undefined ) {
 
+					var dataType = _gl.FLOAT;
+					var normalized = geometryAttribute.normalized;
+					var array = geometryAttribute.array;
+					if ( array instanceof Float32Array ) {
+
+						dataType = _gl.FLOAT;
+
+					} else if ( array instanceof Float64Array ) {
+
+						console.warn("Unsupported data buffer format: Float64Array");
+
+					} else if ( array instanceof Uint16Array ) {
+
+						dataType = _gl.UNSIGNED_SHORT;
+						
+					} else if ( array instanceof Int16Array ) {
+
+						dataType = _gl.SHORT;
+
+					} else if ( array instanceof Uint32Array ) {
+
+						dataType = _gl.UNSIGNED_INT;
+
+					} else if ( array instanceof Int32Array ) {
+
+						dataType = _gl.INT;
+
+					} else if ( array instanceof Int8Array ) {
+
+						dataType = _gl.BYTE;
+
+					} else if ( array instanceof Uint8Array ) {
+
+						dataType = _gl.UNSIGNED_BYTE;
+
+					} else
+					{
+
+						dataType = _gl.FLOAT;
+
+					}
+					
 					var size = geometryAttribute.itemSize;
 					var buffer = objects.getAttributeBuffer( geometryAttribute );
 
@@ -1026,7 +1064,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 						}
 
 						_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
-						_gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, stride * data.array.BYTES_PER_ELEMENT, ( startIndex * stride + offset ) * data.array.BYTES_PER_ELEMENT );
+						_gl.vertexAttribPointer( programAttribute, size, dataType, normalized, stride * data.array.BYTES_PER_ELEMENT, ( startIndex * stride + offset ) * data.array.BYTES_PER_ELEMENT );
 
 					} else {
 
@@ -1046,19 +1084,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 						}
 
-						var type = _gl.FLOAT;
-						var normalized = false;
-						var array = geometryAttribute.array;
-
-						if ( array instanceof Uint8Array ) {
-
-							type = _gl.UNSIGNED_BYTE;
-							normalized = true;
-
-						}
-
 						_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
-						_gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, startIndex * size * array.BYTES_PER_ELEMENT );
+						_gl.vertexAttribPointer( programAttribute, size, dataType, normalized, 0, startIndex * size * geometryAttribute.array.BYTES_PER_ELEMENT ); 
 
 					}