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

BloomNode: Add faster blur strategy. (#33923)

Michael Herzog 1 неделя назад
Родитель
Сommit
35c664fd40
1 измененных файлов с 49 добавлено и 24 удалено
  1. 49 24
      examples/jsm/tsl/display/BloomNode.js

+ 49 - 24
examples/jsm/tsl/display/BloomNode.js

@@ -1,5 +1,5 @@
 import { HalfFloatType, RenderTarget, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, RendererUtils, NodeUpdateType } from 'three/webgpu';
-import { nodeObject, Fn, float, uv, passTexture, uniform, Loop, texture, luminance, smoothstep, mix, vec4, uniformArray, add, int } from 'three/tsl';
+import { nodeObject, Fn, float, uv, passTexture, uniform, Loop, texture, luminance, smoothstep, mix, vec4, uniformArray, add, int, array } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
@@ -106,6 +106,15 @@ class BloomNode extends TempNode {
 		 */
 		this.smoothWidth = uniform( 0.01 );
 
+		/**
+		 * A per-mip tint color for the bloom, applied during the composite pass.
+		 * Defaults to white (no tint) for each of the mips. Mutate the vectors to
+		 * colorize the bloom (e.g. for a warm or anamorphic look).
+		 *
+		 * @type {Array<Vector3>}
+		 */
+		this.bloomTintColors = [ new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ) ];
+
 		/**
 		 * Scale factor for the internal render targets.
 		 *
@@ -420,23 +429,8 @@ class BloomNode extends TempNode {
 
 		// composite material
 
-		const bloomFactors = uniformArray( [ 1.0, 0.8, 0.6, 0.4, 0.2 ] );
-		const bloomTintColors = uniformArray( [ new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ) ] );
-
-		const lerpBloomFactor = Fn( ( [ factor, radius ] ) => {
-
-			const mirrorFactor = float( 1.2 ).sub( factor );
-			return mix( factor, mirrorFactor, radius );
-
-		} ).setLayout( {
-			name: 'lerpBloomFactor',
-			type: 'float',
-			inputs: [
-				{ name: 'factor', type: 'float' },
-				{ name: 'radius', type: 'float' },
-			]
-		} );
-
+		const bloomFactors = array( [ float( 1.0 ), float( 0.8 ), float( 0.6 ), float( 0.4 ), float( 0.2 ) ] );
+		const bloomTintColors = uniformArray( this.bloomTintColors );
 
 		const compositePass = Fn( () => {
 
@@ -513,10 +507,28 @@ class BloomNode extends TempNode {
 
 		}
 
+		// Merge adjacent taps into single bilinear fetches (linear sampling).
+
+		const centerWeight = coefficients[ 0 ];
+		const offsets = [];
+		const weights = [];
+
+		for ( let i = 1; i < kernelRadius; i += 2 ) {
+
+			const wa = coefficients[ i ];
+			const wb = ( i + 1 ) < kernelRadius ? coefficients[ i + 1 ] : 0;
+			const w = wa + wb;
+
+			offsets.push( ( i * wa + ( i + 1 ) * wb ) / w );
+			weights.push( w );
+
+		}
+
 		//
 
 		const colorTexture = texture( null );
-		const gaussianCoefficients = uniformArray( coefficients );
+		const gaussianOffsets = array( offsets.map( ( value ) => float( value ) ) );
+		const gaussianWeights = array( weights.map( ( value ) => float( value ) ) );
 		const invSize = uniform( new Vector2() );
 		const direction = uniform( new Vector2( 0.5, 0.5 ) );
 
@@ -525,13 +537,12 @@ class BloomNode extends TempNode {
 
 		const separableBlurPass = Fn( () => {
 
-			const diffuseSum = sampleTexel( uvNode ).rgb.mul( gaussianCoefficients.element( 0 ) ).toVar();
+			const diffuseSum = sampleTexel( uvNode ).rgb.mul( centerWeight ).toVar();
 
-			Loop( { start: int( 1 ), end: int( kernelRadius ), type: 'int', condition: '<' }, ( { i } ) => {
+			Loop( { start: int( 0 ), end: int( offsets.length ), type: 'int', condition: '<' }, ( { i } ) => {
 
-				const x = float( i );
-				const w = gaussianCoefficients.element( i );
-				const uvOffset = direction.mul( invSize ).mul( x );
+				const w = gaussianWeights.element( i );
+				const uvOffset = direction.mul( invSize ).mul( gaussianOffsets.element( i ) );
 				const sample1 = sampleTexel( uvNode.add( uvOffset ) ).rgb;
 				const sample2 = sampleTexel( uvNode.sub( uvOffset ) ).rgb;
 				diffuseSum.addAssign( add( sample1, sample2 ).mul( w ) );
@@ -558,6 +569,20 @@ class BloomNode extends TempNode {
 
 }
 
+const lerpBloomFactor = Fn( ( [ factor, radius ] ) => {
+
+	const mirrorFactor = float( 1.2 ).sub( factor );
+	return mix( factor, mirrorFactor, radius );
+
+} ).setLayout( {
+	name: 'lerpBloomFactor',
+	type: 'float',
+	inputs: [
+		{ name: 'factor', type: 'float' },
+		{ name: 'radius', type: 'float' },
+	]
+} );
+
 /**
  * TSL function for creating a bloom effect.
  *

粤ICP备19079148号