Search Home Members Contacts
About Us
Products
Downloads
Community
Support
Pages: [1] 2 3 ... 6
  Print  
Author Topic: Screen-Space Ambient Occlusion( SSAO )  (Read 8223 times)
AriusEso
Customers
Community Member
*****
Posts: 376

Esoteric


« on: June 06, 2008, 05:16:52 AM »

A couple guys on IRC requested this. I haven't done the blur pass yet, but it's coming along nicely. I will make a sample when it's done. It's currently SM3, but I will try to squeeze out an SM2 version - obviously the quality will suffer due to less sampling. You'll notice the grain in the shot, this will be gone with the blurring of course. The framerate is crap cause the host app is severly inefficient and hacky atm, I've been at this all night Tongue.

[click for big]

Logged

Raine
Customers
Community Member
*****
Posts: 1189


« Reply #1 on: June 06, 2008, 06:29:41 AM »

Oh joy, I wanted to implement this for Darkmana... looking forward to the SM 2.0 version Smiley

It also looks correct, despite the lack of blur. Can't wait!
Logged

Toaster
Community Member
*
Posts: 147


WWW
« Reply #2 on: June 06, 2008, 07:43:19 AM »

Looks sweet Arius! Normally when rendering the occlusion I believe they use a white or gray background not black but I could be wrong as I have no idea what I am talking about. I like it though. Cheesy

-Toaster
Logged

Visit my site at: Unknown Abstraction
AriusEso
Customers
Community Member
*****
Posts: 376

Esoteric


« Reply #3 on: June 06, 2008, 07:58:09 AM »

I actually have a slight bug at the moment. I'm pretty sure it is to do with the way I am grabbing the frustum corner.

Code:
cTV_3DVECTOR CalculateCorner()
{
cTV_PLANE Planes[6];
m_Camera->GetFrustumPlanes(&Planes[0]);

        //AR = aspect ratio.
        float AR = 1024 / 768;

float FarY = tan(3.14159f / 3 / 2) * Planes[0].Dist;
float FarX = FarY * AR;

return Vector3(FarX, FarY, Planes[0].Dist);
}

Could some math guru check over this for me? Thanks.
Logged

Raine
Customers
Community Member
*****
Posts: 1189


« Reply #4 on: June 06, 2008, 08:23:13 AM »

Shouldn't this line

float FarY = tan(3.14159f / 3 / 2)

have 3f and 2f instead? Might cause an unwanted cast to integer. I am, however, completely unaware of how this works in C++.

Logged

AriusEso
Customers
Community Member
*****
Posts: 376

Esoteric


« Reply #5 on: June 06, 2008, 08:24:36 AM »

Shouldn't this line

float FarY = tan(3.14159f / 3 / 2)

have 3f and 2f instead? Might cause an unwanted cast to integer. I am, however, completely unaware of how this works in C++.



Good idea. But I actually tried this a couple minutes after posting. Smiley
Logged

SylvainTV
Administrator
Community Member
*****
Posts: 4479


WWW
« Reply #6 on: June 06, 2008, 02:43:50 PM »

Now if you did it the easy way, it would be better...

What do you think GetFrustumPoints is for ? Smiley

(    void CTVCamera::GetFrustumPoints(cTV_3DVECTOR* pVertices); )

The vertex 4, 5, 6, 7 defines the far plane
and 0, 1, 2, 3 defines the near plane

Probably would help I guess??
Logged

Regards

Sylvain Dupont
TrueVision3D Developer
sylvain@truevision3d.com

TV3D IRC at http://chat.truevision3d.com or on server irc.truevision3d.com #Truevision3D. Come talk with us !
Lenn
Customers
Community Member
*****
Posts: 454

Ivan Miskelic


« Reply #7 on: June 06, 2008, 06:59:36 PM »

See this is why we need docs, Sylv. Wink

The sooner they are released the sooner many people will find simple solutions to a lot of problems they don't even know TV3D can currently solve for them. Myself included.
Logged

AriusEso
Customers
Community Member
*****
Posts: 376

Esoteric


« Reply #8 on: June 07, 2008, 05:40:08 AM »

Now if you did it the easy way, it would be better...

What do you think GetFrustumPoints is for ? Smiley

(    void CTVCamera::GetFrustumPoints(cTV_3DVECTOR* pVertices); )

The vertex 4, 5, 6, 7 defines the far plane
and 0, 1, 2, 3 defines the near plane

Probably would help I guess??

lmao, I didn't even know that existed Smiley. Thanks Sylvain I'll give it a whirl.
Logged

AriusEso
Customers
Community Member
*****
Posts: 376

Esoteric


« Reply #9 on: June 09, 2008, 06:35:01 AM »

Slowly....

[click for big]


It is flipped on the Y, but Sylv said this might happen on IRC, so I know how to fix( I think.. ).
Logged

AriusEso
Customers
Community Member
*****
Posts: 376

Esoteric


« Reply #10 on: June 09, 2008, 08:19:29 AM »

This is prooving to be a pain, but here is where I am at. Still no blur pass yet ofc.

[click for big]
Logged

Mietze
Community Member
*
Posts: 277

Pleeease, don't let it crash!


WWW
« Reply #11 on: June 09, 2008, 02:31:12 PM »

to be honest: ists a weird effect, isnt it?
Logged

Check out my blog at www.e-studioz.de - The finest in gross trash Wink
Zaknafein
Customers
Community Member
*****
Posts: 2670


WWW
« Reply #12 on: June 09, 2008, 02:37:14 PM »

Hahah yeah, I've been following this thread for a while and I can't say it looks like ambient occlusion to me.
Even though you mention that it's meant to be blurred, it just looks like noisy point-lighting. I can't feel the "occlusion" part yet.
Logged

zaknafein.
>> the instruction limit : my blog & samples repository! <<
AriusEso
Customers
Community Member
*****
Posts: 376

Esoteric


« Reply #13 on: June 09, 2008, 03:01:03 PM »

Hahah yeah, I've been following this thread for a while and I can't say it looks like ambient occlusion to me.
Even though you mention that it's meant to be blurred, it just looks like noisy point-lighting. I can't feel the "occlusion" part yet.

Yea, the occlusion is refusing to work. I've spent all day trying to work it out. Sad

Edit:

Infact, at this point I'm pretty much stuck. Help me.

Code: ("depth")

        float4x4 World   : WORLD;
        float4x4 ViewProj: VIEWPROJ;
        float4x4 wView   : WORLDVIEW;
        float4x4 WVIT    : WORLDVIEWIT;
        float3   Cam;

        texture Diffuse  : TEXTURE0;
       
        sampler2D dSampler = sampler_state
        {
                Texture = (Diffuse);
        };

        struct a2v
        {
                float3 Position: POSITION;
                float3 Normal  : NORMAL;
                float2 UV      : TEXCOORD0;
        };

        struct v2f
        {
                float4 Position: POSITION0;
                float2 UV      : TEXCOORD0;
                float  Depth   : TEXCOORD1;
                float4 Test    : TEXCOORD2;
                float3 Normal  : TEXCOORD3;
        };
       
        struct f2s
        {
                float4 Colour  : COLOR0;
        };
       
        void vp(in a2v IN, out v2f OUT)
        {
                OUT.Position = mul(float4(IN.Position, 1), World);
                OUT.Depth    = length(OUT.Position.xyz - Cam.xyz);
                OUT.Position = mul(OUT.Position, ViewProj);
//                OUT.Test     = mul(IN.Position, ViewProj);
                OUT.Test     = mul(IN.Position, wView);
                OUT.Normal   = mul(IN.Normal, WVIT);
                OUT.UV       = IN.UV;
        }
       
        void fp(in v2f IN, out f2s OUT)
        {
                float  Deep = IN.Test.z / 5000;
                float3 N    = normalize(IN.Normal);
                OUT.Colour = float4(N.r, N.g, N.b, Deep);
//                OUT.Colour = float4(IN.Depth, 0, 0, 1);
        }
       
        technique
        {
                pass Pass0
                {
                        VertexShader = compile vs_1_1 vp();
                        PixelShader  = compile ps_2_0 fp();
                }
        }

Code: ("ssao")
        float4x4 Projection : PROJECTION;

        float  SampleRadius  = 4.5;
        float  DistanceScale = 1000;
        float3 Corner;
       
        texture Deep;
        texture Rand;
       
        float2 PixelOffset   = float2( 0.001953125, 0.001953125 );

        sampler2D DeepSample = sampler_state
        {
                Texture   = (Deep);
                ADDRESSU  = CLAMP;
                ADDRESSV  = CLAMP;
                MAGFILTER = LINEAR;
                MINFILTER = LINEAR;
        };
       
        sampler2D RandSample = sampler_state
        {
                Texture   = (Rand);
                ADDRESSU  = WRAP;
                ADDRESSV  = WRAP;
                MAGFILTER = LINEAR;
                MINFILTER = LINEAR;
        };

        struct app2vp
        {
                float4 Position: POSITION0;
                float2 UV      : TEXCOORD0;
        };

        struct vp2fp
        {
                float4 Position: POSITION0;
                float2 UV      : TEXCOORD0;
                float3 vDir    : TEXCOORD1;
        };
       
        struct fp2app
        {
                float4 Colour  : COLOR0;
        };
       
        void vp(in app2vp IN, out vp2fp OUT)
        {
                OUT.Position   = IN.Position;
                IN.Position.xy = sign(IN.Position.xy);
               
                float2 NewPos = sign(IN.Position.xy);
               
                NewPos.y = -NewPos.y;
                OUT.UV = (NewPos + float2(1, 1)) * 0.5f;
//                OUT.UV = IN.UV  + ( PixelOffset * 0.5 );
               
                float3 Corn = float3(Corner.x * IN.Position.x, Corner.y, Corner.z);
                OUT.vDir = Corn;
        }

        void fp(in vp2fp IN, out fp2app OUT)
        {
                float4 Samples[16] =
                {
                        float4(0.355512,   -0.709318, -0.102371,  0.0 ),
                        float4(0.534186,    0.71511, -0.115167,  0.0 ),
                        float4(-0.87866,    0.157139, -0.115167,  0.0 ),
                        float4(0.140679,   -0.475516, -0.0639818, 0.0 ),
                        float4(-0.0796121,  0.158842, -0.677075,  0.0 ),
                        float4(-0.0759516, -0.101676, -0.483625,  0.0 ),
                        float4(0.12493,    -0.0223423, -0.483625,  0.0 ),
                        float4(-0.0720074,  0.243395, -0.967251,  0.0 ),
                        float4(-0.207641,   0.414286, 0.187755,  0.0 ),
                        float4(-0.277332,  -0.371262, 0.187755,  0.0 ),
                        float4(0.63864,    -0.114214, 0.262857,  0.0 ),
                        float4(-0.184051,   0.622119, 0.262857,  0.0 ),
                        float4(0.110007,   -0.219486, 0.435574,  0.0 ),
                        float4(0.235085,    0.314707,    0.696918,  0.0 ),
                        float4(-0.290012,   0.0518654,   0.522688,  0.0 ),
                        float4(0.0975089,  -0.329594,    0.609803,  0.0 )
        };
       
                IN.UV.x += 1.0/1024;
                IN.UV.y += 1.0/1024;
       
                float3 Dir               = normalize(IN.vDir);
       
                float  Deep              = tex2D(DeepSample, IN.UV).a;
                float3 SE                = Deep * Dir;
               
                float3 Norm              = tex2D(RandSample, IN.UV * 200).rgb;
               
                float3 Normal            = tex2D(DeepSample, IN.UV).rgb;
               
                float  fColour           = 0.0f;
               
                for(int i = 0; i < 16; i++)
                {
                        float3 Ray       = reflect(Samples[i].xyz, Norm) * SampleRadius;
                       
                if(dot(Ray, Normal) < 0) Ray += Normal * SampleRadius;
                       
                        float4 Sample    = float4(SE + Ray, 1.0f);
                        float4 SS        = mul(Sample, Projection);
                       
                        float2 SampleUV  = 0.5f * SS.xy / SS.w + float2(0.5f, 0.5f);
                        SampleUV.x      += 1.0/1024;
                        SampleUV.y      += 1.0/1024;
                       
                        float SampleDeep = tex2D(DeepSample, SampleUV).a;
                       
                        if(SampleDeep == 1.0f)
                        {
                                fColour++;
                        }
                        else
                        {
                                float Occlusion = DistanceScale * max(SampleDeep - Deep, 0.0f);
                                fColour        += 1.0f / (1.0f + Occlusion * Occlusion * 0.1);
                        }
                }
               
                OUT.Colour = float4(fColour/16, fColour/16, fColour/16, 1);
        }
       
        technique SSAO
        {
                pass P0
                {
                        VertexShader = compile vs_3_0 vp();
                        PixelShader  = compile ps_3_0 fp();
                }
        }
« Last Edit: June 09, 2008, 03:07:11 PM by AriusEso » Logged

Raine
Customers
Community Member
*****
Posts: 1189


« Reply #14 on: June 09, 2008, 03:21:41 PM »

Not sure about the latest screenies, but the first one didn't look bad... there's a huge topic over at GameDev I'm sure you've noticed, you might find the help you're looking for there as well...
Logged

AriusEso
Customers
Community Member
*****
Posts: 376

Esoteric


« Reply #15 on: June 10, 2008, 06:36:07 PM »

After wrangling with Waterman and Sylvain on IRC for the last 2 days, and a couple guys on gamedev, finally we have occlusion.


An yea, this isn't blurred yet Tongue.

[click for big]
Logged

Zaknafein
Customers
Community Member
*****
Posts: 2670


WWW
« Reply #16 on: June 10, 2008, 06:44:33 PM »

Awesome job!

Now please release shade. Cheesy
Logged

zaknafein.
>> the instruction limit : my blog & samples repository! <<
AriusEso
Customers
Community Member
*****
Posts: 376

Esoteric


« Reply #17 on: June 10, 2008, 06:45:32 PM »

Now please release shade. Cheesy

It's majorly buggy atm Sad. Can't even resize the window Shocked. But yea, I need to get back on that Cheesy.
Logged

sybixsus
Customers
Community Member
*****
Posts: 1088


WWW
« Reply #18 on: June 10, 2008, 06:48:33 PM »

It's certainly looking much more impressive now. You only need to squint a bit to see how good it would look blurred.

Forgive me if I'm off track here, because I don't know much about SSAO, but I had always assumed it was done by generating a depth map in screen space, comparing depths of neighbouring texels and looking for ones whose neighbours have a smaller depth than they do. They are the ones which should be have a lower ambient.

Looking at your actor in there, there is a thick black shadow along the top of his arms and head. Unless he is pressed up tight against that wall ( which he may be, but does not appear to be ) the wall should not be occluded by him. He's too far away. So I'm wondering whether that's happening because the depth is less on the actor than it is on the neighbouring wall texels, in which case you should have some kind of bias as you do with shadowmapping, and only occlude texels where the depth is lower but within that bias or threshold. If the depth is more than ( for example ) 0.1 less than its neighbour, it's too far away, discard it as far as occlusion goes.

If you already knew this or I'm barking up the wrong tree altogether, then I apologize for  interjecting, but I just thought I'd mention it in case it was helpful.
« Last Edit: June 10, 2008, 06:50:24 PM by sybixsus » Logged
AriusEso
Customers
Community Member
*****
Posts: 376

Esoteric


« Reply #19 on: June 10, 2008, 06:53:51 PM »

It's certainly looking much more impressive now. You only need to squint a bit to see how good it would look blurred.

Forgive me if I'm off track here, because I don't know much about SSAO, but I had always assumed it was done by generating a depth map in screen space, comparing depths of neighbouring texels and looking for ones whose neighbours have a smaller depth than they do. They are the ones which should be have a lower ambient.

Looking at your actor in there, there is a thick black shadow along the top of his arms and head. Unless he is pressed up tight against that wall ( which he may be, but does not appear to be ) the wall should not be occluded by him. He's too far away. So I'm wondering whether that's happening because the depth is less on the actor than it is on the neighbouring wall texels, in which case you should have some kind of bias as you do with shadowmapping, and only occlude texels where the depth is lower but within that bias or threshold. If the depth is more than ( for example ) 0.1 less than its neighbour, it's too far away, discard it as far as occlusion goes.

If you already knew this or I'm barking up the wrong tree altogether, then I apologize for  interjecting, but I just thought I'd mention it in case it was helpful.

You're not barking up the wrong tree, you're spot on, but I did already know that. The reason the check is not in right now is because otherwise, when it wasn't working, it makes it harder to debug - how does one know the occlusion isn't be cut off or the shader is bugged?

But yes, I will be adding a check like that in. Just at the moment, I'm pretty much just sat here with a big grin on my face Tongue.
Logged

Pages: [1] 2 3 ... 6
  Print  
 
Jump to:  

Powered by SMF 1.1.3 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks