Hi,
I followed this article about ssao: http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/a-simple-and-practical-approach-to-ssao-r2753
But i encountered some difficulties as you can see below:
1) Why do the edges of the triangles reappear in the OcclusionBuffer and there for are visible in the final image (Thought that wouldn't be if i calc the normalized normals in pixel shader)?
2) If I look down on a plane surface this surface appears to be occluded (grows dark), should it be that way?
3) Artefacts like the black curvy lines and those rectangles nicly seen in the 3rd picture.
Here are the images:
As far as i can tell the normals and positions seem correct, but anyway:
This is how i generate my normal and position buffer:
PS_INPUT VSMAIN (in VS_INPUT input)
{
PS_INPUT Out;
// viewspace position
Out.viewpos = mul (float4 (input.position, 1.0f), WorldMatrix);
Out.viewpos = mul (Out.viewpos, ViewMatrix);
// projectited position
Out.position = mul (Out.viewpos, ProjMatrix);
// viewspace normals
Out.normal = mul (float4 (input.normal, 0.0f), WorldMatrix);
Out.normal = mul (Out.normal, ViewMatrix);
return Out;
}
struct PS_OUTPUT
{
float4 normal : SV_Target0;
float4 viewpos : SV_Target1;
};
PS_OUTPUT PSMAIN (in PS_INPUT In)
{
PS_OUTPUT Out;
Out.normal = float4((normalize(In.normal)).xyz * 0.5f + 0.5f, 1.0f);
Out.viewpos = In.viewpos;
return Out;
}
This is the ssao algorithm (pretty much the one from the article):
float3 getPosition (in float2 uv)
{
return PositionBuffer.Sample (LinearSampler, uv).xyz;
}
float3 getNormal (in float2 uv)
{
return DepthNormalBuffer.Sample (LinearSampler, uv).xyz;
}
float2 getRandom (in float2 uv)
{
return normalize (RandomTexture.Sample (LinearSampler, uv).xy * 0.5f + 0.5f);
}
float doAmbientOcclusion (in float2 tcoord, in float2 occluder, in float3 p, in float3 cnorm)
{
// vector v from the occludee to the occluder
float3 diff = getPosition (tcoord + occluder) - p;
const float3 v = normalize (diff);
// distance between occluder and occludee
const float d = length (diff) * Scale;
return max (0.0, dot (cnorm,v) - Bias) * (1.0 / (1.0 + d) * Intensity);
}
float PSMAIN (in PS_INPUT In) : SV_Target
{
const float2 vec[4] = {
float2 (1,0), float2 (-1,0),
float2 (0,1), float2 (0,-1)
};
float3 p = getPosition (In.tex);
float3 n = getNormal (In.tex);
float2 rand = getRandom(In.tex);
// amboent occlusion factor
float ao = 0.0f;
float rad = Radius / p.z;
int iterations = 4;
for (int j = 0; j < iterations; ++j)
{
float2 coord1 = reflect(vec[j], rand) * rad;
float2 coord2 = float2 (coord1.x*0.707 - coord1.y*0.707,
coord1.x*0.707 + coord1.y*0.707);
ao += doAmbientOcclusion (In.tex, coord1*0.25, p, n);
ao += doAmbientOcclusion (In.tex, coord2*0.5, p, n);
ao += doAmbientOcclusion (In.tex, coord1*0.75, p, n);
ao += doAmbientOcclusion (In.tex, coord2, p, n);
}
ao /= (float)iterations*4.0;
return 1 - ao;
}
Thank you if you are still reading :)