Initial commit
This commit is contained in:
99
node_modules/three/examples/jsm/nodes/display/BlendModeNode.js
generated
vendored
Normal file
99
node_modules/three/examples/jsm/nodes/display/BlendModeNode.js
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { EPSILON } from '../math/MathNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { addNodeElement, tslFn, nodeProxy, vec3 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
export const BurnNode = tslFn( ( { base, blend } ) => {
|
||||
|
||||
const fn = ( c ) => blend[ c ].lessThan( EPSILON ).cond( blend[ c ], base[ c ].oneMinus().div( blend[ c ] ).oneMinus().max( 0 ) );
|
||||
|
||||
return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
|
||||
|
||||
} );
|
||||
|
||||
export const DodgeNode = tslFn( ( { base, blend } ) => {
|
||||
|
||||
const fn = ( c ) => blend[ c ].equal( 1.0 ).cond( blend[ c ], base[ c ].div( blend[ c ].oneMinus() ).max( 0 ) );
|
||||
|
||||
return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
|
||||
|
||||
} );
|
||||
|
||||
export const ScreenNode = tslFn( ( { base, blend } ) => {
|
||||
|
||||
const fn = ( c ) => base[ c ].oneMinus().mul( blend[ c ].oneMinus() ).oneMinus();
|
||||
|
||||
return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
|
||||
|
||||
} );
|
||||
|
||||
export const OverlayNode = tslFn( ( { base, blend } ) => {
|
||||
|
||||
const fn = ( c ) => base[ c ].lessThan( 0.5 ).cond( base[ c ].mul( blend[ c ], 2.0 ), base[ c ].oneMinus().mul( blend[ c ].oneMinus() ).oneMinus() );
|
||||
|
||||
return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
|
||||
|
||||
} );
|
||||
|
||||
class BlendModeNode extends TempNode {
|
||||
|
||||
constructor( blendMode, baseNode, blendNode ) {
|
||||
|
||||
super();
|
||||
|
||||
this.blendMode = blendMode;
|
||||
|
||||
this.baseNode = baseNode;
|
||||
this.blendNode = blendNode;
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const { blendMode, baseNode, blendNode } = this;
|
||||
const params = { base: baseNode, blend: blendNode };
|
||||
|
||||
let outputNode = null;
|
||||
|
||||
if ( blendMode === BlendModeNode.BURN ) {
|
||||
|
||||
outputNode = BurnNode( params );
|
||||
|
||||
} else if ( blendMode === BlendModeNode.DODGE ) {
|
||||
|
||||
outputNode = DodgeNode( params );
|
||||
|
||||
} else if ( blendMode === BlendModeNode.SCREEN ) {
|
||||
|
||||
outputNode = ScreenNode( params );
|
||||
|
||||
} else if ( blendMode === BlendModeNode.OVERLAY ) {
|
||||
|
||||
outputNode = OverlayNode( params );
|
||||
|
||||
}
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BlendModeNode.BURN = 'burn';
|
||||
BlendModeNode.DODGE = 'dodge';
|
||||
BlendModeNode.SCREEN = 'screen';
|
||||
BlendModeNode.OVERLAY = 'overlay';
|
||||
|
||||
export default BlendModeNode;
|
||||
|
||||
export const burn = nodeProxy( BlendModeNode, BlendModeNode.BURN );
|
||||
export const dodge = nodeProxy( BlendModeNode, BlendModeNode.DODGE );
|
||||
export const overlay = nodeProxy( BlendModeNode, BlendModeNode.OVERLAY );
|
||||
export const screen = nodeProxy( BlendModeNode, BlendModeNode.SCREEN );
|
||||
|
||||
addNodeElement( 'burn', burn );
|
||||
addNodeElement( 'dodge', dodge );
|
||||
addNodeElement( 'overlay', overlay );
|
||||
addNodeElement( 'screen', screen );
|
||||
|
||||
addNodeClass( 'BlendModeNode', BlendModeNode );
|
||||
99
node_modules/three/examples/jsm/nodes/display/BumpMapNode.js
generated
vendored
Normal file
99
node_modules/three/examples/jsm/nodes/display/BumpMapNode.js
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { normalView } from '../accessors/NormalNode.js';
|
||||
import { positionView } from '../accessors/PositionNode.js';
|
||||
import { faceDirection } from './FrontFacingNode.js';
|
||||
import { addNodeElement, tslFn, nodeProxy, float, vec2 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
|
||||
// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
|
||||
|
||||
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
|
||||
|
||||
const dHdxy_fwd = tslFn( ( { textureNode, bumpScale } ) => {
|
||||
|
||||
let texNode = textureNode;
|
||||
|
||||
if ( texNode.isTextureNode !== true ) {
|
||||
|
||||
texNode.traverse( ( node ) => {
|
||||
|
||||
if ( node.isTextureNode === true ) texNode = node;
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
if ( texNode.isTextureNode !== true ) {
|
||||
|
||||
throw new Error( 'THREE.TSL: dHdxy_fwd() requires a TextureNode.' );
|
||||
|
||||
}
|
||||
|
||||
const Hll = float( textureNode );
|
||||
const uvNode = texNode.uvNode || uv();
|
||||
|
||||
// It's used to preserve the same TextureNode instance
|
||||
const sampleTexture = ( uv ) => textureNode.cache().context( { getUVNode: () => uv, forceUVContext: true } );
|
||||
|
||||
return vec2(
|
||||
float( sampleTexture( uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ),
|
||||
float( sampleTexture( uvNode.add( uvNode.dFdy() ) ) ).sub( Hll )
|
||||
).mul( bumpScale );
|
||||
|
||||
} );
|
||||
|
||||
const perturbNormalArb = tslFn( ( inputs ) => {
|
||||
|
||||
const { surf_pos, surf_norm, dHdxy } = inputs;
|
||||
|
||||
// normalize is done to ensure that the bump map looks the same regardless of the texture's scale
|
||||
const vSigmaX = surf_pos.dFdx().normalize();
|
||||
const vSigmaY = surf_pos.dFdy().normalize();
|
||||
const vN = surf_norm; // normalized
|
||||
|
||||
const R1 = vSigmaY.cross( vN );
|
||||
const R2 = vN.cross( vSigmaX );
|
||||
|
||||
const fDet = vSigmaX.dot( R1 ).mul( faceDirection );
|
||||
|
||||
const vGrad = fDet.sign().mul( dHdxy.x.mul( R1 ).add( dHdxy.y.mul( R2 ) ) );
|
||||
|
||||
return fDet.abs().mul( surf_norm ).sub( vGrad ).normalize();
|
||||
|
||||
} );
|
||||
|
||||
class BumpMapNode extends TempNode {
|
||||
|
||||
constructor( textureNode, scaleNode = null ) {
|
||||
|
||||
super( 'vec3' );
|
||||
|
||||
this.textureNode = textureNode;
|
||||
this.scaleNode = scaleNode;
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const bumpScale = this.scaleNode !== null ? this.scaleNode : 1;
|
||||
const dHdxy = dHdxy_fwd( { textureNode: this.textureNode, bumpScale } );
|
||||
|
||||
return perturbNormalArb( {
|
||||
surf_pos: positionView,
|
||||
surf_norm: normalView,
|
||||
dHdxy
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default BumpMapNode;
|
||||
|
||||
export const bumpMap = nodeProxy( BumpMapNode );
|
||||
|
||||
addNodeElement( 'bumpMap', bumpMap );
|
||||
|
||||
addNodeClass( 'BumpMapNode', BumpMapNode );
|
||||
100
node_modules/three/examples/jsm/nodes/display/ColorAdjustmentNode.js
generated
vendored
Normal file
100
node_modules/three/examples/jsm/nodes/display/ColorAdjustmentNode.js
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { dot, mix } from '../math/MathNode.js';
|
||||
import { add } from '../math/OperatorNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { addNodeElement, tslFn, nodeProxy, float, vec3, mat3 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
const saturationNode = tslFn( ( { color, adjustment } ) => {
|
||||
|
||||
return adjustment.mix( luminance( color ), color );
|
||||
|
||||
} );
|
||||
|
||||
const vibranceNode = tslFn( ( { color, adjustment } ) => {
|
||||
|
||||
const average = add( color.r, color.g, color.b ).div( 3.0 );
|
||||
|
||||
const mx = color.r.max( color.g.max( color.b ) );
|
||||
const amt = mx.sub( average ).mul( adjustment ).mul( - 3.0 );
|
||||
|
||||
return mix( color, mx, amt );
|
||||
|
||||
} );
|
||||
|
||||
const hueNode = tslFn( ( { color, adjustment } ) => {
|
||||
|
||||
const RGBtoYIQ = mat3( 0.299, 0.587, 0.114, 0.595716, - 0.274453, - 0.321263, 0.211456, - 0.522591, 0.311135 );
|
||||
const YIQtoRGB = mat3( 1.0, 0.9563, 0.6210, 1.0, - 0.2721, - 0.6474, 1.0, - 1.107, 1.7046 );
|
||||
|
||||
const yiq = RGBtoYIQ.mul( color );
|
||||
|
||||
const hue = yiq.z.atan2( yiq.y ).add( adjustment );
|
||||
const chroma = yiq.yz.length();
|
||||
|
||||
return YIQtoRGB.mul( vec3( yiq.x, chroma.mul( hue.cos() ), chroma.mul( hue.sin() ) ) );
|
||||
|
||||
} );
|
||||
|
||||
class ColorAdjustmentNode extends TempNode {
|
||||
|
||||
constructor( method, colorNode, adjustmentNode = float( 1 ) ) {
|
||||
|
||||
super( 'vec3' );
|
||||
|
||||
this.method = method;
|
||||
|
||||
this.colorNode = colorNode;
|
||||
this.adjustmentNode = adjustmentNode;
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const { method, colorNode, adjustmentNode } = this;
|
||||
|
||||
const callParams = { color: colorNode, adjustment: adjustmentNode };
|
||||
|
||||
let outputNode = null;
|
||||
|
||||
if ( method === ColorAdjustmentNode.SATURATION ) {
|
||||
|
||||
outputNode = saturationNode( callParams );
|
||||
|
||||
} else if ( method === ColorAdjustmentNode.VIBRANCE ) {
|
||||
|
||||
outputNode = vibranceNode( callParams );
|
||||
|
||||
} else if ( method === ColorAdjustmentNode.HUE ) {
|
||||
|
||||
outputNode = hueNode( callParams );
|
||||
|
||||
} else {
|
||||
|
||||
console.error( `${ this.type }: Method "${ this.method }" not supported!` );
|
||||
|
||||
}
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ColorAdjustmentNode.SATURATION = 'saturation';
|
||||
ColorAdjustmentNode.VIBRANCE = 'vibrance';
|
||||
ColorAdjustmentNode.HUE = 'hue';
|
||||
|
||||
export default ColorAdjustmentNode;
|
||||
|
||||
export const saturation = nodeProxy( ColorAdjustmentNode, ColorAdjustmentNode.SATURATION );
|
||||
export const vibrance = nodeProxy( ColorAdjustmentNode, ColorAdjustmentNode.VIBRANCE );
|
||||
export const hue = nodeProxy( ColorAdjustmentNode, ColorAdjustmentNode.HUE );
|
||||
|
||||
export const lumaCoeffs = vec3( 0.2125, 0.7154, 0.0721 );
|
||||
export const luminance = ( color, luma = lumaCoeffs ) => dot( color, luma );
|
||||
|
||||
addNodeElement( 'saturation', saturation );
|
||||
addNodeElement( 'vibrance', vibrance );
|
||||
addNodeElement( 'hue', hue );
|
||||
|
||||
addNodeClass( 'ColorAdjustmentNode', ColorAdjustmentNode );
|
||||
108
node_modules/three/examples/jsm/nodes/display/ColorSpaceNode.js
generated
vendored
Normal file
108
node_modules/three/examples/jsm/nodes/display/ColorSpaceNode.js
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { mix } from '../math/MathNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { addNodeElement, tslFn, nodeObject, nodeProxy, vec4 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
import { LinearSRGBColorSpace, SRGBColorSpace } from 'three';
|
||||
|
||||
const sRGBToLinearShader = tslFn( ( inputs ) => {
|
||||
|
||||
const { value } = inputs;
|
||||
const { rgb } = value;
|
||||
|
||||
const a = rgb.mul( 0.9478672986 ).add( 0.0521327014 ).pow( 2.4 );
|
||||
const b = rgb.mul( 0.0773993808 );
|
||||
const factor = rgb.lessThanEqual( 0.04045 );
|
||||
|
||||
const rgbResult = mix( a, b, factor );
|
||||
|
||||
return vec4( rgbResult, value.a );
|
||||
|
||||
} );
|
||||
|
||||
const LinearTosRGBShader = tslFn( ( inputs ) => {
|
||||
|
||||
const { value } = inputs;
|
||||
const { rgb } = value;
|
||||
|
||||
const a = rgb.pow( 0.41666 ).mul( 1.055 ).sub( 0.055 );
|
||||
const b = rgb.mul( 12.92 );
|
||||
const factor = rgb.lessThanEqual( 0.0031308 );
|
||||
|
||||
const rgbResult = mix( a, b, factor );
|
||||
|
||||
return vec4( rgbResult, value.a );
|
||||
|
||||
} );
|
||||
|
||||
const getColorSpaceMethod = ( colorSpace ) => {
|
||||
|
||||
let method = null;
|
||||
|
||||
if ( colorSpace === LinearSRGBColorSpace ) {
|
||||
|
||||
method = 'Linear';
|
||||
|
||||
} else if ( colorSpace === SRGBColorSpace ) {
|
||||
|
||||
method = 'sRGB';
|
||||
|
||||
}
|
||||
|
||||
return method;
|
||||
|
||||
};
|
||||
|
||||
const getMethod = ( source, target ) => {
|
||||
|
||||
return getColorSpaceMethod( source ) + 'To' + getColorSpaceMethod( target );
|
||||
|
||||
};
|
||||
|
||||
class ColorSpaceNode extends TempNode {
|
||||
|
||||
constructor( method, node ) {
|
||||
|
||||
super( 'vec4' );
|
||||
|
||||
this.method = method;
|
||||
this.node = node;
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const { method, node } = this;
|
||||
|
||||
if ( method === ColorSpaceNode.LINEAR_TO_LINEAR )
|
||||
return node;
|
||||
|
||||
return Methods[ method ]( { value: node } );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ColorSpaceNode.LINEAR_TO_LINEAR = 'LinearToLinear';
|
||||
ColorSpaceNode.LINEAR_TO_sRGB = 'LinearTosRGB';
|
||||
ColorSpaceNode.sRGB_TO_LINEAR = 'sRGBToLinear';
|
||||
|
||||
const Methods = {
|
||||
[ ColorSpaceNode.LINEAR_TO_sRGB ]: LinearTosRGBShader,
|
||||
[ ColorSpaceNode.sRGB_TO_LINEAR ]: sRGBToLinearShader
|
||||
};
|
||||
|
||||
export default ColorSpaceNode;
|
||||
|
||||
export const linearToColorSpace = ( node, colorSpace ) => nodeObject( new ColorSpaceNode( getMethod( LinearSRGBColorSpace, colorSpace ), nodeObject( node ) ) );
|
||||
export const colorSpaceToLinear = ( node, colorSpace ) => nodeObject( new ColorSpaceNode( getMethod( colorSpace, LinearSRGBColorSpace ), nodeObject( node ) ) );
|
||||
|
||||
export const linearTosRGB = nodeProxy( ColorSpaceNode, ColorSpaceNode.LINEAR_TO_sRGB );
|
||||
export const sRGBToLinear = nodeProxy( ColorSpaceNode, ColorSpaceNode.sRGB_TO_LINEAR );
|
||||
|
||||
addNodeElement( 'linearTosRGB', linearTosRGB );
|
||||
addNodeElement( 'sRGBToLinear', sRGBToLinear );
|
||||
addNodeElement( 'linearToColorSpace', linearToColorSpace );
|
||||
addNodeElement( 'colorSpaceToLinear', colorSpaceToLinear );
|
||||
|
||||
addNodeClass( 'ColorSpaceNode', ColorSpaceNode );
|
||||
27
node_modules/three/examples/jsm/nodes/display/FrontFacingNode.js
generated
vendored
Normal file
27
node_modules/three/examples/jsm/nodes/display/FrontFacingNode.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import Node, { addNodeClass } from '../core/Node.js';
|
||||
import { nodeImmutable, float } from '../shadernode/ShaderNode.js';
|
||||
|
||||
class FrontFacingNode extends Node {
|
||||
|
||||
constructor() {
|
||||
|
||||
super( 'bool' );
|
||||
|
||||
this.isFrontFacingNode = true;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
return builder.getFrontFacing();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FrontFacingNode;
|
||||
|
||||
export const frontFacing = nodeImmutable( FrontFacingNode );
|
||||
export const faceDirection = float( frontFacing ).mul( 2.0 ).sub( 1.0 );
|
||||
|
||||
addNodeClass( 'FrontFacingNode', FrontFacingNode );
|
||||
108
node_modules/three/examples/jsm/nodes/display/NormalMapNode.js
generated
vendored
Normal file
108
node_modules/three/examples/jsm/nodes/display/NormalMapNode.js
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { add } from '../math/OperatorNode.js';
|
||||
import { bitangentView } from '../accessors/BitangentNode.js';
|
||||
import { modelNormalMatrix } from '../accessors/ModelNode.js';
|
||||
import { normalView } from '../accessors/NormalNode.js';
|
||||
import { positionView } from '../accessors/PositionNode.js';
|
||||
import { tangentView } from '../accessors/TangentNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { faceDirection } from './FrontFacingNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { addNodeElement, tslFn, nodeProxy, vec3, mat3 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
import { TangentSpaceNormalMap, ObjectSpaceNormalMap } from 'three';
|
||||
|
||||
// Normal Mapping Without Precomputed Tangents
|
||||
// http://www.thetenthplanet.de/archives/1180
|
||||
|
||||
const perturbNormal2Arb = tslFn( ( inputs ) => {
|
||||
|
||||
const { eye_pos, surf_norm, mapN, uv } = inputs;
|
||||
|
||||
const q0 = eye_pos.dFdx();
|
||||
const q1 = eye_pos.dFdy();
|
||||
const st0 = uv.dFdx();
|
||||
const st1 = uv.dFdy();
|
||||
|
||||
const N = surf_norm; // normalized
|
||||
|
||||
const q1perp = q1.cross( N );
|
||||
const q0perp = N.cross( q0 );
|
||||
|
||||
const T = q1perp.mul( st0.x ).add( q0perp.mul( st1.x ) );
|
||||
const B = q1perp.mul( st0.y ).add( q0perp.mul( st1.y ) );
|
||||
|
||||
const det = T.dot( T ).max( B.dot( B ) );
|
||||
const scale = faceDirection.mul( det.inverseSqrt() );
|
||||
|
||||
return add( T.mul( mapN.x, scale ), B.mul( mapN.y, scale ), N.mul( mapN.z ) ).normalize();
|
||||
|
||||
} );
|
||||
|
||||
class NormalMapNode extends TempNode {
|
||||
|
||||
constructor( node, scaleNode = null ) {
|
||||
|
||||
super( 'vec3' );
|
||||
|
||||
this.node = node;
|
||||
this.scaleNode = scaleNode;
|
||||
|
||||
this.normalMapType = TangentSpaceNormalMap;
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
const { normalMapType, scaleNode } = this;
|
||||
|
||||
let normalMap = this.node.mul( 2.0 ).sub( 1.0 );
|
||||
|
||||
if ( scaleNode !== null ) {
|
||||
|
||||
normalMap = vec3( normalMap.xy.mul( scaleNode ), normalMap.z );
|
||||
|
||||
}
|
||||
|
||||
let outputNode = null;
|
||||
|
||||
if ( normalMapType === ObjectSpaceNormalMap ) {
|
||||
|
||||
outputNode = modelNormalMatrix.mul( normalMap ).normalize();
|
||||
|
||||
} else if ( normalMapType === TangentSpaceNormalMap ) {
|
||||
|
||||
const tangent = builder.hasGeometryAttribute( 'tangent' );
|
||||
|
||||
if ( tangent === true ) {
|
||||
|
||||
outputNode = TBNViewMatrix.mul( normalMap ).normalize();
|
||||
|
||||
} else {
|
||||
|
||||
outputNode = perturbNormal2Arb( {
|
||||
eye_pos: positionView,
|
||||
surf_norm: normalView,
|
||||
mapN: normalMap,
|
||||
uv: uv()
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default NormalMapNode;
|
||||
|
||||
export const normalMap = nodeProxy( NormalMapNode );
|
||||
|
||||
export const TBNViewMatrix = mat3( tangentView, bitangentView, normalView );
|
||||
|
||||
addNodeElement( 'normalMap', normalMap );
|
||||
|
||||
addNodeClass( 'NormalMapNode', NormalMapNode );
|
||||
32
node_modules/three/examples/jsm/nodes/display/PosterizeNode.js
generated
vendored
Normal file
32
node_modules/three/examples/jsm/nodes/display/PosterizeNode.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js';
|
||||
|
||||
class PosterizeNode extends TempNode {
|
||||
|
||||
constructor( sourceNode, stepsNode ) {
|
||||
|
||||
super();
|
||||
|
||||
this.sourceNode = sourceNode;
|
||||
this.stepsNode = stepsNode;
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const { sourceNode, stepsNode } = this;
|
||||
|
||||
return sourceNode.mul( stepsNode ).floor().div( stepsNode );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PosterizeNode;
|
||||
|
||||
export const posterize = nodeProxy( PosterizeNode );
|
||||
|
||||
addNodeElement( 'posterize', posterize );
|
||||
|
||||
addNodeClass( 'PosterizeNode', PosterizeNode );
|
||||
141
node_modules/three/examples/jsm/nodes/display/ToneMappingNode.js
generated
vendored
Normal file
141
node_modules/three/examples/jsm/nodes/display/ToneMappingNode.js
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { tslFn, nodeObject, float, mat3 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
import { NoToneMapping, LinearToneMapping, ReinhardToneMapping, CineonToneMapping, ACESFilmicToneMapping } from 'three';
|
||||
|
||||
// exposure only
|
||||
const LinearToneMappingNode = tslFn( ( { color, exposure } ) => {
|
||||
|
||||
return color.mul( exposure ).clamp();
|
||||
|
||||
} );
|
||||
|
||||
// source: https://www.cs.utah.edu/docs/techreports/2002/pdf/UUCS-02-001.pdf
|
||||
const ReinhardToneMappingNode = tslFn( ( { color, exposure } ) => {
|
||||
|
||||
color = color.mul( exposure );
|
||||
|
||||
return color.div( color.add( 1.0 ) ).clamp();
|
||||
|
||||
} );
|
||||
|
||||
// source: http://filmicworlds.com/blog/filmic-tonemapping-operators/
|
||||
const OptimizedCineonToneMappingNode = tslFn( ( { color, exposure } ) => {
|
||||
|
||||
// optimized filmic operator by Jim Hejl and Richard Burgess-Dawson
|
||||
color = color.mul( exposure );
|
||||
color = color.sub( 0.004 ).max( 0.0 );
|
||||
|
||||
const a = color.mul( color.mul( 6.2 ).add( 0.5 ) );
|
||||
const b = color.mul( color.mul( 6.2 ).add( 1.7 ) ).add( 0.06 );
|
||||
|
||||
return a.div( b ).pow( 2.2 );
|
||||
|
||||
} );
|
||||
|
||||
// source: https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs
|
||||
const RRTAndODTFit = tslFn( ( { color } ) => {
|
||||
|
||||
const a = color.mul( color.add( 0.0245786 ) ).sub( 0.000090537 );
|
||||
const b = color.mul( color.add( 0.4329510 ).mul( 0.983729 ) ).add( 0.238081 );
|
||||
|
||||
return a.div( b );
|
||||
|
||||
} );
|
||||
|
||||
// source: https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs
|
||||
const ACESFilmicToneMappingNode = tslFn( ( { color, exposure } ) => {
|
||||
|
||||
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
|
||||
const ACESInputMat = mat3(
|
||||
0.59719, 0.35458, 0.04823,
|
||||
0.07600, 0.90834, 0.01566,
|
||||
0.02840, 0.13383, 0.83777
|
||||
);
|
||||
|
||||
// ODT_SAT => XYZ => D60_2_D65 => sRGB
|
||||
const ACESOutputMat = mat3(
|
||||
1.60475, - 0.53108, - 0.07367,
|
||||
- 0.10208, 1.10813, - 0.00605,
|
||||
- 0.00327, - 0.07276, 1.07602
|
||||
);
|
||||
|
||||
color = color.mul( exposure ).div( 0.6 );
|
||||
|
||||
color = ACESInputMat.mul( color );
|
||||
|
||||
// Apply RRT and ODT
|
||||
color = RRTAndODTFit( { color } );
|
||||
|
||||
color = ACESOutputMat.mul( color );
|
||||
|
||||
// Clamp to [0, 1]
|
||||
return color.clamp();
|
||||
|
||||
} );
|
||||
|
||||
const toneMappingLib = {
|
||||
[ LinearToneMapping ]: LinearToneMappingNode,
|
||||
[ ReinhardToneMapping ]: ReinhardToneMappingNode,
|
||||
[ CineonToneMapping ]: OptimizedCineonToneMappingNode,
|
||||
[ ACESFilmicToneMapping ]: ACESFilmicToneMappingNode
|
||||
};
|
||||
|
||||
class ToneMappingNode extends TempNode {
|
||||
|
||||
constructor( toneMapping = NoToneMapping, exposureNode = float( 1 ), colorNode = null ) {
|
||||
|
||||
super( 'vec3' );
|
||||
|
||||
this.toneMapping = toneMapping;
|
||||
|
||||
this.exposureNode = exposureNode;
|
||||
this.colorNode = colorNode;
|
||||
|
||||
}
|
||||
|
||||
getCacheKey() {
|
||||
|
||||
let cacheKey = super.getCacheKey();
|
||||
cacheKey = '{toneMapping:' + this.toneMapping + ',nodes:' + cacheKey + '}';
|
||||
|
||||
return cacheKey;
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
const colorNode = this.colorNode || builder.context.color;
|
||||
const toneMapping = this.toneMapping;
|
||||
|
||||
if ( toneMapping === NoToneMapping ) return colorNode;
|
||||
|
||||
const toneMappingParams = { exposure: this.exposureNode, color: colorNode };
|
||||
const toneMappingNode = toneMappingLib[ toneMapping ];
|
||||
|
||||
let outputNode = null;
|
||||
|
||||
if ( toneMappingNode ) {
|
||||
|
||||
outputNode = toneMappingNode( toneMappingParams );
|
||||
|
||||
} else {
|
||||
|
||||
console.error( 'ToneMappingNode: Unsupported Tone Mapping configuration.', toneMapping );
|
||||
|
||||
outputNode = colorNode;
|
||||
|
||||
}
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ToneMappingNode;
|
||||
|
||||
export const toneMapping = ( mapping, exposure, color ) => nodeObject( new ToneMappingNode( mapping, nodeObject( exposure ), nodeObject( color ) ) );
|
||||
|
||||
addNodeClass( 'ToneMappingNode', ToneMappingNode );
|
||||
69
node_modules/three/examples/jsm/nodes/display/ViewportDepthNode.js
generated
vendored
Normal file
69
node_modules/three/examples/jsm/nodes/display/ViewportDepthNode.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
import Node, { addNodeClass } from '../core/Node.js';
|
||||
import { nodeImmutable, nodeProxy } from '../shadernode/ShaderNode.js';
|
||||
import { cameraNear, cameraFar } from '../accessors/CameraNode.js';
|
||||
import { positionView } from '../accessors/PositionNode.js';
|
||||
import { viewportDepthTexture } from './ViewportDepthTextureNode.js';
|
||||
|
||||
class ViewportDepthNode extends Node {
|
||||
|
||||
constructor( scope, textureNode = null ) {
|
||||
|
||||
super( 'float' );
|
||||
|
||||
this.scope = scope;
|
||||
this.textureNode = textureNode;
|
||||
|
||||
this.isViewportDepthNode = true;
|
||||
|
||||
}
|
||||
|
||||
setup( /*builder*/ ) {
|
||||
|
||||
const { scope } = this;
|
||||
|
||||
let node = null;
|
||||
|
||||
if ( scope === ViewportDepthNode.DEPTH ) {
|
||||
|
||||
node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar );
|
||||
|
||||
} else if ( scope === ViewportDepthNode.DEPTH_TEXTURE ) {
|
||||
|
||||
const texture = this.textureNode || viewportDepthTexture();
|
||||
|
||||
const viewZ = perspectiveDepthToViewZ( texture, cameraNear, cameraFar );
|
||||
node = viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// NOTE: viewZ, the z-coordinate in camera space, is negative for points in front of the camera
|
||||
|
||||
// -near maps to 0; -far maps to 1
|
||||
export const viewZToOrthographicDepth = ( viewZ, near, far ) => viewZ.add( near ).div( near.sub( far ) );
|
||||
|
||||
// maps orthographic depth in [ 0, 1 ] to viewZ
|
||||
export const orthographicDepthToViewZ = ( depth, near, far ) => near.sub( far ).mul( depth ).sub( near );
|
||||
|
||||
// NOTE: https://twitter.com/gonnavis/status/1377183786949959682
|
||||
|
||||
// -near maps to 0; -far maps to 1
|
||||
export const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ ).mul( far ).div( near.sub( far ).mul( viewZ ) );
|
||||
|
||||
// maps perspective depth in [ 0, 1 ] to viewZ
|
||||
export const perspectiveDepthToViewZ = ( depth, near, far ) => near.mul( far ).div( far.sub( near ).mul( depth ).sub( far ) );
|
||||
|
||||
ViewportDepthNode.DEPTH = 'depth';
|
||||
ViewportDepthNode.DEPTH_TEXTURE = 'depthTexture';
|
||||
|
||||
export default ViewportDepthNode;
|
||||
|
||||
export const depth = nodeImmutable( ViewportDepthNode, ViewportDepthNode.DEPTH );
|
||||
export const depthTexture = nodeProxy( ViewportDepthNode, ViewportDepthNode.DEPTH_TEXTURE );
|
||||
|
||||
addNodeClass( 'ViewportDepthNode', ViewportDepthNode );
|
||||
34
node_modules/three/examples/jsm/nodes/display/ViewportDepthTextureNode.js
generated
vendored
Normal file
34
node_modules/three/examples/jsm/nodes/display/ViewportDepthTextureNode.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import ViewportTextureNode from './ViewportTextureNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js';
|
||||
import { viewportTopLeft } from './ViewportNode.js';
|
||||
import { DepthTexture, LinearMipmapLinearFilter, DepthFormat, UnsignedIntType } from 'three';
|
||||
|
||||
let sharedDepthbuffer = null;
|
||||
|
||||
class ViewportDepthTextureNode extends ViewportTextureNode {
|
||||
|
||||
constructor( uvNode = viewportTopLeft, levelNode = null ) {
|
||||
|
||||
if ( sharedDepthbuffer === null ) {
|
||||
|
||||
sharedDepthbuffer = new DepthTexture();
|
||||
sharedDepthbuffer.minFilter = LinearMipmapLinearFilter;
|
||||
sharedDepthbuffer.type = UnsignedIntType;
|
||||
sharedDepthbuffer.format = DepthFormat;
|
||||
|
||||
}
|
||||
|
||||
super( uvNode, levelNode, sharedDepthbuffer );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ViewportDepthTextureNode;
|
||||
|
||||
export const viewportDepthTexture = nodeProxy( ViewportDepthTextureNode );
|
||||
|
||||
addNodeElement( 'viewportDepthTexture', viewportDepthTexture );
|
||||
|
||||
addNodeClass( 'ViewportDepthTextureNode', ViewportDepthTextureNode );
|
||||
139
node_modules/three/examples/jsm/nodes/display/ViewportNode.js
generated
vendored
Normal file
139
node_modules/three/examples/jsm/nodes/display/ViewportNode.js
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
import Node, { addNodeClass } from '../core/Node.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { nodeImmutable, vec2 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
import { Vector2, Vector4 } from 'three';
|
||||
|
||||
let resolution, viewportResult;
|
||||
|
||||
class ViewportNode extends Node {
|
||||
|
||||
constructor( scope ) {
|
||||
|
||||
super();
|
||||
|
||||
this.scope = scope;
|
||||
|
||||
this.isViewportNode = true;
|
||||
|
||||
}
|
||||
|
||||
getNodeType() {
|
||||
|
||||
return this.scope === ViewportNode.COORDINATE || this.scope === ViewportNode.VIEWPORT ? 'vec4' : 'vec2';
|
||||
|
||||
}
|
||||
|
||||
getUpdateType() {
|
||||
|
||||
let updateType = NodeUpdateType.NONE;
|
||||
|
||||
if ( this.scope === ViewportNode.RESOLUTION || this.scope === ViewportNode.VIEWPORT ) {
|
||||
|
||||
updateType = NodeUpdateType.FRAME;
|
||||
|
||||
}
|
||||
|
||||
this.updateType = updateType;
|
||||
|
||||
return updateType;
|
||||
|
||||
}
|
||||
|
||||
update( { renderer } ) {
|
||||
|
||||
if ( this.scope === ViewportNode.VIEWPORT ) {
|
||||
|
||||
renderer.getViewport( viewportResult );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.getDrawingBufferSize( resolution );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
const scope = this.scope;
|
||||
|
||||
if ( scope === ViewportNode.COORDINATE ) return;
|
||||
|
||||
let output = null;
|
||||
|
||||
if ( scope === ViewportNode.RESOLUTION ) {
|
||||
|
||||
output = uniform( resolution || ( resolution = new Vector2() ) );
|
||||
|
||||
} else if ( scope === ViewportNode.VIEWPORT ) {
|
||||
|
||||
output = uniform( viewportResult || ( viewportResult = new Vector4() ) );
|
||||
|
||||
} else {
|
||||
|
||||
const coordinateNode = vec2( new ViewportNode( ViewportNode.COORDINATE ) );
|
||||
const resolutionNode = new ViewportNode( ViewportNode.RESOLUTION );
|
||||
|
||||
output = coordinateNode.div( resolutionNode );
|
||||
|
||||
let outX = output.x;
|
||||
let outY = output.y;
|
||||
|
||||
if ( /bottom/i.test( scope ) ) outY = outY.oneMinus();
|
||||
if ( /right/i.test( scope ) ) outX = outX.oneMinus();
|
||||
|
||||
output = vec2( outX, outY );
|
||||
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
if ( this.scope === ViewportNode.COORDINATE ) {
|
||||
|
||||
let coord = builder.getFragCoord();
|
||||
|
||||
if ( builder.isFlipY() ) {
|
||||
|
||||
// follow webgpu standards
|
||||
|
||||
const resolution = viewportResolution.build( builder );
|
||||
|
||||
coord = `${ builder.getType( 'vec2' ) }( ${ coord }.x, ${ resolution}.y - ${ coord }.y )`;
|
||||
|
||||
}
|
||||
|
||||
return coord;
|
||||
|
||||
}
|
||||
|
||||
return super.generate( builder );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ViewportNode.COORDINATE = 'coordinate';
|
||||
ViewportNode.RESOLUTION = 'resolution';
|
||||
ViewportNode.VIEWPORT = 'viewport';
|
||||
ViewportNode.TOP_LEFT = 'topLeft';
|
||||
ViewportNode.BOTTOM_LEFT = 'bottomLeft';
|
||||
ViewportNode.TOP_RIGHT = 'topRight';
|
||||
ViewportNode.BOTTOM_RIGHT = 'bottomRight';
|
||||
|
||||
export default ViewportNode;
|
||||
|
||||
export const viewportCoordinate = nodeImmutable( ViewportNode, ViewportNode.COORDINATE );
|
||||
export const viewportResolution = nodeImmutable( ViewportNode, ViewportNode.RESOLUTION );
|
||||
export const viewport = nodeImmutable( ViewportNode, ViewportNode.VIEWPORT );
|
||||
export const viewportTopLeft = nodeImmutable( ViewportNode, ViewportNode.TOP_LEFT );
|
||||
export const viewportBottomLeft = nodeImmutable( ViewportNode, ViewportNode.BOTTOM_LEFT );
|
||||
export const viewportTopRight = nodeImmutable( ViewportNode, ViewportNode.TOP_RIGHT );
|
||||
export const viewportBottomRight = nodeImmutable( ViewportNode, ViewportNode.BOTTOM_RIGHT );
|
||||
|
||||
addNodeClass( 'ViewportNode', ViewportNode );
|
||||
31
node_modules/three/examples/jsm/nodes/display/ViewportSharedTextureNode.js
generated
vendored
Normal file
31
node_modules/three/examples/jsm/nodes/display/ViewportSharedTextureNode.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import ViewportTextureNode from './ViewportTextureNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js';
|
||||
import { viewportTopLeft } from './ViewportNode.js';
|
||||
import { FramebufferTexture } from 'three';
|
||||
|
||||
let sharedFramebuffer = null;
|
||||
|
||||
class ViewportSharedTextureNode extends ViewportTextureNode {
|
||||
|
||||
constructor( uvNode = viewportTopLeft, levelNode = null ) {
|
||||
|
||||
if ( sharedFramebuffer === null ) {
|
||||
|
||||
sharedFramebuffer = new FramebufferTexture();
|
||||
|
||||
}
|
||||
|
||||
super( uvNode, levelNode, sharedFramebuffer );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ViewportSharedTextureNode;
|
||||
|
||||
export const viewportSharedTexture = nodeProxy( ViewportSharedTextureNode );
|
||||
|
||||
addNodeElement( 'viewportSharedTexture', viewportSharedTexture );
|
||||
|
||||
addNodeClass( 'ViewportSharedTextureNode', ViewportSharedTextureNode );
|
||||
75
node_modules/three/examples/jsm/nodes/display/ViewportTextureNode.js
generated
vendored
Normal file
75
node_modules/three/examples/jsm/nodes/display/ViewportTextureNode.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
import TextureNode from '../accessors/TextureNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js';
|
||||
import { viewportTopLeft } from './ViewportNode.js';
|
||||
import { Vector2, FramebufferTexture, LinearMipmapLinearFilter } from 'three';
|
||||
|
||||
const _size = new Vector2();
|
||||
|
||||
class ViewportTextureNode extends TextureNode {
|
||||
|
||||
constructor( uvNode = viewportTopLeft, levelNode = null, framebufferTexture = null ) {
|
||||
|
||||
if ( framebufferTexture === null ) {
|
||||
|
||||
framebufferTexture = new FramebufferTexture();
|
||||
framebufferTexture.minFilter = LinearMipmapLinearFilter;
|
||||
|
||||
}
|
||||
|
||||
super( framebufferTexture, uvNode, levelNode );
|
||||
|
||||
this.generateMipmaps = false;
|
||||
|
||||
this.isOutputTextureNode = true;
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.FRAME;
|
||||
|
||||
}
|
||||
|
||||
updateBefore( frame ) {
|
||||
|
||||
const renderer = frame.renderer;
|
||||
renderer.getDrawingBufferSize( _size );
|
||||
|
||||
//
|
||||
|
||||
const framebufferTexture = this.value;
|
||||
|
||||
if ( framebufferTexture.image.width !== _size.width || framebufferTexture.image.height !== _size.height ) {
|
||||
|
||||
framebufferTexture.image.width = _size.width;
|
||||
framebufferTexture.image.height = _size.height;
|
||||
framebufferTexture.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const currentGenerateMipmaps = framebufferTexture.generateMipmaps;
|
||||
framebufferTexture.generateMipmaps = this.generateMipmaps;
|
||||
|
||||
renderer.copyFramebufferToTexture( framebufferTexture );
|
||||
|
||||
framebufferTexture.generateMipmaps = currentGenerateMipmaps;
|
||||
|
||||
}
|
||||
|
||||
clone() {
|
||||
|
||||
return new this.constructor( this.uvNode, this.levelNode, this.value );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ViewportTextureNode;
|
||||
|
||||
export const viewportTexture = nodeProxy( ViewportTextureNode );
|
||||
export const viewportMipTexture = nodeProxy( ViewportTextureNode, null, null, { generateMipmaps: true } );
|
||||
|
||||
addNodeElement( 'viewportTexture', viewportTexture );
|
||||
addNodeElement( 'viewportMipTexture', viewportMipTexture );
|
||||
|
||||
addNodeClass( 'ViewportTextureNode', ViewportTextureNode );
|
||||
Reference in New Issue
Block a user