Advertisement
Guest User

GTAO temporal filtering shader

a guest
Aug 15th, 2018
1,786
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #version 430 core
  2.  
  3. layout (binding = 0, rgba8) uniform restrict writeonly image2D aoImageOut;
  4.  
  5. #include sharedUniformsBuffer.glsl
  6. /*
  7. The only uniforms needed from this UBO are:
  8.  
  9. vec3 cameraRay00
  10. vec3 cameraRay01
  11. vec3 cameraRay10
  12. vec3 cameraRay11
  13.  
  14. The are the rays that make up the "corners" of the screen
  15. They are not normalized, but rather each is a vector from camera to a plane that is parallel to the camera near and far planes and is placed exactly one unit away from the camera.
  16. This way one can just interpolate these rays to get such a ray for the current pixel
  17. And by mutliplying this result with linear depth we get the world space position (relative to the camera)
  18. See line 123
  19. */
  20.  
  21. // Depth textures need mips
  22. uniform sampler2D aoTexIn;
  23. uniform sampler2D gDepth;
  24. uniform sampler2D texHistoryAo;
  25. uniform sampler2D texHistoryDepth;
  26.  
  27. // sizeDiv = vec2(1.0 / aoImageOutWidth, 1.0 / aoImageOutHeight);
  28. uniform vec2 sizeDiv;
  29.  
  30. // Controls what mip of the textures is used
  31. // This is here because I want to be able to switch between calculating AO at half res and full res
  32. uniform int depthSkip;
  33.  
  34. uniform mat4 matCurrentInverted;
  35. uniform mat4 matPrevious;
  36.  
  37. // Used to calculate the sample's depth in the previous frame
  38. uniform vec4 cameraPlanePrevious;
  39.  
  40. // A trick to avoid integer division
  41. // 5958 = (2^16) / 11
  42. int IntegerDivideBy_11(int i)
  43. {
  44.     return (i * 5958) >> 16;
  45. }
  46.  
  47. ivec2 IntModAndDiv_11(int i)
  48. {
  49.     ivec2 v = ivec2(i, IntegerDivideBy_11(i));
  50.     v.x -= v.y * 11;
  51.     return v;
  52. }
  53.  
  54. float CheckRange(vec2 tc)
  55. {
  56.     if(tc.x <= 0.0 || tc.y <= 0.0 || tc.x >= 1.0 || tc.y >= 1.0)
  57.         return 0.0;
  58.     return 1.0;
  59. }
  60.  
  61. #define SIZEXY 8
  62.  
  63. shared float aoSamples[SIZEXY + 3][SIZEXY + 3];
  64. shared float depthSamples[SIZEXY + 3][SIZEXY + 3];
  65.  
  66. layout (local_size_x = SIZEXY, local_size_y = SIZEXY, local_size_z = 1) in;
  67. void main(void) {
  68.     ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
  69.    
  70.     // Load texels for spacial filter
  71.     int threadID = int(gl_LocalInvocationID.y * 8 + gl_LocalInvocationID.x);
  72.    
  73.     #define OFFSET_FILTER ivec2(-1, -1)
  74.     #define OFFSET_TEXEL ivec2(0, 0)
  75.    
  76.     // Preload all needed texels into shared memory to save texture reads
  77.     // Load 11x11 texels because the thread group size is 8 and we need
  78.     // extra 3 border texels because of the 4x4 spacial filter
  79.    
  80.     // Load first 64 samples
  81.     ivec2 groupTexel = ivec2(gl_WorkGroupID.xy * 8);
  82.     ivec2 local = IntModAndDiv_11(threadID);   
  83.     aoSamples[local.x][local.y] = texelFetch(aoTexIn, groupTexel + OFFSET_FILTER + local, 0).x;
  84.     depthSamples[local.x][local.y] = texelFetch(gDepth, ((groupTexel + OFFSET_FILTER + local)) + OFFSET_TEXEL, depthSkip).x;
  85.  
  86.     // Load the remaining 57 samples (57 = 11 * 11 - 64)
  87.     if(threadID < 57)
  88.     {
  89.         local = IntModAndDiv_11(threadID + 64);
  90.         aoSamples[local.x][local.y] = texelFetch(aoTexIn, groupTexel + OFFSET_FILTER + local, 0).x;
  91.         depthSamples[local.x][local.y] = texelFetch(gDepth, ((groupTexel + OFFSET_FILTER + local)) + OFFSET_TEXEL, depthSkip).x;
  92.     }
  93.    
  94.     memoryBarrierShared();
  95.     barrier();
  96.    
  97.     // Spacial filter
  98.    
  99.     // Get the depth of the "center" sample - this reference depth is used to weight the other samples
  100.     float depth = depthSamples[gl_LocalInvocationID.x - OFFSET_FILTER.x][gl_LocalInvocationID.y - OFFSET_FILTER.y];
  101.     float weightsSpacial = 0.0;
  102.     float aoLocal = 0.0;
  103.    
  104.     for(int y = 0; y < 4; y++)
  105.     {
  106.         for(int x = 0; x < 4; x++)
  107.         {
  108.             // Weight each sample by its distance from the refrence depth - but also scale the weight by 1/10 of the reference depth so that the further from the camera the samples are, the higher the tolerance for depth differences is
  109.             float localWeight = max(0.0, 1.0 - abs(depthSamples[gl_LocalInvocationID.x + x][gl_LocalInvocationID.y + y] - depth) / (depth * 0.1));
  110.             weightsSpacial += localWeight;
  111.             aoLocal += aoSamples[gl_LocalInvocationID.x + x][gl_LocalInvocationID.y + y].x * localWeight;
  112.         }
  113.     }
  114.    
  115.     aoLocal /= weightsSpacial; 
  116.    
  117.     // Temporal filter
  118.    
  119.     // Get history tc and depth
  120.     vec2 textureCoords = (texel + vec2(0.5)) * sizeDiv;
  121.     depth = textureLod(gDepth, textureCoords, depthSkip).x;
  122.    
  123.     // Reconstruct position from depth
  124.     // Note that the position is relative to the camera position (not an absolute world space position)
  125.     vec4 pos = vec4(mix(mix(cameraRay01.xyz, cameraRay11.xyz, textureCoords.x), mix(cameraRay00.xyz, cameraRay10.xyz, textureCoords.x), textureCoords.y) * depth, 1.0);
  126.    
  127.     // Get the linear depth of the projected position in the last frame
  128.     float depthProjected = abs(dot(pos, cameraPlanePrevious));
  129.     // Project the position using last frame's projection
  130.     // Note that the matrix should not contain camera translation (becuase of the lack of absolute world space position)
  131.     // Instead the matrix must contain the relative camera translation since the last frame
  132.     pos = matPrevious * pos;
  133.     pos /= pos.w;
  134.     vec2 tcProjected = pos.xy * 0.5 + 0.5;
  135.  
  136.     float ao = 0.0;
  137.     float temporalWeight = CheckRange(tcProjected);
  138.     // Reject history samples that are too far from current sample - same as in spacial filter
  139.     temporalWeight *= max(0.0, 1.0 - abs(textureLod(texHistoryDepth, tcProjected, depthSkip).x - depthProjected) / (depthProjected * 0.1));
  140.     ao = texture(texHistoryAo, tcProjected).x;
  141.     ao = mix(aoLocal, ao, temporalWeight);
  142.    
  143.     ao = mix(aoLocal, ao, 0.9);
  144.    
  145.     imageStore(aoImageOut, texel, vec4(ao));
  146. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement