Просмотр исходного кода

NodeMaterial: Introduce `.maskNode` and improve `shapeCircle()` (#31127)

* always check `alphaTest` but optimize uniform to constant if necessary

* Introduce `.maskNode`

* improve `shapeCircle`

* `webgpu_compute_particles`: use `shapeCirle()`
sunag 9 месяцев назад
Родитель
Сommit
e07583bc15

+ 5 - 4
examples/webgpu_compute_particles.html

@@ -38,7 +38,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { Fn, If, uniform, float, uv, vec2, vec3, hash,
+			import { Fn, If, uniform, float, uv, vec2, vec3, hash, shapeCircle,
 				instancedArray, instanceIndex } from 'three/tsl';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
@@ -133,13 +133,14 @@
 				computeParticles = computeUpdate().compute( particleCount );
 
 				// create particles
-				
+
 				const material = new THREE.SpriteNodeMaterial();
 				material.colorNode = uv().mul( colors.element( instanceIndex ) );
 				material.positionNode = positions.toAttribute();
 				material.scaleNode = size;
-				material.alphaTestNode = uv().mul( 2 ).distance( vec2( 1 ) );
-				material.transparent = false;
+				material.opacityNode = shapeCircle();
+				material.alphaToCoverage = true;
+				material.transparent = true;
 
 				const particles = new THREE.Sprite( material );
 				particles.count = particleCount;

+ 28 - 5
src/materials/nodes/NodeMaterial.js

@@ -13,7 +13,7 @@ import { positionLocal, positionView } from '../../nodes/accessors/Position.js';
 import { skinning } from '../../nodes/accessors/SkinningNode.js';
 import { morphReference } from '../../nodes/accessors/MorphNode.js';
 import { mix } from '../../nodes/math/MathNode.js';
-import { float, vec3, vec4 } from '../../nodes/tsl/TSLBase.js';
+import { float, vec3, vec4, bool } from '../../nodes/tsl/TSLBase.js';
 import AONode from '../../nodes/lighting/AONode.js';
 import { lightingContext } from '../../nodes/lighting/LightingContextNode.js';
 import IrradianceNode from '../../nodes/lighting/IrradianceNode.js';
@@ -229,6 +229,15 @@ class NodeMaterial extends Material {
 		 */
 		this.alphaTestNode = null;
 
+
+		/**
+		 * Discards the fragment if the mask value is `false`.
+		 *
+		 * @type {?Node<bool>}
+		 * @default null
+		 */
+		this.maskNode = null;
+
 		/**
 		 * The local vertex positions are computed based on multiple factors like the
 		 * attribute data, morphing or skinning. This node property allows to overwrite
@@ -774,6 +783,14 @@ class NodeMaterial extends Material {
 
 		let colorNode = this.colorNode ? vec4( this.colorNode ) : materialColor;
 
+		// MASK
+
+		if ( this.maskNode !== null ) {
+
+			bool( this.maskNode ).discard();
+
+		}
+
 		// VERTEX COLORS
 
 		if ( this.vertexColors === true && geometry.hasAttribute( 'color' ) ) {
@@ -782,7 +799,7 @@ class NodeMaterial extends Material {
 
 		}
 
-		// Instanced colors
+		// INSTANCED COLORS
 
 		if ( object.instanceColor ) {
 
@@ -800,7 +817,6 @@ class NodeMaterial extends Material {
 
 		}
 
-
 		// COLOR
 
 		diffuseColor.assign( colorNode );
@@ -812,14 +828,20 @@ class NodeMaterial extends Material {
 
 		// ALPHA TEST
 
+		let alphaTestNode;
+
 		if ( this.alphaTestNode !== null || this.alphaTest > 0 ) {
 
-			const alphaTestNode = this.alphaTestNode !== null ? float( this.alphaTestNode ) : materialAlphaTest;
+			alphaTestNode = this.alphaTestNode !== null ? float( this.alphaTestNode ) : materialAlphaTest;
+
+		} else {
 
-			diffuseColor.a.lessThanEqual( alphaTestNode ).discard();
+			alphaTestNode = float( 0 );
 
 		}
 
+		diffuseColor.a.lessThanEqual( alphaTestNode ).discard();
+
 		// ALPHA HASH
 
 		if ( this.alphaHash === true ) {
@@ -1189,6 +1211,7 @@ class NodeMaterial extends Material {
 		this.backdropNode = source.backdropNode;
 		this.backdropAlphaNode = source.backdropAlphaNode;
 		this.alphaTestNode = source.alphaTestNode;
+		this.maskNode = source.maskNode;
 
 		this.positionNode = source.positionNode;
 		this.geometryNode = source.geometryNode;

+ 5 - 4
src/nodes/shapes/Shapes.js

@@ -1,4 +1,4 @@
-import { Fn, float } from '../tsl/TSLBase.js';
+import { Fn, float, select } from '../tsl/TSLBase.js';
 import { lengthSq, smoothstep } from '../math/MathNode.js';
 import { uv } from '../accessors/UV.js';
 
@@ -12,18 +12,19 @@ import { uv } from '../accessors/UV.js';
  */
 export const shapeCircle = Fn( ( [ coord = uv() ], { renderer, material } ) => {
 
-	const alpha = float( 1 ).toVar();
 	const len2 = lengthSq( coord.mul( 2 ).sub( 1 ) );
 
+	let alpha;
+
 	if ( material.alphaToCoverage && renderer.samples > 1 ) {
 
 		const dlen = float( len2.fwidth() ).toVar();
 
-		alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() );
+		alpha = smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus();
 
 	} else {
 
-		len2.greaterThan( 1.0 ).discard();
+		alpha = select( len2.greaterThan( 1.0 ), 0, 1 );
 
 	}
 

粤ICP备19079148号