Przeglądaj źródła

WebGPURenderer: Add support for alphaTest. (#21868)

* WebGPURenderer: Add support for alphaTest.

* Examples: Update screenshot.

* WebGPUUniformsGroup: Fix alignment bug.
Michael Herzog 4 lat temu
rodzic
commit
d379666e9b

+ 6 - 1
examples/jsm/renderers/nodes/accessors/MaterialNode.js

@@ -4,6 +4,7 @@ import MaterialReferenceNode from './MaterialReferenceNode.js';
 
 class MaterialNode extends Node {
 
+	static ALPHA_TEST = 'alphaTest';
 	static COLOR = 'color';
 	static OPACITY = 'opacity';
 	static SPECULAR = 'specular';
@@ -49,7 +50,11 @@ class MaterialNode extends Node {
 
 		let node = null;
 
-		if ( scope === MaterialNode.COLOR ) {
+		if ( scope === MaterialNode.ALPHA_TEST ) {
+
+			node = new MaterialReferenceNode( 'alphaTest', 'float' );
+
+		} else if ( scope === MaterialNode.COLOR ) {
 
 			const colorNode = new MaterialReferenceNode( 'color', 'color' );
 

+ 8 - 2
examples/jsm/renderers/webgpu/WebGPUUniformsGroup.js

@@ -68,14 +68,20 @@ class WebGPUUniformsGroup extends WebGPUBinding {
 			const chunkOffset = offset % chunkSize;
 			const remainingSizeInChunk = chunkSize - chunkOffset;
 
-			// check for chunk overflow
+			// conformance tests
 
 			if ( chunkOffset !== 0 && ( remainingSizeInChunk - uniform.boundary ) < 0 ) {
 
-				// add padding and adjust offset
+				// check for chunk overflow
 
 				offset += ( chunkSize - chunkOffset );
 
+			} else if ( chunkOffset % uniform.boundary !== 0 ) {
+
+				// check for correct alignment
+
+				offset += ( chunkOffset % uniform.boundary );
+
 			}
 
 			uniform.offset = ( offset / this.bytesPerElement );

+ 12 - 0
examples/jsm/renderers/webgpu/nodes/ShaderLib.js

@@ -49,6 +49,12 @@ const ShaderLib = {
 
 				#endif
 
+				#ifdef NODE_ALPHA_TEST
+
+					if ( MaterialDiffuseColor.a < NODE_ALPHA_TEST ) discard;
+
+				#endif
+
 				#ifdef NODE_LIGHT
 
 					NODE_CODE_LIGHT
@@ -107,6 +113,12 @@ const ShaderLib = {
 				NODE_CODE_OPACITY
 				MaterialDiffuseColor.a *= NODE_OPACITY;
 
+				#ifdef NODE_ALPHA_TEST
+
+					if ( MaterialDiffuseColor.a < NODE_ALPHA_TEST ) discard;
+
+				#endif
+
 				NODE_CODE_SPECULAR
 				MaterialSpecularColor = NODE_SPECULAR;
 

+ 10 - 0
examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js

@@ -65,6 +65,16 @@ class WebGPUNodeBuilder extends NodeBuilder {
 
 			this.addSlot( 'vertex', new NodeSlot( mvpNode, 'MVP', 'vec4' ) );
 
+			if ( material.alphaTestNode !== undefined ) {
+
+				this.addSlot( 'fragment', new NodeSlot( material.alphaTestNode, 'ALPHA_TEST', 'float' ) );
+
+			} else {
+
+				this.addSlot( 'fragment', new NodeSlot( new MaterialNode( MaterialNode.ALPHA_TEST ), 'ALPHA_TEST', 'float' ) );
+
+			}
+
 			if ( material.colorNode !== undefined ) {
 
 				this.addSlot( 'fragment', new NodeSlot( material.colorNode, 'COLOR', 'vec4' ) );

BIN
examples/screenshots/webgpu_materials.jpg


+ 12 - 0
examples/webgpu_materials.html

@@ -30,6 +30,7 @@
 			import AttributeNode from './jsm/renderers/nodes/core/AttributeNode.js';
 			import PositionNode from './jsm/renderers/nodes/accessors/PositionNode.js';
 			import NormalNode from './jsm/renderers/nodes/accessors/NormalNode.js';
+			import FloatNode from './jsm/renderers/nodes/inputs/FloatNode.js';
 			import TextureNode from './jsm/renderers/nodes/inputs/TextureNode.js';
 
 			import Stats from './jsm/libs/stats.module.js';
@@ -75,6 +76,10 @@
 				texture.wrapS = THREE.RepeatWrapping;
 				texture.wrapT = THREE.RepeatWrapping;
 
+				const opacityTexture = textureLoader.load( './textures/alphaMap.jpg' );
+				opacityTexture.wrapS = THREE.RepeatWrapping;
+				opacityTexture.wrapT = THREE.RepeatWrapping;
+
 				let material;
 
 				// PositionNode.LOCAL
@@ -108,6 +113,13 @@
 				material.transparent = true;
 				materials.push( material );
 
+				// AlphaTest
+				material = new THREE.MeshBasicMaterial();
+				material.colorNode = new TextureNode( texture );
+				material.opacityNode = new TextureNode( opacityTexture );
+				material.alphaTestNode = new FloatNode( 0.5 );
+				materials.push( material );
+
 				// Geometry
 
 				const geometry = new TeapotGeometry( 50, 18 );