0
\$\begingroup\$

My 3d scene consists of three main polygons:

enter image description here

The first and the second polygons overlap each other (have the same World matrix and use the same geometry), the third one is perpendicular to the first two and is positioned a few meters away from them. All three polygons are rendered with a forward shader that uses clip() function to do alpha cutoffs. As I read in a Radeon's article, this causes EarlyZ test to be turned off and my simple subjective tests proved it: I had around 480 FPS when the second polygon's texture was empty (resulting in clip being called in every pixel) and dropping to 415 when it had a colorful for-section square in it (see the picture).

I did try to make sure that Z-test happens: I tried drawing the second polygon first while "rising" it above the ground (polygon #2) and thus bringing it closer to camera - it changed nothing. I also tried removing clip() function from the shader and recieved an FPS boost just as expected. But obviously this produced incorrect results as the ground underneath the second polygon was never drawn as it always failed the Z-Test. So I decided to try using DepthBias to be able to draw two polygons one over another and have no depth-fighting. This is what MSDN writes about it:

Sets or retrieves the depth bias for polygons, which is the amount of bias to apply to the depth of a primitive to alleviate depth testing problems for primitives of similar depth. The default value is 0.

Property Value The amount of bias to apply to the depth of a primitive. The value ranges from 0 to 16 (inclusive).

When I finally managed to make it work, I surprisingly got a performance boost. Now the thing is I even managed to gain FPS applying it to the third polygon! This is how I render them to gain the best performance:

GraphicsDevice.RasterizerState = CCWLayer1;
DrawSecond(gameTime);
GraphicsDevice.RasterizerState = CCWLayer2;
DrawThird(gameTime);
GraphicsDevice.RasterizerState = CCWLayer3;
DrawFirst(gameTime);


public RasterizerState CCWLayer1 = new RasterizerState()
{
    CullMode = CullMode.CullCounterClockwiseFace,
    DepthBias = 0.005f,
};

public RasterizerState CCWLayer2 = new RasterizerState()
{
    CullMode = CullMode.CullCounterClockwiseFace,
    DepthBias = 1,
};

public RasterizerState CCWLayer3 = new RasterizerState()
{
    CullMode = CullMode.CullCounterClockwiseFace,
    DepthBias = 0.015f,
};

I now 525 FPS and it only drops down to 515 when I draw the huge colored square on the second polygon, which clearly shows that only one set of pixels is being drawn at a time in that particular place (which is similar to EarlyZ test!).

So here is the question: can anyone explain to me what is going on? If I could understand this system better I could make more use of it and gain even more FPS.

Update: now I only draw the two polygons (no other geometry), both using clip(), the one with the colored quad (second) is always closer to the camera. With this code:

DrawSecond(gameTime);
DrawFirst(gameTime);

I get 1.5 ms per frame. With this:

GraphicsDevice.RasterizerState = CCWLayer1;
DrawSecond(gameTime);
GraphicsDevice.RasterizerState = CCWLayer2;
DrawFirst(gameTime);

public RasterizerState CCWLayer1 = new RasterizerState()
{
    CullMode = CullMode.CullCounterClockwiseFace,
    DepthBias = 0.03f,
};

public RasterizerState CCWLayer2 = new RasterizerState()
{
    CullMode = CullMode.CullCounterClockwiseFace,
    DepthBias = 0.045f,
};

I get 1.2 ms.

NO BIAS: enter image description here

BIAS APPLIED: enter image description here

\$\endgroup\$
1
\$\begingroup\$

You're using FPS is a profiling metric, which is a pretty bad idea because it is a non-linear measure. 525 FPS is about 0.001904 seconds per frame. 515 FPS is about 0.001941. That is a difference of about 0.000037 seconds, which is significantly less than a millisecond. Even between 480 (0.00208) and 525 FPS, that's only a difference of 0.000176 seconds (again, less than a millisecond).

With a timing delta that small and with the very limited set of information you've provided, it's quite likely that the differential is entirely due to the fact that you are drawing additional geometry and have provided different inputs to the graphics pipeline, causing it to do different things. Especially since your explanation makes it sound like you stopping using clip() (which will be an improvement) and then applied the bias to solve the depth-fighting problems.

\$\endgroup\$
  • \$\begingroup\$ Check the question again, I have provided additional data and measures in ms. \$\endgroup\$ – cubrman Nov 22 '13 at 17:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.