Bladeren bron

WebGPURenderer: Initial support for cube textures.

Mugen87 4 jaren geleden
bovenliggende
commit
932dc84405

+ 15 - 4
examples/jsm/renderers/webgpu/WebGPUBindings.js

@@ -1,7 +1,7 @@
 import WebGPUUniformsGroup from './WebGPUUniformsGroup.js';
-import { FloatUniform, Matrix4Uniform } from './WebGPUUniform.js';
+import { FloatUniform, Matrix3Uniform, Matrix4Uniform } from './WebGPUUniform.js';
 import WebGPUSampler from './WebGPUSampler.js';
-import WebGPUSampledTexture from './WebGPUSampledTexture.js';
+import { WebGPUSampledTexture } from './WebGPUSampledTexture.js';
 
 class WebGPUBindings {
 
@@ -212,11 +212,19 @@ class WebGPUBindings {
 
 				if ( binding.textureGPU === null ) {
 
-					binding.textureGPU = this.textures.getDefaultTexture();
+					if ( binding.isSampledCubeTexture ) {
+
+						binding.textureGPU = this.textures.getDefaultCubeTexture();
+
+					} else {
+
+						binding.textureGPU = this.textures.getDefaultTexture();
+
+					}
 
 				}
 
-				entries.push( { binding: bindingPoint, resource: binding.textureGPU.createView() } );
+				entries.push( { binding: bindingPoint, resource: binding.textureGPU.createView( { dimension: binding.dimension } ) } );
 
 			}
 
@@ -241,15 +249,18 @@ class WebGPUBindings {
 
 		const modelViewUniform = new Matrix4Uniform( 'modelMatrix' );
 		const modelViewMatrixUniform = new Matrix4Uniform( 'modelViewMatrix' );
+		const normalMatrixUniform = new Matrix3Uniform( 'normalMatrix' );
 
 		const modelGroup = new WebGPUUniformsGroup();
 		modelGroup.setName( 'modelUniforms' );
 		modelGroup.addUniform( modelViewUniform );
 		modelGroup.addUniform( modelViewMatrixUniform );
+		modelGroup.addUniform( normalMatrixUniform );
 		modelGroup.setOnBeforeUpdate( function ( object/*, camera */ ) {
 
 			modelViewUniform.setValue( object.matrixWorld );
 			modelViewMatrixUniform.setValue( object.modelViewMatrix );
+			normalMatrixUniform.setValue( object.normalMatrix );
 
 		} );
 

+ 18 - 1
examples/jsm/renderers/webgpu/WebGPUSampledTexture.js

@@ -6,6 +6,8 @@ class WebGPUSampledTexture extends WebGPUBinding {
 
 		super();
 
+		this.dimension = '2d';
+
 		this.type = 'sampled-texture';
 		this.visibility = GPUShaderStage.FRAGMENT;
 
@@ -15,6 +17,21 @@ class WebGPUSampledTexture extends WebGPUBinding {
 
 	}
 
+
+}
+
+class WebGPUSampledCubeTexture extends WebGPUSampledTexture {
+
+	constructor() {
+
+		super();
+
+		this.dimension = 'cube';
+
+		Object.defineProperty( this, 'isSampledCubeTexture', { value: true } );
+
+	}
+
 }
 
-export default WebGPUSampledTexture;
+export { WebGPUSampledTexture, WebGPUSampledCubeTexture };

+ 84 - 26
examples/jsm/renderers/webgpu/WebGPUTextures.js

@@ -1,5 +1,5 @@
 import { GPUTextureFormat, GPUAddressMode, GPUFilterMode } from './constants.js';
-import { Texture, NearestFilter, NearestMipmapNearestFilter, NearestMipmapLinearFilter, LinearFilter, RepeatWrapping, MirroredRepeatWrapping,
+import { CubeTexture, Texture, NearestFilter, NearestMipmapNearestFilter, NearestMipmapLinearFilter, LinearFilter, RepeatWrapping, MirroredRepeatWrapping,
 	RGBFormat, RGBAFormat, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, UnsignedByteType, FloatType, HalfFloatType
 } from '../../../../build/three.module.js';
 import WebGPUTextureUtils from './WebGPUTextureUtils.js';
@@ -14,6 +14,7 @@ class WebGPUTextures {
 		this.glslang = glslang;
 
 		this.defaultTexture = null;
+		this.defaultCubeTexture = null;
 		this.defaultSampler = null;
 
 		this.samplerCache = new Map();
@@ -49,6 +50,22 @@ class WebGPUTextures {
 
 	}
 
+	getDefaultCubeTexture() {
+
+		if ( this.defaultCubeTexture === null ) {
+
+			const texture = new CubeTexture();
+			texture.minFilter = NearestFilter;
+			texture.magFilter = NearestFilter;
+
+			this.defaultCubeTexture = this._createTexture( texture );
+
+		}
+
+		return this.defaultCubeTexture;
+
+	}
+
 	getTextureGPU( texture ) {
 
 		const textureProperties = this.properties.get( texture );
@@ -284,8 +301,21 @@ class WebGPUTextures {
 		const device = this.device;
 		const image = texture.image;
 
-		const width = ( image !== undefined ) ? image.width : 1;
-		const height = ( image !== undefined ) ? image.height : 1;
+		let width, height, depth;
+
+		if ( texture.isCubeTexture ) {
+
+			width = ( image.length > 0 ) ? image[ 0 ].width : 1;
+			height = ( image.length > 0 ) ? image[ 0 ].height : 1;
+			depth = 6;
+
+		} else {
+
+			width = ( image !== undefined ) ? image.width : 1;
+			height = ( image !== undefined ) ? image.height : 1;
+			depth = 1;
+
+		}
 
 		const format = this._getFormat( texture );
 		const needsMipmaps = this._needsMipmaps( texture );
@@ -317,7 +347,7 @@ class WebGPUTextures {
 			size: {
 				width: width,
 				height: height,
-				depth: 1,
+				depth: depth,
 			},
 			mipLevelCount: mipLevelCount,
 			sampleCount: 1,
@@ -338,19 +368,17 @@ class WebGPUTextures {
 
 			this._copyCompressedBufferToTexture( texture.mipmaps, format, textureGPU );
 
-		} else {
+		} else if ( texture.isCubeTexture ) {
 
-			// convert HTML images and canvas elements to ImageBitmap
+			this._copyCubeMapToTexture( image, texture, textureGPU );
 
-			if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
-				( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ) {
+		} else {
 
-				const options = {};
+			if ( image !== undefined ) {
 
-				options.imageOrientation = ( texture.flipY === true ) ? 'flipY' : 'none';
-				options.premultiplyAlpha = ( texture.premultiplyAlpha === true ) ? 'premultiply' : 'default';
+				// assume HTMLImageElement, HTMLCanvasElement or ImageBitmap
 
-				createImageBitmap( image, 0, 0, width, height, options ).then( imageBitmap => {
+				this._getImageBitmap( image, texture ).then( imageBitmap => {
 
 					this._copyImageBitmapToTexture( imageBitmap, textureGPU );
 
@@ -358,18 +386,6 @@ class WebGPUTextures {
 
 				} );
 
-			} else {
-
-				if ( image !== undefined ) {
-
-					// assume ImageBitmap
-
-					this._copyImageBitmapToTexture( image, textureGPU );
-
-					if ( needsMipmaps === true ) this._generateMipmaps( textureGPU, textureGPUDescriptor );
-
-				}
-
 			}
 
 		}
@@ -406,14 +422,31 @@ class WebGPUTextures {
 
 	}
 
-	_copyImageBitmapToTexture( image, textureGPU ) {
+	_copyCubeMapToTexture( images, texture, textureGPU ) {
+
+		for ( let i = 0; i < images.length; i ++ ) {
+
+			const image = images[ i ];
+
+			this._getImageBitmap( image, texture ).then( imageBitmap => {
+
+				this._copyImageBitmapToTexture( imageBitmap, textureGPU, { x: 0, y: 0, z: i } );
+
+			} );
+
+		}
+
+	}
+
+	_copyImageBitmapToTexture( image, textureGPU, origin = { x: 0, y: 0, z: 0 } ) {
 
 		this.device.defaultQueue.copyImageBitmapToTexture(
 			{
 				imageBitmap: image
 			}, {
 				texture: textureGPU,
-				mipLevel: 0
+				mipLevel: 0,
+				origin: origin
 			}, {
 				width: image.width,
 				height: image.height,
@@ -540,6 +573,31 @@ class WebGPUTextures {
 
 	}
 
+	_getImageBitmap( image, texture ) {
+
+		const width = image.width;
+		const height = image.height;
+
+		if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
+			( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ) {
+
+			const options = {};
+
+			options.imageOrientation = ( texture.flipY === true ) ? 'flipY' : 'none';
+			options.premultiplyAlpha = ( texture.premultiplyAlpha === true ) ? 'premultiply' : 'default';
+
+			return createImageBitmap( image, 0, 0, width, height, options );
+
+		} else {
+
+			// assume ImageBitmap
+
+			return Promise.resolve( image );
+
+		}
+
+	}
+
 	_getMipLevelCount( width, height ) {
 
 		return Math.floor( Math.log2( Math.max( width, height ) ) ) + 1;