Created
February 3, 2024 20:21
-
-
Save benanil/d38f1008f47c6143b430a2de874a4d7b to your computer and use it in GitHub Desktop.
Screen Space ambient ocullussion shader from original paper. GTAO technique
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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