ssao_blur.glsl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* clang-format off */
  2. [vertex]
  3. layout(location = 0) in highp vec4 vertex_attrib;
  4. /* clang-format on */
  5. void main() {
  6. gl_Position = vertex_attrib;
  7. gl_Position.z = 1.0;
  8. }
  9. /* clang-format off */
  10. [fragment]
  11. uniform sampler2D source_ssao; //texunit:0
  12. /* clang-format on */
  13. uniform sampler2D source_depth; //texunit:1
  14. uniform sampler2D source_normal; //texunit:3
  15. layout(location = 0) out float visibility;
  16. //////////////////////////////////////////////////////////////////////////////////////////////
  17. // Tunable Parameters:
  18. /** Increase to make depth edges crisper. Decrease to reduce flicker. */
  19. uniform float edge_sharpness;
  20. /** Step in 2-pixel intervals since we already blurred against neighbors in the
  21. first AO pass. This constant can be increased while R decreases to improve
  22. performance at the expense of some dithering artifacts.
  23. Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was
  24. unobjectionable after shading was applied but eliminated most temporal incoherence
  25. from using small numbers of sample taps.
  26. */
  27. uniform int filter_scale;
  28. /** Filter radius in pixels. This will be multiplied by SCALE. */
  29. #define R (4)
  30. //////////////////////////////////////////////////////////////////////////////////////////////
  31. // Gaussian coefficients
  32. const float gaussian[R + 1] =
  33. //float[](0.356642, 0.239400, 0.072410, 0.009869);
  34. //float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0
  35. float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0
  36. //float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0
  37. /** (1, 0) or (0, 1)*/
  38. uniform ivec2 axis;
  39. uniform float camera_z_far;
  40. uniform float camera_z_near;
  41. uniform ivec2 screen_size;
  42. void main() {
  43. ivec2 ssC = ivec2(gl_FragCoord.xy);
  44. float depth = texelFetch(source_depth, ssC, 0).r;
  45. //vec3 normal = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0;
  46. depth = depth * 2.0 - 1.0;
  47. depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
  48. float depth_divide = 1.0 / camera_z_far;
  49. //depth *= depth_divide;
  50. /*
  51. if (depth > camera_z_far * 0.999) {
  52. discard; //skybox
  53. }
  54. */
  55. float sum = texelFetch(source_ssao, ssC, 0).r;
  56. // Base weight for depth falloff. Increase this for more blurriness,
  57. // decrease it for better edge discrimination
  58. float BASE = gaussian[0];
  59. float totalWeight = BASE;
  60. sum *= totalWeight;
  61. ivec2 clamp_limit = screen_size - ivec2(1);
  62. for (int r = -R; r <= R; ++r) {
  63. // We already handled the zero case above. This loop should be unrolled and the static branch optimized out,
  64. // so the IF statement has no runtime cost
  65. if (r != 0) {
  66. ivec2 ppos = ssC + axis * (r * filter_scale);
  67. float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r;
  68. ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit);
  69. float temp_depth = texelFetch(source_depth, rpos, 0).r;
  70. //vec3 temp_normal = texelFetch(source_normal, rpos, 0).rgb * 2.0 - 1.0;
  71. temp_depth = temp_depth * 2.0 - 1.0;
  72. temp_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - temp_depth * (camera_z_far - camera_z_near));
  73. // temp_depth *= depth_divide;
  74. // spatial domain: offset gaussian tap
  75. float weight = 0.3 + gaussian[abs(r)];
  76. //weight *= max(0.0,dot(temp_normal,normal));
  77. // range domain (the "bilateral" weight). As depth difference increases, decrease weight.
  78. weight *= max(0.0, 1.0 - edge_sharpness * abs(temp_depth - depth));
  79. sum += value * weight;
  80. totalWeight += weight;
  81. }
  82. }
  83. const float epsilon = 0.0001;
  84. visibility = sum / (totalWeight + epsilon);
  85. }