created site just for chat
This commit is contained in:
152
site/game/node_modules/three/src/nodes/display/AfterImageNode.js
generated
vendored
Normal file
152
site/game/node_modules/three/src/nodes/display/AfterImageNode.js
generated
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { nodeObject, addNodeElement, tslFn, float, vec4 } from '../shadernode/ShaderNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { texture } from '../accessors/TextureNode.js';
|
||||
import { passTexture } from './PassNode.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { sign, max } from '../math/MathNode.js';
|
||||
import QuadMesh from '../../renderers/common/QuadMesh.js';
|
||||
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
import { RenderTarget } from '../../core/RenderTarget.js';
|
||||
|
||||
const _size = /*@__PURE__*/ new Vector2();
|
||||
|
||||
const _quadMeshComp = /*@__PURE__*/ new QuadMesh();
|
||||
|
||||
class AfterImageNode extends TempNode {
|
||||
|
||||
constructor( textureNode, damp = 0.96 ) {
|
||||
|
||||
super( textureNode );
|
||||
|
||||
this.textureNode = textureNode;
|
||||
this.textureNodeOld = texture();
|
||||
this.damp = uniform( damp );
|
||||
|
||||
this._compRT = new RenderTarget();
|
||||
this._compRT.texture.name = 'AfterImageNode.comp';
|
||||
|
||||
this._oldRT = new RenderTarget();
|
||||
this._oldRT.texture.name = 'AfterImageNode.old';
|
||||
|
||||
this._textureNode = passTexture( this, this._compRT.texture );
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.RENDER;
|
||||
|
||||
}
|
||||
|
||||
getTextureNode() {
|
||||
|
||||
return this._textureNode;
|
||||
|
||||
}
|
||||
|
||||
setSize( width, height ) {
|
||||
|
||||
this._compRT.setSize( width, height );
|
||||
this._oldRT.setSize( width, height );
|
||||
|
||||
}
|
||||
|
||||
updateBefore( frame ) {
|
||||
|
||||
const { renderer } = frame;
|
||||
|
||||
const textureNode = this.textureNode;
|
||||
const map = textureNode.value;
|
||||
|
||||
const textureType = map.type;
|
||||
|
||||
this._compRT.texture.type = textureType;
|
||||
this._oldRT.texture.type = textureType;
|
||||
|
||||
renderer.getDrawingBufferSize( _size );
|
||||
|
||||
this.setSize( _size.x, _size.y );
|
||||
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentTexture = textureNode.value;
|
||||
|
||||
this.textureNodeOld.value = this._oldRT.texture;
|
||||
|
||||
// comp
|
||||
renderer.setRenderTarget( this._compRT );
|
||||
_quadMeshComp.render( renderer );
|
||||
|
||||
// Swap the textures
|
||||
const temp = this._oldRT;
|
||||
this._oldRT = this._compRT;
|
||||
this._compRT = temp;
|
||||
|
||||
renderer.setRenderTarget( currentRenderTarget );
|
||||
textureNode.value = currentTexture;
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
const textureNode = this.textureNode;
|
||||
const textureNodeOld = this.textureNodeOld;
|
||||
|
||||
//
|
||||
|
||||
const uvNode = textureNode.uvNode || uv();
|
||||
|
||||
textureNodeOld.uvNode = uvNode;
|
||||
|
||||
const sampleTexture = ( uv ) => textureNode.uv( uv );
|
||||
|
||||
const when_gt = tslFn( ( [ x_immutable, y_immutable ] ) => {
|
||||
|
||||
const y = float( y_immutable ).toVar();
|
||||
const x = vec4( x_immutable ).toVar();
|
||||
|
||||
return max( sign( x.sub( y ) ), 0.0 );
|
||||
|
||||
} );
|
||||
|
||||
const afterImg = tslFn( () => {
|
||||
|
||||
const texelOld = vec4( textureNodeOld );
|
||||
const texelNew = vec4( sampleTexture( uvNode ) );
|
||||
|
||||
texelOld.mulAssign( this.damp.mul( when_gt( texelOld, 0.1 ) ) );
|
||||
return max( texelNew, texelOld );
|
||||
|
||||
} );
|
||||
|
||||
//
|
||||
|
||||
const materialComposed = this._materialComposed || ( this._materialComposed = builder.createNodeMaterial() );
|
||||
materialComposed.fragmentNode = afterImg();
|
||||
|
||||
_quadMeshComp.material = materialComposed;
|
||||
|
||||
//
|
||||
|
||||
const properties = builder.getNodeProperties( this );
|
||||
properties.textureNode = textureNode;
|
||||
|
||||
//
|
||||
|
||||
return this._textureNode;
|
||||
|
||||
}
|
||||
|
||||
dispose() {
|
||||
|
||||
this._compRT.dispose();
|
||||
this._oldRT.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const afterImage = ( node, damp ) => nodeObject( new AfterImageNode( nodeObject( node ).toTexture(), damp ) );
|
||||
|
||||
addNodeElement( 'afterImage', afterImage );
|
||||
|
||||
export default AfterImageNode;
|
||||
|
145
site/game/node_modules/three/src/nodes/display/AnamorphicNode.js
generated
vendored
Normal file
145
site/game/node_modules/three/src/nodes/display/AnamorphicNode.js
generated
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { nodeObject, addNodeElement, tslFn, float, vec2, vec3 } from '../shadernode/ShaderNode.js';
|
||||
import { loop } from '../utils/LoopNode.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { threshold } from './ColorAdjustmentNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { passTexture } from './PassNode.js';
|
||||
import QuadMesh from '../../renderers/common/QuadMesh.js';
|
||||
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
import { RenderTarget } from '../../core/RenderTarget.js';
|
||||
|
||||
const _quadMesh = /*@__PURE__*/ new QuadMesh();
|
||||
|
||||
class AnamorphicNode extends TempNode {
|
||||
|
||||
constructor( textureNode, tresholdNode, scaleNode, samples ) {
|
||||
|
||||
super( 'vec4' );
|
||||
|
||||
this.textureNode = textureNode;
|
||||
this.tresholdNode = tresholdNode;
|
||||
this.scaleNode = scaleNode;
|
||||
this.colorNode = vec3( 0.1, 0.0, 1.0 );
|
||||
this.samples = samples;
|
||||
this.resolution = new Vector2( 1, 1 );
|
||||
|
||||
this._renderTarget = new RenderTarget();
|
||||
this._renderTarget.texture.name = 'anamorphic';
|
||||
|
||||
this._invSize = uniform( new Vector2() );
|
||||
|
||||
this._textureNode = passTexture( this, this._renderTarget.texture );
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.RENDER;
|
||||
|
||||
}
|
||||
|
||||
getTextureNode() {
|
||||
|
||||
return this._textureNode;
|
||||
|
||||
}
|
||||
|
||||
setSize( width, height ) {
|
||||
|
||||
this._invSize.value.set( 1 / width, 1 / height );
|
||||
|
||||
width = Math.max( Math.round( width * this.resolution.x ), 1 );
|
||||
height = Math.max( Math.round( height * this.resolution.y ), 1 );
|
||||
|
||||
this._renderTarget.setSize( width, height );
|
||||
|
||||
}
|
||||
|
||||
updateBefore( frame ) {
|
||||
|
||||
const { renderer } = frame;
|
||||
|
||||
const textureNode = this.textureNode;
|
||||
const map = textureNode.value;
|
||||
|
||||
this._renderTarget.texture.type = map.type;
|
||||
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentTexture = textureNode.value;
|
||||
|
||||
_quadMesh.material = this._material;
|
||||
|
||||
this.setSize( map.image.width, map.image.height );
|
||||
|
||||
// render
|
||||
|
||||
renderer.setRenderTarget( this._renderTarget );
|
||||
|
||||
_quadMesh.render( renderer );
|
||||
|
||||
// restore
|
||||
|
||||
renderer.setRenderTarget( currentRenderTarget );
|
||||
textureNode.value = currentTexture;
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
const textureNode = this.textureNode;
|
||||
const uvNode = textureNode.uvNode || uv();
|
||||
|
||||
const sampleTexture = ( uv ) => textureNode.uv( uv );
|
||||
|
||||
const anamorph = tslFn( () => {
|
||||
|
||||
const samples = this.samples;
|
||||
const halfSamples = Math.floor( samples / 2 );
|
||||
|
||||
const total = vec3( 0 ).toVar();
|
||||
|
||||
loop( { start: - halfSamples, end: halfSamples }, ( { i } ) => {
|
||||
|
||||
const softness = float( i ).abs().div( halfSamples ).oneMinus();
|
||||
|
||||
const uv = vec2( uvNode.x.add( this._invSize.x.mul( i ).mul( this.scaleNode ) ), uvNode.y );
|
||||
const color = sampleTexture( uv );
|
||||
const pass = threshold( color, this.tresholdNode ).mul( softness );
|
||||
|
||||
total.addAssign( pass );
|
||||
|
||||
} );
|
||||
|
||||
return total.mul( this.colorNode );
|
||||
|
||||
} );
|
||||
|
||||
//
|
||||
|
||||
const material = this._material || ( this._material = builder.createNodeMaterial() );
|
||||
material.fragmentNode = anamorph();
|
||||
|
||||
//
|
||||
|
||||
const properties = builder.getNodeProperties( this );
|
||||
properties.textureNode = textureNode;
|
||||
|
||||
//
|
||||
|
||||
return this._textureNode;
|
||||
|
||||
}
|
||||
|
||||
dispose() {
|
||||
|
||||
this._renderTarget.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const anamorphic = ( node, threshold = .9, scale = 3, samples = 32 ) => nodeObject( new AnamorphicNode( nodeObject( node ).toTexture(), nodeObject( threshold ), nodeObject( scale ), samples ) );
|
||||
|
||||
addNodeElement( 'anamorphic', anamorphic );
|
||||
|
||||
export default AnamorphicNode;
|
||||
|
128
site/game/node_modules/three/src/nodes/display/BlendModeNode.js
generated
vendored
Normal file
128
site/game/node_modules/three/src/nodes/display/BlendModeNode.js
generated
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { /*mix, step,*/ 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' ) );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'burnColor',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'base', type: 'vec3' },
|
||||
{ name: 'blend', type: 'vec3' }
|
||||
]
|
||||
} );
|
||||
|
||||
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' ) );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'dodgeColor',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'base', type: 'vec3' },
|
||||
{ name: 'blend', type: 'vec3' }
|
||||
]
|
||||
} );
|
||||
|
||||
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' ) );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'screenColor',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'base', type: 'vec3' },
|
||||
{ name: 'blend', type: 'vec3' }
|
||||
]
|
||||
} );
|
||||
|
||||
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() );
|
||||
//const fn = ( c ) => mix( base[ c ].oneMinus().mul( blend[ c ].oneMinus() ).oneMinus(), base[ c ].mul( blend[ c ], 2.0 ), step( base[ c ], 0.5 ) );
|
||||
|
||||
return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'overlayColor',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'base', type: 'vec3' },
|
||||
{ name: 'blend', type: 'vec3' }
|
||||
]
|
||||
} );
|
||||
|
||||
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 );
|
333
site/game/node_modules/three/src/nodes/display/BloomNode.js
generated
vendored
Normal file
333
site/game/node_modules/three/src/nodes/display/BloomNode.js
generated
vendored
Normal file
@ -0,0 +1,333 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { addNodeElement, tslFn, nodeObject, float, vec4, int } from '../shadernode/ShaderNode.js';
|
||||
import { mix, smoothstep } from '../math/MathNode.js';
|
||||
import { luminance } from './ColorAdjustmentNode.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { uniforms } from '../accessors/UniformsNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { Color } from '../../math/Color.js';
|
||||
import { passTexture } from './PassNode.js';
|
||||
import { RenderTarget } from '../../core/RenderTarget.js';
|
||||
import { HalfFloatType } from '../../constants.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
import { loop } from '../utils/LoopNode.js';
|
||||
import { add } from '../math/OperatorNode.js';
|
||||
import QuadMesh from '../../renderers/common/QuadMesh.js';
|
||||
import { texture } from '../accessors/TextureNode.js';
|
||||
import { Vector3 } from '../../math/Vector3.js';
|
||||
|
||||
const _quadMesh = /*@__PURE__*/ new QuadMesh();
|
||||
|
||||
const _clearColor = /*@__PURE__*/ new Color( 0, 0, 0 );
|
||||
const _currentClearColor = /*@__PURE__*/ new Color();
|
||||
const _size = /*@__PURE__*/ new Vector2();
|
||||
|
||||
const _BlurDirectionX = /*@__PURE__*/ new Vector2( 1.0, 0.0 );
|
||||
const _BlurDirectionY = /*@__PURE__*/ new Vector2( 0.0, 1.0 );
|
||||
|
||||
class BloomNode extends TempNode {
|
||||
|
||||
constructor( inputNode, strength = 1, radius = 0, threshold = 0 ) {
|
||||
|
||||
super();
|
||||
|
||||
this.inputNode = inputNode;
|
||||
this.strength = uniform( strength );
|
||||
this.radius = uniform( radius );
|
||||
this.threshold = uniform( threshold );
|
||||
|
||||
this.smoothWidth = uniform( 0.01 );
|
||||
|
||||
//
|
||||
|
||||
this._renderTargetsHorizontal = [];
|
||||
this._renderTargetsVertical = [];
|
||||
this._nMips = 5;
|
||||
|
||||
// render targets
|
||||
|
||||
this._renderTargetBright = new RenderTarget( 1, 1, { type: HalfFloatType } );
|
||||
this._renderTargetBright.texture.name = 'UnrealBloomPass.bright';
|
||||
this._renderTargetBright.texture.generateMipmaps = false;
|
||||
|
||||
for ( let i = 0; i < this._nMips; i ++ ) {
|
||||
|
||||
const renderTargetHorizontal = new RenderTarget( 1, 1, { type: HalfFloatType } );
|
||||
|
||||
renderTargetHorizontal.texture.name = 'UnrealBloomPass.h' + i;
|
||||
renderTargetHorizontal.texture.generateMipmaps = false;
|
||||
|
||||
this._renderTargetsHorizontal.push( renderTargetHorizontal );
|
||||
|
||||
const renderTargetVertical = new RenderTarget( 1, 1, { type: HalfFloatType } );
|
||||
|
||||
renderTargetVertical.texture.name = 'UnrealBloomPass.v' + i;
|
||||
renderTargetVertical.texture.generateMipmaps = false;
|
||||
|
||||
this._renderTargetsVertical.push( renderTargetVertical );
|
||||
|
||||
}
|
||||
|
||||
// materials
|
||||
|
||||
this._compositeMaterial = null;
|
||||
this._highPassFilterMaterial = null;
|
||||
this._separableBlurMaterials = [];
|
||||
|
||||
// pass and texture nodes
|
||||
|
||||
this._textureNodeBright = texture( this._renderTargetBright.texture );
|
||||
this._textureNodeBlur0 = texture( this._renderTargetsVertical[ 0 ].texture );
|
||||
this._textureNodeBlur1 = texture( this._renderTargetsVertical[ 1 ].texture );
|
||||
this._textureNodeBlur2 = texture( this._renderTargetsVertical[ 2 ].texture );
|
||||
this._textureNodeBlur3 = texture( this._renderTargetsVertical[ 3 ].texture );
|
||||
this._textureNodeBlur4 = texture( this._renderTargetsVertical[ 4 ].texture );
|
||||
|
||||
this._textureOutput = passTexture( this, this._renderTargetsHorizontal[ 0 ].texture );
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.FRAME;
|
||||
|
||||
}
|
||||
|
||||
getTextureNode() {
|
||||
|
||||
return this._textureOutput;
|
||||
|
||||
}
|
||||
|
||||
setSize( width, height ) {
|
||||
|
||||
let resx = Math.round( width / 2 );
|
||||
let resy = Math.round( height / 2 );
|
||||
|
||||
this._renderTargetBright.setSize( resx, resy );
|
||||
|
||||
for ( let i = 0; i < this._nMips; i ++ ) {
|
||||
|
||||
this._renderTargetsHorizontal[ i ].setSize( resx, resy );
|
||||
this._renderTargetsVertical[ i ].setSize( resx, resy );
|
||||
|
||||
this._separableBlurMaterials[ i ].invSize.value.set( 1 / resx, 1 / resy );
|
||||
|
||||
resx = Math.round( resx / 2 );
|
||||
resy = Math.round( resy / 2 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updateBefore( frame ) {
|
||||
|
||||
const { renderer } = frame;
|
||||
|
||||
const size = renderer.getDrawingBufferSize( _size );
|
||||
this.setSize( size.width, size.height );
|
||||
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentMRT = renderer.getMRT();
|
||||
renderer.getClearColor( _currentClearColor );
|
||||
const currentClearAlpha = renderer.getClearAlpha();
|
||||
|
||||
this.setSize( size.width, size.height );
|
||||
|
||||
renderer.setMRT( null );
|
||||
renderer.setClearColor( _clearColor, 0 );
|
||||
|
||||
// 1. Extract Bright Areas
|
||||
|
||||
renderer.setRenderTarget( this._renderTargetBright );
|
||||
_quadMesh.material = this._highPassFilterMaterial;
|
||||
_quadMesh.render( renderer );
|
||||
|
||||
// 2. Blur All the mips progressively
|
||||
|
||||
let inputRenderTarget = this._renderTargetBright;
|
||||
|
||||
for ( let i = 0; i < this._nMips; i ++ ) {
|
||||
|
||||
_quadMesh.material = this._separableBlurMaterials[ i ];
|
||||
|
||||
this._separableBlurMaterials[ i ].colorTexture.value = inputRenderTarget.texture;
|
||||
this._separableBlurMaterials[ i ].direction.value = _BlurDirectionX;
|
||||
renderer.setRenderTarget( this._renderTargetsHorizontal[ i ] );
|
||||
renderer.clear();
|
||||
_quadMesh.render( renderer );
|
||||
|
||||
this._separableBlurMaterials[ i ].colorTexture.value = this._renderTargetsHorizontal[ i ].texture;
|
||||
this._separableBlurMaterials[ i ].direction.value = _BlurDirectionY;
|
||||
renderer.setRenderTarget( this._renderTargetsVertical[ i ] );
|
||||
renderer.clear();
|
||||
_quadMesh.render( renderer );
|
||||
|
||||
inputRenderTarget = this._renderTargetsVertical[ i ];
|
||||
|
||||
}
|
||||
|
||||
// 3. Composite All the mips
|
||||
|
||||
renderer.setRenderTarget( this._renderTargetsHorizontal[ 0 ] );
|
||||
renderer.clear();
|
||||
_quadMesh.material = this._compositeMaterial;
|
||||
_quadMesh.render( renderer );
|
||||
|
||||
// restore
|
||||
|
||||
renderer.setRenderTarget( currentRenderTarget );
|
||||
renderer.setMRT( currentMRT );
|
||||
renderer.setClearColor( _currentClearColor, currentClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
// luminosity high pass material
|
||||
|
||||
const luminosityHighPass = tslFn( () => {
|
||||
|
||||
const texel = this.inputNode;
|
||||
const v = luminance( texel.rgb );
|
||||
|
||||
const alpha = smoothstep( this.threshold, this.threshold.add( this.smoothWidth ), v );
|
||||
|
||||
return mix( vec4( 0 ), texel, alpha );
|
||||
|
||||
} );
|
||||
|
||||
this._highPassFilterMaterial = this._highPassFilterMaterial || builder.createNodeMaterial();
|
||||
this._highPassFilterMaterial.fragmentNode = luminosityHighPass().context( builder.getSharedContext() );
|
||||
this._highPassFilterMaterial.needsUpdate = true;
|
||||
|
||||
// gaussian blur materials
|
||||
|
||||
const kernelSizeArray = [ 3, 5, 7, 9, 11 ];
|
||||
|
||||
for ( let i = 0; i < this._nMips; i ++ ) {
|
||||
|
||||
this._separableBlurMaterials.push( this._getSeperableBlurMaterial( builder, kernelSizeArray[ i ] ) );
|
||||
|
||||
}
|
||||
|
||||
// composite material
|
||||
|
||||
const bloomFactors = uniforms( [ 1.0, 0.8, 0.6, 0.4, 0.2 ] );
|
||||
const bloomTintColors = uniforms( [ new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ) ] );
|
||||
|
||||
const lerpBloomFactor = tslFn( ( [ factor, radius ] ) => {
|
||||
|
||||
const mirrorFactor = float( 1.2 ).sub( factor );
|
||||
return mix( factor, mirrorFactor, radius );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'lerpBloomFactor',
|
||||
type: 'float',
|
||||
inputs: [
|
||||
{ name: 'factor', type: 'float' },
|
||||
{ name: 'radius', type: 'float' },
|
||||
]
|
||||
} );
|
||||
|
||||
|
||||
const compositePass = tslFn( () => {
|
||||
|
||||
const color0 = lerpBloomFactor( bloomFactors.element( 0 ), this.radius ).mul( vec4( bloomTintColors.element( 0 ), 1.0 ) ).mul( this._textureNodeBlur0 );
|
||||
const color1 = lerpBloomFactor( bloomFactors.element( 1 ), this.radius ).mul( vec4( bloomTintColors.element( 1 ), 1.0 ) ).mul( this._textureNodeBlur1 );
|
||||
const color2 = lerpBloomFactor( bloomFactors.element( 2 ), this.radius ).mul( vec4( bloomTintColors.element( 2 ), 1.0 ) ).mul( this._textureNodeBlur2 );
|
||||
const color3 = lerpBloomFactor( bloomFactors.element( 3 ), this.radius ).mul( vec4( bloomTintColors.element( 3 ), 1.0 ) ).mul( this._textureNodeBlur3 );
|
||||
const color4 = lerpBloomFactor( bloomFactors.element( 4 ), this.radius ).mul( vec4( bloomTintColors.element( 4 ), 1.0 ) ).mul( this._textureNodeBlur4 );
|
||||
|
||||
const sum = color0.add( color1 ).add( color2 ).add( color3 ).add( color4 );
|
||||
|
||||
return sum.mul( this.strength );
|
||||
|
||||
} );
|
||||
|
||||
this._compositeMaterial = this._compositeMaterial || builder.createNodeMaterial();
|
||||
this._compositeMaterial.fragmentNode = compositePass().context( builder.getSharedContext() );
|
||||
this._compositeMaterial.needsUpdate = true;
|
||||
|
||||
//
|
||||
|
||||
return this._textureOutput;
|
||||
|
||||
}
|
||||
|
||||
dispose() {
|
||||
|
||||
for ( let i = 0; i < this._renderTargetsHorizontal.length; i ++ ) {
|
||||
|
||||
this._renderTargetsHorizontal[ i ].dispose();
|
||||
|
||||
}
|
||||
|
||||
for ( let i = 0; i < this._renderTargetsVertical.length; i ++ ) {
|
||||
|
||||
this._renderTargetsVertical[ i ].dispose();
|
||||
|
||||
}
|
||||
|
||||
this._renderTargetBright.dispose();
|
||||
|
||||
}
|
||||
|
||||
_getSeperableBlurMaterial( builder, kernelRadius ) {
|
||||
|
||||
const coefficients = [];
|
||||
|
||||
for ( let i = 0; i < kernelRadius; i ++ ) {
|
||||
|
||||
coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const colorTexture = texture();
|
||||
const gaussianCoefficients = uniforms( coefficients );
|
||||
const invSize = uniform( new Vector2() );
|
||||
const direction = uniform( new Vector2( 0.5, 0.5 ) );
|
||||
|
||||
const uvNode = uv();
|
||||
const sampleTexel = ( uv ) => colorTexture.uv( uv );
|
||||
|
||||
const seperableBlurPass = tslFn( () => {
|
||||
|
||||
const weightSum = gaussianCoefficients.element( 0 ).toVar();
|
||||
const diffuseSum = sampleTexel( uvNode ).rgb.mul( weightSum ).toVar();
|
||||
|
||||
loop( { start: int( 1 ), end: int( kernelRadius ), type: 'int', condition: '<' }, ( { i } ) => {
|
||||
|
||||
const x = float( i );
|
||||
const w = gaussianCoefficients.element( i );
|
||||
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 ) );
|
||||
|
||||
} );
|
||||
|
||||
return vec4( diffuseSum.div( weightSum ), 1.0 );
|
||||
|
||||
} );
|
||||
|
||||
const seperableBlurMaterial = builder.createNodeMaterial();
|
||||
seperableBlurMaterial.fragmentNode = seperableBlurPass().context( builder.getSharedContext() );
|
||||
seperableBlurMaterial.needsUpdate = true;
|
||||
|
||||
// uniforms
|
||||
seperableBlurMaterial.colorTexture = colorTexture;
|
||||
seperableBlurMaterial.direction = direction;
|
||||
seperableBlurMaterial.invSize = invSize;
|
||||
|
||||
return seperableBlurMaterial;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const bloom = ( node, strength, radius, threshold ) => nodeObject( new BloomNode( nodeObject( node ), strength, radius, threshold ) );
|
||||
|
||||
addNodeElement( 'bloom', bloom );
|
||||
|
||||
export default BloomNode;
|
80
site/game/node_modules/three/src/nodes/display/BumpMapNode.js
generated
vendored
Normal file
80
site/game/node_modules/three/src/nodes/display/BumpMapNode.js
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
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
|
||||
|
||||
const dHdxy_fwd = tslFn( ( { textureNode, bumpScale } ) => {
|
||||
|
||||
// It's used to preserve the same TextureNode instance
|
||||
const sampleTexture = ( callback ) => textureNode.cache().context( { getUV: ( texNode ) => callback( texNode.uvNode || uv() ), forceUVContext: true } );
|
||||
|
||||
const Hll = float( sampleTexture( ( uvNode ) => uvNode ) );
|
||||
|
||||
return vec2(
|
||||
float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ),
|
||||
float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdy() ) ) ).sub( Hll )
|
||||
).mul( bumpScale );
|
||||
|
||||
} );
|
||||
|
||||
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
|
||||
|
||||
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 );
|
104
site/game/node_modules/three/src/nodes/display/ColorAdjustmentNode.js
generated
vendored
Normal file
104
site/game/node_modules/three/src/nodes/display/ColorAdjustmentNode.js
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
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 } from '../shadernode/ShaderNode.js';
|
||||
import { ColorManagement } from '../../math/ColorManagement.js';
|
||||
import { Vector3 } from '../../math/Vector3.js';
|
||||
|
||||
const saturationNode = tslFn( ( { color, adjustment } ) => {
|
||||
|
||||
return adjustment.mix( luminance( color.rgb ), color.rgb );
|
||||
|
||||
} );
|
||||
|
||||
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.rgb, mx, amt );
|
||||
|
||||
} );
|
||||
|
||||
const hueNode = tslFn( ( { color, adjustment } ) => {
|
||||
|
||||
const k = vec3( 0.57735, 0.57735, 0.57735 );
|
||||
|
||||
const cosAngle = adjustment.cos();
|
||||
|
||||
return vec3( color.rgb.mul( cosAngle ).add( k.cross( color.rgb ).mul( adjustment.sin() ).add( k.mul( dot( k, color.rgb ).mul( cosAngle.oneMinus() ) ) ) ) );
|
||||
|
||||
} );
|
||||
|
||||
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 );
|
||||
|
||||
const _luminanceCoefficients = /*#__PURE__*/ new Vector3();
|
||||
export const luminance = (
|
||||
color,
|
||||
luminanceCoefficients = vec3( ... ColorManagement.getLuminanceCoefficients( _luminanceCoefficients ) )
|
||||
) => dot( color, luminanceCoefficients );
|
||||
|
||||
export const threshold = ( color, threshold ) => mix( vec3( 0.0 ), color, luminance( color ).sub( threshold ).max( 0 ) );
|
||||
|
||||
addNodeElement( 'saturation', saturation );
|
||||
addNodeElement( 'vibrance', vibrance );
|
||||
addNodeElement( 'hue', hue );
|
||||
addNodeElement( 'threshold', threshold );
|
||||
|
||||
addNodeClass( 'ColorAdjustmentNode', ColorAdjustmentNode );
|
108
site/game/node_modules/three/src/nodes/display/ColorSpaceNode.js
generated
vendored
Normal file
108
site/game/node_modules/three/src/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 '../../constants.js';
|
||||
|
||||
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 );
|
198
site/game/node_modules/three/src/nodes/display/DenoiseNode.js
generated
vendored
Normal file
198
site/game/node_modules/three/src/nodes/display/DenoiseNode.js
generated
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { addNodeElement, tslFn, nodeObject, float, int, vec2, vec3, vec4, mat2, If } from '../shadernode/ShaderNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { uniforms } from '../accessors/UniformsNode.js';
|
||||
import { abs, dot, sin, cos, PI, pow, max } from '../math/MathNode.js';
|
||||
import { loop } from '../utils/LoopNode.js';
|
||||
import { luminance } from './ColorAdjustmentNode.js';
|
||||
import { textureSize } from '../accessors/TextureSizeNode.js';
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
import { Vector3 } from '../../math/Vector3.js';
|
||||
|
||||
class DenoiseNode extends TempNode {
|
||||
|
||||
constructor( textureNode, depthNode, normalNode, noiseNode, camera ) {
|
||||
|
||||
super();
|
||||
|
||||
this.textureNode = textureNode;
|
||||
this.depthNode = depthNode;
|
||||
this.normalNode = normalNode;
|
||||
this.noiseNode = noiseNode;
|
||||
|
||||
this.cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse );
|
||||
this.lumaPhi = uniform( 5 );
|
||||
this.depthPhi = uniform( 5 );
|
||||
this.normalPhi = uniform( 5 );
|
||||
this.radius = uniform( 5 );
|
||||
this.index = uniform( 0 );
|
||||
|
||||
this._resolution = uniform( new Vector2() );
|
||||
this._sampleVectors = uniforms( generatePdSamplePointInitializer( 16, 2, 1 ) );
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.RENDER;
|
||||
|
||||
}
|
||||
|
||||
updateBefore() {
|
||||
|
||||
const map = this.textureNode.value;
|
||||
|
||||
this._resolution.value.set( map.image.width, map.image.height );
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const uvNode = uv();
|
||||
|
||||
const sampleTexture = ( uv ) => this.textureNode.uv( uv );
|
||||
const sampleDepth = ( uv ) => this.depthNode.uv( uv ).x;
|
||||
const sampleNormal = ( uv ) => this.normalNode.uv( uv );
|
||||
const sampleNoise = ( uv ) => this.noiseNode.uv( uv );
|
||||
|
||||
const getViewPosition = tslFn( ( [ screenPosition, depth ] ) => {
|
||||
|
||||
screenPosition = vec2( screenPosition.x, screenPosition.y.oneMinus() ).mul( 2.0 ).sub( 1.0 );
|
||||
|
||||
const clipSpacePosition = vec4( vec3( screenPosition, depth ), 1.0 );
|
||||
const viewSpacePosition = vec4( this.cameraProjectionMatrixInverse.mul( clipSpacePosition ) );
|
||||
|
||||
return viewSpacePosition.xyz.div( viewSpacePosition.w );
|
||||
|
||||
} );
|
||||
|
||||
const denoiseSample = tslFn( ( [ center, viewNormal, viewPosition, sampleUv ] ) => {
|
||||
|
||||
const texel = sampleTexture( sampleUv );
|
||||
const depth = sampleDepth( sampleUv );
|
||||
const normal = sampleNormal( sampleUv ).rgb.normalize();
|
||||
const neighborColor = texel.rgb;
|
||||
const viewPos = getViewPosition( sampleUv, depth );
|
||||
|
||||
const normalDiff = dot( viewNormal, normal ).toVar();
|
||||
const normalSimilarity = pow( max( normalDiff, 0 ), this.normalPhi ).toVar();
|
||||
const lumaDiff = abs( luminance( neighborColor ).sub( luminance( center ) ) ).toVar();
|
||||
const lumaSimilarity = max( float( 1.0 ).sub( lumaDiff.div( this.lumaPhi ) ), 0 ).toVar();
|
||||
const depthDiff = abs( dot( viewPosition.sub( viewPos ), viewNormal ) ).toVar();
|
||||
const depthSimilarity = max( float( 1.0 ).sub( depthDiff.div( this.depthPhi ) ), 0 );
|
||||
const w = lumaSimilarity.mul( depthSimilarity ).mul( normalSimilarity );
|
||||
|
||||
return vec4( neighborColor.mul( w ), w );
|
||||
|
||||
} );
|
||||
|
||||
const denoise = tslFn( ( [ uvNode ] ) => {
|
||||
|
||||
const depth = sampleDepth( uvNode );
|
||||
const viewNormal = sampleNormal( uvNode ).rgb.normalize();
|
||||
|
||||
const texel = sampleTexture( uvNode );
|
||||
|
||||
If( depth.greaterThanEqual( 1.0 ).or( dot( viewNormal, viewNormal ).equal( 0.0 ) ), () => {
|
||||
|
||||
return texel;
|
||||
|
||||
} );
|
||||
|
||||
const center = vec3( texel.rgb );
|
||||
|
||||
const viewPosition = getViewPosition( uvNode, depth );
|
||||
|
||||
const noiseResolution = textureSize( this.noiseNode, 0 );
|
||||
let noiseUv = vec2( uvNode.x, uvNode.y.oneMinus() );
|
||||
noiseUv = noiseUv.mul( this._resolution.div( noiseResolution ) );
|
||||
const noiseTexel = sampleNoise( noiseUv );
|
||||
|
||||
const x = sin( noiseTexel.element( this.index.mod( 4 ).mul( 2 ).mul( PI ) ) );
|
||||
const y = cos( noiseTexel.element( this.index.mod( 4 ).mul( 2 ).mul( PI ) ) );
|
||||
|
||||
const noiseVec = vec2( x, y );
|
||||
const rotationMatrix = mat2( noiseVec.x, noiseVec.y.negate(), noiseVec.x, noiseVec.y );
|
||||
|
||||
const totalWeight = float( 1.0 ).toVar();
|
||||
const denoised = vec3( texel.rgb ).toVar();
|
||||
|
||||
loop( { start: int( 0 ), end: int( 16 ), type: 'int', condition: '<' }, ( { i } ) => {
|
||||
|
||||
const sampleDir = this._sampleVectors.element( i ).toVar();
|
||||
const offset = rotationMatrix.mul( sampleDir.xy.mul( float( 1.0 ).add( sampleDir.z.mul( this.radius.sub( 1 ) ) ) ) ).div( this._resolution ).toVar();
|
||||
const sampleUv = uvNode.add( offset ).toVar();
|
||||
|
||||
const result = denoiseSample( center, viewNormal, viewPosition, sampleUv );
|
||||
|
||||
denoised.addAssign( result.xyz );
|
||||
totalWeight.addAssign( result.w );
|
||||
|
||||
} );
|
||||
|
||||
If( totalWeight.greaterThan( float( 0 ) ), () => {
|
||||
|
||||
denoised.divAssign( totalWeight );
|
||||
|
||||
} );
|
||||
|
||||
return vec4( denoised, texel.a );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'denoise',
|
||||
type: 'vec4',
|
||||
inputs: [
|
||||
{ name: 'uv', type: 'vec2' }
|
||||
]
|
||||
} );
|
||||
|
||||
const output = tslFn( () => {
|
||||
|
||||
return denoise( uvNode );
|
||||
|
||||
} );
|
||||
|
||||
const outputNode = output();
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function generatePdSamplePointInitializer( samples, rings, radiusExponent ) {
|
||||
|
||||
const poissonDisk = generateDenoiseSamples( samples, rings, radiusExponent );
|
||||
|
||||
const array = [];
|
||||
|
||||
for ( let i = 0; i < samples; i ++ ) {
|
||||
|
||||
const sample = poissonDisk[ i ];
|
||||
array.push( sample );
|
||||
|
||||
}
|
||||
|
||||
return array;
|
||||
|
||||
}
|
||||
|
||||
function generateDenoiseSamples( numSamples, numRings, radiusExponent ) {
|
||||
|
||||
const samples = [];
|
||||
|
||||
for ( let i = 0; i < numSamples; i ++ ) {
|
||||
|
||||
const angle = 2 * Math.PI * numRings * i / numSamples;
|
||||
const radius = Math.pow( i / ( numSamples - 1 ), radiusExponent );
|
||||
samples.push( new Vector3( Math.cos( angle ), Math.sin( angle ), radius ) );
|
||||
|
||||
}
|
||||
|
||||
return samples;
|
||||
|
||||
}
|
||||
|
||||
export const denoise = ( node, depthNode, normalNode, noiseNode, camera ) => nodeObject( new DenoiseNode( nodeObject( node ).toTexture(), nodeObject( depthNode ), nodeObject( normalNode ), nodeObject( noiseNode ), camera ) );
|
||||
|
||||
addNodeElement( 'denoise', denoise );
|
||||
|
||||
export default DenoiseNode;
|
119
site/game/node_modules/three/src/nodes/display/DepthOfFieldNode.js
generated
vendored
Normal file
119
site/game/node_modules/three/src/nodes/display/DepthOfFieldNode.js
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { addNodeElement, tslFn, nodeObject, vec2, vec4 } from '../shadernode/ShaderNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { clamp } from '../math/MathNode.js';
|
||||
|
||||
class DepthOfFieldNode extends TempNode {
|
||||
|
||||
constructor( textureNode, viewZNode, focusNode, apertureNode, maxblurNode ) {
|
||||
|
||||
super();
|
||||
|
||||
this.textureNode = textureNode;
|
||||
this.viewZNode = viewZNode;
|
||||
|
||||
this.focusNode = focusNode;
|
||||
this.apertureNode = apertureNode;
|
||||
this.maxblurNode = maxblurNode;
|
||||
|
||||
this._aspect = uniform( 0 );
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.RENDER;
|
||||
|
||||
}
|
||||
|
||||
updateBefore() {
|
||||
|
||||
const map = this.textureNode.value;
|
||||
|
||||
this._aspect.value = map.image.width / map.image.height;
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const textureNode = this.textureNode;
|
||||
const uvNode = textureNode.uvNode || uv();
|
||||
|
||||
const sampleTexture = ( uv ) => textureNode.uv( uv );
|
||||
|
||||
const dof = tslFn( () => {
|
||||
|
||||
const aspectcorrect = vec2( 1.0, this._aspect );
|
||||
|
||||
const factor = this.focusNode.add( this.viewZNode );
|
||||
|
||||
const dofblur = vec2( clamp( factor.mul( this.apertureNode ), this.maxblurNode.negate(), this.maxblurNode ) );
|
||||
|
||||
const dofblur9 = dofblur.mul( 0.9 );
|
||||
const dofblur7 = dofblur.mul( 0.7 );
|
||||
const dofblur4 = dofblur.mul( 0.4 );
|
||||
|
||||
let col = vec4( 0.0 );
|
||||
|
||||
col = col.add( sampleTexture( uvNode ) );
|
||||
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.40, 0.0 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.40, 0.0 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) );
|
||||
col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) );
|
||||
|
||||
col = col.div( 41 );
|
||||
col.a = 1;
|
||||
|
||||
return vec4( col );
|
||||
|
||||
|
||||
} );
|
||||
|
||||
const outputNode = dof();
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const dof = ( node, viewZNode, focus = 1, aperture = 0.025, maxblur = 1 ) => nodeObject( new DepthOfFieldNode( nodeObject( node ).toTexture(), nodeObject( viewZNode ), nodeObject( focus ), nodeObject( aperture ), nodeObject( maxblur ) ) );
|
||||
|
||||
addNodeElement( 'dof', dof );
|
||||
|
||||
export default DepthOfFieldNode;
|
75
site/game/node_modules/three/src/nodes/display/DotScreenNode.js
generated
vendored
Normal file
75
site/game/node_modules/three/src/nodes/display/DotScreenNode.js
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { nodeObject, addNodeElement, tslFn, vec2, vec3, vec4 } from '../shadernode/ShaderNode.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { sin, cos } from '../math/MathNode.js';
|
||||
import { add } from '../math/OperatorNode.js';
|
||||
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
|
||||
class DotScreenNode extends TempNode {
|
||||
|
||||
constructor( inputNode, center = new Vector2( 0.5, 0.5 ), angle = 1.57, scale = 1 ) {
|
||||
|
||||
super( 'vec4' );
|
||||
|
||||
this.inputNode = inputNode;
|
||||
this.center = uniform( center );
|
||||
this.angle = uniform( angle );
|
||||
this.scale = uniform( scale );
|
||||
|
||||
this._size = uniform( new Vector2() );
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.RENDER;
|
||||
|
||||
}
|
||||
|
||||
updateBefore( frame ) {
|
||||
|
||||
const { renderer } = frame;
|
||||
|
||||
renderer.getDrawingBufferSize( this._size.value );
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const inputNode = this.inputNode;
|
||||
|
||||
const pattern = tslFn( () => {
|
||||
|
||||
const s = sin( this.angle );
|
||||
const c = cos( this.angle );
|
||||
|
||||
const tex = uv().mul( this._size ).sub( this.center );
|
||||
const point = vec2( c.mul( tex.x ).sub( s.mul( tex.y ) ), s.mul( tex.x ).add( c.mul( tex.y ) ) ).mul( this.scale );
|
||||
|
||||
return sin( point.x ).mul( sin( point.y ) ).mul( 4 );
|
||||
|
||||
} );
|
||||
|
||||
const dotScreen = tslFn( () => {
|
||||
|
||||
const color = inputNode;
|
||||
|
||||
const average = add( color.r, color.g, color.b ).div( 3 );
|
||||
|
||||
return vec4( vec3( average.mul( 10 ).sub( 5 ).add( pattern() ) ), color.a );
|
||||
|
||||
} );
|
||||
|
||||
const outputNode = dotScreen();
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const dotScreen = ( node, center, angle, scale ) => nodeObject( new DotScreenNode( nodeObject( node ), center, angle, scale ) );
|
||||
|
||||
addNodeElement( 'dotScreen', dotScreen );
|
||||
|
||||
export default DotScreenNode;
|
||||
|
327
site/game/node_modules/three/src/nodes/display/FXAANode.js
generated
vendored
Normal file
327
site/game/node_modules/three/src/nodes/display/FXAANode.js
generated
vendored
Normal file
@ -0,0 +1,327 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { addNodeElement, tslFn, nodeObject, float, vec2, vec4, int, If } from '../shadernode/ShaderNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { abs, max, min, mix, pow } from '../math/MathNode.js';
|
||||
import { sub } from '../math/OperatorNode.js';
|
||||
import { loop, Break } from '../utils/LoopNode.js';
|
||||
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
|
||||
class FXAANode extends TempNode {
|
||||
|
||||
constructor( textureNode ) {
|
||||
|
||||
super();
|
||||
|
||||
this.textureNode = textureNode;
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.RENDER;
|
||||
|
||||
this._invSize = uniform( new Vector2() );
|
||||
|
||||
}
|
||||
|
||||
updateBefore() {
|
||||
|
||||
const map = this.textureNode.value;
|
||||
|
||||
this._invSize.value.set( 1 / map.image.width, 1 / map.image.height );
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const textureNode = this.textureNode.bias( - 100 );
|
||||
const uvNode = textureNode.uvNode || uv();
|
||||
|
||||
// FXAA 3.11 implementation by NVIDIA, ported to WebGL by Agost Biro (biro@archilogic.com)
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// File: es3-kepler\FXAA\assets\shaders/FXAA_DefaultES.frag
|
||||
// SDK Version: v3.00
|
||||
// Email: gameworks@nvidia.com
|
||||
// Site: http://developer.nvidia.com/
|
||||
//
|
||||
// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
const FxaaTexTop = ( p ) => textureNode.uv( p );
|
||||
const FxaaTexOff = ( p, o, r ) => textureNode.uv( p.add( o.mul( r ) ) );
|
||||
|
||||
const NUM_SAMPLES = int( 5 );
|
||||
|
||||
const contrast = tslFn( ( [ a_immutable, b_immutable ] ) => {
|
||||
|
||||
// assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha
|
||||
|
||||
const b = vec4( b_immutable ).toVar();
|
||||
const a = vec4( a_immutable ).toVar();
|
||||
const diff = vec4( abs( a.sub( b ) ) ).toVar();
|
||||
|
||||
return max( max( max( diff.r, diff.g ), diff.b ), diff.a );
|
||||
|
||||
} );
|
||||
|
||||
// FXAA3 QUALITY - PC
|
||||
|
||||
const FxaaPixelShader = tslFn( ( [ uv, fxaaQualityRcpFrame, fxaaQualityEdgeThreshold, fxaaQualityinvEdgeThreshold ] ) => {
|
||||
|
||||
const rgbaM = FxaaTexTop( uv ).toVar();
|
||||
const rgbaS = FxaaTexOff( uv, vec2( 0.0, - 1.0 ), fxaaQualityRcpFrame.xy ).toVar();
|
||||
const rgbaE = FxaaTexOff( uv, vec2( 1.0, 0.0 ), fxaaQualityRcpFrame.xy ).toVar();
|
||||
const rgbaN = FxaaTexOff( uv, vec2( 0.0, 1.0 ), fxaaQualityRcpFrame.xy ).toVar();
|
||||
const rgbaW = FxaaTexOff( uv, vec2( - 1.0, 0.0 ), fxaaQualityRcpFrame.xy ).toVar();
|
||||
// . S .
|
||||
// W M E
|
||||
// . N .
|
||||
|
||||
const contrastN = contrast( rgbaM, rgbaN ).toVar();
|
||||
const contrastS = contrast( rgbaM, rgbaS ).toVar();
|
||||
const contrastE = contrast( rgbaM, rgbaE ).toVar();
|
||||
const contrastW = contrast( rgbaM, rgbaW ).toVar();
|
||||
|
||||
const maxValue = max( contrastN, max( contrastS, max( contrastE, contrastW ) ) ).toVar();
|
||||
|
||||
// . 0 .
|
||||
// 0 0 0
|
||||
// . 0 .
|
||||
|
||||
If( maxValue.lessThan( fxaaQualityEdgeThreshold ), () => {
|
||||
|
||||
return rgbaM; // assuming define FXAA_DISCARD is always 0
|
||||
|
||||
} );
|
||||
|
||||
//
|
||||
|
||||
const relativeVContrast = sub( contrastN.add( contrastS ), ( contrastE.add( contrastW ) ) ).toVar();
|
||||
relativeVContrast.mulAssign( fxaaQualityinvEdgeThreshold );
|
||||
|
||||
// 45 deg edge detection and corners of objects, aka V/H contrast is too similar
|
||||
|
||||
If( abs( relativeVContrast ).lessThan( 0.3 ), () => {
|
||||
|
||||
// locate the edge
|
||||
|
||||
const x = contrastE.greaterThan( contrastW ).cond( 1, - 1 ).toVar();
|
||||
const y = contrastS.greaterThan( contrastN ).cond( 1, - 1 ).toVar();
|
||||
|
||||
const dirToEdge = vec2( x, y ).toVar();
|
||||
// . 2 . . 1 .
|
||||
// 1 0 2 ~= 0 0 1
|
||||
// . 1 . . 0 .
|
||||
|
||||
// tap 2 pixels and see which ones are "outside" the edge, to
|
||||
// determine if the edge is vertical or horizontal
|
||||
|
||||
const rgbaAlongH = FxaaTexOff( uv, vec2( dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy );
|
||||
const matchAlongH = contrast( rgbaM, rgbaAlongH ).toVar();
|
||||
// . 1 .
|
||||
// 0 0 1
|
||||
// . 0 H
|
||||
|
||||
const rgbaAlongV = FxaaTexOff( uv, vec2( dirToEdge.x.negate(), dirToEdge.y.negate() ), fxaaQualityRcpFrame.xy );
|
||||
const matchAlongV = contrast( rgbaM, rgbaAlongV ).toVar();
|
||||
// V 1 .
|
||||
// 0 0 1
|
||||
// . 0 .
|
||||
|
||||
relativeVContrast.assign( matchAlongV.sub( matchAlongH ) );
|
||||
relativeVContrast.mulAssign( fxaaQualityinvEdgeThreshold );
|
||||
|
||||
If( abs( relativeVContrast ).lessThan( 0.3 ), () => { // 45 deg edge
|
||||
|
||||
// 1 1 .
|
||||
// 0 0 1
|
||||
// . 0 1
|
||||
|
||||
// do a simple blur
|
||||
const sum = rgbaN.add( rgbaS ).add( rgbaE ).add( rgbaW );
|
||||
return mix( rgbaM, sum.mul( 0.25 ), 0.4 );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
const offNP = vec2().toVar();
|
||||
|
||||
If( relativeVContrast.lessThanEqual( 0 ), () => {
|
||||
|
||||
rgbaN.assign( rgbaW );
|
||||
rgbaS.assign( rgbaE );
|
||||
|
||||
// . 0 . 1
|
||||
// 1 0 1 -> 0
|
||||
// . 0 . 1
|
||||
|
||||
offNP.x.assign( 0 );
|
||||
offNP.y.assign( fxaaQualityRcpFrame.y );
|
||||
|
||||
} ).else( () => {
|
||||
|
||||
offNP.x.assign( fxaaQualityRcpFrame.x );
|
||||
offNP.y.assign( 0 );
|
||||
|
||||
} );
|
||||
|
||||
const mn = contrast( rgbaM, rgbaN ).toVar();
|
||||
const ms = contrast( rgbaM, rgbaS ).toVar();
|
||||
|
||||
If( mn.lessThanEqual( ms ), () => {
|
||||
|
||||
rgbaN.assign( rgbaS );
|
||||
|
||||
} );
|
||||
|
||||
const doneN = int( 0 ).toVar();
|
||||
const doneP = int( 0 ).toVar();
|
||||
|
||||
const nDist = float( 0 ).toVar();
|
||||
const pDist = float( 0 ).toVar();
|
||||
|
||||
const posN = vec2( uv ).toVar();
|
||||
const posP = vec2( uv ).toVar();
|
||||
|
||||
const iterationsUsedN = int( 0 ).toVar();
|
||||
const iterationsUsedP = int( 0 ).toVar();
|
||||
|
||||
loop( NUM_SAMPLES, ( { i } ) => {
|
||||
|
||||
const increment = i.add( 1 ).toVar();
|
||||
|
||||
If( doneN.equal( 0 ), () => {
|
||||
|
||||
nDist.addAssign( increment );
|
||||
posN.assign( uv.add( offNP.mul( nDist ) ) );
|
||||
const rgbaEndN = FxaaTexTop( posN.xy );
|
||||
|
||||
const nm = contrast( rgbaEndN, rgbaM ).toVar();
|
||||
const nn = contrast( rgbaEndN, rgbaN ).toVar();
|
||||
|
||||
If( nm.greaterThan( nn ), () => {
|
||||
|
||||
doneN.assign( 1 );
|
||||
|
||||
} );
|
||||
|
||||
iterationsUsedN.assign( i );
|
||||
|
||||
} );
|
||||
|
||||
If( doneP.equal( 0 ), () => {
|
||||
|
||||
pDist.addAssign( increment );
|
||||
posP.assign( uv.sub( offNP.mul( pDist ) ) );
|
||||
const rgbaEndP = FxaaTexTop( posP.xy );
|
||||
|
||||
const pm = contrast( rgbaEndP, rgbaM ).toVar();
|
||||
const pn = contrast( rgbaEndP, rgbaN ).toVar();
|
||||
|
||||
If( pm.greaterThan( pn ), () => {
|
||||
|
||||
doneP.assign( 1 );
|
||||
|
||||
} );
|
||||
|
||||
iterationsUsedP.assign( i );
|
||||
|
||||
} );
|
||||
|
||||
If( doneN.equal( 1 ).or( doneP.equal( 1 ) ), () => {
|
||||
|
||||
Break();
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
If( doneN.equal( 0 ).and( doneP.equal( 0 ) ), () => {
|
||||
|
||||
return rgbaM; // failed to find end of edge
|
||||
|
||||
} );
|
||||
|
||||
const distN = float( 1 ).toVar();
|
||||
const distP = float( 1 ).toVar();
|
||||
|
||||
If( doneN.equal( 1 ), () => {
|
||||
|
||||
distN.assign( float( iterationsUsedN ).div( float( NUM_SAMPLES.sub( 1 ) ) ) );
|
||||
|
||||
} );
|
||||
|
||||
If( doneP.equal( 1 ), () => {
|
||||
|
||||
distP.assign( float( iterationsUsedP ).div( float( NUM_SAMPLES.sub( 1 ) ) ) );
|
||||
|
||||
} );
|
||||
|
||||
const dist = min( distN, distP );
|
||||
|
||||
// hacky way of reduces blurriness of mostly diagonal edges
|
||||
// but reduces AA quality
|
||||
dist.assign( pow( dist, 0.5 ) );
|
||||
dist.assign( float( 1 ).sub( dist ) );
|
||||
|
||||
return mix( rgbaM, rgbaN, dist.mul( 0.5 ) );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'FxaaPixelShader',
|
||||
type: 'vec4',
|
||||
inputs: [
|
||||
{ name: 'uv', type: 'vec2' },
|
||||
{ name: 'fxaaQualityRcpFrame', type: 'vec2' },
|
||||
{ name: 'fxaaQualityEdgeThreshold', type: 'float' },
|
||||
{ name: 'fxaaQualityinvEdgeThreshold', type: 'float' },
|
||||
]
|
||||
} );
|
||||
|
||||
const fxaa = tslFn( () => {
|
||||
|
||||
const edgeDetectionQuality = float( 0.2 );
|
||||
const invEdgeDetectionQuality = float( 1 ).div( edgeDetectionQuality );
|
||||
|
||||
return FxaaPixelShader( uvNode, this._invSize, edgeDetectionQuality, invEdgeDetectionQuality );
|
||||
|
||||
} );
|
||||
|
||||
const outputNode = fxaa();
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const fxaa = ( node ) => nodeObject( new FXAANode( nodeObject( node ).toTexture() ) );
|
||||
|
||||
addNodeElement( 'fxaa', fxaa );
|
||||
|
||||
export default FXAANode;
|
52
site/game/node_modules/three/src/nodes/display/FilmNode.js
generated
vendored
Normal file
52
site/game/node_modules/three/src/nodes/display/FilmNode.js
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { addNodeElement, tslFn, nodeProxy, vec4 } from '../shadernode/ShaderNode.js';
|
||||
import { mix, fract, clamp, rand } from '../math/MathNode.js';
|
||||
import { timerLocal } from '../utils/TimerNode.js';
|
||||
|
||||
class FilmNode extends TempNode {
|
||||
|
||||
constructor( inputNode, intensityNode = null, uvNode = null ) {
|
||||
|
||||
super();
|
||||
|
||||
this.inputNode = inputNode;
|
||||
this.intensityNode = intensityNode;
|
||||
this.uvNode = uvNode;
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const uvNode = this.uvNode || uv();
|
||||
|
||||
const film = tslFn( () => {
|
||||
|
||||
const base = this.inputNode.rgb;
|
||||
const noise = rand( fract( uvNode.add( timerLocal() ) ) );
|
||||
|
||||
let color = base.add( base.mul( clamp( noise.add( 0.1 ), 0, 1 ) ) );
|
||||
|
||||
if ( this.intensityNode !== null ) {
|
||||
|
||||
color = mix( base, color, this.intensityNode );
|
||||
|
||||
}
|
||||
|
||||
return vec4( color, this.inputNode.a );
|
||||
|
||||
} );
|
||||
|
||||
const outputNode = film();
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const film = nodeProxy( FilmNode );
|
||||
|
||||
addNodeElement( 'film', film );
|
||||
|
||||
export default FilmNode;
|
41
site/game/node_modules/three/src/nodes/display/FrontFacingNode.js
generated
vendored
Normal file
41
site/game/node_modules/three/src/nodes/display/FrontFacingNode.js
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
import Node, { addNodeClass } from '../core/Node.js';
|
||||
import { nodeImmutable, float } from '../shadernode/ShaderNode.js';
|
||||
|
||||
import { BackSide, WebGLCoordinateSystem } from '../../constants.js';
|
||||
|
||||
class FrontFacingNode extends Node {
|
||||
|
||||
constructor() {
|
||||
|
||||
super( 'bool' );
|
||||
|
||||
this.isFrontFacingNode = true;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const { renderer, material } = builder;
|
||||
|
||||
if ( renderer.coordinateSystem === WebGLCoordinateSystem ) {
|
||||
|
||||
if ( material.side === BackSide ) {
|
||||
|
||||
return 'false';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 );
|
324
site/game/node_modules/three/src/nodes/display/GTAONode.js
generated
vendored
Normal file
324
site/game/node_modules/three/src/nodes/display/GTAONode.js
generated
vendored
Normal file
@ -0,0 +1,324 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { texture } from '../accessors/TextureNode.js';
|
||||
import { textureSize } from '../accessors/TextureSizeNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { addNodeElement, nodeObject, tslFn, mat3, vec2, vec3, vec4, float, int, If } from '../shadernode/ShaderNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { DataTexture } from '../../textures/DataTexture.js';
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
import { Vector3 } from '../../math/Vector3.js';
|
||||
import { PI, cos, sin, pow, clamp, abs, max, mix, sqrt, acos, dot, normalize, cross } from '../math/MathNode.js';
|
||||
import { div, mul, add, sub } from '../math/OperatorNode.js';
|
||||
import { loop } from '../utils/LoopNode.js';
|
||||
import { passTexture } from './PassNode.js';
|
||||
import { RepeatWrapping } from '../../constants.js';
|
||||
import QuadMesh from '../../renderers/common/QuadMesh.js';
|
||||
import { RenderTarget } from '../../core/RenderTarget.js';
|
||||
import { Color } from '../../math/Color.js';
|
||||
|
||||
const _quadMesh = /*@__PURE__*/ new QuadMesh();
|
||||
const _currentClearColor = /*@__PURE__*/ new Color();
|
||||
const _size = /*@__PURE__*/ new Vector2();
|
||||
|
||||
class GTAONode extends TempNode {
|
||||
|
||||
constructor( depthNode, normalNode, camera ) {
|
||||
|
||||
super();
|
||||
|
||||
this.depthNode = depthNode;
|
||||
this.normalNode = normalNode;
|
||||
|
||||
this.radius = uniform( 0.25 );
|
||||
this.resolution = uniform( new Vector2() );
|
||||
this.thickness = uniform( 1 );
|
||||
this.distanceExponent = uniform( 1 );
|
||||
this.distanceFallOff = uniform( 1 );
|
||||
this.scale = uniform( 1 );
|
||||
this.noiseNode = texture( generateMagicSquareNoise() );
|
||||
|
||||
this.cameraProjectionMatrix = uniform( camera.projectionMatrix );
|
||||
this.cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse );
|
||||
|
||||
this.SAMPLES = uniform( 16 );
|
||||
|
||||
this._aoRenderTarget = new RenderTarget();
|
||||
this._aoRenderTarget.texture.name = 'GTAONode.AO';
|
||||
|
||||
this._material = null;
|
||||
this._textureNode = passTexture( this, this._aoRenderTarget.texture );
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.FRAME;
|
||||
|
||||
}
|
||||
|
||||
getTextureNode() {
|
||||
|
||||
return this._textureNode;
|
||||
|
||||
}
|
||||
|
||||
setSize( width, height ) {
|
||||
|
||||
this.resolution.value.set( width, height );
|
||||
this._aoRenderTarget.setSize( width, height );
|
||||
|
||||
}
|
||||
|
||||
updateBefore( frame ) {
|
||||
|
||||
const { renderer } = frame;
|
||||
|
||||
const size = renderer.getDrawingBufferSize( _size );
|
||||
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentMRT = renderer.getMRT();
|
||||
renderer.getClearColor( _currentClearColor );
|
||||
const currentClearAlpha = renderer.getClearAlpha();
|
||||
|
||||
_quadMesh.material = this._material;
|
||||
|
||||
this.setSize( size.width, size.height );
|
||||
|
||||
// clear
|
||||
|
||||
renderer.setMRT( null );
|
||||
renderer.setClearColor( 0xffffff, 1 );
|
||||
|
||||
// ao
|
||||
|
||||
renderer.setRenderTarget( this._aoRenderTarget );
|
||||
_quadMesh.render( renderer );
|
||||
|
||||
// restore
|
||||
|
||||
renderer.setRenderTarget( currentRenderTarget );
|
||||
renderer.setMRT( currentMRT );
|
||||
renderer.setClearColor( _currentClearColor, currentClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
const uvNode = uv();
|
||||
|
||||
const sampleDepth = ( uv ) => this.depthNode.uv( uv ).x;
|
||||
const sampleNoise = ( uv ) => this.noiseNode.uv( uv );
|
||||
|
||||
const getSceneUvAndDepth = tslFn( ( [ sampleViewPos ] )=> {
|
||||
|
||||
const sampleClipPos = this.cameraProjectionMatrix.mul( vec4( sampleViewPos, 1.0 ) );
|
||||
let sampleUv = sampleClipPos.xy.div( sampleClipPos.w ).mul( 0.5 ).add( 0.5 ).toVar();
|
||||
sampleUv = vec2( sampleUv.x, sampleUv.y.oneMinus() );
|
||||
const sampleSceneDepth = sampleDepth( sampleUv );
|
||||
return vec3( sampleUv, sampleSceneDepth );
|
||||
|
||||
} );
|
||||
|
||||
const getViewPosition = tslFn( ( [ screenPosition, depth ] ) => {
|
||||
|
||||
screenPosition = vec2( screenPosition.x, screenPosition.y.oneMinus() ).mul( 2.0 ).sub( 1.0 );
|
||||
|
||||
const clipSpacePosition = vec4( vec3( screenPosition, depth ), 1.0 );
|
||||
const viewSpacePosition = vec4( this.cameraProjectionMatrixInverse.mul( clipSpacePosition ) );
|
||||
|
||||
return viewSpacePosition.xyz.div( viewSpacePosition.w );
|
||||
|
||||
} );
|
||||
|
||||
const ao = tslFn( () => {
|
||||
|
||||
const depth = sampleDepth( uvNode );
|
||||
|
||||
depth.greaterThanEqual( 1.0 ).discard();
|
||||
|
||||
const viewPosition = getViewPosition( uvNode, depth );
|
||||
const viewNormal = this.normalNode.rgb.normalize();
|
||||
|
||||
const radiusToUse = this.radius;
|
||||
|
||||
const noiseResolution = textureSize( this.noiseNode, 0 );
|
||||
let noiseUv = vec2( uvNode.x, uvNode.y.oneMinus() );
|
||||
noiseUv = noiseUv.mul( this.resolution.div( noiseResolution ) );
|
||||
const noiseTexel = sampleNoise( noiseUv );
|
||||
const randomVec = noiseTexel.xyz.mul( 2.0 ).sub( 1.0 );
|
||||
const tangent = vec3( randomVec.xy, 0.0 ).normalize();
|
||||
const bitangent = vec3( tangent.y.mul( - 1.0 ), tangent.x, 0.0 );
|
||||
const kernelMatrix = mat3( tangent, bitangent, vec3( 0.0, 0.0, 1.0 ) );
|
||||
|
||||
const DIRECTIONS = this.SAMPLES.lessThan( 30 ).cond( 3, 5 );
|
||||
const STEPS = add( this.SAMPLES, DIRECTIONS.sub( 1 ) ).div( DIRECTIONS );
|
||||
|
||||
const ao = float( 0 ).toVar();
|
||||
|
||||
loop( { start: int( 0 ), end: DIRECTIONS, type: 'int', condition: '<' }, ( { i } ) => {
|
||||
|
||||
const angle = float( i ).div( float( DIRECTIONS ) ).mul( PI );
|
||||
const sampleDir = vec4( cos( angle ), sin( angle ), 0., add( 0.5, mul( 0.5, noiseTexel.w ) ) );
|
||||
sampleDir.xyz = normalize( kernelMatrix.mul( sampleDir.xyz ) );
|
||||
|
||||
const viewDir = normalize( viewPosition.xyz.negate() );
|
||||
const sliceBitangent = normalize( cross( sampleDir.xyz, viewDir ) );
|
||||
const sliceTangent = cross( sliceBitangent, viewDir );
|
||||
const normalInSlice = normalize( viewNormal.sub( sliceBitangent.mul( dot( viewNormal, sliceBitangent ) ) ) );
|
||||
|
||||
const tangentToNormalInSlice = cross( normalInSlice, sliceBitangent );
|
||||
const cosHorizons = vec2( dot( viewDir, tangentToNormalInSlice ), dot( viewDir, tangentToNormalInSlice.negate() ) ).toVar();
|
||||
|
||||
loop( { end: STEPS, type: 'int', name: 'j', condition: '<' }, ( { j } ) => {
|
||||
|
||||
const sampleViewOffset = sampleDir.xyz.mul( radiusToUse ).mul( sampleDir.w ).mul( pow( div( float( j ).add( 1.0 ), float( STEPS ) ), this.distanceExponent ) );
|
||||
|
||||
// x
|
||||
|
||||
const sampleSceneUvDepthX = getSceneUvAndDepth( viewPosition.add( sampleViewOffset ) );
|
||||
const sampleSceneViewPositionX = getViewPosition( sampleSceneUvDepthX.xy, sampleSceneUvDepthX.z );
|
||||
const viewDeltaX = sampleSceneViewPositionX.sub( viewPosition );
|
||||
|
||||
If( abs( viewDeltaX.z ).lessThan( this.thickness ), () => {
|
||||
|
||||
const sampleCosHorizon = dot( viewDir, normalize( viewDeltaX ) );
|
||||
cosHorizons.x.addAssign( max( 0, mul( sampleCosHorizon.sub( cosHorizons.x ), mix( 1.0, float( 2.0 ).div( float( j ).add( 2 ) ), this.distanceFallOff ) ) ) );
|
||||
|
||||
} );
|
||||
|
||||
// y
|
||||
|
||||
const sampleSceneUvDepthY = getSceneUvAndDepth( viewPosition.sub( sampleViewOffset ) );
|
||||
const sampleSceneViewPositionY = getViewPosition( sampleSceneUvDepthY.xy, sampleSceneUvDepthY.z );
|
||||
const viewDeltaY = sampleSceneViewPositionY.sub( viewPosition );
|
||||
|
||||
If( abs( viewDeltaY.z ).lessThan( this.thickness ), () => {
|
||||
|
||||
const sampleCosHorizon = dot( viewDir, normalize( viewDeltaY ) );
|
||||
cosHorizons.y.addAssign( max( 0, mul( sampleCosHorizon.sub( cosHorizons.y ), mix( 1.0, float( 2.0 ).div( float( j ).add( 2 ) ), this.distanceFallOff ) ) ) );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
const sinHorizons = sqrt( sub( 1.0, cosHorizons.mul( cosHorizons ) ) );
|
||||
const nx = dot( normalInSlice, sliceTangent );
|
||||
const ny = dot( normalInSlice, viewDir );
|
||||
const nxb = mul( 0.5, acos( cosHorizons.y ).sub( acos( cosHorizons.x ) ).add( sinHorizons.x.mul( cosHorizons.x ).sub( sinHorizons.y.mul( cosHorizons.y ) ) ) );
|
||||
const nyb = mul( 0.5, sub( 2.0, cosHorizons.x.mul( cosHorizons.x ) ).sub( cosHorizons.y.mul( cosHorizons.y ) ) );
|
||||
const occlusion = nx.mul( nxb ).add( ny.mul( nyb ) );
|
||||
ao.addAssign( occlusion );
|
||||
|
||||
} );
|
||||
|
||||
ao.assign( clamp( ao.div( DIRECTIONS ), 0, 1 ) );
|
||||
ao.assign( pow( ao, this.scale ) );
|
||||
|
||||
return vec4( vec3( ao ), 1.0 );
|
||||
|
||||
} );
|
||||
|
||||
const material = this._material || ( this._material = builder.createNodeMaterial() );
|
||||
material.fragmentNode = ao().context( builder.getSharedContext() );
|
||||
material.needsUpdate = true;
|
||||
|
||||
//
|
||||
|
||||
return this._textureNode;
|
||||
|
||||
}
|
||||
|
||||
dispose() {
|
||||
|
||||
this._aoRenderTarget.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function generateMagicSquareNoise( size = 5 ) {
|
||||
|
||||
const noiseSize = Math.floor( size ) % 2 === 0 ? Math.floor( size ) + 1 : Math.floor( size );
|
||||
const magicSquare = generateMagicSquare( noiseSize );
|
||||
const noiseSquareSize = magicSquare.length;
|
||||
const data = new Uint8Array( noiseSquareSize * 4 );
|
||||
|
||||
for ( let inx = 0; inx < noiseSquareSize; ++ inx ) {
|
||||
|
||||
const iAng = magicSquare[ inx ];
|
||||
const angle = ( 2 * Math.PI * iAng ) / noiseSquareSize;
|
||||
const randomVec = new Vector3(
|
||||
Math.cos( angle ),
|
||||
Math.sin( angle ),
|
||||
0
|
||||
).normalize();
|
||||
data[ inx * 4 ] = ( randomVec.x * 0.5 + 0.5 ) * 255;
|
||||
data[ inx * 4 + 1 ] = ( randomVec.y * 0.5 + 0.5 ) * 255;
|
||||
data[ inx * 4 + 2 ] = 127;
|
||||
data[ inx * 4 + 3 ] = 255;
|
||||
|
||||
}
|
||||
|
||||
const noiseTexture = new DataTexture( data, noiseSize, noiseSize );
|
||||
noiseTexture.wrapS = RepeatWrapping;
|
||||
noiseTexture.wrapT = RepeatWrapping;
|
||||
noiseTexture.needsUpdate = true;
|
||||
|
||||
return noiseTexture;
|
||||
|
||||
}
|
||||
|
||||
function generateMagicSquare( size ) {
|
||||
|
||||
const noiseSize = Math.floor( size ) % 2 === 0 ? Math.floor( size ) + 1 : Math.floor( size );
|
||||
const noiseSquareSize = noiseSize * noiseSize;
|
||||
const magicSquare = Array( noiseSquareSize ).fill( 0 );
|
||||
let i = Math.floor( noiseSize / 2 );
|
||||
let j = noiseSize - 1;
|
||||
|
||||
for ( let num = 1; num <= noiseSquareSize; ) {
|
||||
|
||||
if ( i === - 1 && j === noiseSize ) {
|
||||
|
||||
j = noiseSize - 2;
|
||||
i = 0;
|
||||
|
||||
} else {
|
||||
|
||||
if ( j === noiseSize ) {
|
||||
|
||||
j = 0;
|
||||
|
||||
}
|
||||
|
||||
if ( i < 0 ) {
|
||||
|
||||
i = noiseSize - 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( magicSquare[ i * noiseSize + j ] !== 0 ) {
|
||||
|
||||
j -= 2;
|
||||
i ++;
|
||||
continue;
|
||||
|
||||
} else {
|
||||
|
||||
magicSquare[ i * noiseSize + j ] = num ++;
|
||||
|
||||
}
|
||||
|
||||
j ++;
|
||||
i --;
|
||||
|
||||
}
|
||||
|
||||
return magicSquare;
|
||||
|
||||
}
|
||||
|
||||
export const ao = ( depthNode, normalNode, camera ) => nodeObject( new GTAONode( nodeObject( depthNode ), nodeObject( normalNode ), camera ) );
|
||||
|
||||
addNodeElement( 'ao', ao );
|
||||
|
||||
export default GTAONode;
|
207
site/game/node_modules/three/src/nodes/display/GaussianBlurNode.js
generated
vendored
Normal file
207
site/game/node_modules/three/src/nodes/display/GaussianBlurNode.js
generated
vendored
Normal file
@ -0,0 +1,207 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { nodeObject, addNodeElement, tslFn, float, vec2, vec4 } from '../shadernode/ShaderNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { mul } from '../math/OperatorNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { passTexture } from './PassNode.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import QuadMesh from '../../renderers/common/QuadMesh.js';
|
||||
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
import { RenderTarget } from '../../core/RenderTarget.js';
|
||||
|
||||
// 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.
|
||||
|
||||
const _quadMesh1 = /*@__PURE__*/ new QuadMesh();
|
||||
const _quadMesh2 = /*@__PURE__*/ new QuadMesh();
|
||||
|
||||
class GaussianBlurNode extends TempNode {
|
||||
|
||||
constructor( textureNode, directionNode = null, sigma = 2 ) {
|
||||
|
||||
super( 'vec4' );
|
||||
|
||||
this.textureNode = textureNode;
|
||||
this.directionNode = directionNode;
|
||||
this.sigma = sigma;
|
||||
|
||||
this._invSize = uniform( new Vector2() );
|
||||
this._passDirection = uniform( new Vector2() );
|
||||
|
||||
this._horizontalRT = new RenderTarget();
|
||||
this._horizontalRT.texture.name = 'GaussianBlurNode.horizontal';
|
||||
this._verticalRT = new RenderTarget();
|
||||
this._verticalRT.texture.name = 'GaussianBlurNode.vertical';
|
||||
|
||||
this._textureNode = passTexture( this, this._verticalRT.texture );
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.RENDER;
|
||||
|
||||
this.resolution = new Vector2( 1, 1 );
|
||||
|
||||
}
|
||||
|
||||
setSize( width, height ) {
|
||||
|
||||
width = Math.max( Math.round( width * this.resolution.x ), 1 );
|
||||
height = Math.max( Math.round( height * this.resolution.y ), 1 );
|
||||
|
||||
this._invSize.value.set( 1 / width, 1 / height );
|
||||
this._horizontalRT.setSize( width, height );
|
||||
this._verticalRT.setSize( width, height );
|
||||
|
||||
}
|
||||
|
||||
updateBefore( frame ) {
|
||||
|
||||
const { renderer } = frame;
|
||||
|
||||
const textureNode = this.textureNode;
|
||||
const map = textureNode.value;
|
||||
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentMRT = renderer.getMRT();
|
||||
|
||||
const currentTexture = textureNode.value;
|
||||
|
||||
_quadMesh1.material = this._material;
|
||||
_quadMesh2.material = this._material;
|
||||
|
||||
this.setSize( map.image.width, map.image.height );
|
||||
|
||||
const textureType = map.type;
|
||||
|
||||
this._horizontalRT.texture.type = textureType;
|
||||
this._verticalRT.texture.type = textureType;
|
||||
|
||||
// clear
|
||||
|
||||
renderer.setMRT( null );
|
||||
|
||||
// horizontal
|
||||
|
||||
renderer.setRenderTarget( this._horizontalRT );
|
||||
|
||||
this._passDirection.value.set( 1, 0 );
|
||||
|
||||
_quadMesh1.render( renderer );
|
||||
|
||||
// vertical
|
||||
|
||||
textureNode.value = this._horizontalRT.texture;
|
||||
renderer.setRenderTarget( this._verticalRT );
|
||||
|
||||
this._passDirection.value.set( 0, 1 );
|
||||
|
||||
_quadMesh2.render( renderer );
|
||||
|
||||
// restore
|
||||
|
||||
renderer.setRenderTarget( currentRenderTarget );
|
||||
renderer.setMRT( currentMRT );
|
||||
textureNode.value = currentTexture;
|
||||
|
||||
}
|
||||
|
||||
getTextureNode() {
|
||||
|
||||
return this._textureNode;
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
const textureNode = this.textureNode;
|
||||
|
||||
if ( textureNode.isTextureNode !== true ) {
|
||||
|
||||
console.error( 'GaussianBlurNode requires a TextureNode.' );
|
||||
|
||||
return vec4();
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const uvNode = textureNode.uvNode || uv();
|
||||
const directionNode = vec2( this.directionNode || 1 );
|
||||
|
||||
const sampleTexture = ( uv ) => textureNode.uv( uv );
|
||||
|
||||
const blur = tslFn( () => {
|
||||
|
||||
const kernelSize = 3 + ( 2 * this.sigma );
|
||||
const gaussianCoefficients = this._getCoefficients( kernelSize );
|
||||
|
||||
const invSize = this._invSize;
|
||||
const direction = directionNode.mul( this._passDirection );
|
||||
|
||||
const weightSum = float( gaussianCoefficients[ 0 ] ).toVar();
|
||||
const diffuseSum = vec4( sampleTexture( uvNode ).mul( weightSum ) ).toVar();
|
||||
|
||||
for ( let i = 1; i < kernelSize; i ++ ) {
|
||||
|
||||
const x = float( i );
|
||||
const w = float( gaussianCoefficients[ i ] );
|
||||
|
||||
const uvOffset = vec2( direction.mul( invSize.mul( x ) ) ).toVar();
|
||||
|
||||
const sample1 = vec4( sampleTexture( uvNode.add( uvOffset ) ) );
|
||||
const sample2 = vec4( sampleTexture( uvNode.sub( uvOffset ) ) );
|
||||
|
||||
diffuseSum.addAssign( sample1.add( sample2 ).mul( w ) );
|
||||
weightSum.addAssign( mul( 2.0, w ) );
|
||||
|
||||
}
|
||||
|
||||
return diffuseSum.div( weightSum );
|
||||
|
||||
} );
|
||||
|
||||
//
|
||||
|
||||
const material = this._material || ( this._material = builder.createNodeMaterial() );
|
||||
material.fragmentNode = blur().context( builder.getSharedContext() );
|
||||
material.needsUpdate = true;
|
||||
|
||||
//
|
||||
|
||||
const properties = builder.getNodeProperties( this );
|
||||
properties.textureNode = textureNode;
|
||||
|
||||
//
|
||||
|
||||
return this._textureNode;
|
||||
|
||||
}
|
||||
|
||||
dispose() {
|
||||
|
||||
this._horizontalRT.dispose();
|
||||
this._verticalRT.dispose();
|
||||
|
||||
}
|
||||
|
||||
_getCoefficients( kernelRadius ) {
|
||||
|
||||
const coefficients = [];
|
||||
|
||||
for ( let i = 0; i < kernelRadius; i ++ ) {
|
||||
|
||||
coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius );
|
||||
|
||||
}
|
||||
|
||||
return coefficients;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const gaussianBlur = ( node, directionNode, sigma ) => nodeObject( new GaussianBlurNode( nodeObject( node ).toTexture(), directionNode, sigma ) );
|
||||
|
||||
addNodeElement( 'gaussianBlur', gaussianBlur );
|
||||
|
||||
export default GaussianBlurNode;
|
||||
|
53
site/game/node_modules/three/src/nodes/display/Lut3DNode.js
generated
vendored
Normal file
53
site/game/node_modules/three/src/nodes/display/Lut3DNode.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { addNodeElement, tslFn, nodeObject, vec3, vec4, float } from '../shadernode/ShaderNode.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { mix } from '../math/MathNode.js';
|
||||
|
||||
class Lut3DNode extends TempNode {
|
||||
|
||||
constructor( inputNode, lutNode, size, intensityNode ) {
|
||||
|
||||
super();
|
||||
|
||||
this.inputNode = inputNode;
|
||||
this.lutNode = lutNode;
|
||||
this.size = uniform( size );
|
||||
this.intensityNode = intensityNode;
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const { inputNode, lutNode } = this;
|
||||
|
||||
const sampleLut = ( uv ) => lutNode.uv( uv );
|
||||
|
||||
const lut3D = tslFn( () => {
|
||||
|
||||
const base = inputNode;
|
||||
|
||||
// pull the sample in by half a pixel so the sample begins at the center of the edge pixels.
|
||||
|
||||
const pixelWidth = float( 1.0 ).div( this.size );
|
||||
const halfPixelWidth = float( 0.5 ).div( this.size );
|
||||
const uvw = vec3( halfPixelWidth ).add( base.rgb.mul( float( 1.0 ).sub( pixelWidth ) ) );
|
||||
|
||||
const lutValue = vec4( sampleLut( uvw ).rgb, base.a );
|
||||
|
||||
return vec4( mix( base, lutValue, this.intensityNode ) );
|
||||
|
||||
} );
|
||||
|
||||
const outputNode = lut3D();
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const lut3D = ( node, lut, size, intensity ) => nodeObject( new Lut3DNode( nodeObject( node ), nodeObject( lut ), size, nodeObject( intensity ) ) );
|
||||
|
||||
addNodeElement( 'lut3D', lut3D );
|
||||
|
||||
export default Lut3DNode;
|
106
site/game/node_modules/three/src/nodes/display/NormalMapNode.js
generated
vendored
Normal file
106
site/game/node_modules/three/src/nodes/display/NormalMapNode.js
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { add } from '../math/OperatorNode.js';
|
||||
|
||||
import { modelNormalMatrix } from '../accessors/ModelNode.js';
|
||||
import { normalView } from '../accessors/NormalNode.js';
|
||||
import { positionView } from '../accessors/PositionNode.js';
|
||||
import { TBNViewMatrix } from '../accessors/AccessorsUtils.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { faceDirection } from './FrontFacingNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { addNodeElement, tslFn, nodeProxy, vec3 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
import { TangentSpaceNormalMap, ObjectSpaceNormalMap } from '../../constants.js';
|
||||
|
||||
// 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 );
|
||||
|
||||
addNodeElement( 'normalMap', normalMap );
|
||||
|
||||
addNodeClass( 'NormalMapNode', NormalMapNode );
|
291
site/game/node_modules/three/src/nodes/display/PassNode.js
generated
vendored
Normal file
291
site/game/node_modules/three/src/nodes/display/PassNode.js
generated
vendored
Normal file
@ -0,0 +1,291 @@
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { default as TextureNode/*, texture*/ } from '../accessors/TextureNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { nodeObject } from '../shadernode/ShaderNode.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { viewZToOrthographicDepth, perspectiveDepthToViewZ } from './ViewportDepthNode.js';
|
||||
|
||||
import { HalfFloatType/*, FloatType*/ } from '../../constants.js';
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
import { DepthTexture } from '../../textures/DepthTexture.js';
|
||||
import { RenderTarget } from '../../core/RenderTarget.js';
|
||||
|
||||
const _size = /*@__PURE__*/ new Vector2();
|
||||
|
||||
class PassTextureNode extends TextureNode {
|
||||
|
||||
constructor( passNode, texture ) {
|
||||
|
||||
super( texture );
|
||||
|
||||
this.passNode = passNode;
|
||||
|
||||
this.setUpdateMatrix( false );
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
this.passNode.build( builder );
|
||||
|
||||
return super.setup( builder );
|
||||
|
||||
}
|
||||
|
||||
clone() {
|
||||
|
||||
return new this.constructor( this.passNode, this.value );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PassMultipleTextureNode extends PassTextureNode {
|
||||
|
||||
constructor( passNode, textureName ) {
|
||||
|
||||
super( passNode, null );
|
||||
|
||||
this.textureName = textureName;
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
this.value = this.passNode.getTexture( this.textureName );
|
||||
|
||||
return super.setup( builder );
|
||||
|
||||
}
|
||||
|
||||
clone() {
|
||||
|
||||
return new this.constructor( this.passNode, this.textureName );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PassNode extends TempNode {
|
||||
|
||||
constructor( scope, scene, camera, options = {} ) {
|
||||
|
||||
super( 'vec4' );
|
||||
|
||||
this.scope = scope;
|
||||
this.scene = scene;
|
||||
this.camera = camera;
|
||||
this.options = options;
|
||||
|
||||
this._pixelRatio = 1;
|
||||
this._width = 1;
|
||||
this._height = 1;
|
||||
|
||||
const depthTexture = new DepthTexture();
|
||||
depthTexture.isRenderTargetTexture = true;
|
||||
//depthTexture.type = FloatType;
|
||||
depthTexture.name = 'depth';
|
||||
|
||||
const renderTarget = new RenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, { type: HalfFloatType, ...options, } );
|
||||
renderTarget.texture.name = 'output';
|
||||
renderTarget.depthTexture = depthTexture;
|
||||
|
||||
this.renderTarget = renderTarget;
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.FRAME;
|
||||
|
||||
this._textures = {
|
||||
output: renderTarget.texture,
|
||||
depth: depthTexture
|
||||
};
|
||||
|
||||
this._textureNodes = {};
|
||||
this._linearDepthNodes = {};
|
||||
this._viewZNodes = {};
|
||||
|
||||
this._cameraNear = uniform( 0 );
|
||||
this._cameraFar = uniform( 0 );
|
||||
|
||||
this._mrt = null;
|
||||
|
||||
this.isPassNode = true;
|
||||
|
||||
}
|
||||
|
||||
setMRT( mrt ) {
|
||||
|
||||
this._mrt = mrt;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
getMRT() {
|
||||
|
||||
return this._mrt;
|
||||
|
||||
}
|
||||
|
||||
isGlobal() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
getTexture( name ) {
|
||||
|
||||
let texture = this._textures[ name ];
|
||||
|
||||
if ( texture === undefined ) {
|
||||
|
||||
const refTexture = this.renderTarget.texture;
|
||||
|
||||
texture = refTexture.clone();
|
||||
texture.isRenderTargetTexture = true;
|
||||
texture.name = name;
|
||||
|
||||
this._textures[ name ] = texture;
|
||||
|
||||
this.renderTarget.textures.push( texture );
|
||||
|
||||
}
|
||||
|
||||
return texture;
|
||||
|
||||
}
|
||||
|
||||
getTextureNode( name = 'output' ) {
|
||||
|
||||
let textureNode = this._textureNodes[ name ];
|
||||
|
||||
if ( textureNode === undefined ) {
|
||||
|
||||
this._textureNodes[ name ] = textureNode = nodeObject( new PassMultipleTextureNode( this, name ) );
|
||||
|
||||
}
|
||||
|
||||
return textureNode;
|
||||
|
||||
}
|
||||
|
||||
getViewZNode( name = 'depth' ) {
|
||||
|
||||
let viewZNode = this._viewZNodes[ name ];
|
||||
|
||||
if ( viewZNode === undefined ) {
|
||||
|
||||
const cameraNear = this._cameraNear;
|
||||
const cameraFar = this._cameraFar;
|
||||
|
||||
this._viewZNodes[ name ] = viewZNode = perspectiveDepthToViewZ( this.getTextureNode( name ), cameraNear, cameraFar );
|
||||
|
||||
}
|
||||
|
||||
return viewZNode;
|
||||
|
||||
}
|
||||
|
||||
getLinearDepthNode( name = 'depth' ) {
|
||||
|
||||
let linearDepthNode = this._linearDepthNodes[ name ];
|
||||
|
||||
if ( linearDepthNode === undefined ) {
|
||||
|
||||
const cameraNear = this._cameraNear;
|
||||
const cameraFar = this._cameraFar;
|
||||
const viewZNode = this.getViewZNode( name );
|
||||
|
||||
// TODO: just if ( builder.camera.isPerspectiveCamera )
|
||||
|
||||
this._linearDepthNodes[ name ] = linearDepthNode = viewZToOrthographicDepth( viewZNode, cameraNear, cameraFar );
|
||||
|
||||
}
|
||||
|
||||
return linearDepthNode;
|
||||
|
||||
}
|
||||
|
||||
setup( { renderer } ) {
|
||||
|
||||
this.renderTarget.samples = this.options.samples === undefined ? renderer.samples : this.options.samples;
|
||||
|
||||
// Disable MSAA for WebGL backend for now
|
||||
if ( renderer.backend.isWebGLBackend === true ) {
|
||||
|
||||
this.renderTarget.samples = 0;
|
||||
|
||||
}
|
||||
|
||||
this.renderTarget.depthTexture.isMultisampleRenderTargetTexture = this.renderTarget.samples > 1;
|
||||
|
||||
return this.scope === PassNode.COLOR ? this.getTextureNode() : this.getLinearDepthNode();
|
||||
|
||||
}
|
||||
|
||||
updateBefore( frame ) {
|
||||
|
||||
const { renderer } = frame;
|
||||
const { scene, camera } = this;
|
||||
|
||||
this._pixelRatio = renderer.getPixelRatio();
|
||||
|
||||
const size = renderer.getSize( _size );
|
||||
|
||||
this.setSize( size.width, size.height );
|
||||
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentMRT = renderer.getMRT();
|
||||
|
||||
this._cameraNear.value = camera.near;
|
||||
this._cameraFar.value = camera.far;
|
||||
|
||||
renderer.setRenderTarget( this.renderTarget );
|
||||
renderer.setMRT( this._mrt );
|
||||
|
||||
renderer.render( scene, camera );
|
||||
|
||||
renderer.setRenderTarget( currentRenderTarget );
|
||||
renderer.setMRT( currentMRT );
|
||||
|
||||
}
|
||||
|
||||
setSize( width, height ) {
|
||||
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
const effectiveWidth = this._width * this._pixelRatio;
|
||||
const effectiveHeight = this._height * this._pixelRatio;
|
||||
|
||||
this.renderTarget.setSize( effectiveWidth, effectiveHeight );
|
||||
|
||||
}
|
||||
|
||||
setPixelRatio( pixelRatio ) {
|
||||
|
||||
this._pixelRatio = pixelRatio;
|
||||
|
||||
this.setSize( this._width, this._height );
|
||||
|
||||
}
|
||||
|
||||
dispose() {
|
||||
|
||||
this.renderTarget.dispose();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
PassNode.COLOR = 'color';
|
||||
PassNode.DEPTH = 'depth';
|
||||
|
||||
export default PassNode;
|
||||
|
||||
export const pass = ( scene, camera, options ) => nodeObject( new PassNode( PassNode.COLOR, scene, camera, options ) );
|
||||
export const passTexture = ( pass, texture ) => nodeObject( new PassTextureNode( pass, texture ) );
|
||||
export const depthPass = ( scene, camera ) => nodeObject( new PassNode( PassNode.DEPTH, scene, camera ) );
|
||||
|
||||
addNodeClass( 'PassNode', PassNode );
|
201
site/game/node_modules/three/src/nodes/display/PixelationPassNode.js
generated
vendored
Normal file
201
site/game/node_modules/three/src/nodes/display/PixelationPassNode.js
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { addNodeElement, tslFn, nodeObject, vec2, vec3, float, If } from '../shadernode/ShaderNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { dot, clamp, smoothstep, sign, step, floor } from '../math/MathNode.js';
|
||||
import { Vector4 } from '../../math/Vector4.js';
|
||||
import { output, property } from '../core/PropertyNode.js';
|
||||
import PassNode from './PassNode.js';
|
||||
import { mrt } from '../core/MRTNode.js';
|
||||
import { normalView } from '../accessors/NormalNode.js';
|
||||
import { NearestFilter } from '../../constants.js';
|
||||
|
||||
class PixelationNode extends TempNode {
|
||||
|
||||
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.RENDER;
|
||||
|
||||
}
|
||||
|
||||
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 = tslFn( () => {
|
||||
|
||||
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 ).cond( 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( nodeObject( node ).toTexture(), nodeObject( depthNode ).toTexture(), nodeObject( normalNode ).toTexture(), nodeObject( pixelSize ), nodeObject( normalEdgeStrength ), nodeObject( depthEdgeStrength ) ) );
|
||||
|
||||
addNodeElement( 'pixelation', pixelation );
|
||||
|
||||
class PixelationPassNode extends PassNode {
|
||||
|
||||
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;
|
32
site/game/node_modules/three/src/nodes/display/PosterizeNode.js
generated
vendored
Normal file
32
site/game/node_modules/three/src/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 );
|
49
site/game/node_modules/three/src/nodes/display/RGBShiftNode.js
generated
vendored
Normal file
49
site/game/node_modules/three/src/nodes/display/RGBShiftNode.js
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { nodeObject, addNodeElement, tslFn, vec2, vec4 } from '../shadernode/ShaderNode.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { sin, cos } from '../math/MathNode.js';
|
||||
|
||||
class RGBShiftNode extends TempNode {
|
||||
|
||||
constructor( textureNode, amount = 0.005, angle = 0 ) {
|
||||
|
||||
super( 'vec4' );
|
||||
|
||||
this.textureNode = textureNode;
|
||||
this.amount = uniform( amount );
|
||||
this.angle = uniform( angle );
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const { textureNode } = this;
|
||||
|
||||
const uvNode = textureNode.uvNode || uv();
|
||||
|
||||
const sampleTexture = ( uv ) => textureNode.uv( uv );
|
||||
|
||||
const rgbShift = tslFn( () => {
|
||||
|
||||
const offset = vec2( cos( this.angle ), sin( this.angle ) ).mul( this.amount );
|
||||
const cr = sampleTexture( uvNode.add( offset ) );
|
||||
const cga = sampleTexture( uvNode );
|
||||
const cb = sampleTexture( uvNode.sub( offset ) );
|
||||
|
||||
return vec4( cr.r, cga.g, cb.b, cga.a );
|
||||
|
||||
} );
|
||||
|
||||
return rgbShift();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const rgbShift = ( node, amount, angle ) => nodeObject( new RGBShiftNode( nodeObject( node ).toTexture(), amount, angle ) );
|
||||
|
||||
addNodeElement( 'rgbShift', rgbShift );
|
||||
|
||||
export default RGBShiftNode;
|
||||
|
56
site/game/node_modules/three/src/nodes/display/RenderOutputNode.js
generated
vendored
Normal file
56
site/game/node_modules/three/src/nodes/display/RenderOutputNode.js
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { addNodeElement, nodeObject } from '../shadernode/ShaderNode.js';
|
||||
|
||||
import { SRGBColorSpace, NoToneMapping } from '../../constants.js';
|
||||
|
||||
class RenderOutputNode extends TempNode {
|
||||
|
||||
constructor( colorNode, toneMapping, outputColorSpace ) {
|
||||
|
||||
super( 'vec4' );
|
||||
|
||||
this.colorNode = colorNode;
|
||||
this.toneMapping = toneMapping;
|
||||
this.outputColorSpace = outputColorSpace;
|
||||
|
||||
this.isRenderOutput = true;
|
||||
|
||||
}
|
||||
|
||||
setup( { context } ) {
|
||||
|
||||
let outputNode = this.colorNode || context.color;
|
||||
|
||||
// tone mapping
|
||||
|
||||
const toneMapping = this.toneMapping !== null ? this.toneMapping : context.toneMapping;
|
||||
const outputColorSpace = this.outputColorSpace !== null ? this.outputColorSpace : context.outputColorSpace;
|
||||
|
||||
if ( toneMapping !== NoToneMapping ) {
|
||||
|
||||
outputNode = outputNode.toneMapping( toneMapping );
|
||||
|
||||
}
|
||||
|
||||
// output color space
|
||||
|
||||
if ( outputColorSpace === SRGBColorSpace ) {
|
||||
|
||||
outputNode = outputNode.linearToColorSpace( outputColorSpace );
|
||||
|
||||
}
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RenderOutputNode;
|
||||
|
||||
export const renderOutput = ( color, toneMapping = null, outputColorSpace = null ) => nodeObject( new RenderOutputNode( nodeObject( color ), toneMapping, outputColorSpace ) );
|
||||
|
||||
addNodeElement( 'renderOutput', renderOutput );
|
||||
|
||||
addNodeClass( 'RenderOutputNode', RenderOutputNode );
|
121
site/game/node_modules/three/src/nodes/display/SobelOperatorNode.js
generated
vendored
Normal file
121
site/game/node_modules/three/src/nodes/display/SobelOperatorNode.js
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { luminance } from './ColorAdjustmentNode.js';
|
||||
import { addNodeElement, tslFn, nodeObject, vec2, vec3, vec4, mat3 } from '../shadernode/ShaderNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { add } from '../math/OperatorNode.js';
|
||||
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
|
||||
class SobelOperatorNode extends TempNode {
|
||||
|
||||
constructor( textureNode ) {
|
||||
|
||||
super();
|
||||
|
||||
this.textureNode = textureNode;
|
||||
|
||||
this.updateBeforeType = NodeUpdateType.RENDER;
|
||||
|
||||
this._invSize = uniform( new Vector2() );
|
||||
|
||||
}
|
||||
|
||||
updateBefore() {
|
||||
|
||||
const map = this.textureNode.value;
|
||||
|
||||
this._invSize.value.set( 1 / map.image.width, 1 / map.image.height );
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const { textureNode } = this;
|
||||
|
||||
const uvNode = textureNode.uvNode || uv();
|
||||
|
||||
const sampleTexture = ( uv ) => textureNode.uv( uv );
|
||||
|
||||
const sobel = tslFn( () => {
|
||||
|
||||
// Sobel Edge Detection (see https://youtu.be/uihBwtPIBxM)
|
||||
|
||||
const texel = this._invSize;
|
||||
|
||||
// kernel definition (in glsl matrices are filled in column-major order)
|
||||
|
||||
const Gx = mat3( - 1, - 2, - 1, 0, 0, 0, 1, 2, 1 ); // x direction kernel
|
||||
const Gy = mat3( - 1, 0, 1, - 2, 0, 2, - 1, 0, 1 ); // y direction kernel
|
||||
|
||||
// fetch the 3x3 neighbourhood of a fragment
|
||||
|
||||
// first column
|
||||
|
||||
const tx0y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, - 1 ) ) ) ).xyz );
|
||||
const tx0y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, 0 ) ) ) ).xyz );
|
||||
const tx0y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, 1 ) ) ) ).xyz );
|
||||
|
||||
// second column
|
||||
|
||||
const tx1y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, - 1 ) ) ) ).xyz );
|
||||
const tx1y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, 0 ) ) ) ).xyz );
|
||||
const tx1y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, 1 ) ) ) ).xyz );
|
||||
|
||||
// third column
|
||||
|
||||
const tx2y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, - 1 ) ) ) ).xyz );
|
||||
const tx2y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, 0 ) ) ) ).xyz );
|
||||
const tx2y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, 1 ) ) ) ).xyz );
|
||||
|
||||
// gradient value in x direction
|
||||
|
||||
const valueGx = add(
|
||||
Gx[ 0 ][ 0 ].mul( tx0y0 ),
|
||||
Gx[ 1 ][ 0 ].mul( tx1y0 ),
|
||||
Gx[ 2 ][ 0 ].mul( tx2y0 ),
|
||||
Gx[ 0 ][ 1 ].mul( tx0y1 ),
|
||||
Gx[ 1 ][ 1 ].mul( tx1y1 ),
|
||||
Gx[ 2 ][ 1 ].mul( tx2y1 ),
|
||||
Gx[ 0 ][ 2 ].mul( tx0y2 ),
|
||||
Gx[ 1 ][ 2 ].mul( tx1y2 ),
|
||||
Gx[ 2 ][ 2 ].mul( tx2y2 )
|
||||
);
|
||||
|
||||
|
||||
// gradient value in y direction
|
||||
|
||||
const valueGy = add(
|
||||
Gy[ 0 ][ 0 ].mul( tx0y0 ),
|
||||
Gy[ 1 ][ 0 ].mul( tx1y0 ),
|
||||
Gy[ 2 ][ 0 ].mul( tx2y0 ),
|
||||
Gy[ 0 ][ 1 ].mul( tx0y1 ),
|
||||
Gy[ 1 ][ 1 ].mul( tx1y1 ),
|
||||
Gy[ 2 ][ 1 ].mul( tx2y1 ),
|
||||
Gy[ 0 ][ 2 ].mul( tx0y2 ),
|
||||
Gy[ 1 ][ 2 ].mul( tx1y2 ),
|
||||
Gy[ 2 ][ 2 ].mul( tx2y2 )
|
||||
);
|
||||
|
||||
// magnitute of the total gradient
|
||||
|
||||
const G = valueGx.mul( valueGx ).add( valueGy.mul( valueGy ) ).sqrt();
|
||||
|
||||
return vec4( vec3( G ), 1 );
|
||||
|
||||
} );
|
||||
|
||||
const outputNode = sobel();
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const sobel = ( node ) => nodeObject( new SobelOperatorNode( nodeObject( node ).toTexture() ) );
|
||||
|
||||
addNodeElement( 'sobel', sobel );
|
||||
|
||||
export default SobelOperatorNode;
|
227
site/game/node_modules/three/src/nodes/display/ToneMappingNode.js
generated
vendored
Normal file
227
site/game/node_modules/three/src/nodes/display/ToneMappingNode.js
generated
vendored
Normal file
@ -0,0 +1,227 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { addNodeClass } from '../core/Node.js';
|
||||
import { addNodeElement, tslFn, nodeObject, float, mat3, vec3, If } from '../shadernode/ShaderNode.js';
|
||||
import { rendererReference } from '../accessors/RendererReferenceNode.js';
|
||||
import { cond } from '../math/CondNode.js';
|
||||
import { clamp, log2, max, min, pow, mix } from '../math/MathNode.js';
|
||||
import { mul, sub, div } from '../math/OperatorNode.js';
|
||||
|
||||
import { NoToneMapping, LinearToneMapping, ReinhardToneMapping, CineonToneMapping, ACESFilmicToneMapping, AgXToneMapping, NeutralToneMapping } from '../../constants.js';
|
||||
|
||||
// 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 LINEAR_REC2020_TO_LINEAR_SRGB = mat3( vec3( 1.6605, - 0.1246, - 0.0182 ), vec3( - 0.5876, 1.1329, - 0.1006 ), vec3( - 0.0728, - 0.0083, 1.1187 ) );
|
||||
const LINEAR_SRGB_TO_LINEAR_REC2020 = mat3( vec3( 0.6274, 0.0691, 0.0164 ), vec3( 0.3293, 0.9195, 0.0880 ), vec3( 0.0433, 0.0113, 0.8956 ) );
|
||||
|
||||
const agxDefaultContrastApprox = tslFn( ( [ x_immutable ] ) => {
|
||||
|
||||
const x = vec3( x_immutable ).toVar();
|
||||
const x2 = vec3( x.mul( x ) ).toVar();
|
||||
const x4 = vec3( x2.mul( x2 ) ).toVar();
|
||||
|
||||
return float( 15.5 ).mul( x4.mul( x2 ) ).sub( mul( 40.14, x4.mul( x ) ) ).add( mul( 31.96, x4 ).sub( mul( 6.868, x2.mul( x ) ) ).add( mul( 0.4298, x2 ).add( mul( 0.1191, x ).sub( 0.00232 ) ) ) );
|
||||
|
||||
} );
|
||||
|
||||
const AGXToneMappingNode = tslFn( ( { color, exposure } ) => {
|
||||
|
||||
const colortone = vec3( color ).toVar();
|
||||
const AgXInsetMatrix = mat3( vec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ), vec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ), vec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 ) );
|
||||
const AgXOutsetMatrix = mat3( vec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ), vec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ), vec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 ) );
|
||||
const AgxMinEv = float( - 12.47393 );
|
||||
const AgxMaxEv = float( 4.026069 );
|
||||
colortone.mulAssign( exposure );
|
||||
colortone.assign( LINEAR_SRGB_TO_LINEAR_REC2020.mul( colortone ) );
|
||||
colortone.assign( AgXInsetMatrix.mul( colortone ) );
|
||||
colortone.assign( max( colortone, 1e-10 ) );
|
||||
colortone.assign( log2( colortone ) );
|
||||
colortone.assign( colortone.sub( AgxMinEv ).div( AgxMaxEv.sub( AgxMinEv ) ) );
|
||||
colortone.assign( clamp( colortone, 0.0, 1.0 ) );
|
||||
colortone.assign( agxDefaultContrastApprox( colortone ) );
|
||||
colortone.assign( AgXOutsetMatrix.mul( colortone ) );
|
||||
colortone.assign( pow( max( vec3( 0.0 ), colortone ), vec3( 2.2 ) ) );
|
||||
colortone.assign( LINEAR_REC2020_TO_LINEAR_SRGB.mul( colortone ) );
|
||||
colortone.assign( clamp( colortone, 0.0, 1.0 ) );
|
||||
|
||||
return colortone;
|
||||
|
||||
} );
|
||||
|
||||
// https://modelviewer.dev/examples/tone-mapping
|
||||
|
||||
const NeutralToneMappingNode = tslFn( ( { color, exposure } ) => {
|
||||
|
||||
const StartCompression = float( 0.8 - 0.04 );
|
||||
const Desaturation = float( 0.15 );
|
||||
|
||||
color = color.mul( exposure );
|
||||
|
||||
const x = min( color.r, min( color.g, color.b ) );
|
||||
const offset = cond( x.lessThan( 0.08 ), x.sub( mul( 6.25, x.mul( x ) ) ), 0.04 );
|
||||
|
||||
color.subAssign( offset );
|
||||
|
||||
const peak = max( color.r, max( color.g, color.b ) );
|
||||
|
||||
If( peak.lessThan( StartCompression ), () => {
|
||||
|
||||
return color;
|
||||
|
||||
} );
|
||||
|
||||
const d = sub( 1, StartCompression );
|
||||
const newPeak = sub( 1, d.mul( d ).div( peak.add( d.sub( StartCompression ) ) ) );
|
||||
color.mulAssign( newPeak.div( peak ) );
|
||||
const g = sub( 1, div( 1, Desaturation.mul( peak.sub( newPeak ) ).add( 1 ) ) );
|
||||
|
||||
return mix( color, vec3( newPeak ), g );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'NeutralToneMapping',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'color', type: 'vec3' },
|
||||
{ name: 'exposure', type: 'float' }
|
||||
]
|
||||
} );
|
||||
|
||||
const toneMappingLib = {
|
||||
[ LinearToneMapping ]: LinearToneMappingNode,
|
||||
[ ReinhardToneMapping ]: ReinhardToneMappingNode,
|
||||
[ CineonToneMapping ]: OptimizedCineonToneMappingNode,
|
||||
[ ACESFilmicToneMapping ]: ACESFilmicToneMappingNode,
|
||||
[ AgXToneMapping ]: AGXToneMappingNode,
|
||||
[ NeutralToneMapping ]: NeutralToneMappingNode
|
||||
};
|
||||
|
||||
class ToneMappingNode extends TempNode {
|
||||
|
||||
constructor( toneMapping = NoToneMapping, exposureNode = toneMappingExposure, 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 ) ) );
|
||||
export const toneMappingExposure = rendererReference( 'toneMappingExposure', 'float' );
|
||||
|
||||
addNodeElement( 'toneMapping', ( color, mapping, exposure ) => toneMapping( mapping, exposure, color ) );
|
||||
|
||||
addNodeClass( 'ToneMappingNode', ToneMappingNode );
|
76
site/game/node_modules/three/src/nodes/display/TransitionNode.js
generated
vendored
Normal file
76
site/game/node_modules/three/src/nodes/display/TransitionNode.js
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { addNodeElement, tslFn, nodeObject, float, int, vec4, If } from '../shadernode/ShaderNode.js';
|
||||
import { clamp, mix } from '../math/MathNode.js';
|
||||
import { sub } from '../math/OperatorNode.js';
|
||||
|
||||
class TransitionNode extends TempNode {
|
||||
|
||||
constructor( textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode ) {
|
||||
|
||||
super();
|
||||
|
||||
// Input textures
|
||||
|
||||
this.textureNodeA = textureNodeA;
|
||||
this.textureNodeB = textureNodeB;
|
||||
this.mixTextureNode = mixTextureNode;
|
||||
|
||||
// Uniforms
|
||||
|
||||
this.mixRatioNode = mixRatioNode;
|
||||
this.thresholdNode = thresholdNode;
|
||||
this.useTextureNode = useTextureNode;
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const { textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode } = this;
|
||||
|
||||
const sampleTexture = ( textureNode ) => {
|
||||
|
||||
const uvNodeTexture = textureNode.uvNode || uv();
|
||||
return textureNode.uv( uvNodeTexture );
|
||||
|
||||
};
|
||||
|
||||
const transition = tslFn( () => {
|
||||
|
||||
const texelOne = sampleTexture( textureNodeA );
|
||||
const texelTwo = sampleTexture( textureNodeB );
|
||||
|
||||
const color = vec4().toVar();
|
||||
|
||||
If( useTextureNode.equal( int( 1 ) ), () => {
|
||||
|
||||
const transitionTexel = sampleTexture( mixTextureNode );
|
||||
const r = mixRatioNode.mul( thresholdNode.mul( 2.0 ).add( 1.0 ) ).sub( thresholdNode );
|
||||
const mixf = clamp( sub( transitionTexel.r, r ).mul( float( 1.0 ).div( thresholdNode ) ), 0.0, 1.0 );
|
||||
|
||||
color.assign( mix( texelOne, texelTwo, mixf ) );
|
||||
|
||||
} ).else( () => {
|
||||
|
||||
color.assign( mix( texelTwo, texelOne, mixRatioNode ) );
|
||||
|
||||
} );
|
||||
|
||||
return color;
|
||||
|
||||
} );
|
||||
|
||||
const outputNode = transition();
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const transition = ( nodeA, nodeB, mixTexture, mixRatio = 0.0, threshold = 0.1, useTexture = 0 ) => nodeObject( new TransitionNode( nodeObject( nodeA ).toTexture(), nodeObject( nodeB ).toTexture(), nodeObject( mixTexture ).toTexture(), nodeObject( mixRatio ), nodeObject( threshold ), nodeObject( useTexture ) ) );
|
||||
|
||||
addNodeElement( 'transition', transition );
|
||||
|
||||
export default TransitionNode;
|
||||
|
120
site/game/node_modules/three/src/nodes/display/ViewportDepthNode.js
generated
vendored
Normal file
120
site/game/node_modules/three/src/nodes/display/ViewportDepthNode.js
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
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, valueNode = null ) {
|
||||
|
||||
super( 'float' );
|
||||
|
||||
this.scope = scope;
|
||||
this.valueNode = valueNode;
|
||||
|
||||
this.isViewportDepthNode = true;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const { scope } = this;
|
||||
|
||||
if ( scope === ViewportDepthNode.DEPTH ) {
|
||||
|
||||
return builder.getFragDepth();
|
||||
|
||||
}
|
||||
|
||||
return super.generate( builder );
|
||||
|
||||
}
|
||||
|
||||
setup( { camera } ) {
|
||||
|
||||
const { scope } = this;
|
||||
const texture = this.valueNode;
|
||||
|
||||
let node = null;
|
||||
|
||||
if ( scope === ViewportDepthNode.DEPTH ) {
|
||||
|
||||
if ( texture !== null ) {
|
||||
|
||||
node = depthBase().assign( texture );
|
||||
|
||||
} else {
|
||||
|
||||
if ( camera.isPerspectiveCamera ) {
|
||||
|
||||
node = viewZToPerspectiveDepth( positionView.z, cameraNear, cameraFar );
|
||||
|
||||
} else {
|
||||
|
||||
node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === ViewportDepthNode.LINEAR_DEPTH ) {
|
||||
|
||||
if ( texture !== null ) {
|
||||
|
||||
if ( camera.isPerspectiveCamera ) {
|
||||
|
||||
const viewZ = perspectiveDepthToViewZ( texture, cameraNear, cameraFar );
|
||||
|
||||
node = viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );
|
||||
|
||||
} else {
|
||||
|
||||
node = texture;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
node = viewZToOrthographicDepth( positionView.z, 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( far.sub( near ).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.LINEAR_DEPTH = 'linearDepth';
|
||||
|
||||
export default ViewportDepthNode;
|
||||
|
||||
const depthBase = nodeProxy( ViewportDepthNode, ViewportDepthNode.DEPTH );
|
||||
|
||||
export const depth = nodeImmutable( ViewportDepthNode, ViewportDepthNode.DEPTH );
|
||||
export const linearDepth = nodeProxy( ViewportDepthNode, ViewportDepthNode.LINEAR_DEPTH );
|
||||
export const viewportLinearDepth = linearDepth( viewportDepthTexture() );
|
||||
|
||||
depth.assign = ( value ) => depthBase( value );
|
||||
|
||||
addNodeClass( 'ViewportDepthNode', ViewportDepthNode );
|
32
site/game/node_modules/three/src/nodes/display/ViewportDepthTextureNode.js
generated
vendored
Normal file
32
site/game/node_modules/three/src/nodes/display/ViewportDepthTextureNode.js
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
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 } from '../../textures/DepthTexture.js';
|
||||
|
||||
let sharedDepthbuffer = null;
|
||||
|
||||
class ViewportDepthTextureNode extends ViewportTextureNode {
|
||||
|
||||
constructor( uvNode = viewportTopLeft, levelNode = null ) {
|
||||
|
||||
if ( sharedDepthbuffer === null ) {
|
||||
|
||||
sharedDepthbuffer = new DepthTexture();
|
||||
|
||||
}
|
||||
|
||||
super( uvNode, levelNode, sharedDepthbuffer );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ViewportDepthTextureNode;
|
||||
|
||||
export const viewportDepthTexture = nodeProxy( ViewportDepthTextureNode );
|
||||
|
||||
addNodeElement( 'viewportDepthTexture', viewportDepthTexture );
|
||||
|
||||
addNodeClass( 'ViewportDepthTextureNode', ViewportDepthTextureNode );
|
137
site/game/node_modules/three/src/nodes/display/ViewportNode.js
generated
vendored
Normal file
137
site/game/node_modules/three/src/nodes/display/ViewportNode.js
generated
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
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 } from '../../math/Vector2.js';
|
||||
import { Vector4 } from '../../math/Vector4.js';
|
||||
|
||||
let resolution, viewportResult;
|
||||
|
||||
class ViewportNode extends Node {
|
||||
|
||||
constructor( scope ) {
|
||||
|
||||
super();
|
||||
|
||||
this.scope = scope;
|
||||
|
||||
this.isViewportNode = true;
|
||||
|
||||
}
|
||||
|
||||
getNodeType() {
|
||||
|
||||
if ( this.scope === ViewportNode.VIEWPORT ) return 'vec4';
|
||||
else if ( this.scope === ViewportNode.COORDINATE ) return 'vec3';
|
||||
else return 'vec2';
|
||||
|
||||
}
|
||||
|
||||
getUpdateType() {
|
||||
|
||||
let updateType = NodeUpdateType.NONE;
|
||||
|
||||
if ( this.scope === ViewportNode.RESOLUTION || this.scope === ViewportNode.VIEWPORT ) {
|
||||
|
||||
updateType = NodeUpdateType.RENDER;
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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 {
|
||||
|
||||
output = viewportCoordinate.div( viewportResolution );
|
||||
|
||||
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 = builder.getNodeProperties( viewportResolution ).outputNode.build( builder );
|
||||
|
||||
coord = `${ builder.getType( 'vec3' ) }( ${ coord }.x, ${ resolution }.y - ${ coord }.y, ${ coord }.z )`;
|
||||
|
||||
}
|
||||
|
||||
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 );
|
38
site/game/node_modules/three/src/nodes/display/ViewportSharedTextureNode.js
generated
vendored
Normal file
38
site/game/node_modules/three/src/nodes/display/ViewportSharedTextureNode.js
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
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 '../../textures/FramebufferTexture.js';
|
||||
|
||||
let _sharedFramebuffer = null;
|
||||
|
||||
class ViewportSharedTextureNode extends ViewportTextureNode {
|
||||
|
||||
constructor( uvNode = viewportTopLeft, levelNode = null ) {
|
||||
|
||||
if ( _sharedFramebuffer === null ) {
|
||||
|
||||
_sharedFramebuffer = new FramebufferTexture();
|
||||
|
||||
}
|
||||
|
||||
super( uvNode, levelNode, _sharedFramebuffer );
|
||||
|
||||
}
|
||||
|
||||
updateReference() {
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ViewportSharedTextureNode;
|
||||
|
||||
export const viewportSharedTexture = nodeProxy( ViewportSharedTextureNode );
|
||||
|
||||
addNodeElement( 'viewportSharedTexture', viewportSharedTexture );
|
||||
|
||||
addNodeClass( 'ViewportSharedTextureNode', ViewportSharedTextureNode );
|
81
site/game/node_modules/three/src/nodes/display/ViewportTextureNode.js
generated
vendored
Normal file
81
site/game/node_modules/three/src/nodes/display/ViewportTextureNode.js
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
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 } from '../../math/Vector2.js';
|
||||
import { FramebufferTexture } from '../../textures/FramebufferTexture.js';
|
||||
import { LinearMipmapLinearFilter } from '../../constants.js';
|
||||
|
||||
const _size = /*@__PURE__*/ 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() {
|
||||
|
||||
const viewportTextureNode = new this.constructor( this.uvNode, this.levelNode, this.value );
|
||||
viewportTextureNode.generateMipmaps = this.generateMipmaps;
|
||||
|
||||
return viewportTextureNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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