Selaa lähdekoodia

WebGPURenderer: Add DepthTexture.compareFunction (#26420)

* WebGPURenderer: Add DepthTexture.compareFunction

* Update webgpu_audio_processing.html

* Add createBindingsLayout()

* fix fog

* cleanup

* fix fog

* Cleanup getTextureCompare

* fix conflict

* Added normalBias

* AnalyticLightNode:  Added PCFShadowMap (WIP)
sunag 2 vuotta sitten
vanhempi
commit
3166056814

+ 21 - 4
examples/jsm/nodes/accessors/TextureNode.js

@@ -5,12 +5,12 @@ import { colorSpaceToLinear } from '../display/ColorSpaceNode.js';
 import { context } from '../core/ContextNode.js';
 import { expression } from '../code/ExpressionNode.js';
 import { addNodeClass } from '../core/Node.js';
-import { addNodeElement, nodeProxy, vec3 } from '../shadernode/ShaderNode.js';
+import { addNodeElement, nodeProxy, vec3, nodeObject } from '../shadernode/ShaderNode.js';
 import { NodeUpdateType } from '../core/constants.js';
 
 class TextureNode extends UniformNode {
 
-	constructor( value, uvNode = null, levelNode = null ) {
+	constructor( value, uvNode = null, levelNode = null, compareNode = null ) {
 
 		super( value );
 
@@ -18,6 +18,7 @@ class TextureNode extends UniformNode {
 
 		this.uvNode = uvNode;
 		this.levelNode = levelNode;
+		this.compareNode = compareNode;
 
 		this.updateType = NodeUpdateType.FRAME;
 
@@ -88,6 +89,7 @@ class TextureNode extends UniformNode {
 
 		const { uvNode, levelNode } = builder.getNodeProperties( this );
 
+		const compareNode = this.compareNode;
 		const texture = this.value;
 
 		if ( ! texture || texture.isTexture !== true ) {
@@ -128,6 +130,12 @@ class TextureNode extends UniformNode {
 
 					snippet = builder.getTextureLevel( texture, textureProperty, uvSnippet, levelSnippet );
 
+				} else if ( compareNode !== null ) {
+
+					const compareSnippet = compareNode.build( builder, 'float' );
+
+					snippet = builder.getTextureCompare( texture, textureProperty, uvSnippet, compareSnippet );
+
 				} else {
 
 					snippet = builder.getTexture( texture, textureProperty, uvSnippet );
@@ -160,7 +168,7 @@ class TextureNode extends UniformNode {
 		const textureNode = this.clone();
 		textureNode.uvNode = uvNode;
 
-		return textureNode;
+		return nodeObject( textureNode );
 
 	}
 
@@ -181,6 +189,15 @@ class TextureNode extends UniformNode {
 
 	}
 
+	compare( compareNode ) {
+
+		const textureNode = this.clone();
+		textureNode.compareNode = nodeObject( compareNode );
+
+		return nodeObject( textureNode );
+
+	}
+
 	serialize( data ) {
 
 		super.serialize( data );
@@ -211,7 +228,7 @@ class TextureNode extends UniformNode {
 
 	clone() {
 
-		return new this.constructor( this.value, this.uvNode, this.levelNode );
+		return new this.constructor( this.value, this.uvNode, this.levelNode, this.compareNode );
 
 	}
 

+ 58 - 20
examples/jsm/nodes/lighting/AnalyticLightNode.js

@@ -2,14 +2,14 @@ import LightingNode from './LightingNode.js';
 import { NodeUpdateType } from '../core/constants.js';
 import { uniform } from '../core/UniformNode.js';
 import { addNodeClass } from '../core/Node.js';
-import { vec3 } from '../shadernode/ShaderNode.js';
+import { /*vec2,*/ vec3 } from '../shadernode/ShaderNode.js';
 import { reference } from '../accessors/ReferenceNode.js';
 import { texture } from '../accessors/TextureNode.js';
 import { positionWorld } from '../accessors/PositionNode.js';
-//import { step } from '../math/MathNode.js';
-import { cond } from '../math/CondNode.js';
+import { normalWorld } from '../accessors/NormalNode.js';
+//import { add } from '../math/OperatorNode.js';
 
-import { Color, DepthTexture, NearestFilter } from 'three';
+import { Color, DepthTexture, NearestFilter, LessCompare } from 'three';
 
 let depthMaterial = null;
 
@@ -53,7 +53,7 @@ class AnalyticLightNode extends LightingNode {
 			depthTexture.magFilter = NearestFilter;
 			depthTexture.image.width = shadow.mapSize.width;
 			depthTexture.image.height = shadow.mapSize.height;
-			//depthTexture.compareFunction = THREE.LessCompare;
+			depthTexture.compareFunction = LessCompare;
 
 			rtt.depthTexture = depthTexture;
 
@@ -62,31 +62,69 @@ class AnalyticLightNode extends LightingNode {
 			//
 
 			const bias = reference( 'bias', 'float', shadow );
+			const normalBias = reference( 'normalBias', 'float', shadow );
 
-			//const diffuseFactor = normalView.dot( objectViewPosition( this.light ).sub( positionView ).normalize().negate() );
-			//bias = mix( bias, 0, diffuseFactor );
-
-			let shadowCoord = uniform( shadow.matrix ).mul( positionWorld );
+			let shadowCoord = uniform( shadow.matrix ).mul( positionWorld.add( normalWorld.mul( normalBias ) ) );
 			shadowCoord = shadowCoord.xyz.div( shadowCoord.w );
 
+			const frustumTest = shadowCoord.x.greaterThanEqual( 0 )
+				.and( shadowCoord.x.lessThanEqual( 1 ) )
+				.and( shadowCoord.y.greaterThanEqual( 0 ) )
+				.and( shadowCoord.y.lessThanEqual( 1 ) )
+				.and( shadowCoord.z.lessThanEqual( 1 ) );
+
 			shadowCoord = vec3(
 				shadowCoord.x,
-				shadowCoord.y.oneMinus(),
-				shadowCoord.z
+				shadowCoord.y.oneMinus(), // WebGPU: Flip Y
+				shadowCoord.z.add( bias ).mul( 2 ).sub( 1 ) // WebGPU: Convertion [ 0, 1 ] to [ - 1, 1 ]
 			);
 
-			// @TODO: Optimize using WebGPU compare-sampler
-
-			let depth = texture( depthTexture, shadowCoord.xy );
-			depth = depth.mul( .5 ).add( .5 ).add( bias );
-
-			shadowNode = cond( shadowCoord.z.lessThan( depth ).or( shadowCoord.y.lessThan( .000001 ) /*@TODO: find the cause and remove it soon */ ), 1, 0 );
-			//shadowNode = step( shadowCoord.z, depth );
-
+			const textureCompare = ( depthTexture, shadowCoord, compare ) => texture( depthTexture, shadowCoord ).compare( compare );
+			//const textureCompare = ( depthTexture, shadowCoord, compare ) => compare.step( texture( depthTexture, shadowCoord ) );
+
+			// BasicShadowMap
+
+			shadowNode = textureCompare( depthTexture, shadowCoord.xy, shadowCoord.z );
+
+			// PCFShadowMap
+			/*
+			const mapSize = reference( 'mapSize', 'vec2', shadow );
+			const radius = reference( 'radius', 'float', shadow );
+
+			const texelSize = vec2( 1 ).div( mapSize );
+			const dx0 = texelSize.x.negate().mul( radius );
+			const dy0 = texelSize.y.negate().mul( radius );
+			const dx1 = texelSize.x.mul( radius );
+			const dy1 = texelSize.y.mul( radius );
+			const dx2 = dx0.mul( 2 );
+			const dy2 = dy0.mul( 2 );
+			const dx3 = dx1.mul( 2 );
+			const dy3 = dy1.mul( 2 );
+
+			shadowNode = add(
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx0, dy0 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( 0, dy0 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx1, dy0 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx2, dy2 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( 0, dy2 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx3, dy2 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx0, 0 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx2, 0 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy, shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx3, 0 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx1, 0 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx2, dy3 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( 0, dy3 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx3, dy3 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx0, dy1 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( 0, dy1 ) ), shadowCoord.z ),
+				textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx1, dy1 ) ), shadowCoord.z )
+			).mul( 1 / 17 );
+			*/
 			//
 
 			this.rtt = rtt;
-			this.colorNode = this.colorNode.mul( shadowNode );
+			this.colorNode = this.colorNode.mul( frustumTest.mix( 1, shadowNode ) );
 
 			this.shadowNode = shadowNode;
 

+ 8 - 0
examples/jsm/renderers/common/Binding.js

@@ -4,6 +4,14 @@ class Binding {
 
 		this.name = name;
 
+		this.visibility = 0;
+
+	}
+
+	setVisibility( visibility ) {
+
+		this.visibility |= visibility;
+
 	}
 
 }

+ 2 - 6
examples/jsm/renderers/common/Bindings.js

@@ -34,9 +34,7 @@ class Bindings extends DataMap {
 
 			this._init( bindings );
 
-			const pipeline = this.pipelines.getForRender( renderObject );
-
-			this.backend.createBindings( bindings, pipeline );
+			this.backend.createBindings( bindings );
 
 		}
 
@@ -58,9 +56,7 @@ class Bindings extends DataMap {
 
 			this._init( bindings );
 
-			const pipeline = this.pipelines.getForCompute( computeNode );
-
-			this.backend.createBindings( bindings, pipeline );
+			this.backend.createBindings( bindings );
 
 		}
 

+ 10 - 4
examples/jsm/renderers/common/Pipelines.js

@@ -23,7 +23,7 @@ class Pipelines extends DataMap {
 
 	}
 
-	getForCompute( computeNode ) {
+	getForCompute( computeNode, bindings ) {
 
 		const { backend } = this;
 
@@ -69,7 +69,7 @@ class Pipelines extends DataMap {
 
 				if ( previousPipeline && previousPipeline.usedTimes === 0 ) this._releasePipeline( computeNode );
 
-				pipeline = this._getComputePipeline( computeNode, stageCompute, cacheKey );
+				pipeline = this._getComputePipeline( computeNode, stageCompute, cacheKey, bindings );
 
 			}
 
@@ -222,7 +222,13 @@ class Pipelines extends DataMap {
 
 	}
 
-	_getComputePipeline( computeNode, stageCompute, cacheKey ) {
+	updateForRender( renderObject ) {
+
+		this.getForRender( renderObject );
+
+	}
+
+	_getComputePipeline( computeNode, stageCompute, cacheKey, bindings ) {
 
 		// check for existing pipeline
 
@@ -236,7 +242,7 @@ class Pipelines extends DataMap {
 
 			this.caches.set( cacheKey, pipeline );
 
-			this.backend.createComputePipeline( pipeline );
+			this.backend.createComputePipeline( pipeline, bindings );
 
 		}
 

+ 2 - 1
examples/jsm/renderers/common/Renderer.js

@@ -639,8 +639,8 @@ class Renderer {
 			nodes.updateForCompute( computeNode );
 			bindings.updateForCompute( computeNode );
 
-			const computePipeline = pipelines.getForCompute( computeNode );
 			const computeBindings = bindings.getForCompute( computeNode );
+			const computePipeline = pipelines.getForCompute( computeNode, computeBindings );
 
 			backend.compute( computeNodes, computeNode, computeBindings, computePipeline );
 
@@ -882,6 +882,7 @@ class Renderer {
 		this._nodes.updateForRender( renderObject );
 		this._geometries.updateForRender( renderObject );
 		this._bindings.updateForRender( renderObject );
+		this._pipelines.updateForRender( renderObject );
 
 		//
 

+ 3 - 3
examples/jsm/renderers/common/Textures.js

@@ -79,10 +79,10 @@ class Textures extends DataMap {
 		const textureData = this.get( texture );
 		if ( textureData.initialized === true && textureData.version === texture.version ) return;
 
-		const isRenderTexture = texture.isRenderTargetTexture || texture.isDepthTexture || texture.isFramebufferTexture;
+		const isRenderTarget = texture.isRenderTargetTexture || texture.isDepthTexture || texture.isFramebufferTexture;
 		const backend = this.backend;
 
-		if ( isRenderTexture && textureData.initialized === true ) {
+		if ( isRenderTarget && textureData.initialized === true ) {
 
 			// it's an update
 
@@ -93,7 +93,7 @@ class Textures extends DataMap {
 
 		//
 
-		if ( isRenderTexture ) {
+		if ( isRenderTarget ) {
 
 			backend.createSampler( texture );
 			backend.createTexture( texture );

+ 6 - 6
examples/jsm/renderers/webgpu/WebGPUBackend.js

@@ -614,23 +614,23 @@ class WebGPUBackend extends Backend {
 
 	}
 
-	createComputePipeline( computePipeline ) {
+	createComputePipeline( computePipeline, bindings ) {
 
-		this.pipelineUtils.createComputePipeline( computePipeline );
+		this.pipelineUtils.createComputePipeline( computePipeline, bindings );
 
 	}
 
 	// bindings
 
-	createBindings( bindings, pipeline ) {
+	createBindings( bindings ) {
 
-		this.bindingUtils.createBindings( bindings, pipeline );
+		this.bindingUtils.createBindings( bindings );
 
 	}
 
-	updateBindings( bindings, pipeline ) {
+	updateBindings( bindings ) {
 
-		this.bindingUtils.createBindings( bindings, pipeline );
+		this.bindingUtils.createBindings( bindings );
 
 	}
 

+ 32 - 7
examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js

@@ -19,13 +19,11 @@ import { NodeBuilder, CodeNode, NodeMaterial } from '../../../nodes/Nodes.js';
 
 import WGSLNodeParser from './WGSLNodeParser.js';
 
-/*
 const gpuShaderStageLib = {
 	'vertex': GPUShaderStage.VERTEX,
 	'fragment': GPUShaderStage.FRAGMENT,
 	'compute': GPUShaderStage.COMPUTE
 };
-*/
 
 const supports = {
 	instance: true
@@ -207,6 +205,20 @@ class WGSLNodeBuilder extends NodeBuilder {
 
 	}
 
+	getTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, shaderStage = this.shaderStage ) {
+
+		if ( shaderStage === 'fragment' ) {
+
+			return `textureSampleCompare( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${compareSnippet} )`;
+
+		} else {
+
+			console.error( `WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${ shaderStage } shader.` );
+
+		}
+
+	}
+
 	getTextureLevel( texture, textureProperty, uvSnippet, biasSnippet, shaderStage = this.shaderStage ) {
 
 		let snippet = null;
@@ -273,8 +285,6 @@ class WGSLNodeBuilder extends NodeBuilder {
 
 			if ( type === 'texture' || type === 'cubeTexture' ) {
 
-				const sampler = new NodeSampler( `${uniformNode.name}_sampler`, uniformNode.node );
-
 				let texture = null;
 
 				if ( type === 'texture' ) {
@@ -287,12 +297,17 @@ class WGSLNodeBuilder extends NodeBuilder {
 
 				}
 
+				texture.setVisibility( gpuShaderStageLib[ shaderStage ] );
+
 				// add first textures in sequence and group for last
 				const lastBinding = bindings[ bindings.length - 1 ];
 				const index = lastBinding && lastBinding.isUniformsGroup ? bindings.length - 1 : bindings.length;
 
 				if ( shaderStage === 'fragment' ) {
 
+					const sampler = new NodeSampler( `${uniformNode.name}_sampler`, uniformNode.node );
+					sampler.setVisibility( gpuShaderStageLib[ shaderStage ] );
+
 					bindings.splice( index, 0, sampler, texture );
 
 					uniformGPU = [ sampler, texture ];
@@ -309,7 +324,7 @@ class WGSLNodeBuilder extends NodeBuilder {
 
 				const bufferClass = type === 'storageBuffer' ? StorageBuffer : UniformBuffer;
 				const buffer = new bufferClass( 'NodeBuffer_' + node.id, node.value );
-				//buffer.setVisibility( gpuShaderStageLib[ shaderStage ] );
+				buffer.setVisibility( gpuShaderStageLib[ shaderStage ] );
 
 				// add first textures in sequence and group for last
 				const lastBinding = bindings[ bindings.length - 1 ];
@@ -326,7 +341,7 @@ class WGSLNodeBuilder extends NodeBuilder {
 				if ( uniformsGroup === undefined ) {
 
 					uniformsGroup = new UniformsGroup( 'nodeUniforms' );
-					//uniformsGroup.setVisibility( gpuShaderStageLib[ shaderStage ] );
+					uniformsGroup.setVisibility( gpuShaderStageLib[ shaderStage ] );
 
 					this.uniformsGroup[ shaderStage ] = uniformsGroup;
 
@@ -568,7 +583,17 @@ class WGSLNodeBuilder extends NodeBuilder {
 
 				if ( shaderStage === 'fragment' ) {
 
-					bindingSnippets.push( `@binding( ${index ++} ) @group( 0 ) var ${uniform.name}_sampler : sampler;` );
+					const texture = uniform.node.value;
+
+					if ( texture.isDepthTexture === true && texture.compareFunction !== null ) {
+
+						bindingSnippets.push( `@binding( ${index ++} ) @group( 0 ) var ${uniform.name}_sampler : sampler_comparison;` );
+
+					} else {
+
+						bindingSnippets.push( `@binding( ${index ++} ) @group( 0 ) var ${uniform.name}_sampler : sampler;` );
+
+					}
 
 				}
 

+ 83 - 5
examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js

@@ -1,5 +1,5 @@
 import {
-	GPUTextureAspect, GPUTextureViewDimension
+	GPUTextureAspect, GPUTextureViewDimension, GPUBufferBindingType
 } from './WebGPUConstants.js';
 
 class WebGPUBindingUtils {
@@ -10,16 +10,94 @@ class WebGPUBindingUtils {
 
 	}
 
-	createBindings( bindings, pipeline ) {
+	createBindingsLayout( bindings ) {
+
+		const backend = this.backend;
+		const device = backend.device;
+
+		const entries = [];
+
+		let index = 0;
+
+		for ( const binding of bindings ) {
+
+			const bindingGPU = {
+				binding: index ++,
+				visibility: binding.visibility
+			};
+
+			if ( binding.isUniformBuffer || binding.isStorageBuffer ) {
+
+				const buffer = {}; // GPUBufferBindingLayout
+
+				if ( binding.isStorageBuffer ) {
+
+					buffer.type = GPUBufferBindingType.Storage;
+
+				}
+
+				bindingGPU.buffer = buffer;
+
+			} else if ( binding.isSampler ) {
+
+				const sampler = {}; // GPUSamplerBindingLayout
+
+				if ( binding.texture.isDepthTexture ) {
+
+					if ( binding.texture.compareFunction !== null ) {
+
+						sampler.type = 'comparison';
+
+					}
+
+				}
+
+				bindingGPU.sampler = sampler;
+
+			} else if ( binding.isSampledTexture && binding.texture.isVideoTexture ) {
+
+				bindingGPU.externalTexture = {}; // GPUExternalTextureBindingLayout
+
+			} else if ( binding.isSampledTexture ) {
+
+				const texture = {}; // GPUTextureBindingLayout
+
+				if ( binding.texture.isDepthTexture ) {
+
+					texture.sampleType = 'depth';
+
+				}
+
+				if ( binding.isSampledCubeTexture ) {
+
+					texture.viewDimension = GPUTextureViewDimension.Cube;
+
+				}
+
+				bindingGPU.texture = texture;
+
+			} else {
+
+				console.error( 'WebGPUBindingUtils: Unsupported binding "${ binding }".' );
+
+			}
+
+			entries.push( bindingGPU );
+
+		}
+
+		return device.createBindGroupLayout( { entries } );
+
+	}
+
+	createBindings( bindings ) {
 
 		const backend = this.backend;
 		const bindingsData = backend.get( bindings );
 
 		// setup (static) binding layout and (dynamic) binding group
 
-		const pipelineGPU = backend.get( pipeline ).pipeline;
-
-		const bindLayoutGPU = pipelineGPU.getBindGroupLayout( 0 );
+		const bindLayoutGPU = this.createBindingsLayout( bindings );
 		const bindGroupGPU = this.createBindGroup( bindings, bindLayoutGPU );
 
 		bindingsData.layout = bindLayoutGPU;

+ 18 - 16
examples/jsm/renderers/webgpu/utils/WebGPUConstants.js

@@ -214,12 +214,6 @@ export const GPUAddressMode = {
 	MirrorRepeat: 'mirror-repeat'
 };
 
-export const GPUSamplerBindingType = {
-	Filtering: 'filtering',
-	NonFiltering: 'non-filtering',
-	Comparison: 'comparison'
-};
-
 export const GPUFilterMode = {
 	Linear: 'linear',
 	Nearest: 'nearest'
@@ -269,16 +263,24 @@ export const GPUStencilOperation = {
 	DecrementWrap: 'decrement-wrap'
 };
 
-export const GPUBindingType = {
-	UniformBuffer: 'uniform-buffer',
-	StorageBuffer: 'storage-buffer',
-	ReadonlyStorageBuffer: 'readonly-storage-buffer',
-	Sampler: 'sampler',
-	ComparisonSampler: 'comparison-sampler',
-	SampledTexture: 'sampled-texture',
-	MultisampledTexture: 'multisampled-texture',
-	ReadonlyStorageTexture: 'readonly-storage-texture',
-	WriteonlyStorageTexture: 'writeonly-storage-texture'
+export const GPUBufferBindingType = {
+	Uniform: 'uniform',
+	Storage: 'storage',
+	ReadOnlyStorage: 'read-only-storage'
+};
+
+export const GPUSamplerBindingType = {
+	Filtering: 'filtering',
+	NonFiltering: 'non-filtering',
+	Comparison: 'comparison'
+};
+
+export const GPUTextureSampleType = {
+	Float: 'float',
+	UnfilterableFloat: 'unfilterable-float',
+	Depth: 'depth',
+	SInt: 'sint',
+	UInt: 'uint'
 };
 
 export const GPUTextureDimension = {

+ 9 - 3
examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js

@@ -33,6 +33,7 @@ class WebGPUPipelineUtils {
 		const utils = backend.utils;
 
 		const pipelineData = backend.get( pipeline );
+		const bindingsData = backend.get( renderObject.getBindings() );
 
 		// vertex buffers
 
@@ -98,12 +99,14 @@ class WebGPUPipelineUtils {
 			multisample: {
 				count: sampleCount
 			},
-			layout: 'auto'
+			layout: device.createPipelineLayout( {
+				bindGroupLayouts: [ bindingsData.layout ]
+			} )
 		} );
 
 	}
 
-	createComputePipeline( pipeline ) {
+	createComputePipeline( pipeline, bindings ) {
 
 		const backend = this.backend;
 		const device = backend.device;
@@ -111,10 +114,13 @@ class WebGPUPipelineUtils {
 		const computeProgram = backend.get( pipeline.computeProgram ).module;
 
 		const pipelineGPU = backend.get( pipeline );
+		const bindingsData = backend.get( bindings );
 
 		pipelineGPU.pipeline = device.createComputePipeline( {
 			compute: computeProgram,
-			layout: 'auto'
+			layout: device.createPipelineLayout( {
+				bindGroupLayouts: [ bindingsData.layout ]
+			} )
 		} );
 
 	}

+ 6 - 6
examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js

@@ -19,13 +19,13 @@ import WebGPUTextureMipmapUtils from './WebGPUTextureMipmapUtils.js';
 
 const _compareToWebGPU = {
 	[ NeverCompare ]: 'never',
-	[ AlwaysCompare ]: 'less',
-	[ LessCompare ]: 'equal',
+	[ LessCompare ]: 'less',
+	[ EqualCompare ]: 'equal',
 	[ LessEqualCompare ]: 'less-equal',
-	[ EqualCompare ]: 'greater',
-	[ GreaterEqualCompare ]: 'not-equal',
-	[ GreaterCompare ]: 'greater-equal',
-	[ NotEqualCompare ]: 'always'
+	[ GreaterCompare ]: 'greater',
+	[ GreaterEqualCompare ]: 'greater-equal',
+	[ AlwaysCompare ]: 'always',
+	[ NotEqualCompare ]: 'not-equal'
 };
 
 class WebGPUTextureUtils {

+ 1 - 1
examples/webgpu_audio_processing.html

@@ -56,7 +56,7 @@
 
 				renderer.compute( computeNode );
 
-				const waveArray = new Float32Array( await renderer.getArrayBuffer( waveGPUBuffer ) );
+				const waveArray = new Float32Array( await renderer.getArrayBufferAsync( waveGPUBuffer ) );
 
 				// play result
 

+ 13 - 8
examples/webgpu_shadowmap.html

@@ -59,24 +59,26 @@
 
 				// lights
 
-				scene.add( new THREE.AmbientLight( 0x444444 ) );
+				scene.add( new THREE.AmbientLight( 0x444444, 2 ) );
 
-				spotLight = new THREE.SpotLight( 0xff8888, 300 );
+				spotLight = new THREE.SpotLight( 0xff8888, 400 );
 				spotLight.angle = Math.PI / 5;
 				spotLight.penumbra = 0.3;
 				spotLight.position.set( 8, 10, 5 );
 				spotLight.castShadow = true;
 				spotLight.shadow.camera.near = 8;
-				spotLight.shadow.camera.far = 1000;
+				spotLight.shadow.camera.far = 200;
 				spotLight.shadow.mapSize.width = 2048;
 				spotLight.shadow.mapSize.height = 2048;
-				spotLight.shadow.bias = .01;
+				spotLight.shadow.bias = - 0.002;
+				spotLight.shadow.radius = 4;
 				scene.add( spotLight );
 
-				dirLight = new THREE.DirectionalLight( 0x8888ff, 2 );
-				dirLight.position.set( 3, 20, 12 );
+
+				dirLight = new THREE.DirectionalLight( 0x8888ff, 3 );
+				dirLight.position.set( 3, 12, 17 );
 				dirLight.castShadow = true;
-				dirLight.shadow.camera.near = 8;
+				dirLight.shadow.camera.near = 0.1;
 				dirLight.shadow.camera.far = 500;
 				dirLight.shadow.camera.right = 17;
 				dirLight.shadow.camera.left = - 17;
@@ -84,7 +86,8 @@
 				dirLight.shadow.camera.bottom = - 17;
 				dirLight.shadow.mapSize.width = 2048;
 				dirLight.shadow.mapSize.height = 2048;
-				dirLight.shadow.bias = .0001;
+				dirLight.shadow.radius = 4;
+				dirLight.shadow.bias = - 0.0005;
 
 				dirGroup = new THREE.Group();
 				dirGroup.add( dirLight );
@@ -151,6 +154,8 @@
 				// Mouse control
 				const controls = new OrbitControls( camera, renderer.domElement );
 				controls.target.set( 0, 2, 0 );
+				controls.minDistance = 7;
+				controls.maxDistance = 40;
 				controls.update();
 
 				clock = new THREE.Clock();