|
|
@@ -1,8 +1,7 @@
|
|
|
import { RenderTarget, Vector2, NodeMaterial, PostProcessingUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu';
|
|
|
import { nodeObject, Fn, If, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, mul } from 'three/tsl';
|
|
|
|
|
|
-// WebGPU: The use of a single QuadMesh for both gaussian blur passes results in a single RenderObject with a SampledTexture binding that
|
|
|
-// alternates between source textures and triggers creation of new BindGroups and BindGroupLayouts every frame.
|
|
|
+/** @module GaussianBlurNode **/
|
|
|
|
|
|
const _quadMesh = /*@__PURE__*/ new QuadMesh();
|
|
|
|
|
|
@@ -34,6 +33,11 @@ const unpremult = /*@__PURE__*/ Fn( ( [ color ] ) => {
|
|
|
]
|
|
|
} );
|
|
|
|
|
|
+/**
|
|
|
+ * Post processing node for creating a gaussian blur effect.
|
|
|
+ *
|
|
|
+ * @augments TempNode
|
|
|
+ */
|
|
|
class GaussianBlurNode extends TempNode {
|
|
|
|
|
|
static get type() {
|
|
|
@@ -42,33 +46,116 @@ class GaussianBlurNode extends TempNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Constructs a new gaussian blur node.
|
|
|
+ *
|
|
|
+ * @param {TextureNode} textureNode - The texture node that represents the input of the effect.
|
|
|
+ * @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 ) {
|
|
|
|
|
|
super( 'vec4' );
|
|
|
|
|
|
+ /**
|
|
|
+ * The texture node that represents the input of the effect.
|
|
|
+ *
|
|
|
+ * @type {TextureNode}
|
|
|
+ */
|
|
|
this.textureNode = textureNode;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Defines the direction and radius of the blur.
|
|
|
+ *
|
|
|
+ * @type {Node<vec2|float>}
|
|
|
+ */
|
|
|
this.directionNode = directionNode;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Controls the kernel of the blur filter. Higher values mean a wider blur radius.
|
|
|
+ *
|
|
|
+ * @type {Number}
|
|
|
+ */
|
|
|
this.sigma = sigma;
|
|
|
|
|
|
+ /**
|
|
|
+ * A uniform node holding the inverse resolution value.
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @type {UniformNode<vec2>}
|
|
|
+ */
|
|
|
this._invSize = uniform( new Vector2() );
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Gaussian blur is applied in two passes (horizontal, vertical).
|
|
|
+ * This node controls the direction of each pass.
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @type {UniformNode<vec2>}
|
|
|
+ */
|
|
|
this._passDirection = uniform( new Vector2() );
|
|
|
|
|
|
+ /**
|
|
|
+ * The render target used for the horizontal pass.
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @type {RenderTarget}
|
|
|
+ */
|
|
|
this._horizontalRT = new RenderTarget( 1, 1, { depthBuffer: false } );
|
|
|
this._horizontalRT.texture.name = 'GaussianBlurNode.horizontal';
|
|
|
+
|
|
|
+ /**
|
|
|
+ * The render target used for the vertical pass.
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @type {RenderTarget}
|
|
|
+ */
|
|
|
this._verticalRT = new RenderTarget( 1, 1, { depthBuffer: false } );
|
|
|
this._verticalRT.texture.name = 'GaussianBlurNode.vertical';
|
|
|
|
|
|
+ /**
|
|
|
+ * The result of the effect is represented as a separate texture node.
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @type {PassTextureNode}
|
|
|
+ */
|
|
|
this._textureNode = passTexture( this, this._verticalRT.texture );
|
|
|
this._textureNode.uvNode = textureNode.uvNode;
|
|
|
|
|
|
+ /**
|
|
|
+ * The `updateBeforeType` is set to `NodeUpdateType.FRAME` since the node renders
|
|
|
+ * its effect once per frame in `updateBefore()`.
|
|
|
+ *
|
|
|
+ * @type {String}
|
|
|
+ * @default 'frame'
|
|
|
+ */
|
|
|
this.updateBeforeType = NodeUpdateType.FRAME;
|
|
|
|
|
|
+ /**
|
|
|
+ * Controls the resolution of the effect.
|
|
|
+ *
|
|
|
+ * @type {Vector2}
|
|
|
+ * @default (1,1)
|
|
|
+ */
|
|
|
this.resolution = new Vector2( 1, 1 );
|
|
|
|
|
|
+ /**
|
|
|
+ * Whether the effect should use premultiplied alpha or not. Set this to `true`
|
|
|
+ * if you are going to blur texture input with transparency.
|
|
|
+ *
|
|
|
+ * @type {Boolean}
|
|
|
+ * @default false
|
|
|
+ */
|
|
|
this.premultipliedAlpha = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Sets the given premultiplied alpha value.
|
|
|
+ *
|
|
|
+ * @param {Boolean} value - Whether the effect should use premultiplied alpha or not.
|
|
|
+ * @return {GaussianBlurNode} height - A reference to this node.
|
|
|
+ */
|
|
|
setPremultipliedAlpha( value ) {
|
|
|
|
|
|
this.premultipliedAlpha = value;
|
|
|
@@ -77,12 +164,23 @@ class GaussianBlurNode extends TempNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns the premultiplied alpha value.
|
|
|
+ *
|
|
|
+ * @return {Boolean} Whether the effect should use premultiplied alpha or not.
|
|
|
+ */
|
|
|
getPremultipliedAlpha() {
|
|
|
|
|
|
return this.premultipliedAlpha;
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Sets the size of the effect.
|
|
|
+ *
|
|
|
+ * @param {Number} width - The width of the effect.
|
|
|
+ * @param {Number} height - The height of the effect.
|
|
|
+ */
|
|
|
setSize( width, height ) {
|
|
|
|
|
|
width = Math.max( Math.round( width * this.resolution.x ), 1 );
|
|
|
@@ -94,6 +192,11 @@ class GaussianBlurNode extends TempNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * This method is used to render the effect once per frame.
|
|
|
+ *
|
|
|
+ * @param {NodeFrame} frame - The current node frame.
|
|
|
+ */
|
|
|
updateBefore( frame ) {
|
|
|
|
|
|
const { renderer } = frame;
|
|
|
@@ -141,12 +244,23 @@ class GaussianBlurNode extends TempNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns the result of the effect as a texture node.
|
|
|
+ *
|
|
|
+ * @return {PassTextureNode} A texture node that represents the result of the effect.
|
|
|
+ */
|
|
|
getTextureNode() {
|
|
|
|
|
|
return this._textureNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * This method is used to setup the effect's TSL code.
|
|
|
+ *
|
|
|
+ * @param {NodeBuilder} builder - The current node builder.
|
|
|
+ * @return {PassTextureNode}
|
|
|
+ */
|
|
|
setup( builder ) {
|
|
|
|
|
|
const textureNode = this.textureNode;
|
|
|
@@ -220,6 +334,10 @@ class GaussianBlurNode extends TempNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Frees internal resources. This method should be called
|
|
|
+ * when the effect is no longer required.
|
|
|
+ */
|
|
|
dispose() {
|
|
|
|
|
|
this._horizontalRT.dispose();
|
|
|
@@ -227,6 +345,13 @@ class GaussianBlurNode extends TempNode {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Computes gaussian coefficients depending on the given kernel radius.
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @param {Number} kernelRadius - The kernel radius.
|
|
|
+ * @return {Array<Number>}
|
|
|
+ */
|
|
|
_getCoefficients( kernelRadius ) {
|
|
|
|
|
|
const coefficients = [];
|
|
|
@@ -245,5 +370,24 @@ class GaussianBlurNode extends TempNode {
|
|
|
|
|
|
export default GaussianBlurNode;
|
|
|
|
|
|
+/**
|
|
|
+ * TSL function for creating gaussian blur node for post processing.
|
|
|
+ *
|
|
|
+ * @function
|
|
|
+ * @param {Node<vec4>} node - The node that represents the input of the effect.
|
|
|
+ * @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.
|
|
|
+ * @returns {GaussianBlurNode}
|
|
|
+ */
|
|
|
export const gaussianBlur = ( node, directionNode, sigma ) => nodeObject( new GaussianBlurNode( convertToTexture( node ), directionNode, sigma ) );
|
|
|
+
|
|
|
+/**
|
|
|
+ * TSL function for creating gaussian blur node for post processing with enabled premultiplied alpha.
|
|
|
+ *
|
|
|
+ * @function
|
|
|
+ * @param {Node<vec4>} node - The node that represents the input of the effect.
|
|
|
+ * @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.
|
|
|
+ * @returns {GaussianBlurNode}
|
|
|
+ */
|
|
|
export const premultipliedGaussianBlur = ( node, directionNode, sigma ) => nodeObject( new GaussianBlurNode( convertToTexture( node ), directionNode, sigma ).setPremultipliedAlpha( true ) );
|