I try to implement a glsl shader for screen-space ambient occlusion.
I tried somthing similar to this:
https://gist.github.com/fisch0920/6770311
But there are some strange black dots in the render. What is wrong ?
No AO: http://s18.postimg.org/k21sqjgav/SAO1.jpg
With AO : http://s3.postimg.org/7lxraqehd/SAO2.jpg
Code:
#version 330
uniform sampler2D ColorSampler;
uniform sampler2D NormalSampler;
uniform sampler2D WorldPosSampler;
uniform mat4 ViewMatrix;
uniform mat4 ProjMatrix;
out float FragAO;
float SampleRadius = 20.0;
float PI = 3.14159265359;
float Random(vec4 seed4)
{
float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673));
return fract(sin(dot_product) * 43758.5453);
}
float GetAOSample(vec3 SamplePos, vec3 fNormal, vec4 fViewPos)
{
vec4 SampleCoord = ProjMatrix * vec4(SamplePos, 1.0);
SampleCoord.xy /= SampleCoord.w;
SampleCoord.xy = SampleCoord.xy * 0.5 + 0.5;
vec4 sWorldPos = vec4(texture(WorldPosSampler, SampleCoord.xy, 0).xyz, 1.0);
vec4 sViewPos = ViewMatrix*sWorldPos;
vec3 sampleDir = sViewPos.xyz-fViewPos.xyz;
float NdotS = max(dot(fNormal, sampleDir), 0.0);
float dist2 = dot(sampleDir,sampleDir);
float SampleRadius2 = SampleRadius * SampleRadius;
float f = max(SampleRadius2 - dist2, 0.0) / SampleRadius2;
return f * f * f * NdotS / (0.0001 + dist2);
}
void main(void)
{
ivec2 FragCoord = ivec2(gl_FragCoord.xy);
vec4 fWorldPos = vec4(texelFetch(WorldPosSampler, FragCoord, 0).xyz, 1.0);
vec3 fNormal = texelFetch(NormalSampler, FragCoord, 0).xyz * 2.0 - 1.0;
vec4 fViewPos = ViewMatrix*fWorldPos;
fNormal.z = sqrt(1.0-dot(fNormal.xy, fNormal.xy));
float AOValue = 0.0;
float thetaRand = Random(vec4(gl_FragCoord.yyxx))*2.0*PI;
for(int i=0; i<32; i++)
{
float iStep = float(i) / 32.0;
float radius = iStep*SampleRadius;
float theta = thetaRand + iStep * 4.0*PI;
vec3 offset = vec3(radius*cos(theta), radius*sin(theta), 0.0);
offset *= sign(dot(offset,fNormal));
vec3 SamplePos = fViewPos.xyz + offset;
AOValue += GetAOSample(SamplePos, fNormal, fViewPos);
}
FragAO = max( AOValue/32.0, 0.0);
}
Then in my final shader I use:
float AO = pow(1.0 - texelFetch(AOSampler, FragCoord, 0).x, 1.0 + AOCoeff * 8.0);