ColorAdjustmentNode.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import { TempNode } from '../core/TempNode.js';
  2. import { FunctionNode } from '../core/FunctionNode.js';
  3. import { LuminanceNode } from './LuminanceNode.js';
  4. function ColorAdjustmentNode( rgb, adjustment, method ) {
  5. TempNode.call( this, 'v3' );
  6. this.rgb = rgb;
  7. this.adjustment = adjustment;
  8. this.method = method || ColorAdjustmentNode.SATURATION;
  9. }
  10. ColorAdjustmentNode.Nodes = ( function () {
  11. var hue = new FunctionNode( [
  12. 'vec3 hue(vec3 rgb, float adjustment) {',
  13. ' const mat3 RGBtoYIQ = mat3(0.299, 0.587, 0.114, 0.595716, -0.274453, -0.321263, 0.211456, -0.522591, 0.311135);',
  14. ' const mat3 YIQtoRGB = mat3(1.0, 0.9563, 0.6210, 1.0, -0.2721, -0.6474, 1.0, -1.107, 1.7046);',
  15. ' vec3 yiq = RGBtoYIQ * rgb;',
  16. ' float hue = atan(yiq.z, yiq.y) + adjustment;',
  17. ' float chroma = sqrt(yiq.z * yiq.z + yiq.y * yiq.y);',
  18. ' return YIQtoRGB * vec3(yiq.x, chroma * cos(hue), chroma * sin(hue));',
  19. '}'
  20. ].join( '\n' ) );
  21. var saturation = new FunctionNode( [
  22. // Algorithm from Chapter 16 of OpenGL Shading Language
  23. 'vec3 saturation(vec3 rgb, float adjustment) {',
  24. ' vec3 intensity = vec3( luminance( rgb ) );',
  25. ' return mix( intensity, rgb, adjustment );',
  26. '}'
  27. ].join( '\n' ), [ LuminanceNode.Nodes.luminance ] ); // include LuminanceNode function
  28. var vibrance = new FunctionNode( [
  29. // Shader by Evan Wallace adapted by @lo-th
  30. 'vec3 vibrance(vec3 rgb, float adjustment) {',
  31. ' float average = (rgb.r + rgb.g + rgb.b) / 3.0;',
  32. ' float mx = max(rgb.r, max(rgb.g, rgb.b));',
  33. ' float amt = (mx - average) * (-3.0 * adjustment);',
  34. ' return mix(rgb.rgb, vec3(mx), amt);',
  35. '}'
  36. ].join( '\n' ) );
  37. return {
  38. hue: hue,
  39. saturation: saturation,
  40. vibrance: vibrance
  41. };
  42. } )();
  43. ColorAdjustmentNode.SATURATION = 'saturation';
  44. ColorAdjustmentNode.HUE = 'hue';
  45. ColorAdjustmentNode.VIBRANCE = 'vibrance';
  46. ColorAdjustmentNode.BRIGHTNESS = 'brightness';
  47. ColorAdjustmentNode.CONTRAST = 'contrast';
  48. ColorAdjustmentNode.prototype = Object.create( TempNode.prototype );
  49. ColorAdjustmentNode.prototype.constructor = ColorAdjustmentNode;
  50. ColorAdjustmentNode.prototype.nodeType = 'ColorAdjustment';
  51. ColorAdjustmentNode.prototype.hashProperties = [ 'method' ];
  52. ColorAdjustmentNode.prototype.generate = function ( builder, output ) {
  53. var rgb = this.rgb.build( builder, 'v3' ),
  54. adjustment = this.adjustment.build( builder, 'f' );
  55. switch ( this.method ) {
  56. case ColorAdjustmentNode.BRIGHTNESS:
  57. return builder.format( '( ' + rgb + ' + ' + adjustment + ' )', this.getType( builder ), output );
  58. break;
  59. case ColorAdjustmentNode.CONTRAST:
  60. return builder.format( '( ' + rgb + ' * ' + adjustment + ' )', this.getType( builder ), output );
  61. break;
  62. }
  63. var method = builder.include( ColorAdjustmentNode.Nodes[ this.method ] );
  64. return builder.format( method + '( ' + rgb + ', ' + adjustment + ' )', this.getType( builder ), output );
  65. };
  66. ColorAdjustmentNode.prototype.copy = function ( source ) {
  67. TempNode.prototype.copy.call( this, source );
  68. this.rgb = source.rgb;
  69. this.adjustment = source.adjustment;
  70. this.method = source.method;
  71. return this;
  72. };
  73. ColorAdjustmentNode.prototype.toJSON = function ( meta ) {
  74. var data = this.getJSONNode( meta );
  75. if ( ! data ) {
  76. data = this.createJSONNode( meta );
  77. data.rgb = this.rgb.toJSON( meta ).uuid;
  78. data.adjustment = this.adjustment.toJSON( meta ).uuid;
  79. data.method = this.method;
  80. }
  81. return data;
  82. };
  83. export { ColorAdjustmentNode };