dof.glsl 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // DoF with bokeh GLSL shader by Martins Upitis (martinsh) (devlog-martinsh.blogspot.com)
  2. // Creative Commons Attribution 3.0 Unported License
  3. #include "compiled.inc"
  4. #include "std/math.glsl"
  5. // const float compoDOFDistance = 10.0; // Focal distance value in meters
  6. // const float compoDOFLength = 160.0; // Focal length in mm 18-200
  7. // const float compoDOFFstop = 128.0; // F-stop value
  8. const int samples = 6; // Samples on the first ring
  9. const int rings = 6; // Ring count
  10. const vec2 focus = vec2(0.5, 0.5);
  11. const float coc = 0.11; // Circle of confusion size in mm (35mm film = 0.03mm)
  12. const float maxblur = 1.0;
  13. const float threshold = 0.5; // Highlight threshold
  14. const float gain = 2.0; // Highlight gain
  15. const float bias = 0.5; // Bokeh edge bias
  16. const float fringe = 0.7; // Bokeh chromatic aberration/fringing
  17. const float namount = 0.0001; // Dither amount
  18. vec3 color(vec2 coords, const float blur, const sampler2D tex, const vec2 texStep) {
  19. vec3 col = vec3(0.0);
  20. col.r = textureLod(tex, coords + vec2(0.0, 1.0) * texStep * fringe * blur, 0.0).r;
  21. col.g = textureLod(tex, coords + vec2(-0.866, -0.5) * texStep * fringe * blur, 0.0).g;
  22. col.b = textureLod(tex, coords + vec2(0.866, -0.5) * texStep * fringe * blur, 0.0).b;
  23. const vec3 lumcoeff = vec3(0.299, 0.587, 0.114);
  24. float lum = dot(col.rgb, lumcoeff);
  25. float thresh = max((lum - threshold) * gain, 0.0);
  26. return col + mix(vec3(0.0), col, thresh * blur);
  27. }
  28. vec3 dof(const vec2 texCoord, const float gdepth, const sampler2D tex, const sampler2D gbufferD, const vec2 texStep, const vec2 cameraProj) {
  29. float depth = linearize(gdepth, cameraProj);
  30. // const float fDepth = compoDOFDistance;
  31. float fDepth = linearize(textureLod(gbufferD, focus, 0.0).r * 2.0 - 1.0, cameraProj); // Autofocus
  32. const float f = compoDOFLength; // Focal length in mm
  33. const float d = fDepth * 1000.0; // Focal plane in mm
  34. float o = depth * 1000.0; // Depth in mm
  35. float a = (o * f) / (o - f);
  36. float b = (d * f) / (d - f);
  37. float c = (d - f) / (d * compoDOFFstop * coc);
  38. float blur = abs(a - b) * c;
  39. blur = clamp(blur, 0.0, 1.0);
  40. vec2 noise = rand2(texCoord) * namount * blur;
  41. float w = (texStep.x) * blur * maxblur + noise.x;
  42. float h = (texStep.y) * blur * maxblur + noise.y;
  43. vec3 col = vec3(0.0);
  44. if (blur < 0.05) {
  45. col = textureLod(tex, texCoord, 0.0).rgb;
  46. }
  47. else {
  48. col = textureLod(tex, texCoord, 0.0).rgb;
  49. float s = 1.0;
  50. int ringsamples;
  51. for (int i = 1; i <= rings; ++i) {
  52. ringsamples = i * samples;
  53. for (int j = 0 ; j < ringsamples; ++j) {
  54. float step = PI2 / float(ringsamples);
  55. float pw = (cos(float(j) * step) * float(i));
  56. float ph = (sin(float(j) * step) * float(i));
  57. float p = 1.0;
  58. // if (pentagon) p = penta(vec2(pw, ph));
  59. col += color(texCoord + vec2(pw * w, ph * h), blur, tex, texStep) * mix(1.0, (float(i)) / (float(rings)), bias) * p;
  60. s += 1.0 * mix(1.0, (float(i)) / (float(rings)), bias) * p;
  61. }
  62. }
  63. col /= s;
  64. }
  65. return col;
  66. }