So I’ve written a GLSL SSAO filter, and it does work, with nice results. However, every now and then I come across a problem. Right now the script is just generally not doing what is expected of it. Even if I revert to a working version, the problem is still there.

What might I be doing wrong?

I’m reluctant to post the .blend file, as there are a lot of problematic changes in there, and it wouldn’t be much help.

I’m on an ATI Radeon HD 4550. Ubuntu 9.04 Karmic. Blender 2.49b.

First, check for errors in the console. Also, it might be helpful to give us more information than just “it’s not working”. Is the shader running at all? Maybe you could post the shader?

No errors, the filter runs, I just get really bad artefacts. It has absolutely nothing to do with the filter.

Certain changes cause the filter to offset things, incorrectly output values, or streak the original image across the screen. Changing back to a working version does not fix this. Certain random changes appear to fix it temporarily, but soon enough it goes back to not working.

uniform sampler2D bgl_RenderedTexture;
uniform sampler2D bgl_DepthTexture;
uniform float timer;
//Reads and converts depth. Function by martinsh.
float readDepth(in vec2 coord)
{
if (coord.x<0||coord.y<0) return 1.0;
float nearZ = 1.0;
float farZ = 128.0;
float posZ = texture2D(bgl_DepthTexture, coord).x;
return (2.0 * nearZ) / (nearZ + farZ - posZ * (farZ - nearZ));
}
//Generates random numbers. The owning object must have a property named "timer"! Also by martinsh.
vec4 rand(vec2 co)
{
float noiseR = (fract(sin(dot(co ,vec2(12.9898,78.233))+timer) * 43758.5453));
float noiseG = (fract(sin(dot(co ,vec2(12.9898,78.233)*2)+timer) * 43758.5453));
float noiseB = (fract(sin(dot(co ,vec2(12.9898,78.233)*3)+timer) * 43758.5453));
return vec4(noiseR,noiseG,noiseB,1.0)*0.3;
}
void main(void)
{
//Collects random numbers.
vec2 fres = vec2(20,20);
vec3 random = vec3(rand(gl_TexCoord[0].st*fres.xy));
//Random factor for coarse AO pass.
vec3 coarseRandom = random*1.5;
//Counter variable i. Also the temporary values of the fine and coarse AO passes.
int i = 0;
float fine = 0.0;
float coarse = 0.0;
//Tuning factors for the fine and coarse AO passes.
float fineBlur = 0.03;
float coarseBlur = 0.2;
//Z-Buffer of the current pixel.
float depth = readDepth(gl_TexCoord[0].st);
for( i=0; i<81; ++i )
{
//Generate a grid coordinate from a single looping variable.
float x = ((i%9)/9.0)-0.5;
float y = (i/81.0)-0.5;
//Add random values to destroy bias.
x += coarseRandom.x;
y += coarseRandom.y;
//Combine into a displacement vector.
vec2 bump = vec2(x, y);
vec2 coord = gl_TexCoord[0].st+(bump*coarseBlur);
//Get the Z-Buffer of the sample pixel.
float sampDepth = readDepth(coord);
//Parabolic function based on distance from the current pixel. Used to remove some of the self-shadowing.
float dist = (x*x)+(y*y);
//Create the cutoff for the sample.
float falloff = depth+((dist-0.01)/10)-0.01;
//Temporary value for the coarse occlusion.
float tmp = 0.0;
//If the sample is farther than the falloff function, then illuminate the pixel.
if( (sampDepth) >= (falloff) || (depth-sampDepth) >= 0.5 )
{
tmp = 1.0;
}
coarse += tmp/81;
}
//Random factor for the fine AO pass.
vec3 fineRandom = random*0.3;
for( i=0; i<36; ++i )
{
//Generate a grid coordinate from a single looping variable.
float x = ((i%6)/6.0)-0.5;
float y = (i/36.0)-0.5;
//Add random values to destroy bias.
x += fineRandom.x;
y += fineRandom.y;
//Combine into a displacement vector.
vec2 bump = vec2(x, y);
vec2 coord = gl_TexCoord[0].st+(bump*fineBlur);
//Get the Z-Buffer of the sample pixel.
float sampDepth = readDepth(coord);
//Parabolic function based on distance from the current pixel. Used to remove some of the self-shadowing.
float dist = (x*x)+(y*y);
//Create the cutoff for the sample.
float falloff = depth+((dist-0.01)/10)-0.01;
//Temporary value for the fine occlusion.
float tmp = 0.0;
//If the sample is farther than the falloff function, then illuminate the pixel.
if( (sampDepth) >= (falloff) || (depth-sampDepth) >= 0.1 )
{
tmp = 1.0;
}
fine += tmp/36;
}
//Combine fine details with coarse global effect.
float AO = fine*coarse;
if( AO >= 1.0 )
{
AO = 1.0;
}
else if( AO <= 0.0 )
{
AO = 0.0;
}
//Compositing the AO back into the scene.
vec4 color = texture2D(bgl_RenderedTexture, gl_TexCoord[0].st);
color.x = (color.x+0.05)*AO;
color.y = (color.y+0.05)*AO;
color.z = (color.z+0.05)*AO;
gl_FragColor = color;
//Uncomment this line to experience pure AO!
// gl_FragColor = vec4(AO);
}
//And we're done!

There’s the shader. Please don’t use it for your own stuff, I haven’t released it yet.

hi, it looks fine to me. I fixed some stuff, like fixed some int`s where should be floats, otherwise it may not work on ATI cards. also done some little tweaking to remove the flickering and that near plane intersecting the view…
And i would suggest to use as less samples as possible (81 and 36 is alot :))

uniform sampler2D bgl_RenderedTexture;
uniform sampler2D bgl_DepthTexture;
uniform float timer;
//Reads and converts depth. Function by martinsh.
float readDepth(in vec2 coord)
{
if (coord.x<0.0||coord.y<0.0) return 1.0;
float nearZ = 0.1;
float farZ = 100.0;
float posZ = texture2D(bgl_DepthTexture, coord).x;
return (2.0 * nearZ) / (nearZ + farZ - posZ * (farZ - nearZ));
}
//Generates random numbers. The owning object must have a property named "timer"! Also by martinsh.
vec4 rand(vec2 co)
{
float noiseR = (fract(sin(dot(co ,vec2(12.9898,78.233))+timer) * 43758.5453));
float noiseG = (fract(sin(dot(co ,vec2(12.9898,78.233)*2)+timer) * 43758.5453));
float noiseB = (fract(sin(dot(co ,vec2(12.9898,78.233)*3)+timer) * 43758.5453));
return vec4(noiseR,noiseG,noiseB,1.0)*0.1;
}
void main(void)
{
//Collects random numbers.
vec3 random = vec3(rand(gl_TexCoord[0].st));
//Random factor for coarse AO pass.
vec3 coarseRandom = random*1.5;
//Counter variable i. Also the temporary values of the fine and coarse AO passes.
int i = 0;
float fine = 0.0;
float coarse = 0.0;
//Tuning factors for the fine and coarse AO passes.
float fineBlur = 0.03;
float coarseBlur = 0.2;
//Z-Buffer of the current pixel.
float depth = readDepth(gl_TexCoord[0].st);
for( i=0; i<8; ++i )
{
//Generate a grid coordinate from a single looping variable.
float x = ((i%9)/9.0)-0.5;
float y = (i/8.0)-0.5;
//Add random values to destroy bias.
x += coarseRandom.x;
y += coarseRandom.y;
//Combine into a displacement vector.
vec2 bump = vec2(x, y);
vec2 coord = gl_TexCoord[0].st+(bump*coarseBlur);
//Get the Z-Buffer of the sample pixel.
float sampDepth = readDepth(coord);
//Parabolic function based on distance from the current pixel. Used to remove some of the self-shadowing.
float dist = (x*x)+(y*y);
//Create the cutoff for the sample.
float falloff = depth+((dist-0.01)/50.0)-0.01;
//Temporary value for the coarse occlusion.
float tmp = 0.0;
//If the sample is farther than the falloff function, then illuminate the pixel.
if( (sampDepth) >= (falloff) || (depth-sampDepth) >= 0.5 )
{
tmp = 1.0;
}
coarse += tmp/8.0;
}
//Random factor for the fine AO pass.
vec3 fineRandom = random*0.3;
for( i=0; i<16; ++i )
{
//Generate a grid coordinate from a single looping variable.
float x = ((i%6)/6.0)-0.5;
float y = (i/16.0)-0.5;
//Add random values to destroy bias.
x += fineRandom.x;
y += fineRandom.y;
//Combine into a displacement vector.
vec2 bump = vec2(x, y);
vec2 coord = gl_TexCoord[0].st+(bump*fineBlur);
//Get the Z-Buffer of the sample pixel.
float sampDepth = readDepth(coord);
//Parabolic function based on distance from the current pixel. Used to remove some of the self-shadowing.
float dist = (x*x)+(y*y);
//Create the cutoff for the sample.
float falloff = depth+((dist-0.01)/50.0)-0.01;
//Temporary value for the fine occlusion.
float tmp = 0.0;
//If the sample is farther than the falloff function, then illuminate the pixel.
if( (sampDepth) >= (falloff) || (depth-sampDepth) >= 0.1 )
{
tmp = 1.0;
}
fine += tmp/16.0;
}
//Combine fine details with coarse global effect.
float AO = fine*coarse;
//tresholding AO (martinsh)
AO = min((AO)+0.5, 1.0);
if( AO >= 1.0 )
{
AO = 1.0;
}
else if( AO <= 0.0 )
{
AO = 0.0;
}
//Compositing the AO back into the scene.
vec4 color = texture2D(bgl_RenderedTexture, gl_TexCoord[0].st);
color.x = (color.x+0.05)*AO;
color.y = (color.y+0.05)*AO;
color.z = (color.z+0.05)*AO;
color.a = 1.0;
gl_FragColor = color;
//Uncomment this line to experience pure AO!
//gl_FragColor = vec4(vec3(AO,AO,AO),1.0);
}
//And we're done!