Disk to Disk SSAO + SSGI shader

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
devsh
Competition winner
Posts: 2049
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Disk to Disk SSAO + SSGI shader

Post by devsh »

Image
The following are darker to show the GI
Image
Image

OK, this shader is for DEFERRED PIPELINES because I dont really see anyone using 2 passes to have a depth and normal texture

This SSAO technique is superior to any you may have seen like the one in XEffects, because it uses normals to calculate occlusion (it may be a bit slower, but it does SSAO on parallax mapped flat surfaces :) ). The shader samples in a disk, that means the pixel samples are not boxes etc. but arranged in rings radiating from the occluded pixel. You can modify the radius (sample size) and the number of rings, you can also change the angle multiplier (from 3.0 to something else) to obtain more samples. Beware the number of samples is proportional to the diameter of the ring, i.e. 5th ring out would have 15 samples. To obtain faster and more global occlusion, make the jitter parameter huge and increase the sample size. Then blur the output and then combine it.

I have coded my normals, depth and color in a particular way. The ambient texture(tex0) contains ambient rgb + the x coord of a normal(alpha) (32 bit 8 bit per channel), the other texture (tex2) contains the depth (red) + the y coord of a normal(green) (16 bit float *2). You may have to rework the shader to fit your GBuffer layout.

LASTLY, the OCCLUSION is NOT CONSISTENT YET. Because I haven't paid any attention to position reconstruction (depending on the FoV and aspect ratio), the occlusion is "stretched" in the y direction (darker at the top and bottom of the screen).

Code: Select all

"uniform sampler2D tex0;"\
"uniform sampler2D tex1;"\
"uniform sampler2D tex2;"\
"uniform sampler2D tex3;"\
"uniform vec2 screenSz;"\
"uniform float camFar;"\
"float rand(vec2 co){"\
"        return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * vec2(43758.5453,43458.5734));"\
"}\n"\
"#define smplsz 7.05\n"\
"#define jitter 8.95\n"\
"#define range 10.0\n"\
"#define gi_scale 6.85\n"\
"#define ao_scale 1.55\n"\
"#define gi_mul_ao 0.45\n"\
"void main() {"\
"   vec2 UV = gl_TexCoord[0].xy;"\
"   vec2 sample3 = texture2D(tex2,UV).xy;"\
"   if (sample3.x==1.0)"\
"       discard;"\
"   float mult = camFar/range;"\
"   vec4 col = texture2D(tex0,UV);"\
"   col.w = col.w*2.0-1.0;"\
"   vec3 n = vec3(col.w,sample3.y,sqrt(max((1.0-sample3.y*sample3.y-col.w*col.w),0.0)));"\
"   vec3 p = (vec3(UV*2.0-1.0,1.0)*sample3.x*mult);"\
"   vec2 fres = UV*screenSz*vec2(5.0/128.0);"\
"   vec2 jitterSz = jitter/screenSz;"\
"   float ao = 0.0;"\
"   vec3 gi = vec3(0.0,0.0,0.0);"\
"   vec2 inc = vec2(smplsz)/screenSz;"\
"   vec2 UVoff;"\
"   float Adiv = 4.0/(screenSz.x*screenSz.y);"\
"   for(float i=1.0; i<4.0; ++i) {"\
"       float samples = i*3.0;"\
"       for(float j=0.0; j<samples; ++j) {"\
"           float angle = j*6.283185308/samples;"\
"           UVoff = clamp(UV+vec2(sin(angle),cos(angle))*i*inc+rand(fres+UVoff)*jitterSz,0.000386,0.999614);"\
"           vec2 sample4 = texture2D(tex2, UVoff).rg;"\
"           float sampleDepth = mult*sample4.r;"\
"           vec3 ddiff = vec3(UVoff*2.0*sampleDepth-vec2(sampleDepth),sampleDepth)-p;"\
"           float rd = dot(ddiff,ddiff)*3.141592654;"\
"           ddiff = normalize(ddiff);"\
"           vec4 colSmp = texture2D(tex0,UVoff);"\
"           colSmp.w = colSmp.w*2.0-1.0;"\
"           vec3 nmlE = vec3(colSmp.w,sample4.y,sqrt(max((1.0-sample4.y*sample4.y-colSmp.w*colSmp.w),0.0)));"\
"           float A = sampleDepth*sampleDepth*Adiv;"\
"           float cosE = max(dot(nmlE,-ddiff),0.0);"\
"           float cosR = dot( n,ddiff );"\
"           ao += cosE*max(cosR*4.0,0.0)/sqrt(A/rd + 1.0);"\
"           gi += colSmp.rgb*max(cosR,0.0)*cosE*(A/rd+1.0);"\
"       }"\
"   }"\
"   ao *= ao_scale/30.0;"\
"   gi *= gi_scale/30.0;"\
"   gl_FragColor = vec4((col.rgb+gi*gi_mul_ao)*vec3(max(-pow(ao,0.936),-1.0))+col.rgb+gi,1.0);"\
"}"
Radikalizm
Posts: 1215
Joined: Tue Jan 09, 2007 7:03 pm
Location: Leuven, Belgium

Post by Radikalizm »

Very nice, I already have a similar SSAO implementation though

Maybe for those not familiar with SSAO and global illumination, post a before and after screenshot to show the impact of the shader or something like that
Kalango
Posts: 157
Joined: Thu Apr 26, 2007 12:46 am

Post by Kalango »

Is it just me or the images are alll a frog and cubes of ice and text talking about this not being a registered domain?
Mel
Competition winner
Posts: 2293
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

I see the images.

Nice implementation. But it seems to miss the edges of the polygons. Like when it is too close to the edge, the effect simply disappears.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Post Reply