Skip to content

Instantly share code, notes, and snippets.

@benanil
Created February 3, 2024 20:21
Show Gist options
  • Save benanil/d38f1008f47c6143b430a2de874a4d7b to your computer and use it in GitHub Desktop.
Save benanil/d38f1008f47c6143b430a2de874a4d7b to your computer and use it in GitHub Desktop.
Screen Space ambient ocullussion shader from original paper. GTAO technique
// Jimenez et al. / Practical Real-Time Strategies for Accurate Indirect Occlusion
// https://www.activision.com/cdn/research/Practical_Real_Time_Strategies_for_Accurate_Indirect_Occlusion_NEW%20VERSION_COLOR.pdf
out float Result;
in vec2 texCoord;
uniform sampler2D depthMap;
uniform sampler2D normalTex;
uniform mat4 Proj;
uniform mat4 View;
vec3 ViewSpacePosFromDepthBuffer(mat4 invProj, vec2 uv) {
float depth = texture(depthMap, uv).r;
vec4 vsPos = invProj * vec4(uv, depth, 1.0);
return vsPos.xyz / vsPos.w;
}
void main()
{
vec3 normal = texture(normalRG, texCoord).rgb;
normal.z = sqrt(1.0 - normal.x * normal.x - normal.y * normal.y);
normal = normalize(vec3(View * vec4(normal, 0.0))); // < view space normal
float depth = texture(depthMap, texCoord).r;
mat4 invProj = inverse(Proj);
vec3 cPos = ViewSpacePosFromDepthBuffer(invProj, texCoord);
vec3 view = normalize(-cPos);
vec2 texelSize = vec2(1.0) / vec2(textureSize(depthMap, 0));
const float sliceCount = 2.0;
float visibility = 0.0;
for (float slice = 0.0; slice < sliceCount; slice += 1.0)
{
float theta = (PI / sliceCount) * slice;
vec2 w = vec2(cos(theta), sin(theta));
vec3 direction = vec3(w.x, w.y, 0.0);
vec3 orthoDirection = direction - dot(direction, view) * view;
vec3 axis = cross(direction, view);
vec3 projNormal = normal - axis * dot(normal, axis);
float signN = sign(dot(orthoDirection, projNormal));
float cosN = saturate(dot(projNormal, view) / length(projNormal));
float n = signN * acos(cosN);
const float sideCount = 2.0;
for (float side = 0.0; side < sideCount; side += 1.0)
{
float cHorizonCos = -1.0;
const float sampleCount = 6.0;
for (float Sample = 0.0; Sample < sampleCount; Sample += 1.0)
{
float s = Sample / sampleCount;
const float scaling = 1.5;
vec2 sTexCoord = texCoord + (vec2(-1.0 + 2.0 * side) * s * scaling * vec2(w.x, w.y) * texelSize);
float depth = texture(depthMap, sTexCoord).r;
// sTexCoord = sTexCoord * 2.0 - 1.0;
vec3 sPos = ViewSpacePosFromDepthBuffer(invProj, sTexCoord);
vec3 sHorizon = normalize(sPos - cPos);
cHorizonCos = max(cHorizonCos, dot(sHorizon, view));
}
float hs = n + clamp((-1.0 + 2.0 * side) * acos(cHorizonCos) - n, -PI / 2.0, PI / 2.0);
visibility += length(projNormal) * (cosN + 2.0 * hs * sin(n) - cos(2.0 * hs - n)) / 4.0;
}
}
visibility = visibility / sliceCount;
Result = vec4(visibility); // vec4(CustomToneMapping(texture(albedo, texCoord).rgb * visibility), 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment