imageProcessing.fragment.fx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Samplers
  2. varying vec2 vUV;
  3. uniform sampler2D textureSampler;
  4. const float GammaEncodePowerApprox = 1.0 / 2.2;
  5. const vec3 RGBLuminanceCoefficients = vec3(0.2126, 0.7152, 0.0722);
  6. uniform float contrast;
  7. uniform vec4 vignetteSettings1;
  8. uniform vec4 vignetteSettings2;
  9. uniform vec4 vignetteSettings3;
  10. uniform float cameraExposureLinear;
  11. uniform float toneMappingEnabled;
  12. uniform vec4 vCameraColorCurveNegative;
  13. uniform vec4 vCameraColorCurveNeutral;
  14. uniform vec4 vCameraColorCurvePositive;
  15. uniform bool hasTextureColorTransform;
  16. uniform sampler2D txColorTransform;
  17. uniform vec4 colorTransformSettings;
  18. #define VignetteBlendModeMultiply 0.0
  19. #define VignetteBlendModeOpaque 1.0
  20. vec3 applyEaseInOut(vec3 x){
  21. return x * x * (3.0 - 2.0 * x);
  22. }
  23. /**
  24. * Polyfill for SAMPLE_TEXTURE_3D, which is unsupported in WebGL.
  25. * colorTransformSettings.y = textureOffset (0.5 / textureSize).
  26. * colorTransformSettings.z = textureSize.
  27. */
  28. vec3 sampleTexture3D(sampler2D colorTransform, vec3 color)
  29. {
  30. float sliceSize = 2.0 * colorTransformSettings.y; // Size of 1 slice relative to the texture, for example 1/8
  31. float sliceContinuous = (color.y - colorTransformSettings.y) * colorTransformSettings.z;
  32. float sliceInteger = floor(sliceContinuous);
  33. // Note: this is mathematically equivalent to fract(sliceContinuous); but we use explicit subtract
  34. // rather than separate fract() for correct results near slice boundaries (matching sliceInteger choice)
  35. float sliceFraction = sliceContinuous - sliceInteger;
  36. vec2 sliceUV = color.xz;
  37. sliceUV.x *= sliceSize;
  38. sliceUV.x += sliceInteger * sliceSize;
  39. vec4 slice0Color = texture2D(colorTransform, sliceUV);
  40. sliceUV.x += sliceSize;
  41. vec4 slice1Color = texture2D(colorTransform, sliceUV);
  42. vec3 result = mix(slice0Color.rgb, slice1Color.rgb, sliceFraction);
  43. color.rgb = result.bgr;
  44. return color;
  45. }
  46. vec4 applyImageProcessing(vec4 result, vec2 viewportXY){
  47. result.rgb *= cameraExposureLinear;
  48. //vignette
  49. vec3 vignetteXY1 = vec3(viewportXY * vignetteSettings1.xy + vignetteSettings1.zw, 1.0);
  50. float vignetteTerm = dot(vignetteXY1, vignetteXY1);
  51. float vignette = pow(vignetteTerm, vignetteSettings2.w);
  52. // Interpolate between the artist 'color' and white based on the physical transmission value 'vignette'.
  53. vec3 vignetteColor = vignetteSettings2.rgb;
  54. float vignetteBlendMode = vignetteSettings3.w;
  55. if (vignetteBlendMode == VignetteBlendModeMultiply) {
  56. vec3 vignetteColorMultiplier = mix(vignetteColor, vec3(1, 1, 1), vignette);
  57. result.rgb *= vignetteColorMultiplier;
  58. }
  59. if (vignetteBlendMode == VignetteBlendModeOpaque) {
  60. result.rgb = mix(vignetteColor, result.rgb, vignette);
  61. }
  62. float tonemappingCalibration = 1.590579;
  63. vec3 tonemapped = 1.0 - exp2(-tonemappingCalibration * result.rgb);
  64. result.rgb = mix(result.rgb, tonemapped, toneMappingEnabled);
  65. result.rgb = pow(result.rgb, vec3(GammaEncodePowerApprox));
  66. result.rgb = clamp(result.rgb, 0.0, 1.0);
  67. vec3 resultHighContrast = applyEaseInOut(result.rgb);
  68. if (contrast < 1.0) {
  69. result.rgb = mix(vec3(0.5, 0.5, 0.5), result.rgb, contrast);
  70. } else {
  71. result.rgb = mix(result.rgb, resultHighContrast, contrast - 1.0);
  72. }
  73. // Apply Color Transform
  74. if (hasTextureColorTransform) {
  75. vec3 colorTransformInput = result.rgb * colorTransformSettings.xxx + colorTransformSettings.yyy;
  76. vec3 colorTransformOutput = sampleTexture3D(txColorTransform, colorTransformInput).rgb;
  77. result.rgb = mix(result.rgb, colorTransformOutput, colorTransformSettings.www);
  78. }
  79. // Apply Color Curves
  80. float luma = dot(result.rgb, RGBLuminanceCoefficients);
  81. vec2 curveMix = clamp(vec2(luma * 3.0 - 1.5, luma * -3.0 + 1.5), vec2(0.0), vec2(1.0));
  82. vec4 colorCurve = vCameraColorCurveNeutral + curveMix.x * vCameraColorCurvePositive - curveMix.y * vCameraColorCurveNegative;
  83. result.rgb *= colorCurve.rgb;
  84. result.rgb = mix(vec3(luma), result.rgb, colorCurve.a);
  85. return result;
  86. }
  87. void main(void)
  88. {
  89. vec4 result = texture2D(textureSampler, vUV);
  90. vec2 viewportXY = texelCoord * 2.0 - 1.0;
  91. result = applyImageProcessing(result, viewportXY);
  92. gl_FragColor = result;
  93. }