SSAO seems strange, help needed...

Started by
15 comments, last by Jason Z 15 years, 9 months ago
hi i created SSAO effect but its seems very strange, i hope that some one will tell me whats wrong because i cant see any problem with my code. first i see the edges of the triangles popping out second, there is white line at the corners, where it needs to be black/shaded triangles edges: Image Hosted by ImageShack.us<br/>By orenk2k at 2008-07-15 white lines: Image Hosted by ImageShack.us<br/>By orenk2k at 2008-07-15 here is the depth shader: Vertex shader

REAL4 vPositionView = mul(In.vPosition, g_matWorldView);
Output.fDepth = length(vPositionView.xyz);
Output.vNormal = mul((In.dwNormal)*2-1, (REAL3x3)g_matWorldView);
Output.vNormal = normalize(Output.vNormal);

Pixel shader

return REAL4(In.vNormal.x, In.vNormal.y, In.vNormal.z, In.fDepth);

frustum corner calc (in client side)

FLOAT farY = tanf(m_pCamera->GetFov() / 2) * m_pCamera->GetFarPlane();
FLOAT farX = farY * m_pCamera->GetAspect();
D3DXVECTOR4 vCorner(farX, farY, m_pCamera->GetFarPlane(), 0.0f);
// note: camera fov in radians

SSAO Shader: Vertex shader:

In.vPosition.xy = sign( In.vPosition.xy);
Output.vPosition = REAL4( In.vPosition.xy, 0.0f, 1.0f);
Output.vTexCoords = In.vTexCoords;
Output.vViewDirToFrustumCorner = REAL3(In.vPosition.xy,1)*g_vDirection.xyz; 
// note: g_vDirection = vCorner computed in client side

Pixel shader:


//reconstruct eye-space position from the depth buffer
REAL depth = tex2D(DepthSampler, In.vTexCoords).a;
REAL3 se = depth * normalize(In.vViewDirToFrustumCorner);

REAL3 randNormal = tex2D( RandNormalSampler, In.vTexCoords*20).rgb;
REAL3 normal = tex2D(DepthSampler, In.vTexCoords).xyz;   

const int num_samples = 16;
REAL finalColor = 0.0f;
for (int i = 0; i < num_samples; i++)
{
	REAL3 ray = reflect(samples.xyz, randNormal);
	
	// add view space normal and bias  
	ray += normal * g_fNormalBias;	    
	ray *= g_fSampleRadius;
	    
	// new (view-space) sample in a sphere of sampleRadius
	REAL4 sample = REAL4(se + ray, 1.0f);

	//determine clip-space locations of our current sample point
	REAL4 ss = mul(sample, g_matProjection);

	//determine the texture coordinate of our current sample point
	REAL2 sampleTexCoord = 0.5f * (ss.xy/ss.w) + REAL2(0.5f, 0.5f);
	sampleTexCoord.y = 1.0 - sampleTexCoord.y;	
	    
	//read the depth of our sample point from the depth buffer
	REAL sampleDepth = tex2D(DepthSampler, sampleTexCoord).a;
		
	//compute our occulusion factor
	REAL depth_diff = depth - sampleDepth;
	REAL occlusion = g_fDistanceScale * max(depth_diff, 0.0f);
	finalColor += 1.0 / (1.0f + (occlusion * occlusion) * 0.1);
}
	
REAL col = finalColor/num_samples;
return REAL4(col, col, col, 1.0f);

Advertisement
I can't see any obvious errors, but:

1) why does finalColor += 1.0 / (1.0f + (occlusion * occlusion) * 0.1); have that multiply by 0.1? What if you remove it?

2) for the depth shader, what happens if you interpolate the view-space position to the pixel shader and then take the length there? I believe that's why you can actually "see" the triangle edges

3) what does g_fDistanceScale look like?
Quote:Original post by agi_shi
I can't see any obvious errors, but:

1) why does finalColor += 1.0 / (1.0f + (occlusion * occlusion) * 0.1); have that multiply by 0.1? What if you remove it?

2) for the depth shader, what happens if you interpolate the view-space position to the pixel shader and then take the length there? I believe that's why you can actually "see" the triangle edges

3) what does g_fDistanceScale look like?


hi 'agi_shi' thanks for replaying
i read your thread with geoff wilson on gamedev, i hope you could help me as much as you help him :)
i also saw your 'disorder engine' pics, the ssao look very good, how did you do it?
1. the 0.1 is a scale factor on the depth diff, this allows me to control how it will influence the result.
if i remove it the scene will be brighter.
2. i tried that but it did not give me better results
3. fDistanceScale is scale factor like in (1), allows me to control it from the app, basically i can remove the 0.1 from finalColor += ... and set fDistanceScale = 0.1 you are right - this will save me a mul :)
Quote:Original post by orenk
Quote:Original post by agi_shi
I can't see any obvious errors, but:

1) why does finalColor += 1.0 / (1.0f + (occlusion * occlusion) * 0.1); have that multiply by 0.1? What if you remove it?

2) for the depth shader, what happens if you interpolate the view-space position to the pixel shader and then take the length there? I believe that's why you can actually "see" the triangle edges

3) what does g_fDistanceScale look like?


hi 'agi_shi' thanks for replaying
i read your thread with geoff wilson on gamedev, i hope you could help me as much as you help him :)

I'll try [smile]
Quote:
i also saw your 'disorder engine' pics, the ssao look very good, how did you do it?

I released my SSAO as a complete demo over at Ogre3D's forums: here. Feel free to inspect and dissect the source [grin]. The ssao shader itself is found in /data/ssao.cg - the code is infact very, very similar to your's, and that is why I cannot spot any obvious errors.
Quote:
1. the 0.1 is a scale factor on the depth diff, this allows me to control how it will influence the result.
if i remove it the scene will be brighter.

I believe you should remove it and only play with the distance scale.
Quote:
2. i tried that but it did not give me better results

Alright, just checking, because I usually encounter odd depth discontinuities by interpolate the depth instead of the view-space vector.
Quote:
3. fDistanceScale is scale factor like in (1), allows me to control it from the app, basically i can remove the 0.1 from finalColor += ... and set fDistanceScale = 0.1 you are right - this will save me a mul :)

What units are you using? 1 unit = 1 meter, or 1 unit = 1 inch, or..? My scene uses meters, and my distance scale is ~50 units.

Like I said, though, I can't really spot any obvious errors in there that would just "pop out", you know what I mean? And thus, something that would help us make sure that the data you're feeding your SSAO is correct:
1) a screen shot of se - just output se.xyzz to the final colour for debugging
2) a screen shot of In.vViewDirToFrustumCorner - same way as above
3) a screen shot of normal - again, same way

Anyways, good luck!
hi
yes i know what you mean ;)

0. my units is inches (i'm using q4 editor - they use inches)
1. se.xyzz
Image Hosted by ImageShack.us<br/>By orenk2k at 2008-07-17

2. In.vViewDirToFrustumCorner.xyzz - look the same as 1

3. normal.xyzz
Image Hosted by ImageShack.us<br/>By orenk2k at 2008-07-17

can you show me how your textures looks like (se, corner, normal)?
Aha! The problem is your far corner calculation. It should indeed have those 4 quadrants, but they should have single-component colours (such as [1,0,0] or [0,1,0], but in your case you have [1,1,1] or [1,0,1] and so on). Like this:


Your normals look fine. Now about what is wrong with your corner, I honestly don't know, since I don't calculate it that way. getFrustumCorners() holds my hand for me [grin]. See if you have some type of function like that available to you, if you're working with some kind of framework. Then what I do, is I pass the 4 far frustum corners as the NORMAL attributes of the 4 vertices - so there's no calculations going on, I simply pass the NORMAL as the camera-to-pixel ray.

As for se.xyzz - it should indeed look similar to the ray, but it should be in a gradient of the depth. For example:


Also, check your depth output. Simply output depth.xxxx / N, where N is some constant so that you get a lager range of depths in the smaller [0..1] range of colours (otherwise you'll only see whatever is 1 inch in front of you, since the higher colours will get clamped to 1).
hi
i can see the problem now, no gradient of depth that i could see, its just the same as the 'se'
i'm using my own engine, so i need to make my own functions.
1. what exactly the function 'getFrustumCorners' do? is it calculate the 8 vertices pos the lies at the near and far planes? (4 near and 4 far)
2. assuming i have that function, is the order of corner vertices mater? do i need to map them in a certain order to full screen quad vertices?
You only need the 4 far corners of the frustum. As far as the order, the vertices of your quad need to be mapped to the corresponding corner of the frustum. So the top-right vertex gets the the top-right corner, etc.
ok, thanks (agi, mjp) i think i have some material to work with ;)
i try it out in hope it will fix the problem

This topic is closed to new replies.

Advertisement