Hey all,
I decided to get:
http://www.gamedev.net/page/resources/_ ... ssao-r2753Working in horde3d. It was quite fun and horde made it incredibly easy
. Thanks guys for an awsome engine!! I figured I would share some code and results. I know there are/were a couple of ssao demos tutorials around, but I could not seem to find anything with a valid link sadly
.
The ssao fragment shader:
Code:
#include "shaders/utilityLib/fragDeferredRead.glsl"
uniform sampler2D randomBuf; //A buffer to an image containing random directions.
uniform vec2 frameBufSize;
varying vec2 texCoords;
vec2 getRandom(vec2 coord)
{
float randBufSize = 64.0;
return normalize(texture2D(randomBuf, frameBufSize * coord / randBufSize).xy * 2.0 - 1.0);
}
float doAmbientOcclusion(vec2 tcoord, vec2 uv, vec3 p, vec3 cnorm)
{
float g_scale = 5.5;
float g_bias = .02;
float g_intensity = 5.5;
vec3 diff = getPos(tcoord+uv)-p;
vec3 v = normalize(diff);
float d = length(diff)*g_scale;
return max(0.0, dot(cnorm, v)-g_bias)*(1.0/(1.0+d))*g_intensity;
}
void main( void )
{
vec2 vec[8];
vec[0] = vec2(1,0);
vec[1] = vec2(-1,0);
vec[2] = vec2(0,1);
vec[3] = vec2(0,-1);
vec[4] = vec2(.707, .707);
vec[5] = vec2(-.707, .707);
vec[6] = vec2(.707, -.707);
vec[7] = vec2(-.707, -.707);
vec3 p = getPos(texCoords);
vec3 n = getNormal(texCoords);
vec2 rand = getRandom(texCoords);
float ao = 0.0;
float rad = 0.25/p.z;
int iterations = 4; //Larger this value the higher the quality.
for (int j=0; j < iterations; ++j) {
vec2 coord1 = reflect(vec[j], rand)*rad;
vec2 coord2 = vec2(coord1.x*.707 - coord1.y*0.707,
coord1.x*.707 + coord1.y*.707);
ao += doAmbientOcclusion(texCoords, coord1*.25, p, n);
ao += doAmbientOcclusion(texCoords, coord1*.5, p, n);
ao += doAmbientOcclusion(texCoords, coord1*.75, p, n);
ao += doAmbientOcclusion(texCoords, coord1*1., p, n);
}
ao /= iterations*4.0;
ao = 1-clamp(ao, 0, 1);
gl_FragColor = vec4(ao, ao, ao, 1);
}
My blur step took place in two steps. One horizontal and one vertical.
Sample of the horizontal is bellow.
Code:
uniform sampler2D buf0;
uniform vec2 frameBufSize;
varying vec2 texCoords;
void main( void )
{
float blur[7]; //This vector represents some blur distribution. The one bellow is made up.
blur[0] = 1;
blur[1] = 1;
blur[2] = 2;
blur[3] = 3;
blur[4] = 2;
blur[5] = 1;
blur[6] = 1;
float dev = 11.0;
float width = 3.5;
vec4 outCol = vec4(0.0, 0.0, 0.0, 0.0);
for (int i = 0; i < 7; ++i ) {
outCol += texture2D(buf0, texCoords+vec2(width*(i-3), 0)/frameBufSize)/dev*blur[i];
}
gl_FragColor = outCol;
}
Results:
My first tests where with a full size ssao buffer. On my computer this was quite slow.
Attachment:
File comment: Full size buffer with no blur
highssao.jpg [ 188.37 KiB | Viewed 11121 times ]
I found that scaling the buffer down to .25 of the original size then bluring like crazy gave fairly fast speeds.
Attachment:
File comment: .25 size buffer. With blur.
ssaolow.jpg [ 81.96 KiB | Viewed 11121 times ]
And when multiplied with the actual render
Attachment:
File comment: .25 size buffer with blur multiplied by actual render.
lowComp.jpg [ 97.88 KiB | Viewed 11121 times ]
Some questions I still have is how to improve performance: What causes it to be slow? Is it mostly just the texture2D calls per pixel?
Currently all the source for the shader is at:
https://github.com/lukemetz/Azurite/blo ... sao.shaderThe pipeline is at
https://github.com/lukemetz/Azurite/blo ... peline.xmlThis is a personal project, just for fun... So the source can be messy in places, such as not removing constants from the .shader file
.
Thanks for reading,
Hope this might come in handy to somebody. Feel free to post questions bellow if needed.