BlendModeNode.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import TempNode from '../core/TempNode.js';
  2. import { /*mix, step,*/ EPSILON } from '../math/MathNode.js';
  3. import { addNodeClass } from '../core/Node.js';
  4. import { addNodeElement, tslFn, nodeProxy, vec3 } from '../shadernode/ShaderNode.js';
  5. export const BurnNode = tslFn( ( { base, blend } ) => {
  6. const fn = ( c ) => blend[ c ].lessThan( EPSILON ).cond( blend[ c ], base[ c ].oneMinus().div( blend[ c ] ).oneMinus().max( 0 ) );
  7. return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
  8. } ).setLayout( {
  9. name: 'burnColor',
  10. type: 'vec3',
  11. inputs: [
  12. { name: 'base', type: 'vec3' },
  13. { name: 'blend', type: 'vec3' }
  14. ]
  15. } );
  16. export const DodgeNode = tslFn( ( { base, blend } ) => {
  17. const fn = ( c ) => blend[ c ].equal( 1.0 ).cond( blend[ c ], base[ c ].div( blend[ c ].oneMinus() ).max( 0 ) );
  18. return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
  19. } ).setLayout( {
  20. name: 'dodgeColor',
  21. type: 'vec3',
  22. inputs: [
  23. { name: 'base', type: 'vec3' },
  24. { name: 'blend', type: 'vec3' }
  25. ]
  26. } );
  27. export const ScreenNode = tslFn( ( { base, blend } ) => {
  28. const fn = ( c ) => base[ c ].oneMinus().mul( blend[ c ].oneMinus() ).oneMinus();
  29. return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
  30. } ).setLayout( {
  31. name: 'screenColor',
  32. type: 'vec3',
  33. inputs: [
  34. { name: 'base', type: 'vec3' },
  35. { name: 'blend', type: 'vec3' }
  36. ]
  37. } );
  38. export const OverlayNode = tslFn( ( { base, blend } ) => {
  39. const fn = ( c ) => base[ c ].lessThan( 0.5 ).cond( base[ c ].mul( blend[ c ], 2.0 ), base[ c ].oneMinus().mul( blend[ c ].oneMinus() ).oneMinus() );
  40. //const fn = ( c ) => mix( base[ c ].oneMinus().mul( blend[ c ].oneMinus() ).oneMinus(), base[ c ].mul( blend[ c ], 2.0 ), step( base[ c ], 0.5 ) );
  41. return vec3( fn( 'x' ), fn( 'y' ), fn( 'z' ) );
  42. } ).setLayout( {
  43. name: 'overlayColor',
  44. type: 'vec3',
  45. inputs: [
  46. { name: 'base', type: 'vec3' },
  47. { name: 'blend', type: 'vec3' }
  48. ]
  49. } );
  50. class BlendModeNode extends TempNode {
  51. constructor( blendMode, baseNode, blendNode ) {
  52. super();
  53. this.blendMode = blendMode;
  54. this.baseNode = baseNode;
  55. this.blendNode = blendNode;
  56. }
  57. setup() {
  58. const { blendMode, baseNode, blendNode } = this;
  59. const params = { base: baseNode, blend: blendNode };
  60. let outputNode = null;
  61. if ( blendMode === BlendModeNode.BURN ) {
  62. outputNode = BurnNode( params );
  63. } else if ( blendMode === BlendModeNode.DODGE ) {
  64. outputNode = DodgeNode( params );
  65. } else if ( blendMode === BlendModeNode.SCREEN ) {
  66. outputNode = ScreenNode( params );
  67. } else if ( blendMode === BlendModeNode.OVERLAY ) {
  68. outputNode = OverlayNode( params );
  69. }
  70. return outputNode;
  71. }
  72. }
  73. BlendModeNode.BURN = 'burn';
  74. BlendModeNode.DODGE = 'dodge';
  75. BlendModeNode.SCREEN = 'screen';
  76. BlendModeNode.OVERLAY = 'overlay';
  77. export default BlendModeNode;
  78. export const burn = nodeProxy( BlendModeNode, BlendModeNode.BURN );
  79. export const dodge = nodeProxy( BlendModeNode, BlendModeNode.DODGE );
  80. export const overlay = nodeProxy( BlendModeNode, BlendModeNode.OVERLAY );
  81. export const screen = nodeProxy( BlendModeNode, BlendModeNode.SCREEN );
  82. addNodeElement( 'burn', burn );
  83. addNodeElement( 'dodge', dodge );
  84. addNodeElement( 'overlay', overlay );
  85. addNodeElement( 'screen', screen );
  86. addNodeClass( 'BlendModeNode', BlendModeNode );