Skip to content

Commit 2675048

Browse files
NoxDawnsongNox Dawnsong
andauthored
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 <[email protected]>
1 parent ba0568f commit 2675048

File tree

6 files changed

+17
-18
lines changed

6 files changed

+17
-18
lines changed

examples/jsm/tsl/display/BloomNode.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,9 @@ class BloomNode extends TempNode {
364364

365365
// gaussian blur materials
366366

367-
const kernelSizeArray = [ 3, 5, 7, 9, 11 ];
367+
// These sizes have been changed to account for the altered coefficents-calculation to avoid blockiness,
368+
// while retaining the same blur-strength. For details see https://github.com/mrdoob/three.js/pull/31528
369+
const kernelSizeArray = [ 6, 10, 14, 18, 22 ];
368370

369371
for ( let i = 0; i < this._nMips; i ++ ) {
370372

@@ -449,10 +451,11 @@ class BloomNode extends TempNode {
449451
_getSeparableBlurMaterial( builder, kernelRadius ) {
450452

451453
const coefficients = [];
454+
const sigma = kernelRadius / 3;
452455

453456
for ( let i = 0; i < kernelRadius; i ++ ) {
454457

455-
coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius );
458+
coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( sigma * sigma ) ) / sigma );
456459

457460
}
458461

@@ -468,8 +471,7 @@ class BloomNode extends TempNode {
468471

469472
const separableBlurPass = Fn( () => {
470473

471-
const weightSum = gaussianCoefficients.element( 0 ).toVar();
472-
const diffuseSum = sampleTexel( uvNode ).rgb.mul( weightSum ).toVar();
474+
const diffuseSum = sampleTexel( uvNode ).rgb.mul( gaussianCoefficients.element( 0 ) ).toVar();
473475

474476
Loop( { start: int( 1 ), end: int( kernelRadius ), type: 'int', condition: '<' }, ( { i } ) => {
475477

@@ -478,12 +480,11 @@ class BloomNode extends TempNode {
478480
const uvOffset = direction.mul( invSize ).mul( x );
479481
const sample1 = sampleTexel( uvNode.add( uvOffset ) ).rgb;
480482
const sample2 = sampleTexel( uvNode.sub( uvOffset ) ).rgb;
481-
diffuseSum.addAssign( add( sample1, sample2 ).mul( w ) );
482-
weightSum.addAssign( float( 2.0 ).mul( w ) );
483+
diffuseSum.addAssign( add( sample1, sample2 ).mul( w ) );
483484

484485
} );
485486

486-
return vec4( diffuseSum.div( weightSum ), 1.0 );
487+
return vec4( diffuseSum, 1.0 );
487488

488489
} );
489490

examples/jsm/tsl/display/GaussianBlurNode.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
2-
import { nodeObject, Fn, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, mul, premultiplyAlpha, unpremultiplyAlpha } from 'three/tsl';
2+
import { nodeObject, Fn, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, premultiplyAlpha, unpremultiplyAlpha } from 'three/tsl';
33

44
const _quadMesh = /*@__PURE__*/ new QuadMesh();
55

@@ -26,7 +26,7 @@ class GaussianBlurNode extends TempNode {
2626
* @param {Node<vec2|float>} directionNode - Defines the direction and radius of the blur.
2727
* @param {number} sigma - Controls the kernel of the blur filter. Higher values mean a wider blur radius.
2828
*/
29-
constructor( textureNode, directionNode = null, sigma = 2 ) {
29+
constructor( textureNode, directionNode = null, sigma = 4 ) {
3030

3131
super( 'vec4' );
3232

@@ -267,8 +267,7 @@ class GaussianBlurNode extends TempNode {
267267
const invSize = this._invSize;
268268
const direction = directionNode.mul( this._passDirection );
269269

270-
const weightSum = float( gaussianCoefficients[ 0 ] ).toVar();
271-
const diffuseSum = vec4( sampleTexture( uvNode ).mul( weightSum ) ).toVar();
270+
const diffuseSum = vec4( sampleTexture( uvNode ).mul( gaussianCoefficients[ 0 ] ) ).toVar();
272271

273272
for ( let i = 1; i < kernelSize; i ++ ) {
274273

@@ -281,11 +280,9 @@ class GaussianBlurNode extends TempNode {
281280
const sample2 = sampleTexture( uvNode.sub( uvOffset ) );
282281

283282
diffuseSum.addAssign( sample1.add( sample2 ).mul( w ) );
284-
weightSum.addAssign( mul( 2.0, w ) );
285-
286283
}
287284

288-
return output( diffuseSum.div( weightSum ) );
285+
return output( diffuseSum );
289286

290287
} );
291288

@@ -328,10 +325,11 @@ class GaussianBlurNode extends TempNode {
328325
_getCoefficients( kernelRadius ) {
329326

330327
const coefficients = [];
328+
const sigma = kernelRadius / 3;
331329

332330
for ( let i = 0; i < kernelRadius; i ++ ) {
333331

334-
coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius );
332+
coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( sigma * sigma ) ) / sigma );
335333

336334
}
337335

2.11 KB
Loading

examples/webgpu_compute_particles_snow.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@
299299
const vignette = screenUV.distance( .5 ).mul( 1.35 ).clamp().oneMinus();
300300

301301
const teapotTreePass = pass( teapotTree, camera ).getTextureNode();
302-
const teapotTreePassBlurred = gaussianBlur( teapotTreePass, vec2( 1 ), 3 );
302+
const teapotTreePassBlurred = gaussianBlur( teapotTreePass, vec2( 1 ), 6 );
303303
teapotTreePassBlurred.resolution = new THREE.Vector2( .2, .2 );
304304

305305
const scenePassColorBlurred = gaussianBlur( scenePassColor );

examples/webgpu_mrt_mask.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@
132132

133133
postProcessing = new THREE.PostProcessing( renderer );
134134
postProcessing.outputColorTransform = false;
135-
postProcessing.outputNode = colorPass.add( gaussianBlur( maskPass, 1, 10 ).mul( .3 ) ).renderOutput();
135+
postProcessing.outputNode = colorPass.add( gaussianBlur( maskPass, 1, 20 ).mul( .3 ) ).renderOutput();
136136

137137
// controls
138138

examples/webgpu_procedural_texture.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
const procedural = checker( uv().mul( uvScale ) );
5252
const proceduralToTexture = convertToTexture( procedural, 512, 512 ); // ( node, width, height )
5353

54-
const colorNode = gaussianBlur( proceduralToTexture, blurAmount, 10 );
54+
const colorNode = gaussianBlur( proceduralToTexture, blurAmount, 20 );
5555

5656
// extra
5757

0 commit comments

Comments
 (0)