cs_assao_apply.sc 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * Copyright 2018 Attila Kocsis. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
  4. */
  5. #include "bgfx_compute.sh"
  6. #include "uniforms.sh"
  7. IMAGE2D_WO(s_target, r8, 0);
  8. SAMPLER2DARRAY(s_finalSSAO, 1);
  9. // unpacking for edges; 2 bits per edge mean 4 gradient values (0, 0.33, 0.66, 1) for smoother transitions!
  10. vec4 UnpackEdges( float _packedVal )
  11. {
  12. uint packedVal = uint(_packedVal * 255.5);
  13. vec4 edgesLRTB;
  14. edgesLRTB.x = float((packedVal >> 6) & 0x03) / 3.0; // there's really no need for mask (as it's an 8 bit input) but I'll leave it in so it doesn't cause any trouble in the future
  15. edgesLRTB.y = float((packedVal >> 4) & 0x03) / 3.0;
  16. edgesLRTB.z = float((packedVal >> 2) & 0x03) / 3.0;
  17. edgesLRTB.w = float((packedVal >> 0) & 0x03) / 3.0;
  18. return saturate( edgesLRTB + u_invSharpness );
  19. }
  20. NUM_THREADS(8, 8, 1)
  21. void main()
  22. {
  23. uvec2 dtID = uvec2(gl_GlobalInvocationID.xy) + uvec2(u_rect.xy);
  24. if (all(lessThan(dtID.xy, u_rect.zw) ) )
  25. {
  26. float ao;
  27. uvec2 pixPos = uvec2(dtID.xy);
  28. uvec2 pixPosHalf = pixPos / uvec2(2, 2);
  29. // calculate index in the four deinterleaved source array texture
  30. int mx = (int(pixPos.x) % 2);
  31. #if BGFX_SHADER_LANGUAGE_GLSL
  32. int dimy = imageSize(s_target).y;
  33. int my = (int(dimy-1-pixPos.y) % 2);
  34. #else
  35. int my = (int(pixPos.y) % 2);
  36. #endif
  37. int ic = mx + my * 2; // center index
  38. int ih = (1-mx) + my * 2; // neighbouring, horizontal
  39. int iv = mx + (1-my) * 2; // neighbouring, vertical
  40. int id = (1-mx) + (1-my)*2; // diagonal
  41. vec2 centerVal = texelFetch(s_finalSSAO, ivec3(pixPosHalf, ic), 0 ).xy;
  42. ao = centerVal.x;
  43. #if 1 // change to 0 if you want to disable last pass high-res blur (for debugging purposes, etc.)
  44. vec4 edgesLRTB = UnpackEdges( centerVal.y );
  45. // return 1.0 - vec4( edgesLRTB.x, edgesLRTB.y * 0.5 + edgesLRTB.w * 0.5, edgesLRTB.z, 0.0 ); // debug show edges
  46. // convert index shifts to sampling offsets
  47. float fmx = float(mx);
  48. float fmy = float(my);
  49. // in case of an edge, push sampling offsets away from the edge (towards pixel center)
  50. float fmxe = (edgesLRTB.y - edgesLRTB.x);
  51. float fmye = (edgesLRTB.w - edgesLRTB.z);
  52. // calculate final sampling offsets and sample using bilinear filter
  53. #if BGFX_SHADER_LANGUAGE_GLSL
  54. vec2 uvH = (dtID.xy + vec2( fmx + fmxe - 0.5, 1.0 - (0.5 - fmy) ) ) * 0.5 * u_halfViewportPixelSize;
  55. #else
  56. vec2 uvH = (dtID.xy + vec2( fmx + fmxe - 0.5, 0.5 - fmy ) ) * 0.5 * u_halfViewportPixelSize;
  57. #endif
  58. float aoH = texture2DArrayLod(s_finalSSAO, vec3( uvH, ih ), 0 ).x;
  59. #if BGFX_SHADER_LANGUAGE_GLSL
  60. vec2 uvV = (dtID.xy + vec2( 0.5 - fmx, 1.0 - (fmy - 0.5 + fmye) ) ) * 0.5 * u_halfViewportPixelSize;
  61. #else
  62. vec2 uvV = (dtID.xy + vec2( 0.5 - fmx, fmy - 0.5 + fmye ) ) * 0.5 * u_halfViewportPixelSize;
  63. #endif
  64. float aoV = texture2DArrayLod(s_finalSSAO, vec3( uvV, iv ), 0 ).x;
  65. #if BGFX_SHADER_LANGUAGE_GLSL
  66. vec2 uvD = (dtID.xy + vec2( fmx - 0.5 + fmxe, 1.0 - (fmy - 0.5 + fmye) ) ) * 0.5 * u_halfViewportPixelSize;
  67. #else
  68. vec2 uvD = (dtID.xy + vec2( fmx - 0.5 + fmxe, fmy - 0.5 + fmye ) ) * 0.5 * u_halfViewportPixelSize;
  69. #endif
  70. float aoD = texture2DArrayLod(s_finalSSAO, vec3( uvD, id ), 0 ).x;
  71. // reduce weight for samples near edge - if the edge is on both sides, weight goes to 0
  72. vec4 blendWeights;
  73. blendWeights.x = 1.0;
  74. blendWeights.y = (edgesLRTB.x + edgesLRTB.y) * 0.5;
  75. blendWeights.z = (edgesLRTB.z + edgesLRTB.w) * 0.5;
  76. blendWeights.w = (blendWeights.y + blendWeights.z) * 0.5;
  77. // calculate weighted average
  78. float blendWeightsSum = dot( blendWeights, vec4( 1.0, 1.0, 1.0, 1.0 ) );
  79. ao = dot( vec4( ao, aoH, aoV, aoD ), blendWeights ) / blendWeightsSum;
  80. #endif
  81. ao = pow(ao,1.0/2.2);
  82. imageStore(s_target, ivec2(dtID.xy), ao.xxxx);
  83. }
  84. }