Ssao - Applying To Final Texture

Started by
13 comments, last by razor1911 13 years, 3 months ago


Finally my SSAO looks as i require, and now it comes to have it 'mixed' with a final frame texture.

Here's the deal:

after the ssao calculations are done, the texture is returned from shader and applied to main frame via:

gl_FragColor=texture2D(frameMap,texcoord)*ssaoMap;




This is 'kinda' ok, cause it is obvious that effect will fail when a fog is applied to the scene, as SSAO is going to be 'blended' with the fog.

Additionaly, it looks v.ugly especially on the trees that are high above player and their background is a clouds/sky mainly (bright) - again ssao parts look max ugly.

Just take a look:

SSAO results

aa9610fa.jpg

SCENE without SSAO

2c3d9ba2.jpg

SCENE with SSAO

059df49b.jpg







I was thinking if there is any better 'idea' cruising around guys, or any suggestion to make this look 'optimal' .. can't find any possible solution,

many thanks for anything that can force this whole scene with ssao - look more realistic.













Advertisement
SSAO is n effect of the ambient lighting, so SSAO should only be applied to the ambient part of the lighting.
You have to apply it at an early stage of your lighting calculation.
Danny02,




i don't think i understood you correctly.

Can you be more specific pls?




somewhere you have your lighting shader, which properly looks something like this.


in normal;
in vec3, diffuse, specular, ambient
uniform vec3 lightdir;
uniform sampler2D diff_sampler, spec_sampler;

#ifdef SSAO
uniform sampler2D ssao_sampler;
#endif

main()
{
vec3 color;

vec3 diff = texture(diff_sampler, texcoord).rgb * diffuse;

float NdotL = dot(normal, lightdir);
if(NdotL > 0.)
{ vec3 spec = texture(spec_sampler, texcoord).rgb * specular;
color += NdotL * diffe;
color += [specular calculation]*specr;

}

#ifdef SSAO
color += diff * ambient * texture(ssao_sampler, texcoord);
#else
color += diff * ambient
#endif

FragColor = vec4(color);
}


[size="4"]ps:properly not bug free
too fast.




danny,lemme check that..




will come back with rslts

What texcoords do you pass in ?
ah sry forgot about this, you will need the projected position


out vec2 ssao_texcoord;

main()
{
...
gl_position= ftransform();
ssao_texcoord = (gl_position.xy +1.) *0.5;;
...
}
I am now applying ssao generated texture to the models renderer.

I pass the SSAO texture via texture2D and in vertex shader:



varying vec2 ssao_texcoord;

...

gl_Position= ftransform();
ssao_texcoord = (gl_Position.xy +1.) *0.5;



...



fragment shader



...

vec4 ambient = gl_FrontLightProduct[0].ambient*texture2D(ssaoMap,ssao_texcoord);

...






And the results are as follows.

b35208af.jpg

39113faf.jpg



ec1219cd.jpg




Shouldn't i calculate ssao texture coordinate for each shaded pixel - in some more extramathematical way?
are you sure that you don't mix up some texture bindings?

If you sure that's not the case, could you provide us with your model shader?
Ok finally board is up.

Here is exactly what is done.




My rendering looks as below - all on Framebuffers, main scene rendered with Multisampled FBO then finally blitted.


1. RTT shadowmap (ARB0)
2. RTT water reflections (ARB3)
3. RTT (Multisampled) full scene (terrain, foliage, sky, clouds,... MODELS)

MODELS render
|_run shader
|_pass color texture (ARB1) (generated at model loading step)
|_pass normal texture (ARB2) (generated at model loading step)
|_pass shadow texture (ARB0) (generated at step 1)
|_pass SSAO_texture (ARB7) (generated by SSAO_shader below)
| Normal/Color texcoords are passed via VBO/IBO - as GL_TEXTURE1
| Tangents passed via VBO/IBO - as GL_TEXTURE2
\
|
Calculate shadowmap projection
Compute lighting

Apply textures (color+normal go with coords gl_MultiTexCoord1)
Apply shadowmap texture
apply fog

4. Blit to FBO - color+depth buffer
5. end of render - time to run the final shaders
6.
HIGHPASS/BLOOM/...
|
SSAO shader
|_ takes input from depthtexture
|_ performs ssao
|_ returns ssao_texture
POSTPROCESSING shaders

7. Final draw onto the screen



Now - i made previously a bad assumption that to have a SSAO running it is enough to blend it over the final scene, surely that's a mistake.
To do it properly, as you mentioned my model ambient colour should be multiplied by the actual SSAO_texture.

This is why SSAO_texture is now passed to my models shader, but to multiply by SSAO_texture i need to know which UV coord of this texture should
be taken into consideration, and here is the actual problem i believe. I don't pass any texcoords for SSAO_texture, as they should be somehow calculated
for every pixel that is being computed by the shader.



Here is the model shader, that is running for every model i draw on the scene(batched of course).



[VERTEX SHADER]

varying vec4 projCoord;
varying vec3 lightDir;
varying vec3 halfVector;
uniform float Timer;
varying vec3 normal;
uniform int useBumpMap;
uniform int objectType;



varying vec2 ssao_texcoord; //ssao texture coords


void main()
{
gl_TexCoord[1] = gl_MultiTexCoord1; //color map/normalmap texcoords
const float WINDSPEED=0.025; //animate speed for flagged objects

/*
* CALCULATE SSAO TEXCOORD
*/

gl_Position= ftransform();
ssao_texcoord = (gl_Position.xy +1.) *0.5;



/*
* This is used for VSM
*/
vec3 vertexPos = vec3(gl_ModelViewMatrix * gl_Vertex);
vec4 realPos = gl_ModelViewMatrix * gl_Vertex;
projCoord = gl_TextureMatrix[0] * realPos ;



/*
* Perform additional tasks for object types
*/
//LEAFS
if(objectType==8)
{

if(gl_Vertex.x>0.1 ||gl_Vertex.x<-0.1 )
{
gl_Vertex.z+=cos(Timer*gl_Vertex.x)*0.5;
}

gl_Normal.y=1;
gl_Normal.x=0;
gl_Normal.z=0;
normal = gl_NormalMatrix * gl_Normal;
}
//VEGETATION
else if(objectType==16)
{


if ( gl_Vertex.y > 0.1 )
{
float angle1 = (Timer*gl_TexCoord[1].x);
gl_Vertex += 0.2*vec4 (sin(angle1), 0,0, 0 );
}

gl_Normal.y=1;
gl_Normal.x=0;
gl_Normal.z=0;
normal = gl_NormalMatrix * gl_Normal;


}
//TREEBARK
else if(objectType==4)
{
if(gl_Vertex.y>5){
gl_Vertex.z+=cos(Timer)*gl_Vertex.y*WINDSPEED;
}

normal = gl_NormalMatrix * gl_Normal;
}
//NON CLASSIFIED (0) OBJECTS
else
{
normal = gl_NormalMatrix * gl_Normal;

}




gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;



/*
* Perform lighting calculations if no normalmap is required
*/
if(useBumpMap)
{

vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 t = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz); //multitexcoord2 tangents.
vec3 b = cross(n, t) * gl_MultiTexCoord2.w;
mat3 tbnMatrix = mat3(t.x, b.x, n.x,
t.y, b.y, n.y,
t.z, b.z, n.z);
lightDir = gl_LightSource[0].position.xyz;
lightDir = tbnMatrix * lightDir;
halfVector = gl_LightSource[0].halfVector.xyz;
halfVector = tbnMatrix * halfVector;


}
else
{
vec4 diffuse, ambient, globalAmbient;
float NdotL;
lightDir = normalize(vec3(gl_LightSource[0].position));
NdotL = max(dot(normal, lightDir), 0.0);
diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
gl_FrontColor = NdotL * diffuse + ambient;

}


/*
* Store fog info in color
*/
gl_FrontColor.a = clamp( ( gl_Position.z-gl_Fog.start ) / ( gl_Fog.end - gl_Fog.start ) , 0.0 , 1.0 );

}








[FRAGMENT SHADER]

uniform sampler2D colorMap; //comes in with vbo texture1
uniform sampler2D normalMap; //comes in with vbo texture2
uniform sampler2D shadowMap; //comes in as texture0
uniform sampler2D ssaoMap; //comes in as texture7
varying vec2 ssao_texcoord; //calculated in vx shader

uniform int useBumpMap;
varying vec3 normal;
varying vec3 lightDir;
varying vec3 halfVector;
varying vec4 projCoord;




/*
* SM
*/
vec4 ShadowCoordPostW;
float chebyshevUpperBound( float distance,float SHADOWPOWER)
{
// We retrive the two moments previously stored (depth and depth*depth)
vec2 moments = texture2D(shadowMap,ShadowCoordPostW.xy).rg;

// Surface is fully lit. as the current fragment is before the light occluder
if (distance <= moments.x)
return 1.0 ;

// The fragment is either in shadow or penumbra. We now use chebyshev's upperBound to check
// How likely this pixel is to be lit (p_max)
float variance = moments.y - (moments.x*moments.x);
variance = max(variance,SHADOWPOWER);
float d = distance - moments.x;
float p_max = variance / (variance + d*d);

return p_max;
}


void main()
{

vec3 n;
vec4 color;

//NORMALMAP non NORMALMAP render
if(useBumpMap==1)
{
n = normalize(texture2D(normalMap, gl_TexCoord[1].st).xyz * 2.0 - 1.0);

vec3 l = normalize(lightDir);
vec3 h = normalize(halfVector);
float nDotL = max(0.0, dot(n, l));
float nDotH = max(0.0, dot(n, h));
float power=(nDotL == 0.0) ? 0.0 : pow(nDotH, gl_FrontMaterial.shininess);

//HERE IS WHERE I MULTIPLY THE AMBIENT BY THE SSAO TEXTURE
//HERE IS WHERE I MULTIPLY THE AMBIENT BY THE SSAO TEXTURE

vec4 ambient = gl_FrontLightProduct[0].ambient*texture2D(ssaoMap,ssao_texcoord);


vec4 diffuse = gl_FrontLightProduct[0].diffuse * nDotL;
vec4 specular = gl_FrontLightProduct[0].specular * power;
color = (gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular);

}
else
{
color=gl_Color;
}



//TO VISUALIZE THE SSAO TEXCOORDS I APPLY THE TEXTURE ONTO THE MODEL HERE
//THIS IS FOR DEBUG PURPOSES ONLY

/*NORMALLY I PASS THE COLOR HERE*/
color*=texture2D(colorMap, gl_TexCoord[1].st);

/*TEMPORARILY I PASS THE SSAO TEX HERE*/
//temp solution to see the ssao on the models

color*=texture2D(ssaoMap,ssao_texcoord);





/*Compute SM and all what's left...*/
ShadowCoordPostW = projCoord / projCoord.w;
float SHADOWPOWER=0.5;
float shadow = chebyshevUpperBound(ShadowCoordPostW.z,SHADOWPOWER);


if(ShadowCoordPostW.x >= 0.0 && ShadowCoordPostW.y >= 0.0 && ShadowCoordPostW.x <= 1.0 && ShadowCoordPostW.y <= 1.0 )
{
color*=vec4(shadow);
}

if( gl_Color.a > 0.0 )
{
gl_FragColor.rgb = mix( color.rgb , gl_Fog.color.rgb ,gl_Color.a );
gl_FragColor.a =texture2D(colorMap, gl_TexCoord[1].st).a;

}
else
{
gl_FragColor = color;
}

}




This topic is closed to new replies.

Advertisement