Hi!
I want to desarrollate a SSAO Pass for my project. Its a Visualization of a buiding in 3d. I want to desarrollate it because i want to give more realism to the scene.
I have been following the others posts of SSAO but i'm stuck.
I created a Depth Shader that create a texture with the z depth in View Space of the objects. I "codificated" the value in a vec4 to use 32 bits of precision instead of 8 bits that i would get with just using one channel.
I used this in the context " context.enforceState(DepthShader) " and rendered the rootSpatial in a TextureRenderer to obtain DepthTexture.
This is the Vertex and the Fragment Shaders of Depth
//VS
varying float posz;
void main()
{
vec4 viewPos = gl_ModelViewMatrix * gl_Vertex;
posz = -viewPos.z;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
//FS
varying float posz;
uniform float zfar;
vec4 packFloatToVec4i(const float value)
{
const vec4 bitSh = vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);
const vec4 bitMsk = vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
vec4 res = fract(value * bitSh);
res -= res.xxyz * bitMsk;
return res;
}
void main ()
{
float depth = posz/zfar;
gl_FragColor= packFloatToVec4i(depth);
}
For SSAO shader i use the BlommRenderPass for Base.
I applied the ssaoShader to a Fullscreen quad.
For the shader i need the position of top right vertex of the far plane.
I use this to obtain the ViewDirection to the vertex (and use this interpolated in fragment )
I think that the problem is arround here. I obtain the point by :
// JME code
float farY = (float)Math.tan(Math.PI / 3.0 / 2.0) * cam.getFrustumFar();
float farX = farY * 1.33333333f;
return new Vector3f(farX, farY,cam.getFrustumFar());
//and I use the shader like this:
ssaoShader.setUniform("depthtex", 0);
ssaoShader.setUniform("normaltex", 1);
ssaoShader.setUniform("escala", 2000f);
ssaoShader.setUniform("radi", 25f);
ssaoShader.setUniform("cornerFustrum", calcularPunt0());
Batchpantalla.states[RenderState.RS_GLSL_SHADER_OBJECTS] = ssaoShader;
trend.render(quadpantalla, ssaomap);
PI / 3.0 / 2.0 = FOV In the example im relying on they use this fov value (its a XNA SSAO implementation
http://www.codeplex.com/XNACommunity/Wiki/View.aspx?title=SSAO&referringTitle=Ejemplos ).
//VS
//Basically I obtain the view direction by:
uniform vec3 cornerFustrum;
varying vec3 direccioVisio;
void main(void)
{
vec4 pos = vec4 ( gl_ModelViewProjectionMatrix * gl_Vertex );
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position= gl_ModelViewProjectionMatrix * gl_Vertex;
vec3 corner = vec3(-cornerFustrum.x * gl_Position.x,
cornerFustrum.y * gl_Position.y, cornerFustrum.z);
direccioVisio = corner;
}
//FS
uniform sampler2D depthtex;
uniform sampler2D normaltex; // texture with random normals
uniform float escala;
uniform float radi;
//uniform float resx,resy;
varying vec3 direccioVisio; //ViewDir
float unpackFloatFromVec4i(const vec4 value)
{
const vec4 bitSh = vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0);
return(dot(value, bitSh));
}
void main()
{
// array amb 16 punts per calcular els samplers. Array with the randomized points
vec3 samples[16];
samples[0]=vec3(0.355512, -0.709318, -0.102371 );
samples[1]=vec3(0.534186, 0.71511, -0.115167 );
samples[2]= vec3(-0.87866, 0.157139, -0.115167 );
samples[3]= vec3(0.140679, -0.475516, -0.0639818 );
samples[4]= vec3(-0.0796121, 0.158842, -0.677075);
samples[5]= vec3(-0.0759516, -0.101676, -0.483625);
samples[6]= vec3(0.12493, -0.0223423, -0.483625);
samples[7]= vec3(-0.0720074, 0.243395, -0.967251);
samples[8]= vec3(-0.207641, 0.414286, 0.187755 );
samples[9]= vec3(-0.277332, -0.371262, 0.187755 );
samples[10]= vec3(0.63864, -0.114214, 0.262857);
samples[11]= vec3(-0.184051, 0.622119, 0.262857);
samples[12]= vec3(0.110007, -0.219486, 0.435574 );
samples[13]= vec3(0.235085, 0.314707, 0.696918 );
samples[14]= vec3(-0.290012, 0.0518654, 0.522688 );
samples[15]= vec3(0.0975089, -0.329594, 0.609803 );
//vec3 dv = normalize(direccioVisio);
// in XNA example they normalize the viewDir in others say DONT NORMALIZE!...
//This is the depth
float prof = unpackFloatFromVec4i(texture2D( depthtex, gl_TexCoord[0].st)); // busquem la profunditat
// ViewPos = depth * ViewDirection
vec3 posicio = prof*direccioVisio; // calculem la posicio en ViewSpace del punt que tractem
vec3 normalrandom = texture2D( normaltex, gl_TexCoord[0].st*200.0).rgb; //carreguem una normal aleatoria
int n;
float color = 0.0;
for (n=0;n<16;n++){
//aki ve el calcul de random normal per millorar el resultat
vec3 vector = reflect(samples[n].xyz,normalrandom)* radi;
//obtenim un punt a samplejar . This is the sample point
vec4 sample = vec4(posicio+vector,1.0); //punt a samplejar falta cambiar coordenades
vec4 posEI; // posicio Espai-Imatge Sample point in Clip Space to obtain the texture coords
posEI = sample*gl_ProjectionMatrix; //obtenim la posicio en lespai Imatge
//les coord del sample son les coordenades del punt / resolucio pantalla ?
//vec2 TexCoordpunt =0.5* (posEI.xy) ; // calculem les uv
vec2 TexCoordpunt = posEI.xy;
float profpunt= unpackFloatFromVec4i(texture2D( depthtex, TexCoordpunt )); // depth of the sample
if(profpunt==1.0){
color++;
} else {
float occlusio= escala*max(profpunt- prof,0.0); // formula de la occlusio
color += 1.0/ (1.0+ occlusio*occlusio*0.1);
}
}
vec4 final = vec4(color/16.0,color/16.0,color/16.0,1.0); // dividim el color pel num de samplers
gl_FragColor = final;
}
I have 2 critical problems.
1 I think i obtain the View Direction bad and i obtain a lot of artifacts.
2 I think im using a bad system in Fragment shader when i try to obtain the TextureCoords of the sample point, (to obtain the depth).
I have other questions like: Whats the diference to use ViewSpace Coordinates to calculate depth or ClipSpace Coordinates.
Thats is my result of the SSAO
http://img230.imageshack.us/my.php?image=64726988hh7.png

the problem its that: it only works in 1 direction, in the others directions i only get artifacts.
I will upload a video in youtube to explain me.
Thanks to everyone.