Advertisement
Guest User

sao_apply.fs

a guest
Jul 29th, 2022
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #version 140
  2.  
  3. // sao_downscale_and_reconstruct.fs
  4.  
  5. #extension GL_ARB_gpu_shader5 : enable
  6.  
  7. #include "sao_include.fs"
  8.  
  9. out vec3            out_FragColor;
  10.  
  11. #define visibility      out_FragColor.r
  12. #define bilateralKey    out_FragColor.gb
  13.  
  14. ////////////////////////////////////////////////////////////////
  15. // Tweakable parameters. You can mess with these, to change
  16. // the look of the effect.
  17. #define projScale 250.0
  18. #define radius 0.75
  19. #define radius2 (radius * radius)
  20. #define bias 0.01
  21. #define intensity 0.33
  22. #define intensityDivR6 0.333333
  23. #define epsilon 0.001
  24.  
  25. //** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */
  26. vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR)
  27. {
  28.     // Radius relative to ssR
  29.     float alpha = float(sampleNumber + 0.5) * (1.0 / NUM_SAMPLES);
  30.     float angle = alpha * (NUM_SPIRAL_TURNS * 6.28) + spinAngle;
  31.  
  32.     ssR = alpha;
  33.     return vec2(cos(angle), sin(angle));
  34. }
  35.  
  36.  
  37. //** Read the camera-space position of the point at screen-space pixel ssP */
  38. vec3 getPosition(ivec2 ssP)
  39. {
  40.     vec3 P;
  41.     P.z = texelFetch(PostSourceTexture, ssP, 0).r;
  42.  
  43.     // Offset to pixel center
  44.     P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
  45.     return P;
  46. }
  47.  
  48.  
  49. // Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR.  Assumes length(unitOffset) == 1 */
  50. vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR)
  51. {
  52.     // Derivation:
  53.     //  mipLevel = floor(log(ssR / MAX_OFFSET));
  54. #   ifdef GL_ARB_gpu_shader5
  55.         int mipLevel = clamp(findMSB(int(ssR)) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL);
  56. #   else
  57.         int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL);
  58. #   endif
  59.  
  60.     ivec2 ssP = ivec2(ssR * unitOffset) + ssC;
  61.    
  62.     vec3 P;
  63.  
  64.     // We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map.  
  65.     // Manually clamp to the texture size because texelFetch bypasses the texture unit
  66.     ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), textureSize(PostSourceTexture, mipLevel) - ivec2(1));
  67.     P.z = texelFetch(PostSourceTexture, mipP, mipLevel).r;
  68.  
  69.     // Offset to pixel center
  70.     P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
  71.  
  72.     return P;
  73. }
  74.  
  75. //** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds
  76. //    to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius
  77. //
  78. //    Note that units of H() in the HPG12 paper are meters, not
  79. //    unitless.  The whole falloff/sampling function is therefore
  80. //    unitless.  In this implementation, we factor out (9 / radius).
  81. //  
  82. //    Four versions of the falloff function are implemented below
  83. //  
  84. float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in int tapIndex, in float randomPatternRotationAngle)
  85. {
  86.     // Offset on the unit disk, spun for this pixel
  87.     float ssR;
  88.     vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR);
  89.     ssR *= ssDiskRadius;
  90.        
  91.     // The occluding point in camera space
  92.     vec3 Q = getOffsetPosition(ssC, unitOffset, ssR);
  93.  
  94.     vec3 v = Q - C;
  95.  
  96.     float vv = dot(v, v);
  97.     float vn = dot(v, n_C);
  98.  
  99.     // A: From the HPG12 paper
  100.     // Note large epsilon to avoid overdarkening within cracks
  101.     // return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6;
  102.  
  103.     // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended]
  104.     float f = max(radius2 - vv, 0.0); return f * f * f * max((vn - bias) / (epsilon + vv), 0.0);
  105.  
  106.     // C: Medium contrast (which looks better at high radii), no division.  Note that the
  107.     // contribution still falls off with radius^2, but we've adjusted the rate in a way that is
  108.     // more computationally efficient and happens to be aesthetically pleasing.
  109.     // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0);
  110.  
  111.     // D: Low contrast, no division operation
  112.     // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0);
  113. }
  114.  
  115. void main()
  116. {
  117.  
  118.     // Pixel being shaded
  119.     ivec2 ssC = ivec2(gl_FragCoord.xy);
  120.  
  121.     // World space point being shaded
  122.     vec3 C = getPosition(ssC);
  123.  
  124.     packKey(CSZToKey(C.z), bilateralKey);
  125.    
  126. //    if (C.z < FAR_PLANE_Z)
  127. //    {
  128. //        // We're on the skybox
  129. //        discard;
  130. //    }
  131.  
  132.     // Hash function used in the HPG12 AlchemyAO paper
  133.     float randomPatternRotationAngle = (3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10;
  134.  
  135.     // Reconstruct normals from positions. These will lead to 1-pixel black lines
  136.     // at depth discontinuities, however the blur will wipe those out so they are not visible
  137.     // in the final image.
  138.     vec3 n_C = reconstructCSFaceNormal(C);
  139.    
  140.     // Choose the screen-space sample radius
  141.     // proportional to the projected area of the sphere
  142.     float ssDiskRadius = -projScale * radius / C.z;
  143.    
  144.     float sum = 0.0;
  145.     for (int i = 0; i < NUM_SAMPLES; ++i)
  146.     {
  147.         sum += sampleAO(ssC, C, n_C, ssDiskRadius, i, randomPatternRotationAngle);
  148.     }
  149.  
  150.     float A = max(0.0, 1.0 - sum * intensityDivR6 * (5.0 / NUM_SAMPLES));
  151.  
  152.     // Bilateral box-filter over a quad for free, respecting depth edges
  153.     // (the difference that this makes is subtle)
  154.     if (abs(dFdx(C.z)) < 0.02)
  155.     {
  156.         A -= dFdx(A) * ((ssC.x & 1) - 0.5);
  157.     }
  158.     if (abs(dFdy(C.z)) < 0.02)
  159.     {
  160.         A -= dFdy(A) * ((ssC.y & 1) - 0.5);
  161.     }
  162.    
  163.     visibility = A;
  164. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement