129 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			129 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | 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 ); |