ColorSpaceNode.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import TempNode from '../core/TempNode.js';
  2. import { mix } from '../math/MathNode.js';
  3. import { addNodeClass } from '../core/Node.js';
  4. import { addNodeElement, tslFn, nodeObject, nodeProxy, vec4 } from '../shadernode/ShaderNode.js';
  5. import { LinearSRGBColorSpace, SRGBColorSpace } from 'three';
  6. const sRGBToLinearShader = tslFn( ( inputs ) => {
  7. const { value } = inputs;
  8. const { rgb } = value;
  9. const a = rgb.mul( 0.9478672986 ).add( 0.0521327014 ).pow( 2.4 );
  10. const b = rgb.mul( 0.0773993808 );
  11. const factor = rgb.lessThanEqual( 0.04045 );
  12. const rgbResult = mix( a, b, factor );
  13. return vec4( rgbResult, value.a );
  14. } );
  15. const LinearTosRGBShader = tslFn( ( inputs ) => {
  16. const { value } = inputs;
  17. const { rgb } = value;
  18. const a = rgb.pow( 0.41666 ).mul( 1.055 ).sub( 0.055 );
  19. const b = rgb.mul( 12.92 );
  20. const factor = rgb.lessThanEqual( 0.0031308 );
  21. const rgbResult = mix( a, b, factor );
  22. return vec4( rgbResult, value.a );
  23. } );
  24. const getColorSpaceMethod = ( colorSpace ) => {
  25. let method = null;
  26. if ( colorSpace === LinearSRGBColorSpace ) {
  27. method = 'Linear';
  28. } else if ( colorSpace === SRGBColorSpace ) {
  29. method = 'sRGB';
  30. }
  31. return method;
  32. };
  33. const getMethod = ( source, target ) => {
  34. return getColorSpaceMethod( source ) + 'To' + getColorSpaceMethod( target );
  35. };
  36. class ColorSpaceNode extends TempNode {
  37. constructor( method, node ) {
  38. super( 'vec4' );
  39. this.method = method;
  40. this.node = node;
  41. }
  42. setup() {
  43. const { method, node } = this;
  44. if ( method === ColorSpaceNode.LINEAR_TO_LINEAR )
  45. return node;
  46. return Methods[ method ]( { value: node } );
  47. }
  48. }
  49. ColorSpaceNode.LINEAR_TO_LINEAR = 'LinearToLinear';
  50. ColorSpaceNode.LINEAR_TO_sRGB = 'LinearTosRGB';
  51. ColorSpaceNode.sRGB_TO_LINEAR = 'sRGBToLinear';
  52. const Methods = {
  53. [ ColorSpaceNode.LINEAR_TO_sRGB ]: LinearTosRGBShader,
  54. [ ColorSpaceNode.sRGB_TO_LINEAR ]: sRGBToLinearShader
  55. };
  56. export default ColorSpaceNode;
  57. export const linearToColorSpace = ( node, colorSpace ) => nodeObject( new ColorSpaceNode( getMethod( LinearSRGBColorSpace, colorSpace ), nodeObject( node ) ) );
  58. export const colorSpaceToLinear = ( node, colorSpace ) => nodeObject( new ColorSpaceNode( getMethod( colorSpace, LinearSRGBColorSpace ), nodeObject( node ) ) );
  59. export const linearTosRGB = nodeProxy( ColorSpaceNode, ColorSpaceNode.LINEAR_TO_sRGB );
  60. export const sRGBToLinear = nodeProxy( ColorSpaceNode, ColorSpaceNode.sRGB_TO_LINEAR );
  61. addNodeElement( 'linearTosRGB', linearTosRGB );
  62. addNodeElement( 'sRGBToLinear', sRGBToLinear );
  63. addNodeElement( 'linearToColorSpace', linearToColorSpace );
  64. addNodeElement( 'colorSpaceToLinear', colorSpaceToLinear );
  65. addNodeClass( 'ColorSpaceNode', ColorSpaceNode );