BlendModeNode.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import TempNode from '../core/Node.js';
  2. import { ShaderNode, EPSILON, vec3, sub, mul, div, cond, lessThan, equal, max } from '../shadernode/ShaderNodeBaseElements.js';
  3. export const BurnNode = new ShaderNode( ( { base, blend } ) => {
  4. const fn = ( c ) => cond( lessThan( blend[ c ], EPSILON ), blend[ c ], max( sub( 1.0, div( sub( 1.0, base[ c ] ), blend[ c ] ) ), 0 ) );
  5. return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
  6. } );
  7. export const DodgeNode = new ShaderNode( ( { base, blend } ) => {
  8. const fn = ( c ) => cond( equal( blend[ c ], 1.0 ), blend[ c ], max( div( base[ c ], sub( 1.0, blend[ c ] ) ), 0 ) );
  9. return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
  10. } );
  11. export const ScreenNode = new ShaderNode( ( { base, blend } ) => {
  12. const fn = ( c ) => sub( 1.0, mul( sub( 1.0, base[ c ] ), sub( 1.0, blend[ c ] ) ) );
  13. return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
  14. } );
  15. export const OverlayNode = new ShaderNode( ( { base, blend } ) => {
  16. const fn = ( c ) => cond( lessThan( base[ c ], 0.5 ), mul( 2.0, base[ c ], blend[ c ] ), sub( 1.0, mul( sub( 1.0, base[ c ] ), sub( 1.0, blend[ c ] ) ) ) );
  17. return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
  18. } );
  19. class BlendModeNode extends TempNode {
  20. constructor( blendMode, baseNode, blendNode ) {
  21. super();
  22. this.blendMode = blendMode;
  23. this.baseNode = baseNode;
  24. this.blendNode = blendNode;
  25. }
  26. construct() {
  27. const { blendMode, baseNode, blendNode } = this;
  28. const params = { base: baseNode, blend: blendNode };
  29. let outputNode = null;
  30. if ( blendMode === BlendModeNode.BURN ) {
  31. outputNode = BurnNode.call( params );
  32. } else if ( blendMode === BlendModeNode.DODGE ) {
  33. outputNode = DodgeNode.call( params );
  34. } else if ( blendMode === BlendModeNode.SCREEN ) {
  35. outputNode = ScreenNode.call( params );
  36. } else if ( blendMode === BlendModeNode.OVERLAY ) {
  37. outputNode = OverlayNode.call( params );
  38. }
  39. return outputNode;
  40. }
  41. }
  42. BlendModeNode.BURN = 'burn';
  43. BlendModeNode.DODGE = 'dodge';
  44. BlendModeNode.SCREEN = 'screen';
  45. BlendModeNode.OVERLAY = 'overlay';
  46. export default BlendModeNode;