first commit
This commit is contained in:
201
web-app/node_modules/three/examples/jsm/tsl/display/PixelationPassNode.js
generated
vendored
Normal file
201
web-app/node_modules/three/examples/jsm/tsl/display/PixelationPassNode.js
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
import { NearestFilter, Vector4 } from 'three';
|
||||
import { TempNode, nodeObject, Fn, float, NodeUpdateType, uv, uniform, convertToTexture, vec2, vec3, clamp, floor, dot, smoothstep, If, sign, step, mrt, output, normalView, PassNode, property } from 'three/tsl';
|
||||
|
||||
class PixelationNode extends TempNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'PixelationNode';
|
||||
|
||||
}
|
||||
|
||||
constructor( textureNode, depthNode, normalNode, pixelSize, normalEdgeStrength, depthEdgeStrength ) {
|
||||
|
||||
super();
|
||||
|
||||
// Input textures
|
||||
|
||||
this.textureNode = textureNode;
|
||||
this.depthNode = depthNode;
|
||||
this.normalNode = normalNode;
|
||||
|
||||
// Input uniforms
|
||||
|
||||
this.pixelSize = pixelSize;
|
||||
this.normalEdgeStrength = normalEdgeStrength;
|
||||
this.depthEdgeStrength = depthEdgeStrength;
|
||||
|
||||
// Private uniforms
|
||||
|
||||
this._resolution = uniform( new Vector4() );
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.FRAME;
|
||||
|
||||
}
|
||||
|
||||
updateBefore() {
|
||||
|
||||
const map = this.textureNode.value;
|
||||
|
||||
const width = map.image.width;
|
||||
const height = map.image.height;
|
||||
|
||||
this._resolution.value.set( width, height, 1 / width, 1 / height );
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const { textureNode, depthNode, normalNode } = this;
|
||||
|
||||
const uvNodeTexture = textureNode.uvNode || uv();
|
||||
const uvNodeDepth = depthNode.uvNode || uv();
|
||||
const uvNodeNormal = normalNode.uvNode || uv();
|
||||
|
||||
const sampleTexture = () => textureNode.uv( uvNodeTexture );
|
||||
|
||||
const sampleDepth = ( x, y ) => depthNode.uv( uvNodeDepth.add( vec2( x, y ).mul( this._resolution.zw ) ) ).r;
|
||||
|
||||
const sampleNormal = ( x, y ) => normalNode.uv( uvNodeNormal.add( vec2( x, y ).mul( this._resolution.zw ) ) ).rgb.normalize();
|
||||
|
||||
const depthEdgeIndicator = ( depth ) => {
|
||||
|
||||
const diff = property( 'float', 'diff' );
|
||||
diff.addAssign( clamp( sampleDepth( 1, 0 ).sub( depth ) ) );
|
||||
diff.addAssign( clamp( sampleDepth( - 1, 0 ).sub( depth ) ) );
|
||||
diff.addAssign( clamp( sampleDepth( 0, 1 ).sub( depth ) ) );
|
||||
diff.addAssign( clamp( sampleDepth( 0, - 1 ).sub( depth ) ) );
|
||||
|
||||
return floor( smoothstep( 0.01, 0.02, diff ).mul( 2 ) ).div( 2 );
|
||||
|
||||
};
|
||||
|
||||
const neighborNormalEdgeIndicator = ( x, y, depth, normal ) => {
|
||||
|
||||
const depthDiff = sampleDepth( x, y ).sub( depth );
|
||||
const neighborNormal = sampleNormal( x, y );
|
||||
|
||||
// Edge pixels should yield to faces who's normals are closer to the bias normal.
|
||||
|
||||
const normalEdgeBias = vec3( 1, 1, 1 ); // This should probably be a parameter.
|
||||
const normalDiff = dot( normal.sub( neighborNormal ), normalEdgeBias );
|
||||
const normalIndicator = clamp( smoothstep( - 0.01, 0.01, normalDiff ), 0.0, 1.0 );
|
||||
|
||||
// Only the shallower pixel should detect the normal edge.
|
||||
|
||||
const depthIndicator = clamp( sign( depthDiff.mul( .25 ).add( .0025 ) ), 0.0, 1.0 );
|
||||
|
||||
return float( 1.0 ).sub( dot( normal, neighborNormal ) ).mul( depthIndicator ).mul( normalIndicator );
|
||||
|
||||
};
|
||||
|
||||
const normalEdgeIndicator = ( depth, normal ) => {
|
||||
|
||||
const indicator = property( 'float', 'indicator' );
|
||||
|
||||
indicator.addAssign( neighborNormalEdgeIndicator( 0, - 1, depth, normal ) );
|
||||
indicator.addAssign( neighborNormalEdgeIndicator( 0, 1, depth, normal ) );
|
||||
indicator.addAssign( neighborNormalEdgeIndicator( - 1, 0, depth, normal ) );
|
||||
indicator.addAssign( neighborNormalEdgeIndicator( 1, 0, depth, normal ) );
|
||||
|
||||
return step( 0.1, indicator );
|
||||
|
||||
};
|
||||
|
||||
const pixelation = Fn( () => {
|
||||
|
||||
const texel = sampleTexture();
|
||||
|
||||
const depth = property( 'float', 'depth' );
|
||||
const normal = property( 'vec3', 'normal' );
|
||||
|
||||
If( this.depthEdgeStrength.greaterThan( 0.0 ).or( this.normalEdgeStrength.greaterThan( 0.0 ) ), () => {
|
||||
|
||||
depth.assign( sampleDepth( 0, 0 ) );
|
||||
normal.assign( sampleNormal( 0, 0 ) );
|
||||
|
||||
} );
|
||||
|
||||
const dei = property( 'float', 'dei' );
|
||||
|
||||
If( this.depthEdgeStrength.greaterThan( 0.0 ), () => {
|
||||
|
||||
dei.assign( depthEdgeIndicator( depth ) );
|
||||
|
||||
} );
|
||||
|
||||
const nei = property( 'float', 'nei' );
|
||||
|
||||
If( this.normalEdgeStrength.greaterThan( 0.0 ), () => {
|
||||
|
||||
nei.assign( normalEdgeIndicator( depth, normal ) );
|
||||
|
||||
} );
|
||||
|
||||
const strength = dei.greaterThan( 0 ).select( float( 1.0 ).sub( dei.mul( this.depthEdgeStrength ) ), nei.mul( this.normalEdgeStrength ).add( 1 ) );
|
||||
|
||||
return texel.mul( strength );
|
||||
|
||||
} );
|
||||
|
||||
const outputNode = pixelation();
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const pixelation = ( node, depthNode, normalNode, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) => nodeObject( new PixelationNode( convertToTexture( node ), convertToTexture( depthNode ), convertToTexture( normalNode ), nodeObject( pixelSize ), nodeObject( normalEdgeStrength ), nodeObject( depthEdgeStrength ) ) );
|
||||
|
||||
class PixelationPassNode extends PassNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'PixelationPassNode';
|
||||
|
||||
}
|
||||
|
||||
constructor( scene, camera, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) {
|
||||
|
||||
super( 'color', scene, camera, { minFilter: NearestFilter, magFilter: NearestFilter } );
|
||||
|
||||
this.pixelSize = pixelSize;
|
||||
this.normalEdgeStrength = normalEdgeStrength;
|
||||
this.depthEdgeStrength = depthEdgeStrength;
|
||||
|
||||
this.isPixelationPassNode = true;
|
||||
|
||||
this._mrt = mrt( {
|
||||
output: output,
|
||||
normal: normalView
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
setSize( width, height ) {
|
||||
|
||||
const pixelSize = this.pixelSize.value ? this.pixelSize.value : this.pixelSize;
|
||||
|
||||
const adjustedWidth = Math.floor( width / pixelSize );
|
||||
const adjustedHeight = Math.floor( height / pixelSize );
|
||||
|
||||
super.setSize( adjustedWidth, adjustedHeight );
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const color = super.getTextureNode( 'output' );
|
||||
const depth = super.getTextureNode( 'depth' );
|
||||
const normal = super.getTextureNode( 'normal' );
|
||||
|
||||
return pixelation( color, depth, normal, this.pixelSize, this.normalEdgeStrength, this.depthEdgeStrength );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const pixelationPass = ( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) => nodeObject( new PixelationPassNode( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) );
|
||||
|
||||
export default PixelationPassNode;
|
||||
Reference in New Issue
Block a user