浏览代码

Merge pull request #6638 from tschw/Uniform_caching

Uniform & attribute caching
Ricardo Cabello 10 年之前
父节点
当前提交
3506a689ab

+ 9 - 9
docs/api/renderers/webgl/WebGLProgram.html

@@ -109,12 +109,6 @@
 
 		<h2>Properties</h2>
 
-		<h3>[property:Object uniforms]</h3>
-		<div></div> 
-
-		<h3>[property:Object attributes]</h3>
-		<div></div> 
-
 		<h3>[property:String id]</h3>
 		<div></div> 
 
@@ -133,11 +127,17 @@
 		<h3>[property:WebGLShader fragmentShader]</h3>
 		<div></div> 
 
-
 		<h2>Methods</h2>
 		
-		<h3>none</h3>
-		<div></div>
+		<h3>[method:Object getUniforms]()</h3>
+		<div>
+		Returns a name-value mapping of all active uniform locations.
+		</div>
+
+		<h3>[method:Object getAttributes]()</h3>
+		<div>
+		Returns a name-value mapping of all active vertex attribute locations.
+		</div>
 
 		<h2>Source</h2>
 

+ 1 - 1
editor/js/Sidebar.Material.js

@@ -642,7 +642,7 @@ Sidebar.Material = function ( editor ) {
 			'emissive': materialEmissiveRow,
 			'specular': materialSpecularRow,
 			'shininess': materialShininessRow,
-			'program': materialProgramRow,
+			'vertexShader': materialProgramRow,
 			'vertexColors': materialVertexColorsRow,
 			'skinning': materialSkinningRow,
 			'map': materialMapRow,

+ 34 - 19
src/renderers/WebGLRenderer.js

@@ -779,14 +779,15 @@ THREE.WebGLRenderer = function ( parameters ) {
 		if ( object.hasUvs && ! object.__webglUvBuffer ) object.__webglUvBuffer = _gl.createBuffer();
 		if ( object.hasColors && ! object.__webglColorBuffer ) object.__webglColorBuffer = _gl.createBuffer();
 
+		var attributes = program.getAttributes();
+
 		if ( object.hasPositions ) {
 
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglVertexBuffer );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
 
-			state.enableAttribute( program.attributes.position );
-
-			_gl.vertexAttribPointer( program.attributes.position, 3, _gl.FLOAT, false, 0, 0 );
+			state.enableAttribute( attributes.position );
+			_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
 
 		}
 
@@ -839,9 +840,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
 
-			state.enableAttribute( program.attributes.normal );
+			state.enableAttribute( attributes.normal );
 
-			_gl.vertexAttribPointer( program.attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
+			_gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
 
 		}
 
@@ -850,9 +851,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglUvBuffer );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
 
-			state.enableAttribute( program.attributes.uv );
+			state.enableAttribute( attributes.uv );
 
-			_gl.vertexAttribPointer( program.attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
+			_gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
 
 		}
 
@@ -861,9 +862,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglColorBuffer );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
 
-			state.enableAttribute( program.attributes.color );
+			state.enableAttribute( attributes.color );
 
-			_gl.vertexAttribPointer( program.attributes.color, 3, _gl.FLOAT, false, 0, 0 );
+			_gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
 
 		}
 
@@ -893,7 +894,10 @@ THREE.WebGLRenderer = function ( parameters ) {
 		}
 
 		var geometryAttributes = geometry.attributes;
-		var programAttributes = program.attributes;
+
+		var programAttributes = program.getAttributes();
+
+		var materialDefaultAttributeValues = material.defaultAttributeValues;
 
 		for ( var name in programAttributes ) {
 
@@ -962,17 +966,27 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 					}
 
-				} else if ( material.defaultAttributeValues !== undefined ) {
+				} else if ( materialDefaultAttributeValues !== undefined ) {
+
+					var value = materialDefaultAttributeValues[ name ];
+					if ( value !== undefined ) {
 
-					if ( material.defaultAttributeValues[ name ] !== undefined ) {
+						switch ( value.length ) {
 
-						if ( material.defaultAttributeValues[ name ].length === 2 ) {
+							case 2:
+								_gl.vertexAttrib2fv( programAttribute, value );
+								break;
 
-							_gl.vertexAttrib2fv( programAttribute, material.defaultAttributeValues[ name ] );
+							case 3:
+								_gl.vertexAttrib3fv( programAttribute, value );
+								break;
 
-						} else if ( material.defaultAttributeValues[ name ].length === 3 ) {
+							case 4:
+								_gl.vertexAttrib4fv( programAttribute, value );
+								break;
 
-							_gl.vertexAttrib3fv( programAttribute, material.defaultAttributeValues[ name ] );
+							default:
+								_gl.vertexAttrib1fv( programAttribute, value );
 
 						}
 
@@ -1983,7 +1997,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		material.program = program;
 
-		var attributes = program.attributes;
+		var attributes = program.getAttributes();
 
 		if ( material.morphTargets ) {
 
@@ -2019,9 +2033,10 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		material.uniformsList = [];
 
+		var uniformLocations = material.program.getUniforms();
 		for ( var u in material.__webglShader.uniforms ) {
 
-			var location = material.program.uniforms[ u ];
+			var location = uniformLocations[ u ];
 
 			if ( location ) {
 				material.uniformsList.push( [ material.__webglShader.uniforms[ u ], location ] );
@@ -2067,7 +2082,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		var refreshLights = false;
 
 		var program = material.program,
-			p_uniforms = program.uniforms,
+			p_uniforms = program.getUniforms(),
 			m_uniforms = material.__webglShader.uniforms;
 
 		if ( program.id !== _currentProgram ) {

+ 74 - 78
src/renderers/webgl/WebGLProgram.js

@@ -20,14 +20,28 @@ THREE.WebGLProgram = ( function () {
 
 	}
 
-	function cacheUniformLocations( gl, program, identifiers ) {
+	function fetchUniformLocations( gl, program, identifiers ) {
+
 
 		var uniforms = {};
 
-		for ( var i = 0, l = identifiers.length; i < l; i ++ ) {
+		var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
+		for ( var i = 0; i < n; i ++ ) {
+
+			var info = gl.getActiveUniform( program , i );
+			var name = info.name;
+			var location = gl.getUniformLocation( program, name );
+
+			//console.log("THREE.WebGLProgram: ACTIVE UNIFORM:", name);
+
+			var suffixPos = name.lastIndexOf( '[0]' );
+			if ( suffixPos !== -1 && suffixPos === name.length - 3 ) {
 
-			var id = identifiers[ i ];
-			uniforms[ id ] = gl.getUniformLocation( program, id );
+				uniforms[ name.substr( 0, suffixPos ) ] = location;
+
+			}
+
+			uniforms[ name ] = location;
 
 		}
 
@@ -35,14 +49,19 @@ THREE.WebGLProgram = ( function () {
 
 	}
 
-	function cacheAttributeLocations( gl, program, identifiers ) {
+	function fetchAttributeLocations( gl, program, identifiers ) {
 
 		var attributes = {};
 
-		for ( var i = 0, l = identifiers.length; i < l; i ++ ) {
+		var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
+		for ( var i = 0; i < n; i ++ ) {
+
+			var info = gl.getActiveAttrib( program , i );
+			var name = info.name;
 
-			var id = identifiers[ i ];
-			attributes[ id ] = gl.getAttribLocation( program, id );
+			//console.log("THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:", name);
+
+			attributes[ name ] = gl.getAttribLocation( program, name );
 
 		}
 
@@ -154,16 +173,16 @@ THREE.WebGLProgram = ( function () {
 
 		var program = gl.createProgram();
 
-		var prefix_vertex, prefix_fragment;
+		var prefixVertex, prefixFragment;
 
 		if ( material instanceof THREE.RawShaderMaterial ) {
 
-			prefix_vertex = '';
-			prefix_fragment = '';
+			prefixVertex = '';
+			prefixFragment = '';
 
 		} else {
 
-			prefix_vertex = [
+			prefixVertex = [
 
 				'precision ' + parameters.precision + ' float;',
 				'precision ' + parameters.precision + ' int;',
@@ -270,7 +289,7 @@ THREE.WebGLProgram = ( function () {
 
 			].filter( filterEmptyLine ).join( '\n' );
 
-			prefix_fragment = [
+			prefixFragment = [
 
 				( parameters.bumpMap || parameters.normalMap || parameters.flatShading || material.derivatives ) ? '#extension GL_OES_standard_derivatives : enable' : '',
 
@@ -331,8 +350,11 @@ THREE.WebGLProgram = ( function () {
 
 		}
 
-		var glVertexShader = new THREE.WebGLShader( gl, gl.VERTEX_SHADER, prefix_vertex + vertexShader );
-		var glFragmentShader = new THREE.WebGLShader( gl, gl.FRAGMENT_SHADER, prefix_fragment + fragmentShader );
+		var vertexGlsl = prefixVertex + vertexShader;
+		var fragmentGlsl = prefixFragment + fragmentShader;
+
+		var glVertexShader = new THREE.WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
+		var glFragmentShader = new THREE.WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
 
 		gl.attachShader( program, glVertexShader );
 		gl.attachShader( program, glFragmentShader );
@@ -370,91 +392,65 @@ THREE.WebGLProgram = ( function () {
 		gl.deleteShader( glVertexShader );
 		gl.deleteShader( glFragmentShader );
 
-		// cache uniform locations
-
-		var identifiers = [
-
-			'viewMatrix',
-			'modelViewMatrix',
-			'projectionMatrix',
-			'normalMatrix',
-			'modelMatrix',
-			'cameraPosition',
-			'morphTargetInfluences',
-			'bindMatrix',
-			'bindMatrixInverse'
-
-		];
-
-		if ( parameters.useVertexTexture ) {
-
-			identifiers.push( 'boneTexture', 'boneTextureWidth', 'boneTextureHeight' );
-
-		} else {
-
-			identifiers.push( 'boneGlobalMatrices' );
-
-		}
-
-		if ( parameters.logarithmicDepthBuffer ) {
-
-			identifiers.push( 'logDepthBufFC' );
-
-		}
+		// set up caching for uniform locations
 
-		for ( var u in uniforms ) {
+		var getUniforms = function() { return this._cachedUniforms; };
 
-			identifiers.push( u );
+		this.getUniforms = function() {
 
-		}
-
-		this.uniforms = cacheUniformLocations( gl, program, identifiers );
+			// fetch, cache, and next time just use a dumb accessor
+			var uniforms = fetchUniformLocations( gl, program );
+			this._cachedUniforms = uniforms;
+			this.getUniforms = getUniforms;
+			return uniforms;
 
-		// cache attributes locations
+		};
 
-		if ( material instanceof THREE.RawShaderMaterial ) {
+		// set up caching for attribute locations
 
-			identifiers = attributes;
+		var getAttributes = function() { return this._cachedAttributes; };
 
-		} else {
+		this.getAttributes = function() {
 
-			identifiers = [
+			var attributes = fetchAttributeLocations( gl, program );
+			this._cachedAttributes = attributes;
+			this.getAttributes = getAttributes;
+			return attributes;
 
-				'position',
-				'normal',
-				'uv',
-				'uv2',
-				'tangent',
-				'color',
-				'skinIndex',
-				'skinWeight',
-				'lineDistance'
+		};
 
-			];
+		// DEPRECATED
 
-			for ( var i = 0; i < parameters.maxMorphTargets; i ++ ) {
+		Object.defineProperties( this, {
 
-				identifiers.push( 'morphTarget' + i );
+			uniforms: {
+				get: function() {
 
-			}
+					console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' );
+					return this.getUniforms();
 
-			for ( var i = 0; i < parameters.maxMorphNormals; i ++ ) {
+				}
+			},
 
-				identifiers.push( 'morphNormal' + i );
+			attributes: {
+				get: function() {
 
-			}
+					console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' );
+					return this.getAttributes();
 
-			// ShaderMaterial attributes
+				}
+			},
 
-			if ( Array.isArray( attributes ) ) {
+			attributesKeys: {
+				get: function() {
 
-				identifiers = identifiers.concat( attributes );
+					console.warn( 'THREE.WebGLProgram: .attributesKeys has been removed.' );
+					return Object.keys( this.getAttributes() );
 
+				}
 			}
+		});
 
-		}
-
-		this.attributes = cacheAttributeLocations( gl, program, identifiers );
 
 		//