Hi, I currently try to implement SSAO with MonoGame OpenGL project.
But i can’t figure out what I’m doing wrong?
the Depth shader:
float4x4 WorldView;
float3x3 ITWorldView;
float4x4 WorldViewProjection;
float FarClip;
struct VS_INPUT {
float4 Position: SV_Position0;
float3 Normal : NORMAL0;
};
struct VS_OUTPUT {
float4 Position: SV_Position0;
float3 Normal : TEXCOORD0;
float4 vPositionVS : TEXCOORD1;
};
VS_OUTPUT DepthVertexShaderFunction(VS_INPUT IN) {
VS_OUTPUT Output;
//
Output.Position = mul(IN.Position, WorldViewProjection);
Output.vPositionVS = mul(IN.Position, WorldView);
Output.Normal = mul(IN.Normal, ITWorldView);
//
return Output;
}
float4 DepthPixelShaderFunction(VS_OUTPUT IN) : COLOR0 {
float depth = IN.vPositionVS.z / FarClip;
IN.Normal = normalize(IN.Normal);
return float4(IN.Normal, -depth);
}
technique Depth {
pass P0 {
VertexShader = compile vs_3_0 DepthVertexShaderFunction();
PixelShader = compile ps_3_0 DepthPixelShaderFunction();
}
}
the SSAO effect:
float sampleRadius;
float distanceScale;
float4x4 Projection;
float3 cornerFustrum;
struct VS_INPUT {
float4 Position : SV_Position0;
float2 TexCoord : TEXCOORD0;
};
struct VS_OUTPUT {
float4 pos : SV_Position0;
float2 TexCoord : TEXCOORD0;
float3 viewDirection : TEXCOORD1;
};
VS_OUTPUT VS(VS_INPUT IN) {
VS_OUTPUT Out = (VS_OUTPUT)0;
Out.pos = IN.Position;
float2 p = sign(IN.Position.xy);
Out.TexCoord = (float2(p.x, -p.y) + float2( 1.0f, 1.0f ) ) * 0.5f;
float3 corner = float3(-cornerFustrum.x * p.x, cornerFustrum.y * p.y, cornerFustrum.z);
Out.viewDirection = corner;
return Out;
}
texture depthTexture;
texture randomTexture;
sampler2D depthSampler = sampler_state {
Texture = <depthTexture>;
ADDRESSU = CLAMP;
ADDRESSV = CLAMP;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
};
sampler2D RandNormal = sampler_state {
Texture = <randomTexture>;
ADDRESSU = WRAP;
ADDRESSV = WRAP;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
};
float4 PS(VS_OUTPUT IN) : COLOR0 {
float3 samples[16] = {
float3(0.355512, -0.709318, -0.102371),
float3(0.534186, 0.71511, -0.115167),
float3(-0.87866, 0.157139, -0.115167),
float3(0.140679, -0.475516, -0.0639818),
float3(-0.0796121, 0.158842, -0.677075),
float3(-0.0759516, -0.101676, -0.483625),
float3(0.12493, -0.0223423, -0.483625),
float3(-0.0720074, 0.243395, -0.967251),
float3(-0.207641, 0.414286, 0.187755),
float3(-0.277332, -0.371262, 0.187755),
float3(0.63864, -0.114214, 0.262857),
float3(-0.184051, 0.622119, 0.262857),
float3(0.110007, -0.219486, 0.435574),
float3(0.235085, 0.314707, 0.696918),
float3(-0.290012, 0.0518654, 0.522688),
float3(0.0975089, -0.329594, 0.609803)
};
normalize (IN.viewDirection);
float depth = tex2D(depthSampler, IN.TexCoord).a;
float3 se = depth * IN.viewDirection;
float3 randNormal = tex2D( RandNormal, IN.TexCoord * 200.0 ).rgb;
float3 normal = tex2D(depthSampler, IN.TexCoord).rgb;
float finalColor = 0.0f;
for (int i = 0; i < 16; i++) {
float3 ray = reflect(samples[i],randNormal) * sampleRadius;
//if (dot(ray, normal) < 0)
// ray += normal * sampleRadius;
float4 sample = float4(se + ray, 1.0f);
float4 ss = mul(sample, Projection);
float2 sampleTexCoord = 0.5f * ss.xy / ss.w + float2(0.5f, 0.5f);
float sampleDepth = tex2D(depthSampler, sampleTexCoord).a;
if (sampleDepth == 1.0) {
finalColor ++;
} else {
float occlusion = distanceScale * max(sampleDepth - depth, 0.0f);
finalColor += 1.0f / (1.0f + occlusion * occlusion * 0.1);
}
}
finalColor /= 16.0;
return float4(finalColor, finalColor, finalColor, 1.0f);
}
technique SSAO {
pass P0 {
VertexShader = compile vs_3_0 VS();
PixelShader = compile ps_3_0 PS();
}
}
the result with depth in bottom corner, SSAO in upper and the scene without SSAO in background:
As you can see the SSAO pass seems to only show the depth from Y and Z axis…