post_effects.fs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #version 120
  2. /* Headers */
  3. vec3 unsharp_mask(sampler2D screen, vec2 coords, float strength, int width, int height);
  4. vec3 chromatic_aberration(sampler2D screen, vec2 coords, float offset);
  5. vec3 basic_dof(int width, int height, sampler2D screen, sampler2D screendepth, sampler2D random, vec2 coords);
  6. vec3 bokeh_dof(int width, int height, float near, float far, sampler2D screen, sampler2D screendepth, sampler2D random, vec2 coords, float focalDepth);
  7. float linear_depth(float depth, float near, float far);
  8. /* End */
  9. vec3 unsharp_mask(sampler2D screen, vec2 coords, float strength, int width, int height) {
  10. float off_x = 1.0 / float(width);
  11. float off_y = 1.0 / float(height);
  12. vec3 s0 = texture2D(screen, coords + vec2(-off_x, off_y)).rgb;
  13. vec3 s1 = texture2D(screen, coords + vec2(0.0, off_y)).rgb;
  14. vec3 s2 = texture2D(screen, coords + vec2(off_x, off_y)).rgb;
  15. vec3 s3 = texture2D(screen, coords + vec2(-off_x, 0.0)).rgb;
  16. vec3 s4 = texture2D(screen, coords + vec2(0.0, 0.0)).rgb;
  17. vec3 s5 = texture2D(screen, coords + vec2(off_x, 0.0)).rgb;
  18. vec3 s6 = texture2D(screen, coords + vec2(-off_x, -off_y)).rgb;
  19. vec3 s7 = texture2D(screen, coords + vec2(0.0, 0.0)).rgb;
  20. vec3 s8 = texture2D(screen, coords + vec2(off_x, -off_y)).rgb;
  21. vec3 avg = (s0 + s1 + s2 + s3 + s5 + s6 + s7 + s8) / 8.0;
  22. vec3 diff = s4 - avg;
  23. return s4 + (diff * strength);
  24. }
  25. vec3 chromatic_aberration(sampler2D screen, vec2 coords, float offset) {
  26. offset = offset / 1000.0;
  27. vec3 result;
  28. result.r = texture2D(screen, coords + vec2(offset,0.0)).r;
  29. result.g = texture2D(screen, coords - vec2(offset,0.0)).g;
  30. result.b = texture2D(screen, coords - vec2(offset,0.0)).b;
  31. return result;
  32. }
  33. float linear_depth(float depth, float near, float far) {
  34. return (2.0 * near) / (far + near - depth * (far - near));
  35. }
  36. // Depth of field
  37. vec2 sample_circle[32] = vec2[32](vec2(-0.00, 0.02), vec2(0.35, 0.04), vec2(0.66, 0.32), vec2(-0.04, 0.04), vec2(0.24, 0.22), vec2(-0.09, 0.10), vec2(0.24, 0.04), vec2(0.37, 0.88), vec2(0.02, 0.11), vec2(-0.04, 0.83), vec2(0.33, 0.11), vec2(0.21, 0.17), vec2(0.48, 0.30), vec2(0.39, 0.72), vec2(0.19, 0.20), vec2(0.35, 0.04), vec2(-0.00, 0.02), vec2(-0.07, 0.12), vec2(0.00, 0.01), vec2(-0.27, 0.41), vec2(0.13, 0.26), vec2(0.15, 0.19), vec2(-0.32, 0.29), vec2(-0.00, 0.00), vec2(-0.36, 0.18), vec2(0.70, 0.21), vec2(-0.36, 0.17), vec2(-0.11, 0.12), vec2(-0.59, 0.67), vec2(-0.24, 0.75), vec2(0.18, 0.04), vec2(-0.16, 0.11));
  38. vec3 pow_3(vec3 x, float f) {
  39. vec3 y;
  40. y.r = pow(x.r, f);
  41. y.g = pow(x.g, f);
  42. y.b = pow(x.b, f);
  43. return y;
  44. }
  45. vec3 circle_blur(int width, int height, sampler2D screen, sampler2D random, vec2 coords, float amount, float size) {
  46. vec2 texel = vec2(1.0/float(width), 1.0/float(height));
  47. vec3 pixel = texture2D(screen, coords).rgb;
  48. const float randscale = 50;
  49. vec2 rand = texture2D(random, coords * randscale).xy;
  50. vec3 accum = vec3(0.0, 0.0, 0.0);
  51. const int samples = 16;
  52. for(int i = 0; i < samples; i++) {
  53. vec2 reflected = reflect(sample_circle[i], rand);
  54. vec3 sample = texture2D(screen, coords + reflected * texel * size).rgb;
  55. accum += sample;
  56. }
  57. accum /= samples;
  58. return mix(pixel, accum, clamp(amount, 0.0, 1.0));
  59. }
  60. vec3 basic_dof(int width, int height, sampler2D screen, sampler2D screendepth, sampler2D random, vec2 coords) {
  61. vec3 pixel = texture2D(screen, coords).rgb;
  62. float depth = texture2D(screendepth, coords).r;
  63. float center_depth = texture2D(screendepth, vec2(0.5, 0.5)).r;
  64. float amount = pow( abs(depth-center_depth), 2.0);
  65. float brightness = pow( dot(pixel, vec3(1.0, 1.0, 1.0)), 2.0);
  66. amount = abs(amount) * 1.0;
  67. return circle_blur(width, height, screen, random, coords, amount, 50.0);
  68. }
  69. vec3 bokeh_color(sampler2D screen, vec2 coords, vec2 texel, float blur) {
  70. const float threshold = 0.5;
  71. const float gain = 5.0;
  72. const float fringe = 0.75;
  73. vec3 col;
  74. col.r = texture2D(screen, coords + vec2(0.0,1.0)*texel*fringe*blur).r;
  75. col.g = texture2D(screen, coords + vec2(-0.866,-0.5)*texel*fringe*blur).g;
  76. col.b = texture2D(screen, coords + vec2(0.866,-0.5)*texel*fringe*blur).b;
  77. vec3 lumcoeff = vec3(0.299, 0.587, 0.114);
  78. float lum = dot(col.rgb, lumcoeff);
  79. float thresh = max((lum-threshold)*gain, 0.0);
  80. return col + mix(vec3(0.0, 0.0, 0.0), col, thresh * blur);
  81. }
  82. vec3 bokeh_dof(int width, int height, sampler2D screen, sampler2D screendepth, sampler2D random, vec2 coords, float focal_depth) {
  83. vec2 texel = vec2(1.0/width,1.0/height);
  84. const float focal_length = 0.5; // Lower is wider range of sharp focus
  85. const float fstop = 1000.0; // Lower increases over exposure
  86. const float CoC = 0.003; // Just multiplied by fstop
  87. const float fblur = 30.0;
  88. float depth = texture2D(screendepth, coords).x;
  89. float center_depth = texture2D(screendepth, vec2(0.5, 0.5)).x;
  90. float focus_depth = focal_depth > 0.0 ? focal_depth : center_depth;
  91. float f = focal_length; //focal length in mm
  92. float d = focus_depth * 1000.0; //focal plane in mm
  93. float o = depth * 1000.0; //depth in mm
  94. float a = (o*f)/(o-f);
  95. float b = (d*f)/(d-f);
  96. float c = (d-f)/(d * fstop * CoC);
  97. float blur = abs(a-b)*c;
  98. blur = clamp(blur, 0.0, 1.0);
  99. vec2 noise = texture2D(random, coords * 100 * blur).rg;
  100. // getting blur x and y step factor
  101. vec2 offset = noise * texel * blur * fblur;
  102. // calculation of final color
  103. const int samples = 3; //samples on the first ring
  104. const int rings = 3; //ring count
  105. const float bias = 0.5; //bokeh edge bias
  106. vec3 col = vec3(0.0);
  107. if(blur < 0.05) {
  108. col = texture2D(screen, coords).rgb;
  109. } else {
  110. col = texture2D(screen, coords).rgb;
  111. float s = 1.0;
  112. for (int i = 1; i <= rings; i += 1) {
  113. int ringsamples = i * samples;
  114. for (int j = 0 ; j < ringsamples ; j += 1) {
  115. float step = 3.141*2.0 / float(ringsamples);
  116. float pw = (cos(float(j)*step)*float(i));
  117. float ph = (sin(float(j)*step)*float(i));
  118. float amount = mix(1.0,(float(i))/(float(rings)),bias);
  119. col += bokeh_color(screen, coords + vec2(pw,ph) * offset, texel, blur) * amount;
  120. s += 1.0 * mix(1.0,(float(i))/(float(rings)),bias);
  121. }
  122. }
  123. col /= s;
  124. }
  125. return col;
  126. }