Jump to content
  • Advertisement
Sign in to follow this  
toto5100

Problem with SSAO (solved)

This topic is 1577 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

i tried to implement the Disk to Disk SSAO method from Arkano22 (http://www.gamedev.net/topic/556187-the-best-ssao-ive-seen/) in Unity, which doesn't use GLSL but CG. The problem is : it doesn't look like SSAO at all. I really have no idea on where is the problem. Input texures seems good, and i didnt modified anything (i only ported the code), it uses the same method with the same functions (except for the position buffer reconstruction). Here is the code i use :

 

Shader "FXLab/PostProcessing/Bunell Disk SSAO" {
    Properties {
_FXDepthTexture ("Depth Texture (FXDepthTexture)", 2D) = "" {}
_FXWorldNormalTexture ("World Normal Texture (FXWorldNormalTexture)", 2D) = "" {}
_noiseTex ("NoiseTex", 2D) = ""{}
}
SubShader {
//Blend One Zero
Blend Zero SrcColor
Tags { "Queue"="Overlay" "IgnoreProjector"="True" "RenderType"="Opaque"}
Lighting Off
Cull Off
Fog { Mode Off }
ZWrite Off
 
Pass {
CGPROGRAM
 
#pragma vertex vert
#pragma fragment frag 
#pragma target 3.0
#pragma glsl
 
#include "UnityCG.cginc"
 
#define FORCE_TEX2DLOD
#include "../FXLab.cginc"
 
float _Bias;
sampler2D noiseTex;
float4 _ProjInfo;
float4x4 _InvProj;
 
struct appdata {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
float3 normal : NORMAL;
};
 
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
 
};
 
v2f vert (appdata v) {
v2f o;
o.pos = mul( UNITY_MATRIX_MVP, v.vertex );
o.uv = v.texcoord.xy;
 
return o;
}
 
float3 posFromDepth(float2 coord)
{
float Depth=sampleDepth(coord); //sampleDepth return the depth value (0...1 range)
float4 Pos=float4((coord.x-0.5)*2,(0.5-coord.y)*2,1,1);
float4 Ray=mul(Pos,_InvProjMatrix);
return Ray.xyz*Depth;
}
 
 
float aoFF(in half3 ddiff, in half3 cnorm, in float c1, in float c2, in float2 uv)
{
half3 vv = normalize(ddiff);
float rd = length(ddiff);
return (1.0-clamp(dot(sampleWorldNormal(uv+half2(c1,c2)),-vv),0.0,1.0)) *
            clamp(dot( cnorm,vv ),0.0,1.0)* 
             (1.0 - 1.0/sqrt(1.0/(rd*rd) + 1.0));
}
 
 
fixed4 frag( v2f o ) : COLOR
{
float dep = sampleFloat(_FXDepthTexture, o.uv);
half3 n = sampleWorldNormal(o.uv);
half3 p = posFromDepth(o.uv);
 
half2 fres = half2(_ScreenParams.x/64.0*5,_ScreenParams.y/64.0*5);
half3 random = tex2D(noiseTex,o.uv*fres.xy);
random = random*2.0-half3(1.0);
 
float ao = 0.0;
float incx = 1/_ScreenParams.x*0.1;
float incy = 1.0/_ScreenParams.y*0.1;
float pw = incx;
float ph = incy;
float cdepth = sampleDepth(o.uv);
for(float i=0.0; i<3.0; ++i) 
    {
        float npw = (pw+0.0007)/cdepth;
        float nph = (ph+0.0007)/cdepth;
 
        half3 ddiff = posFromDepth(o.uv+half2(npw,nph))-p;
        half3 ddiff2 = posFromDepth(o.uv+half2(npw,-nph))-p;
        half3 ddiff3 = posFromDepth(o.uv+half2(-npw,nph))-p;
        half3 ddiff4 = posFromDepth(o.uv+half2(-npw,-nph))-p;
        half3 ddiff5 = posFromDepth(o.uv+half2(0,nph))-p;
        half3 ddiff6 = posFromDepth(o.uv+half2(0,-nph))-p;
        half3 ddiff7 = posFromDepth(o.uv+half2(npw,0))-p;
        half3 ddiff8 = posFromDepth(o.uv+half2(-npw,0))-p;
 
        ao+=  aoFF(ddiff,n,npw,nph,o.uv);
        ao+=  aoFF(ddiff2,n,npw,-nph,o.uv);
        ao+=  aoFF(ddiff3,n,-npw,nph,o.uv);
        ao+=  aoFF(ddiff4,n,-npw,-nph,o.uv);
        ao+=  aoFF(ddiff5,n,0,nph,o.uv);
        ao+=  aoFF(ddiff6,n,0,-nph,o.uv);
        ao+=  aoFF(ddiff7,n,npw,0,o.uv);
        ao+=  aoFF(ddiff8,n,-npw,0,o.uv);
 
        //increase sampling area:
        pw += incx;  
        ph += incy;    
   
    ao/=24.0;
 
fixed3 color = saturate(1- ao);
 
return fixed4(color, 1);
}
ENDCG
}
}
 
    Fallback off
CustomEditor "FXMaterialEditor"
}
 
And here is what i have :
AO only :
[attachment=21775:SSAO Bad.jpg]
Depth Texture (8 bit):
[attachment=21772:SSAO Depth.jpg]
World Normal texture :
[attachment=21773:SSAO Normal.jpg]
Reconstructed from depth position buffer :
[attachment=21774:SSAO Position.jpg]
 
Someone can help me ?
Thanking you in advance.

 

Share this post


Link to post
Share on other sites
Advertisement

Now, i have a working SSAO but i have problems : there is many black halo and the ao intensity decrease when we are near. Only the far ao can be seeing : 

 

No one can help me ?

Edited by toto5100

Share this post


Link to post
Share on other sites

Sorry for mention this, but dude in the first post the screenshots show that you were having a wrong depth data, so for that, your reconstruction from depth calculation was bad and your SSAO failing.

 

It seems that your dynamic objects depth are being calculated different than your static ones.

 

I havent analyzed your code nor know if you are having LH or RH coordenates, take a  look on it.

 

Just trying to help you... best wishes smile.png

Share this post


Link to post
Share on other sites

Ok. I did tweked a little my shader and its works well, but i have self occlusion artifacts.

How can i avoid them ?

1401295010-ssao-self-occlusion.jpg

Edited by toto5100

Share this post


Link to post
Share on other sites

Well, the occlusion factor is applied in the pixel phase and it should be based on the convexe difference of a drawn geometry to give the observer the natural shadows given by a natural ambient light.

 

 

Ok. I did tweked a little my shader and its works well...

 

Your shader is not working well obviously.... wacko.png but yep, certainly you seem to be advancing smile.png

Edited by #Include Graphics

Share this post


Link to post
Share on other sites

Deffo still some kinks to work out but you can avoid some self shadowing issues by checking normals, if you get the normal at each sample and dot it against the main normal you can use that value to determine influence. Normals that are essentially pointing in the same direction means the surface should not be casting shadow... if the normals are facing away then they should have more shadowing. You can get the normals from the depth map or if you have a normal pass available, use that.

It also looks like pixels from very different depths are having influence when they shouldn't, you need to sort out that cut-off/threshold.

 

You want my super duper top tip for building post processing effects?

Do it on the CPU first! It is so easy to render out some test maps (depth, normal etc...) then use the IDE of your choice to smash out the screen space effects on software.

No need for triangle rasterization just loop through all the pixels and boom.

Why do this you ask? Well being able to debug EVERYTHING at EVERY stage is very very handy! It isn't suited to every situation but I was able to build and SSAO in Flash with actionscript in a lunch break no less to prove my point:

W8ZFr6M.jpg

 

It is not perfect but I was able to test things out and tweak variables incredibly easy, once it was working I just ported it to the GPU one step at a time and just checked it matched the results I was expecting as I went though!

 

It will help you spot issues very fast indeed, and if you get it working in software you then have a clear understanding of what you need to mimic on the GPU.

Also note the self shadowing on the banana where it shouldn't be, this is because this was a depth only approximation with no normal reconstruction.

 

:)

Share this post


Link to post
Share on other sites

Another render with tweaked settings:
eXWbH4N.jpg

You can see banding in these due to the precision of the depth texture but it can be overcome easily with float packing or a float texture... but as a proof of concept it worked very well (takes about 5 seconds to produce the final result)

Share this post


Link to post
Share on other sites

Yeah your SSAO looks good smile.png

if you get the normal at each sample and dot it against the main normal you can use that value to determine influence.

 

Where do the dot ? In my code, there is already 2 dot products in the aoFF function (functions which calculate ao contribution) :

float aoFF(in half3 ddiff, in half3 cnorm, in float c1, in float c2, in float2 uv)
//cnorm -> main normal and readDepthNormal(uv+half2(c1,c2).xyz -> sample normal
{
half3 vv = normalize(ddiff);
float rd = length(ddiff);
 
return clamp(1.0-dot(readDepthNormal(uv+half2(c1,c2)).xyz,-vv),0.0,1.0) *
            clamp(dot( cnorm,vv )-_Bias,0.0,1.0)* 
             (1.0 - 1.0/sqrt(1.0/(rd*rd*_scale) + 1.0));
}
 
Because currently, i have a little self occlusion and "grey" planes surfaces caused i think by the self occlusion (but my depth buffer is precise so it renders grey and not like lines).
I can't combine ambient term with ao, i can just blend the ao on the screen because i'm using Unity Free and it doesn't allow rendertextures. So i "fake" it by using a method which is very slow so i can use just 1 grabpass because 2 or more would be too expensive. I capture both depth and normals in 1 pass.
 
EDIT : ok, i solved the self occlusion by my self, i just added a condition about a dot threshold and it done the job :)
Edited by toto5100

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!