Przeglądaj źródła

Skeleton: Moved useVertexTexture logic to WebGLRenderer. See #10754.

Mr.doob 8 lat temu
rodzic
commit
07b64132c4

+ 16 - 0
src/Three.Legacy.js

@@ -60,6 +60,7 @@ import { LineSegments } from './objects/LineSegments.js';
 import { LOD } from './objects/LOD.js';
 import { Points } from './objects/Points.js';
 import { Sprite } from './objects/Sprite.js';
+import { Skeleton } from './objects/Skeleton.js';
 import { WebGLRenderer } from './renderers/WebGLRenderer.js';
 import { WebGLRenderTarget } from './renderers/WebGLRenderTarget.js';
 import { WebGLShadowMap } from './renderers/webgl/WebGLShadowMap.js';
@@ -760,6 +761,21 @@ Object.defineProperties( LOD.prototype, {
 
 } );
 
+Object.defineProperty( Skeleton.prototype, 'useVertexTexture', {
+
+	get: function () {
+
+		console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
+
+	},
+	set: function () {
+
+		console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
+
+	}
+
+} );
+
 //
 
 PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {

+ 14 - 41
src/objects/Skeleton.js

@@ -1,7 +1,4 @@
 import { Matrix4 } from '../math/Matrix4';
-import { FloatType, RGBAFormat } from '../constants';
-import { DataTexture } from '../textures/DataTexture';
-import { _Math } from '../math/Math';
 
 /**
  * @author mikael emtinger / http://gomo.se/
@@ -10,9 +7,7 @@ import { _Math } from '../math/Math';
  * @author ikerr / http://verold.com
  */
 
-function Skeleton( bones, boneInverses, useVertexTexture ) {
-
-	this.useVertexTexture = useVertexTexture !== undefined ? useVertexTexture : true;
+function Skeleton( bones, boneInverses ) {
 
 	this.identityMatrix = new Matrix4();
 
@@ -21,34 +16,7 @@ function Skeleton( bones, boneInverses, useVertexTexture ) {
 	bones = bones || [];
 
 	this.bones = bones.slice( 0 );
-
-	// create a bone texture or an array of floats
-
-	if ( this.useVertexTexture ) {
-
-		// layout (1 matrix = 4 pixels)
-		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
-		//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
-		//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
-		//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
-		//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
-
-
-		var size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix
-		size = _Math.nextPowerOfTwo( Math.ceil( size ) );
-		size = Math.max( size, 4 );
-
-		this.boneTextureWidth = size;
-		this.boneTextureHeight = size;
-
-		this.boneMatrices = new Float32Array( this.boneTextureWidth * this.boneTextureHeight * 4 ); // 4 floats per RGBA pixel
-		this.boneTexture = new DataTexture( this.boneMatrices, this.boneTextureWidth, this.boneTextureHeight, RGBAFormat, FloatType );
-
-	} else {
-
-		this.boneMatrices = new Float32Array( 16 * this.bones.length );
-
-	}
+	this.boneMatrices = new Float32Array( this.bones.length * 16 );
 
 	// use the supplied bone inverses or calculate the inverses
 
@@ -153,22 +121,27 @@ Object.assign( Skeleton.prototype, {
 
 		return function update() {
 
+			var bones = this.bones;
+			var boneInverses = this.boneInverses;
+			var boneMatrices = this.boneMatrices;
+			var boneTexture = this.boneTexture;
+
 			// flatten bone matrices to array
 
-			for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
+			for ( var b = 0, bl = bones.length; b < bl; b ++ ) {
 
 				// compute the offset between the current and the original transform
 
-				var matrix = this.bones[ b ] ? this.bones[ b ].matrixWorld : this.identityMatrix;
+				var matrix = bones[ b ] ? bones[ b ].matrixWorld : this.identityMatrix;
 
-				offsetMatrix.multiplyMatrices( matrix, this.boneInverses[ b ] );
-				offsetMatrix.toArray( this.boneMatrices, b * 16 );
+				offsetMatrix.multiplyMatrices( matrix, boneInverses[ b ] );
+				offsetMatrix.toArray( boneMatrices, b * 16 );
 
 			}
 
-			if ( this.useVertexTexture ) {
+			if ( boneTexture !== undefined ) {
 
-				this.boneTexture.needsUpdate = true;
+				boneTexture.needsUpdate = true;
 
 			}
 
@@ -178,7 +151,7 @@ Object.assign( Skeleton.prototype, {
 
 	clone: function () {
 
-		return new Skeleton( this.bones, this.boneInverses, this.useVertexTexture );
+		return new Skeleton( this.bones, this.boneInverses );
 
 	}
 

+ 3 - 3
src/objects/SkinnedMesh.js

@@ -10,7 +10,7 @@ import { Matrix4 } from '../math/Matrix4';
  * @author ikerr / http://verold.com
  */
 
-function SkinnedMesh( geometry, material, useVertexTexture ) {
+function SkinnedMesh( geometry, material ) {
 
 	Mesh.call( this, geometry, material );
 
@@ -67,7 +67,7 @@ function SkinnedMesh( geometry, material, useVertexTexture ) {
 	this.normalizeSkinWeights();
 
 	this.updateMatrixWorld( true );
-	this.bind( new Skeleton( bones, undefined, useVertexTexture ), this.matrixWorld );
+	this.bind( new Skeleton( bones ), this.matrixWorld );
 
 }
 
@@ -179,7 +179,7 @@ SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
 
 	clone: function () {
 
-		return new this.constructor( this.geometry, this.material, this.skeleton.useVertexTexture ).copy( this );
+		return new this.constructor( this.geometry, this.material ).copy( this );
 
 	}
 

+ 2 - 3
src/renderers/WebGLRenderer.js

@@ -1832,11 +1832,10 @@ function WebGLRenderer( parameters ) {
 
 			if ( skeleton ) {
 
-				if ( capabilities.floatVertexTextures && skeleton.useVertexTexture ) {
+				if ( capabilities.floatVertexTextures ) {
 
 					p_uniforms.set( _gl, skeleton, 'boneTexture' );
-					p_uniforms.set( _gl, skeleton, 'boneTextureWidth' );
-					p_uniforms.set( _gl, skeleton, 'boneTextureHeight' );
+					p_uniforms.set( _gl, skeleton, 'boneTextureSize' );
 
 				} else {
 

+ 5 - 6
src/renderers/shaders/ShaderChunk/skinning_pars_vertex.glsl

@@ -6,17 +6,16 @@
 	#ifdef BONE_TEXTURE
 
 		uniform sampler2D boneTexture;
-		uniform int boneTextureWidth;
-		uniform int boneTextureHeight;
+		uniform int boneTextureSize;
 
 		mat4 getBoneMatrix( const in float i ) {
 
 			float j = i * 4.0;
-			float x = mod( j, float( boneTextureWidth ) );
-			float y = floor( j / float( boneTextureWidth ) );
+			float x = mod( j, float( boneTextureSize ) );
+			float y = floor( j / float( boneTextureSize ) );
 
-			float dx = 1.0 / float( boneTextureWidth );
-			float dy = 1.0 / float( boneTextureHeight );
+			float dx = 1.0 / float( boneTextureSize );
+			float dy = 1.0 / float( boneTextureSize );
 
 			y = dy * ( y + 0.5 );
 

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

@@ -311,7 +311,6 @@ function WebGLProgram( renderer, code, material, parameters ) {
 
 		prefixVertex = [
 
-        
 			'precision ' + parameters.precision + ' float;',
 			'precision ' + parameters.precision + ' int;',
 
@@ -327,7 +326,6 @@ function WebGLProgram( renderer, code, material, parameters ) {
 			( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
 			( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
 
-
 			parameters.map ? '#define USE_MAP' : '',
 			parameters.envMap ? '#define USE_ENVMAP' : '',
 			parameters.envMap ? '#define ' + envMapModeDefine : '',

+ 38 - 14
src/renderers/webgl/WebGLPrograms.js

@@ -2,8 +2,10 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
+import { BackSide, DoubleSide, FlatShading, CubeUVRefractionMapping, CubeUVReflectionMapping, GammaEncoding, LinearEncoding, FloatType, RGBAFormat } from '../../constants';
+import { _Math } from '../../math/Math';
+import { DataTexture } from '../../textures/DataTexture';
 import { WebGLProgram } from './WebGLProgram';
-import { BackSide, DoubleSide, FlatShading, CubeUVRefractionMapping, CubeUVReflectionMapping, GammaEncoding, LinearEncoding } from '../../constants';
 
 function WebGLPrograms( renderer, capabilities ) {
 
@@ -39,7 +41,35 @@ function WebGLPrograms( renderer, capabilities ) {
 
 	function allocateBones( object ) {
 
-		if ( capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture ) {
+		var skeleton = object.skeleton;
+		var bones = skeleton.bones;
+
+		if ( capabilities.floatVertexTextures ) {
+
+			if ( skeleton.boneTexture === undefined ) {
+
+				// layout (1 matrix = 4 pixels)
+				//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
+				//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
+				//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
+				//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
+				//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
+
+
+				var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
+				size = _Math.nextPowerOfTwo( Math.ceil( size ) );
+				size = Math.max( size, 4 );
+
+				var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
+				boneMatrices.set( skeleton.boneMatrices ); // copy current values
+
+				var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
+
+				skeleton.boneMatrices = boneMatrices;
+				skeleton.boneTexture = boneTexture;
+				skeleton.boneTextureSize = size;
+
+			}
 
 			return 1024;
 
@@ -55,18 +85,12 @@ function WebGLPrograms( renderer, capabilities ) {
 			var nVertexUniforms = capabilities.maxVertexUniforms;
 			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
 
-			var maxBones = nVertexMatrices;
-
-			if ( object && object.isSkinnedMesh ) {
-
-				maxBones = Math.min( object.skeleton.bones.length, maxBones );
-
-				if ( maxBones < object.skeleton.bones.length ) {
+			var maxBones = Math.min( nVertexMatrices, bones.length );
 
-					console.warn( 'WebGLRenderer: too many bones - ' + object.skeleton.bones.length + ', this GPU supports just ' + maxBones + ' (try OpenGL instead of ANGLE)' );
-					return 0;
+			if ( maxBones < bones.length ) {
 
-				}
+				console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
+				return 0;
 
 			}
 
@@ -113,7 +137,7 @@ function WebGLPrograms( renderer, capabilities ) {
 		// heuristics to create shader parameters according to lights in the scene
 		// (not to blow over maxLights budget)
 
-		var maxBones = allocateBones( object );
+		var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
 		var precision = renderer.getPrecision();
 
 		if ( material.precision !== null ) {
@@ -172,7 +196,7 @@ function WebGLPrograms( renderer, capabilities ) {
 
 			skinning: ( object && object.isSkinnedMesh ) && maxBones > 0,
 			maxBones: maxBones,
-			useVertexTexture: capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture,
+			useVertexTexture: capabilities.floatVertexTextures,
 
 			morphTargets: material.morphTargets,
 			morphNormals: material.morphNormals,

+ 1 - 1
src/textures/DataTexture.js

@@ -14,7 +14,7 @@ function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT,
 	this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
 	this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
 
-	this.generateMipmaps  = false;
+	this.generateMipmaps = false;
 	this.flipY = false;
 	this.unpackAlignment = 1;