DavidNorgren

GLSL SSAO

Jul 26th, 2015
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Do not change samples unless you change it in SSAO_INIT!
  2. #define SAMPLES 16
  3.  
  4. varying vec2 vTexCoord;
  5.  
  6. uniform sampler2D uDepthBuffer;
  7. uniform sampler2D uNormalBuffer;
  8. uniform sampler2D uNoiseBuffer;
  9.  
  10. uniform float uCamNear;
  11. uniform float uCamFar;
  12.  
  13. uniform mat4 uProjMatrix;
  14. uniform mat4 uProjMatrixInv;
  15.  
  16. uniform vec2 uScreenSize;
  17.  
  18. uniform vec3 uSSAOKernel[16];
  19. uniform float uSSAORadius;
  20. uniform float uSSAOStrength;
  21. uniform float uSSAOPower;
  22.  
  23. // Get Depth Value
  24. float unpackDepth(vec4 c){
  25.     return clamp(c.r + c.g / 255.0 + c.b / (255.0 * 255.0), 0.0, 1.0);
  26. }
  27.  
  28. // Get Normal Value
  29. vec3 unpackNormal(vec4 c) {
  30.     return normalize(c.xyz * 2.0 - 1.0);
  31. }
  32.  
  33. // Transform linear depth to exponential depth
  34. float transformDepth(float depth) {
  35.     return (uCamFar - (uCamNear * uCamFar) / (depth * (uCamFar - uCamNear) + uCamNear)) / (uCamFar - uCamNear);
  36. }
  37.  
  38. // Reconstruct a position from a screen space coordinate and (linear) depth
  39. vec3 posFromBuffer(vec2 coord, float depth) {
  40.     vec4 pos = uProjMatrixInv * vec4(coord.x * 2.0 - 1.0, 1.0 - coord.y * 2.0, transformDepth(depth), 1.0);
  41.     return pos.xyz / pos.w;
  42. }
  43.  
  44. void main() {
  45.     // Perform alpha test to ignore background
  46.     if (texture2D(uDepthBuffer,vTexCoord).a < 1.0)
  47.         discard;
  48.    
  49.     // Get view space origin
  50.     float originDepth = unpackDepth(texture2D(uDepthBuffer,vTexCoord));
  51.     vec3 origin = posFromBuffer(vTexCoord, originDepth);
  52.    
  53.     // Get scaled radius
  54.     float sampleRadius = uSSAORadius * (1.0 - originDepth);
  55.    
  56.     // Get normal
  57.     vec3 normal = unpackNormal(texture2D(uNormalBuffer, vTexCoord));
  58.    
  59.     // Random vector from noise
  60.     vec2 noiseScale = (uScreenSize / 4.0);
  61.     vec3 randVec = unpackNormal(texture2D(uNoiseBuffer, vTexCoord * noiseScale));
  62.    
  63.     // Construct kernel basis matrix
  64.     vec3 tangent = normalize(randVec - normal * dot(randVec, normal));
  65.     vec3 bitangent = cross(tangent, normal);
  66.     mat3 kernelBasis = mat3(tangent, bitangent, normal);
  67.    
  68.     // Calculate occlusion factor
  69.     float occlusion = 0.0;
  70.     for (int i = 0; i < SAMPLES; i++) {
  71.         // Get sample position
  72.         vec3 samplePos = origin + kernelBasis * uSSAOKernel[i] * sampleRadius;
  73.        
  74.         // Project sample position
  75.         vec4 sampleScreen = uProjMatrix * vec4(samplePos, 1.0);
  76.         vec2 sampleTex = (sampleScreen.xy / sampleScreen.w) * 0.5 + 0.5;
  77.         sampleTex.y = 1.0 - sampleTex.y;
  78.        
  79.         // Get sample depth
  80.         float sampleDepth = posFromBuffer(sampleTex, unpackDepth(texture2D(uDepthBuffer,sampleTex))).z;
  81.        
  82.         // Add occlusion if checks succeed
  83.         float bias = 1.0 / sampleRadius; // Bigger bias for smaller radius's (to fix artifacts)
  84.         float depthCheck = (sampleDepth < samplePos.z - bias) ? 1.0 : 0.0;
  85.         float rangeCheck = (abs(sampleDepth - origin.z) < sampleRadius) ? 1.0 : 0.0;
  86.         occlusion += depthCheck * rangeCheck *  uSSAOStrength;
  87.     }
  88.    
  89.     // Invert and raise to power
  90.     float power = uSSAOPower;
  91.     float col = 1.0 - (occlusion / float(SAMPLES));
  92.     col = pow(clamp(col, 0.0, 1.0), power);
  93.    
  94.     gl_FragColor = vec4(vec3(col), 1.0);
  95. }
  96.  
  97.  
  98. // Reconstruct Position From Depth
  99. /*vec3 reconstructPosition(vec2 texCoord) {
  100.     // Calculate out of the fragment in screen space the view space position.
  101.     float xx = texCoord.s * 2.0 - 1.0;
  102.     float yy = texCoord.t * 2.0 - 1.0;
  103.     float zz = unpackDepth(texture2D(uDepthBuffer, texCoord));
  104.  
  105.     vec4 posView = uProjMatrixInv * vec4(xx, yy, zz, 1.0);
  106.     posView /= posView.w;
  107.     return posView.xyz;
  108. }
  109.  
  110. // Calculate SSAO
  111. void main() {
  112.     // Information about the current screen-pixel
  113.     float depth         = unpackDepth(texture2D(uDepthBuffer, vTexCoord)) * uCamFar;
  114.     vec3 depthPosition  = reconstructPosition(vTexCoord);
  115.     vec3 normal         = unpackNormal(texture2D(uNormalBuffer, vTexCoord));
  116.    
  117.     // Calculate adjusted SSAO radius
  118.     float offsetScale   = uSSAORadius / depth;
  119.    
  120.     // Calculate Noise
  121.     vec2 noiseScale     = uScreenSize / 4.0;
  122.     vec2 noiseVector    = normalize(texture2D(uNoiseBuffer, vTexCoord * noiseScale).xy * 2.0 - 1.0);
  123.    
  124.     // Get Aspect Ratio
  125.     float iAspectRatio  = uScreenSize.y / uScreenSize.x;
  126.    
  127.     // Do the SSAO calculation
  128.     float occlusion         = 0.0;
  129.     float samplesOccluded   = 0.0;
  130.    
  131.     for (int i = 0; i < SAMPLES; i++) {
  132.         // Get sample position
  133.         vec2 offset          = reflect(uSSAOKernel[i].xy, noiseVector) * offsetScale;
  134.         offset.x            *= iAspectRatio;
  135.         vec2 sampleCoords    = vTexCoord + offset;
  136.        
  137.         // Test if Samplecoords are inside the actual texture-range
  138.         float TEXCHECK      = (sampleCoords.x >= 0.0 && sampleCoords.x <= 1.0 && sampleCoords.y >= 0.0 && sampleCoords.y <= 1.0) ? 1.0 : 0.0;
  139.         samplesOccluded    += TEXCHECK;
  140.        
  141.         vec3 sample         = reconstructPosition(sampleCoords);
  142.         vec3 sampleNormal   = unpackNormal(texture2D(uNormalBuffer, sampleCoords));
  143.        
  144.         // Calculate check variables
  145.         vec3 normalDifference = sampleNormal - normal;
  146.         float normalDot       = dot(sampleNormal, normal);
  147.         //float normalAngle     =
  148.         float normalCheck     = abs(normalDifference.x) + abs(normalDifference.y) + abs(normalDifference.z);
  149.         float depthCheck      = (depthPosition.z >= sample.z) ? 1.0 : 0.0;
  150.         float rangeCheck      = (abs(depthPosition.z - sample.z) * uCamFar < uSSAORadius * 2.0) ? 1.0 : 0.0;
  151.        
  152.         // Calculate SSAO (Has to pass range-check, normal-check, and depth-check)
  153.         occlusion += (rangeCheck * normalCheck * depthCheck) * uSSAOStrength * TEXCHECK;
  154.     }
  155.    
  156.     // Invert SSAO
  157.     occlusion = 1.0 - (occlusion / samplesOccluded);
  158.    
  159.     // Power
  160.     float power = uSSAOPower;
  161.     occlusion = pow(clamp(occlusion, 0.0, 1.0), power);
  162.    
  163.     // Send the final color
  164.     gl_FragColor = vec4(occlusion, occlusion, occlusion, 1.0);
  165. }*/
Add Comment
Please, Sign In to add comment