Skip to main content
GameDev.net gamedev.net
🔒 Locked

[??]SSAO ON D3D9 with HLSL

Started by zinking May 12, 2009 at 10:22 AM 5 replies 3.9k views
Original Post
zinking
zinking
I've seen numerous threads on this, but I'm not ashamed of still posting a thread on SSAO, after all I'm going to implement it on D3D9 I've seen a lot cool demos on that, opengl ones, d3d10 ones, ogre ones, etc.. some links I collected. http://www.malmer.nu/index.php/2008-04-09_ssao-c-style-pseudo-source-code/ AO - ON - XNA http://sites.google.com/site/shadedpixels/realtime-ambient-occlusion DETAILED SRC ON SSAO http://www.gamerendering.com/2009/01/14/ssao/ http://www.gamedev.net/community/forums/topic.asp?topic_id=523054 http://www.gamedev.net/community/forums/topic.asp?topic_id=517130&PageSize=25&WhichPage=1 http://www.francois-tarlier.com/blog/?tag=ssao now comes my problem, It seems not easy to access depth buffer on d3d9, it seems two passes are needed, any one point me some directions? surely I need to implement the whole thing on D3D9 [Edited by - zinking on May 14, 2009 8:10:35 PM]
Promit
Promit
You need to sample the depth, which means making a copy of it to texture on PC. There's no way around that. Your options are doing a render to texture depth pass, or copying the depth buffer after rendering your scene. I'm not sure which one's preferred nowadays, actually. I implemented this on for 360 and PS3, where you can just sample depth directly (more or less).
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
MJP
MJP
Quote:
Original post by Promit
You need to sample the depth, which means making a copy of it to texture on PC. There's no way around that. Your options are doing a render to texture depth pass, or copying the depth buffer after rendering your scene. I'm not sure which one's preferred nowadays, actually. I implemented this on for 360 and PS3, where you can just sample depth directly (more or less).


Just rendering out depth to a texture is generally the way to go. It's pretty quick, it's the most flexible, and it lets you lay out linear depth if you want to avoid precision issues.

In D3D9 there are Nvidia and ATI-specific methods for sampling a depth buffer, but they're aimed at shadowmapping and aren't useful for SSAO.

zinking
zinking
thanks for the quick reply

and I have no idea of how this is done( because I have used opengl gl before this and I am not farmiliar with framebuffer operations), and I have searched some threads but still got no idea, is there some links or url worth noticing?

thanks very much for you guys
and still I would like to mention that I'm using D3D9( I have no that hardware to support higher versions, or maybe later),
remigius
remigius
Quote:
Original post by zinking
I would like to mention that I'm using D3D9( I have no that hardware to support higher versions, or maybe later),


You might want to check out Windows XNA samples in particular then. XNA on Windows also use D3D9 under the hood and the HLSL should mostly be reusable. This article might be of use to get started with rendering to textures in D3D9.
zinking
zinking
Pack & Unpack Depth value is really painful for me, especially the weird TEXEL format A8R8G8B8 why A8first?

and that shit depth texture can just not be released, why
I did that in OnDestroyDevice()

this is far from the SSAO on D3D9 as I expected, some one give a hand?
zinking
zinking
I have stepped to the SSAO stage and I found following problems
http://farm3.static.flickr.com/2391/3531058578_37d82fc9fd.jpg?v=0

1. How could I check the depth buffer I rendered is right or wrong, I debug that in PIX found all the RGBA values are 1 ( I used the _R32F texture render target fomat)
2. obviously I've got my pixel shader wrong,but where?

here is my ps+VS code ( I hope it is self explain )
VS_OUTPUT RenderSSAOSceneVS( float4 inPosition : POSITION,
float2 inTexCoord : TEXCOORD0,
float3 inN : NORMAL
)
{
VS_OUTPUT Out;

Out.position = mul( inPosition, g_mWorldViewProjection );

float2 uv = sign( inPosition );
uv = (float2(uv.x, -uv.y) + 1.0) * 0.5;
Out.uv = uv;
Out.ray = inN;
return Out;
}


float4 RenderSceneSSAOPS( PS_INPUT IN ) : COLOR0
{
#define MAX_RAND_SAMPLES 14
const float3 RAND_SAMPLES[MAX_RAND_SAMPLES] =
{
float3(1, 0, 0),
float3( -1, 0, 0),
float3(0, 1, 0),
float3(0, -1, 0),
float3(0, 0, 1),
float3(0, 0, -1),
normalize(float3(1, 1, 1)),
normalize(float3(-1, 1, 1)),
normalize(float3(1, -1, 1)),
normalize(float3(1, 1, -1)),
normalize(float3(-1, -1, 1)),
normalize(float3(-1, 1, -1)),
normalize(float3(1, -1, -1)),
normalize(float3(-1, -1, -1))
};

#define NUM_BASE_SAMPLES 6

// random normal lookup from a texture and expand to [-1..1]
float3 randN = tex2D( g_samNoise, IN.uv * 24).xyz * 2.0 - 1.0;
float4 geom = tex2D(g_samDepth, IN.uv);
float depth = geom.x;

const float RADIUS = 0.12;//0.08;
const int NUM_SAMPLES = 12;

float4 D = computeViewPos(IN.ray, depth );

float3 N = IN.ray;

// accumulated occlusion factor
float occ = 0;
for (int i = 0; i < NUM_SAMPLES; ++i) {
// (based on random samples and a random texture sample)
float3 RN = reflect(RAND_SAMPLES, randN);

// bias the random direction away from the normal
// this tends to minimize self occlusion
const float DIR_BIAS = 1.5;
RN += N * DIR_BIAS;

// new (view-space) position in a sphere of RADIUS
float3 vp = D.xyz + RN * RADIUS;

// move this new position back into texture space
float4 nuv = mul(g_mProjection, float4(vp, 1));
nuv.xy /= nuv.w;

// look up the new depth
float depth = tex2D(g_samDepth, float4(nuv.xy, 0, 0)).r;

// get the (scaled) Z difference
const float ZSCALE = 50;
float ZD = ZSCALE * max(D.w - depth, 0);

// quadratic falloff is both accurate
const float MAX_DIFF = 2;
const float NO_OCC = 4;
occ += (ZD < ZSCALE * MAX_DIFF ? occlusion(ZD) : NO_OCC);
}
occ = occ / NUM_SAMPLES;
occ = lerp(0.3, 1, occ);

return float4(occ.xxx, 1);
}

[Edited by - zinking on May 14, 2009 8:18:41 AM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.