ColorAdjustmentNode.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import TempNode from '../core/TempNode.js';
  2. import { ShaderNode, vec3, mat3, add, sub, mul, max, div, float, mix, cos, sin, atan2, sqrt, luminance } from '../shadernode/ShaderNodeBaseElements.js';
  3. const saturationNode = new ShaderNode( ( { color, adjustment } ) => {
  4. return mix( luminance( color ), color, adjustment );
  5. } );
  6. const vibranceNode = new ShaderNode( ( { color, adjustment } ) => {
  7. const average = div( add( color.r, color.g, color.b ), 3.0 );
  8. const mx = max( color.r, max( color.g, color.b ) );
  9. const amt = mul( sub( mx, average ), mul( - 3.0, adjustment ) );
  10. return mix( color.rgb, vec3( mx ), amt );
  11. } );
  12. const hueNode = new ShaderNode( ( { color, adjustment } ) => {
  13. const RGBtoYIQ = mat3( 0.299, 0.587, 0.114, 0.595716, - 0.274453, - 0.321263, 0.211456, - 0.522591, 0.311135 );
  14. const YIQtoRGB = mat3( 1.0, 0.9563, 0.6210, 1.0, - 0.2721, - 0.6474, 1.0, - 1.107, 1.7046 );
  15. const yiq = mul( RGBtoYIQ, color );
  16. const hue = add( atan2( yiq.z, yiq.y ), adjustment );
  17. const chroma = sqrt( add( mul( yiq.z, yiq.z ), mul( yiq.y, yiq.y ) ) );
  18. return mul( YIQtoRGB, vec3( yiq.x, mul( chroma, cos( hue ) ), mul( chroma, sin( hue ) ) ) );
  19. } );
  20. class ColorAdjustmentNode extends TempNode {
  21. constructor( method, colorNode, adjustmentNode = float( 1 ) ) {
  22. super( 'vec3' );
  23. this.method = method;
  24. this.colorNode = colorNode;
  25. this.adjustmentNode = adjustmentNode;
  26. }
  27. construct() {
  28. const { method, colorNode, adjustmentNode } = this;
  29. const callParams = { color: colorNode, adjustment: adjustmentNode };
  30. let outputNode = null;
  31. if ( method === ColorAdjustmentNode.SATURATION ) {
  32. outputNode = saturationNode.call( callParams );
  33. } else if ( method === ColorAdjustmentNode.VIBRANCE ) {
  34. outputNode = vibranceNode.call( callParams );
  35. } else if ( method === ColorAdjustmentNode.HUE ) {
  36. outputNode = hueNode.call( callParams );
  37. } else {
  38. console.error( `${ this.type }: Method "${ this.method }" not supported!` );
  39. }
  40. return outputNode;
  41. }
  42. }
  43. ColorAdjustmentNode.SATURATION = 'saturation';
  44. ColorAdjustmentNode.VIBRANCE = 'vibrance';
  45. ColorAdjustmentNode.HUE = 'hue';
  46. export default ColorAdjustmentNode;