Nachdem ich das verzögerte Rendern implementiert hatte, versuchte ich mein Glück mit einer SSAO-Implementierung unter Verwendung dieses Lernprogramms . Leider bekomme ich nichts, was aussieht wie SSAO, Sie können mein Ergebnis unten sehen.
Sie können sehen, dass sich ein seltsames Muster bildet und es keine Okklusionsschattierung gibt, wo dies erforderlich ist (dh zwischen den Objekten und auf dem Boden). Die von mir implementierten Shader folgen:
#VS
#version 330 core
uniform mat4 invProjMatrix;
layout(location = 0) in vec3 in_Position;
layout(location = 2) in vec2 in_TexCoord;
noperspective out vec2 pass_TexCoord;
smooth out vec3 viewRay;
void main(void){
pass_TexCoord = in_TexCoord;
viewRay = (invProjMatrix * vec4(in_Position, 1.0)).xyz;
gl_Position = vec4(in_Position, 1.0);
}
#FS
#version 330 core
uniform sampler2D DepthMap;
uniform sampler2D NormalMap;
uniform sampler2D noise;
uniform vec2 projAB;
uniform ivec3 noiseScale_kernelSize;
uniform vec3 kernel[16];
uniform float RADIUS;
uniform mat4 projectionMatrix;
noperspective in vec2 pass_TexCoord;
smooth in vec3 viewRay;
layout(location = 0) out float out_AO;
vec3 CalcPosition(void){
float depth = texture(DepthMap, pass_TexCoord).r;
float linearDepth = projAB.y / (depth - projAB.x);
vec3 ray = normalize(viewRay);
ray = ray / ray.z;
return linearDepth * ray;
}
mat3 CalcRMatrix(vec3 normal, vec2 texcoord){
ivec2 noiseScale = noiseScale_kernelSize.xy;
vec3 rvec = texture(noise, texcoord * noiseScale).xyz;
vec3 tangent = normalize(rvec - normal * dot(rvec, normal));
vec3 bitangent = cross(normal, tangent);
return mat3(tangent, bitangent, normal);
}
void main(void){
vec2 TexCoord = pass_TexCoord;
vec3 Position = CalcPosition();
vec3 Normal = normalize(texture(NormalMap, TexCoord).xyz);
mat3 RotationMatrix = CalcRMatrix(Normal, TexCoord);
int kernelSize = noiseScale_kernelSize.z;
float occlusion = 0.0;
for(int i = 0; i < kernelSize; i++){
// Get sample position
vec3 sample = RotationMatrix * kernel[i];
sample = sample * RADIUS + Position;
// Project and bias sample position to get its texture coordinates
vec4 offset = projectionMatrix * vec4(sample, 1.0);
offset.xy /= offset.w;
offset.xy = offset.xy * 0.5 + 0.5;
// Get sample depth
float sample_depth = texture(DepthMap, offset.xy).r;
float linearDepth = projAB.y / (sample_depth - projAB.x);
if(abs(Position.z - linearDepth ) < RADIUS){
occlusion += (linearDepth <= sample.z) ? 1.0 : 0.0;
}
}
out_AO = 1.0 - (occlusion / kernelSize);
}
Ich zeichne ein Vollbild-Quad und übergebe Tiefen- und Normaltexturen. Normalen sind in RGBA16F, wobei der Alpha-Kanal für den AO-Faktor im Unschärfepass reserviert ist. Ich speichere die Tiefe in einem nichtlinearen Tiefenpuffer (32F) und stelle die lineare Tiefe wieder her mit:
float linearDepth = projAB.y / (depth - projAB.x);
wo projAB.y
wird berechnet als:
und projAB.x
als:
Diese leiten sich aus der Matrix glm :: perspective (gluperspective) ab. z_n und z_f sind die nahen und fernen Clipabstände.
Wie in dem Link beschrieben, den ich oben gepostet habe, erstellt die Methode Proben in einer Halbkugel mit höherer Verteilung nahe der Mitte. Anschließend werden zufällige Vektoren aus einer Textur verwendet, um die Hemisphäre zufällig um die Z-Richtung zu drehen und sie schließlich entlang der Normalen am angegebenen Pixel auszurichten. Da das Ergebnis verrauscht ist, folgt auf den SSAO-Durchgang ein Weichzeichnungsdurchgang.
Wie auch immer, meine Positionsrekonstruktion scheint nicht falsch zu sein, da ich auch versucht habe, das Gleiche zu tun, wobei jedoch die Position von einer Textur übergeben wurde, anstatt rekonstruiert zu werden.
Ich habe auch versucht, mit dem Radius, der Rauschtexturgröße und der Anzahl der Samples und mit verschiedenen Texturformaten zu spielen, ohne Erfolg. Aus irgendeinem Grund ändert sich beim Ändern des Radius nichts.
Hat jemand irgendwelche Vorschläge? Was könnte schief gehen?