소스 검색

Structured Uniforms Completion (#8585)

* WebGLProgram: Rewrote uniform name parser.

* Revised structured uniforms.

- Allowed arbitrary nesting
- Removed map iteration
tschw 9 년 전
부모
커밋
fc4687acd3
2개의 변경된 파일74개의 추가작업 그리고 74개의 파일을 삭제
  1. 12 29
      src/renderers/WebGLRenderer.js
  2. 62 45
      src/renderers/webgl/WebGLProgram.js

+ 12 - 29
src/renderers/WebGLRenderer.js

@@ -2487,39 +2487,22 @@ THREE.WebGLRenderer = function ( parameters ) {
 			// single THREE.Color
 			_gl.uniform3f( location, value.r, value.g, value.b );
 
-		} else if ( type === 's' ) {
+		} else if ( type === 's' || type === 'sa' ) {
 
-			// TODO: Optimize this
+			var properties = uniform.properties,
+				identifiers = location.ids,
+				nestedInfos = location.infos;
 
-			var properties = uniform.properties;
+			for ( var i = 0, n = identifiers.length; i !== n; ++ i ) {
 
-			for ( var name in properties ) {
+				var id = identifiers[ i ],
+					isArray = typeof id === 'number',
+					nestedUniform = isArray ? uniform : properties[ id ],
+					nestedInfo = nestedInfos[ i ],
+					nestedType = nestedInfo.infos !== undefined ? 's' : nestedUniform.type,
+					nestedValue = value[ id ];
 
-				var property = properties[ name ];
-				var locationProperty = location[ name ];
-				var valueProperty = value[ name ];
-
-				loadUniform( property, property.type, locationProperty, valueProperty );
-
-			}
-
-		} else if ( type === 'sa' ) {
-
-			// TODO: Optimize this
-
-			var properties = uniform.properties;
-
-			for ( var i = 0, l = value.length; i < l; i ++ ) {
-
-				for ( var name in properties ) {
-
-					var property = properties[ name ];
-					var locationProperty =  location[ i ][ name ];
-					var valueProperty = value[ i ][ name ];
-
-					loadUniform( property, property.type, locationProperty, valueProperty );
-
-				}
+				loadUniform( nestedUniform, nestedType, nestedInfo, nestedValue );
 
 			}
 

+ 62 - 45
src/renderers/webgl/WebGLProgram.js

@@ -2,11 +2,6 @@ THREE.WebGLProgram = ( function () {
 
 	var programIdCount = 0;
 
-	// TODO: Combine the regex
-	var structRe = /^([\w\d_]+)\.([\w\d_]+)$/;
-	var arrayStructRe = /^([\w\d_]+)\[(\d+)\]\.([\w\d_]+)$/;
-	var arrayRe = /^([\w\d_]+)\[0\]$/;
-
 	function getEncodingComponents( encoding ) {
 
 		switch ( encoding ) {
@@ -110,83 +105,105 @@ THREE.WebGLProgram = ( function () {
 
 	}
 
-	function fetchUniformLocations( gl, program, identifiers ) {
 
-		var uniforms = {};
+	var ReNamePart = /([\w\d_]+)(\])?(\[|\.)?/g;
 
-		var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
+	function attachUniformInfo( name, info, root ) {
+		// attaches 'info' at the right spot according to parsed name
 
-		for ( var i = 0; i < n; i ++ ) {
+		var ctx = root,
+			len = name.length;
 
-			var info = gl.getActiveUniform( program, i );
-			var name = info.name;
-			var location = gl.getUniformLocation( program, name );
+		for (; ;) {
+
+			var ids = ctx.ids,
+				infos = ctx.infos,
 
-			//console.log("THREE.WebGLProgram: ACTIVE UNIFORM:", name);
+				match = ReNamePart.exec( name ),
+				matchEnd = ReNamePart.lastIndex,
 
-			var matches = structRe.exec( name );
-			if ( matches ) {
+				id = match[ 1 ],
+				idIsIndex = match[ 2 ] === ']',
+				subscript = match[ 3 ];
 
-				var structName = matches[ 1 ];
-				var structProperty = matches[ 2 ];
+			if ( idIsIndex ) id = + id; // avoid parsing strings in renderer
 
-				var uniformsStruct = uniforms[ structName ];
+			if ( subscript === undefined ||
+					subscript === '[' && matchEnd + 2 === len ) {
+				// bare name or pure bottom-level array with "[0]" suffix
 
-				if ( ! uniformsStruct ) {
+				if ( ctx === root ) {
 
-					uniformsStruct = uniforms[ structName ] = {};
+					ctx[ id ] = info;
+
+				} else {
+
+					ids.push( id );
+					infos.push( info );
 
 				}
 
-				uniformsStruct[ structProperty ] = location;
+				break;
 
-				continue;
+			} else {
+				// step into context and create it in case it doesn't exist
 
-			}
+				if ( ctx === root ) {
 
-			matches = arrayStructRe.exec( name );
+					var nextCtx = ctx[ id ];
 
-			if ( matches ) {
+					if ( nextCtx === undefined ) {
 
-				var arrayName = matches[ 1 ];
-				var arrayIndex = matches[ 2 ];
-				var arrayProperty = matches[ 3 ];
+						nextCtx = { ids: [], infos: [] };
+						ctx[ id ] = nextCtx;
 
-				var uniformsArray = uniforms[ arrayName ];
+					}
 
-				if ( ! uniformsArray ) {
+					ctx = nextCtx;
 
-					uniformsArray = uniforms[ arrayName ] = [];
+				} else {
 
-				}
+					var i = ids.indexOf( id );
 
-				var uniformsArrayIndex = uniformsArray[ arrayIndex ];
+					if ( i === -1 ) {
 
-				if ( ! uniformsArrayIndex ) {
+						i = ids.length;
 
-					uniformsArrayIndex = uniformsArray[ arrayIndex ] = {};
+						ids.push( id );
+						infos.push( { ids: [], infos: [] } );
 
-				}
+					}
 
-				uniformsArrayIndex[ arrayProperty ] = location;
+					ctx = ctx.infos[ i ];
 
-				continue;
+				}
 
 			}
 
-			matches = arrayRe.exec( name );
+		}
 
-			if ( matches ) {
+		// reset stateful RegExp object, because of early exit
+		ReNamePart.lastIndex = 0;
 
-				var arrayName = matches[ 1 ];
+	}
 
-				uniforms[ arrayName ] = location;
 
-				continue;
+	function fetchUniformLocations( gl, program, identifiers ) {
 
-			}
+		var uniforms = {};
+
+		var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
+
+		for ( var i = 0; i !== n; ++ i ) {
+
+			var info = gl.getActiveUniform( program, i ),
+				name = info.name,
+
+				location = gl.getUniformLocation( program, name );
+
+			// console.log("THREE.WebGLProgram: ACTIVE UNIFORM:", name);
 
-			uniforms[ name ] = location;
+			attachUniformInfo( name, location, uniforms );
 
 		}