Przeglądaj źródła

TSL: Fix blocky gaussian blur (#31528)

* Fix for blocky gaussian blur

Calculate a proper sigma from kernel-size to avoid blocky gaussian blur.

* Remove weightSum

* Remove 'mul' import

* Provide screenshots for checks

* Double kernel-radii for BloomNode

* Add comment to explain change of kernel-sizes

* Change default sigma value of GaussianBlurNode

* Update examples

* Roll back screenshots for tests

* Update screenshot for procedural texture example

* Update screenshot for procedural texture example again

* Update BloomNode.js

* Update GaussianBlurNode.js

---------

Co-authored-by: Nox Dawnsong <nobody@nowhere.void>
NoxDawnsong 8 miesięcy temu
rodzic
commit
26750486d6

+ 8 - 7
examples/jsm/tsl/display/BloomNode.js

@@ -364,7 +364,9 @@ class BloomNode extends TempNode {
 
 		// gaussian blur materials
 
-		const kernelSizeArray = [ 3, 5, 7, 9, 11 ];
+		// These sizes have been changed to account for the altered coefficents-calculation to avoid blockiness,
+		// while retaining the same blur-strength. For details see https://github.com/mrdoob/three.js/pull/31528
+		const kernelSizeArray = [ 6, 10, 14, 18, 22 ]; 
 
 		for ( let i = 0; i < this._nMips; i ++ ) {
 
@@ -449,10 +451,11 @@ class BloomNode extends TempNode {
 	_getSeparableBlurMaterial( builder, kernelRadius ) {
 
 		const coefficients = [];
+		const sigma = kernelRadius / 3;
 
 		for ( let i = 0; i < kernelRadius; i ++ ) {
 
-			coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius );
+			coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( sigma * sigma ) ) / sigma );
 
 		}
 
@@ -468,8 +471,7 @@ class BloomNode extends TempNode {
 
 		const separableBlurPass = Fn( () => {
 
-			const weightSum = gaussianCoefficients.element( 0 ).toVar();
-			const diffuseSum = sampleTexel( uvNode ).rgb.mul( weightSum ).toVar();
+			const diffuseSum = sampleTexel( uvNode ).rgb.mul( gaussianCoefficients.element( 0 ) ).toVar();
 
 			Loop( { start: int( 1 ), end: int( kernelRadius ), type: 'int', condition: '<' }, ( { i } ) => {
 
@@ -478,12 +480,11 @@ class BloomNode extends TempNode {
 				const uvOffset = direction.mul( invSize ).mul( x );
 				const sample1 = sampleTexel( uvNode.add( uvOffset ) ).rgb;
 				const sample2 = sampleTexel( uvNode.sub( uvOffset ) ).rgb;
-				diffuseSum.addAssign( add( sample1, sample2 ).mul( w ) );
-				weightSum.addAssign( float( 2.0 ).mul( w ) );
+				diffuseSum.addAssign( add( sample1, sample2 ).mul( w ) );		
 
 			} );
 
-			return vec4( diffuseSum.div( weightSum ), 1.0 );
+			return vec4( diffuseSum, 1.0 );
 
 		} );
 

+ 6 - 8
examples/jsm/tsl/display/GaussianBlurNode.js

@@ -1,5 +1,5 @@
 import { RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
-import { nodeObject, Fn, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, mul, premultiplyAlpha, unpremultiplyAlpha } from 'three/tsl';
+import { nodeObject, Fn, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, premultiplyAlpha, unpremultiplyAlpha } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 
@@ -26,7 +26,7 @@ class GaussianBlurNode extends TempNode {
 	 * @param {Node<vec2|float>} directionNode - Defines the direction and radius of the blur.
 	 * @param {number} sigma - Controls the kernel of the blur filter. Higher values mean a wider blur radius.
 	 */
-	constructor( textureNode, directionNode = null, sigma = 2 ) {
+	constructor( textureNode, directionNode = null, sigma = 4 ) {
 
 		super( 'vec4' );
 
@@ -267,8 +267,7 @@ class GaussianBlurNode extends TempNode {
 			const invSize = this._invSize;
 			const direction = directionNode.mul( this._passDirection );
 
-			const weightSum = float( gaussianCoefficients[ 0 ] ).toVar();
-			const diffuseSum = vec4( sampleTexture( uvNode ).mul( weightSum ) ).toVar();
+			const diffuseSum = vec4( sampleTexture( uvNode ).mul( gaussianCoefficients[ 0 ] ) ).toVar();
 
 			for ( let i = 1; i < kernelSize; i ++ ) {
 
@@ -281,11 +280,9 @@ class GaussianBlurNode extends TempNode {
 				const sample2 = sampleTexture( uvNode.sub( uvOffset ) );
 
 				diffuseSum.addAssign( sample1.add( sample2 ).mul( w ) );
-				weightSum.addAssign( mul( 2.0, w ) );
-
 			}
 
-			return output( diffuseSum.div( weightSum ) );
+			return output( diffuseSum );
 
 		} );
 
@@ -328,10 +325,11 @@ class GaussianBlurNode extends TempNode {
 	_getCoefficients( kernelRadius ) {
 
 		const coefficients = [];
+		const sigma = kernelRadius / 3;
 
 		for ( let i = 0; i < kernelRadius; i ++ ) {
 
-			coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius );
+			coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( sigma * sigma ) ) / sigma );
 
 		}
 

BIN
examples/screenshots/webgpu_procedural_texture.jpg


+ 1 - 1
examples/webgpu_compute_particles_snow.html

@@ -299,7 +299,7 @@
 				const vignette = screenUV.distance( .5 ).mul( 1.35 ).clamp().oneMinus();
 
 				const teapotTreePass = pass( teapotTree, camera ).getTextureNode();
-				const teapotTreePassBlurred = gaussianBlur( teapotTreePass, vec2( 1 ), 3 );
+				const teapotTreePassBlurred = gaussianBlur( teapotTreePass, vec2( 1 ), 6 );
 				teapotTreePassBlurred.resolution = new THREE.Vector2( .2, .2 );
 
 				const scenePassColorBlurred = gaussianBlur( scenePassColor );

+ 1 - 1
examples/webgpu_mrt_mask.html

@@ -132,7 +132,7 @@
 
 				postProcessing = new THREE.PostProcessing( renderer );
 				postProcessing.outputColorTransform = false;
-				postProcessing.outputNode = colorPass.add( gaussianBlur( maskPass, 1, 10 ).mul( .3 ) ).renderOutput();
+				postProcessing.outputNode = colorPass.add( gaussianBlur( maskPass, 1, 20 ).mul( .3 ) ).renderOutput();
 
 				// controls
 

+ 1 - 1
examples/webgpu_procedural_texture.html

@@ -51,7 +51,7 @@
 				const procedural = checker( uv().mul( uvScale ) );
 				const proceduralToTexture = convertToTexture( procedural, 512, 512 ); // ( node, width, height )
 
-				const colorNode = gaussianBlur( proceduralToTexture, blurAmount, 10 );
+				const colorNode = gaussianBlur( proceduralToTexture, blurAmount, 20 );
 
 				// extra
 

粤ICP备19079148号