diff --git a/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl b/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl index 34a63c1..9ab0f35 100644 --- a/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl +++ b/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl @@ -45,12 +45,77 @@ void main() { fragColor = 0; const int samples = 8; - const float samplesInv = PI2 * (1.0 / samples); - for (int i = 0; i < samples; ++i) { - float theta = samplesInv * (i + 0.5) + phi; + const float samplesInv = PI2 * (1.0 / 8.0); + + // Manually unrolled sampling loop for better performance on older hardware + // Sample 0 + { + float theta = samplesInv * (0 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 1 + { + float theta = samplesInv * (1 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 2 + { + float theta = samplesInv * (2 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 3 + { + float theta = samplesInv * (3 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 4 + { + float theta = samplesInv * (4 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 5 + { + float theta = samplesInv * (5 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 6 + { + float theta = samplesInv * (6 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 7 + { + float theta = samplesInv * (7 + 0.5) + phi; vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; - // vec3 pos = getPosNoEye(eyeLook, vray, depth, cameraProj) - currentPos; vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); }