Jump to content

  • Log In with Google      Sign In   
  • Create Account

Problem with SSAO (solved)


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
7 replies to this topic

#1 toto5100   Members   -  Reputation: 169

Like
1Likes
Like

Posted 23 May 2014 - 08:53 AM

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 :
SSAO Bad.jpg
Depth Texture (8 bit):
SSAO Depth.jpg
World Normal texture :
SSAO Normal.jpg
Reconstructed from depth position buffer :
SSAO Position.jpg
 
Someone can help me ?
Thanking you in advance.

 



Sponsor:

#2 toto5100   Members   -  Reputation: 169

Like
0Likes
Like

Posted 27 May 2014 - 12:48 PM

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, 27 May 2014 - 12:49 PM.


#3 #Include Graphics   Members   -  Reputation: 405

Like
0Likes
Like

Posted 28 May 2014 - 01:39 AM

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



#4 toto5100   Members   -  Reputation: 169

Like
0Likes
Like

Posted 28 May 2014 - 10:36 AM

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, 28 May 2014 - 10:37 AM.


#5 #Include Graphics   Members   -  Reputation: 405

Like
0Likes
Like

Posted 29 May 2014 - 03:03 AM

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, 29 May 2014 - 03:04 AM.


#6 bwhiting   Members   -  Reputation: 816

Like
0Likes
Like

Posted 29 May 2014 - 03:24 AM

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.

 

:)



#7 bwhiting   Members   -  Reputation: 816

Like
0Likes
Like

Posted 29 May 2014 - 03:26 AM

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)



#8 toto5100   Members   -  Reputation: 169

Like
0Likes
Like

Posted 29 May 2014 - 11:51 AM

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, 29 May 2014 - 12:34 PM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS