瀏覽代碼

Support for uncompressed ARGB DDS

benoitjacquier 12 年之前
父節點
當前提交
d9d78d20a6

二進制
examples/textures/compressed/Mountains_argb_mip.dds


二進制
examples/textures/compressed/Mountains_argb_nomip.dds


二進制
examples/textures/compressed/disturb_argb_mip.dds


二進制
examples/textures/compressed/disturb_argb_nomip.dds


+ 59 - 12
examples/webgl_materials_texture_compressed.html

@@ -68,56 +68,103 @@
 				DXT3 - RGBA - transparent textures with sharp alpha transitions
 				DXT3 - RGBA - transparent textures with sharp alpha transitions
 				DXT5 - RGBA - transparent textures with full alpha range
 				DXT5 - RGBA - transparent textures with full alpha range
 				*/
 				*/
-
-				var map1 = THREE.ImageUtils.loadCompressedTexture( 'textures/compressed/disturb_dxt1_nomip.dds' );
+											
+				var map1 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/disturb_dxt1_nomip.dds' );
 				map1.minFilter = map1.magFilter = THREE.LinearFilter;
 				map1.minFilter = map1.magFilter = THREE.LinearFilter;
 				map1.anisotropy = 4;
 				map1.anisotropy = 4;
 
 
-				var map2 = THREE.ImageUtils.loadCompressedTexture( 'textures/compressed/disturb_dxt1_mip.dds' );
+				var map2 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/disturb_dxt1_mip.dds' );
 				map2.anisotropy = 4;
 				map2.anisotropy = 4;
 
 
-				var map3 = THREE.ImageUtils.loadCompressedTexture( 'textures/compressed/hepatica_dxt3_mip.dds' );
+				var map3 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/hepatica_dxt3_mip.dds' );
 				map3.anisotropy = 4;
 				map3.anisotropy = 4;
 
 
-				var map4 = THREE.ImageUtils.loadCompressedTexture( 'textures/compressed/explosion_dxt5_mip.dds' );
+				var map4 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/explosion_dxt5_mip.dds' );
 				map4.anisotropy = 4;
 				map4.anisotropy = 4;
 
 
-				var cubemap = THREE.ImageUtils.loadCompressedTextureCube( 'textures/compressed/Mountains.dds', new THREE.CubeReflectionMapping, function( cubemap ) {
+				var map5 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/disturb_argb_nomip.dds' );
+				map5.minFilter = map5.magFilter = THREE.LinearFilter;
+				map5.anisotropy = 4;
+
+				var map6 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/disturb_argb_mip.dds' );
+				map6.anisotropy = 4;
 
 
-					cubemap.magFilter = cubemap.minFilter = THREE.LinearFilter;
+				var cubemap1 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/Mountains.dds', new THREE.CubeReflectionMapping, function( cubemap ) {
+					cubemap1.magFilter = cubemap1.minFilter = THREE.LinearFilter;
 					material1.needsUpdate = true;
 					material1.needsUpdate = true;
 
 
 				} );
 				} );
 
 
-				var material1 = new THREE.MeshBasicMaterial( { map: map1, envMap: cubemap } );
+				var cubemap2 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/Mountains_argb_mip.dds', new THREE.CubeReflectionMapping, function( cubemap ) {
+					cubemap2.magFilter = cubemap2.minFilter = THREE.LinearFilter;
+					material5.needsUpdate = true;
+				} );
+
+				var cubemap3 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/Mountains_argb_nomip.dds', new THREE.CubeReflectionMapping, function( cubemap ) {
+					cubemap3.magFilter = cubemap3.minFilter = THREE.LinearFilter;
+					material6.needsUpdate = true;
+				} );
+
+
+				var material1 = new THREE.MeshBasicMaterial( { map: map1, envMap: cubemap1 } );
 				var material2 = new THREE.MeshBasicMaterial( { map: map2 } );
 				var material2 = new THREE.MeshBasicMaterial( { map: map2 } );
 				var material3 = new THREE.MeshBasicMaterial( { map: map3, alphaTest: 0.5, side: THREE.DoubleSide } );
 				var material3 = new THREE.MeshBasicMaterial( { map: map3, alphaTest: 0.5, side: THREE.DoubleSide } );
 				var material4 = new THREE.MeshBasicMaterial( { map: map4, side: THREE.DoubleSide, blending: THREE.AdditiveBlending, depthTest: false, transparent: true } );
 				var material4 = new THREE.MeshBasicMaterial( { map: map4, side: THREE.DoubleSide, blending: THREE.AdditiveBlending, depthTest: false, transparent: true } );
+				var material5 = new THREE.MeshBasicMaterial( { envMap: cubemap2 } );
+				var material6 = new THREE.MeshBasicMaterial( { envMap: cubemap3 } );
+				var material7 = new THREE.MeshBasicMaterial( { map: map5 } );
+				var material8 = new THREE.MeshBasicMaterial( { map: map6 } );
+				
 
 
 				var mesh = new THREE.Mesh( new THREE.TorusGeometry( 100, 50, 32, 16 ), material1 );
 				var mesh = new THREE.Mesh( new THREE.TorusGeometry( 100, 50, 32, 16 ), material1 );
-				mesh.position.x = -200;
+				mesh.position.x = -600;
 				mesh.position.y = -200;
 				mesh.position.y = -200;
 				scene.add( mesh );
 				scene.add( mesh );
 				meshes.push( mesh );
 				meshes.push( mesh );
 
 
 				mesh = new THREE.Mesh( geometry, material2 );
 				mesh = new THREE.Mesh( geometry, material2 );
-				mesh.position.x = 200;
+				mesh.position.x = -200;
 				mesh.position.y = -200;
 				mesh.position.y = -200;
 				scene.add( mesh );
 				scene.add( mesh );
 				meshes.push( mesh );
 				meshes.push( mesh );
 
 
 				mesh = new THREE.Mesh( geometry, material3 );
 				mesh = new THREE.Mesh( geometry, material3 );
-				mesh.position.x = 200;
+				mesh.position.x = -200;
 				mesh.position.y = 200;
 				mesh.position.y = 200;
 				scene.add( mesh );
 				scene.add( mesh );
 				meshes.push( mesh );
 				meshes.push( mesh );
 
 
 				mesh = new THREE.Mesh( geometry, material4 );
 				mesh = new THREE.Mesh( geometry, material4 );
-				mesh.position.x = -200;
+				mesh.position.x = -600;
+				mesh.position.y = 200;
+				scene.add( mesh );
+				meshes.push( mesh );
+
+				mesh = new THREE.Mesh( new THREE.CubeGeometry( 200, 200, 200 ), material5 );
+				mesh.position.x = 200;
+				mesh.position.y = 200;
+				scene.add( mesh );
+				meshes.push( mesh );
+
+				mesh = new THREE.Mesh( new THREE.CubeGeometry( 200, 200, 200 ), material6 );
+				mesh.position.x = 200;
+				mesh.position.y = -200;
+				scene.add( mesh );
+				meshes.push( mesh );
+
+				mesh = new THREE.Mesh( geometry, material7 );
+				mesh.position.x = 600;
+				mesh.position.y = -200;
+				scene.add( mesh );
+				meshes.push( mesh );
+
+				mesh = new THREE.Mesh( geometry, material8 );
+				mesh.position.x = 600;
 				mesh.position.y = 200;
 				mesh.position.y = 200;
 				scene.add( mesh );
 				scene.add( mesh );
 				meshes.push( mesh );
 				meshes.push( mesh );
 
 
+
 				renderer = new THREE.WebGLRenderer( { antialias: true } );
 				renderer = new THREE.WebGLRenderer( { antialias: true } );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				document.body.appendChild( renderer.domElement );
 				document.body.appendChild( renderer.domElement );

+ 119 - 6
src/extras/ImageUtils.js

@@ -230,6 +230,77 @@ THREE.ImageUtils = {
 
 
 	},
 	},
 
 
+	loadDDSTexture: function ( url, mapping, onLoad, onError ) {
+
+		var images = [];
+		images.loadCount = 0;
+
+		var texture = new THREE.CompressedTexture();
+		texture.image = images;
+		if ( mapping !== undefined ) texture.mapping = mapping;
+
+		// no flipping for cube textures
+		// (also flipping doesn't work for compressed textures )
+
+		texture.flipY = false;
+
+		// can't generate mipmaps for compressed textures
+		// mips must be embedded in DDS files
+
+		texture.generateMipmaps = false;
+
+		{
+			var request = new XMLHttpRequest();
+
+			request.onload = function( ) {
+
+				var buffer = request.response;
+				var dds = THREE.ImageUtils.parseDDS( buffer, true );
+
+				if ( dds.isCubemap ) {
+
+					var faces = dds.mipmaps.length / dds.mipmapCount;
+
+					for ( var f = 0; f < faces; f ++ ) {
+
+						images[ f ] = { mipmaps : [] };
+
+						for ( var i = 0; i < dds.mipmapCount; i ++ ) {
+
+							images[ f ].mipmaps.push( dds.mipmaps[ f * dds.mipmapCount + i ] );
+							images[ f ].format = dds.format;
+							images[ f ].width = dds.width;
+							images[ f ].height = dds.height;
+
+						}
+
+					}
+
+
+				} else {
+					texture.image.width = dds.width;
+					texture.image.height = dds.height;
+					texture.mipmaps = dds.mipmaps;
+				}
+
+				texture.format = dds.format;
+				texture.needsUpdate = true;
+				if ( onLoad ) onLoad( texture );
+
+			}
+
+			request.onerror = onError;
+
+			request.open( 'GET', url, true );
+			request.responseType = "arraybuffer";
+			request.send( null );
+
+		}
+
+		return texture;
+
+	},
+
 	parseDDS: function ( buffer, loadMipmaps ) {
 	parseDDS: function ( buffer, loadMipmaps ) {
 
 
 		var dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 };
 		var dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 };
@@ -290,6 +361,27 @@ THREE.ImageUtils = {
 			);
 			);
 		}
 		}
 
 
+		function loadARGBMip( buffer, dataOffset, width, height ) {
+			var dataLength = width*height*4;
+			var srcBuffer = new Uint8Array( buffer, dataOffset, dataLength );
+			var byteArray = new Uint8Array( dataLength );
+			var dst = 0;
+			var src = 0;
+			for ( var y = 0; y < height; y++ ) {
+				for ( var x = 0; x < width; x++ ) {
+					var b = srcBuffer[src]; src++;
+					var g = srcBuffer[src]; src++;
+					var r = srcBuffer[src]; src++;
+					var a = srcBuffer[src]; src++;
+					byteArray[dst] = r; dst++;	//r
+					byteArray[dst] = g; dst++;	//g
+					byteArray[dst] = b; dst++;	//b
+					byteArray[dst] = a; dst++;	//a
+				}
+			}
+			return byteArray;
+		}
+
 		var FOURCC_DXT1 = fourCCToInt32("DXT1");
 		var FOURCC_DXT1 = fourCCToInt32("DXT1");
 		var FOURCC_DXT3 = fourCCToInt32("DXT3");
 		var FOURCC_DXT3 = fourCCToInt32("DXT3");
 		var FOURCC_DXT5 = fourCCToInt32("DXT5");
 		var FOURCC_DXT5 = fourCCToInt32("DXT5");
@@ -309,6 +401,11 @@ THREE.ImageUtils = {
 
 
 		var off_pfFlags = 20;
 		var off_pfFlags = 20;
 		var off_pfFourCC = 21;
 		var off_pfFourCC = 21;
+		var off_RGBBitCount = 22;
+		var off_RBitMask = 23;
+		var off_GBitMask = 24;
+		var off_BBitMask = 25;
+		var off_ABitMask = 26;
 
 
 		var off_caps = 27;
 		var off_caps = 27;
 		var off_caps2 = 28;
 		var off_caps2 = 28;
@@ -337,6 +434,8 @@ THREE.ImageUtils = {
 
 
 		var fourCC = header[ off_pfFourCC ];
 		var fourCC = header[ off_pfFourCC ];
 
 
+		var isRGBAUncompressed = false;
+
 		switch ( fourCC ) {
 		switch ( fourCC ) {
 
 
 			case FOURCC_DXT1:
 			case FOURCC_DXT1:
@@ -359,9 +458,18 @@ THREE.ImageUtils = {
 
 
 			default:
 			default:
 
 
-				console.error( "ImageUtils.parseDDS(): Unsupported FourCC code: ", int32ToFourCC( fourCC ) );
-				return dds;
-
+				if( header[off_RGBBitCount] ==32 
+					&& header[off_RBitMask]&0xff0000
+					&& header[off_GBitMask]&0xff00 
+					&& header[off_BBitMask]&0xff
+					&& header[off_ABitMask]&0xff000000  ) {
+					isRGBAUncompressed = true;
+					blockBytes = 64;
+					dds.format = THREE.RGBAFormat;
+				} else {
+					console.error( "ImageUtils.parseDDS(): Unsupported FourCC code: ", int32ToFourCC( fourCC ) );
+					return dds;
+				}
 		}
 		}
 
 
 		dds.mipmapCount = 1;
 		dds.mipmapCount = 1;
@@ -392,9 +500,14 @@ THREE.ImageUtils = {
 
 
 			for ( var i = 0; i < dds.mipmapCount; i ++ ) {
 			for ( var i = 0; i < dds.mipmapCount; i ++ ) {
 
 
-				var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes;
-				var byteArray = new Uint8Array( buffer, dataOffset, dataLength );
-
+				if( isRGBAUncompressed ) {
+					var byteArray = loadARGBMip( buffer, dataOffset, width, height );
+					var dataLength = byteArray.length;
+				} else {
+					var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes;
+					var byteArray = new Uint8Array( buffer, dataOffset, dataLength );
+				}
+				
 				var mipmap = { "data": byteArray, "width": width, "height": height };
 				var mipmap = { "data": byteArray, "width": width, "height": height };
 				dds.mipmaps.push( mipmap );
 				dds.mipmaps.push( mipmap );
 
 

+ 16 - 11
src/renderers/WebGLRenderer.js

@@ -6149,13 +6149,14 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			} else if ( texture instanceof THREE.CompressedTexture ) {
 			} else if ( texture instanceof THREE.CompressedTexture ) {
 
 
-				// compressed textures can only use manually created mipmaps
-				// WebGL can't generate mipmaps for DDS textures
-
 				for( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 				for( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
 
 					mipmap = mipmaps[ i ];
 					mipmap = mipmaps[ i ];
-					_gl.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
+					if ( texture.format!==THREE.RGBAFormat ) {
+						_gl.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
+					} else {
+						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
+					}
 
 
 				}
 				}
 
 
@@ -6273,23 +6274,27 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 				for ( var i = 0; i < 6; i ++ ) {
 				for ( var i = 0; i < 6; i ++ ) {
 
 
-					if ( isCompressed ) {
+					if( !isCompressed ) {
 
 
+						_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
+
+					} else {
+						
 						var mipmap, mipmaps = cubeImage[ i ].mipmaps;
 						var mipmap, mipmaps = cubeImage[ i ].mipmaps;
 
 
 						for( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
 						for( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
 
 
 							mipmap = mipmaps[ j ];
 							mipmap = mipmaps[ j ];
-							_gl.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
+							if ( texture.format!==THREE.RGBAFormat ) {
 
 
-						}
-
-					} else {
+								_gl.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
 
 
-						_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
+							} else {
+								_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
+							}
 
 
+						}
 					}
 					}
-
 				}
 				}
 
 
 				if ( texture.generateMipmaps && isImagePowerOfTwo ) {
 				if ( texture.generateMipmaps && isImagePowerOfTwo ) {