Page 1 of 1

Depth sorting

PostPosted: Mon Nov 06, 2017 3:15 pm
by Ian
The model3 draws many co-planar polys and you never see z fighting. I know there is a stencil test option, and as far as I can see it's only ever used for the shadow under the car in sega rally2. That's the only game to set that bit anyway. For the rest of the games, z fighting seems to magically disappear.

My working theory is the hardware must be doing a depth only pass on translucent polys. By translucent I mean PolyAlpha() not TextureAlpha(). Texture alpha is a different issue.
So it could be doing something like

Pass 1, render opaque polygons normally.
Pass 2, render translucent polys but just write depth values
Pass 3, render translucent polys normally.

The z buffer would be already filled so only the topmost polygons would render.

This is what we have currently (without the stencil hack)
Image

The left side is fully opaque, because the back side renders first, then the front of the balloon renders ontop and blends together. On the right side the front renders first, so the back is automatically depth tested out and never draws.

This is what the real hardware is doing. Quality is the best I could find :(
Image

Image

Image

Looks to me like the entire balloon is semi transparent. This is probably only possible with either depth sorting each individual poly .. which seems extremely unlikely. Or doing a depth only pass first.

Using the stencil test instead of a Z pass results in this monster
Image

The shading is wrong because on the left you only see the back side, and on the right you only see the front. So this can't be the solution that was used.

Re: Depth sorting

PostPosted: Mon Nov 06, 2017 3:20 pm
by Ian
To disprove this .. should be able to find some examples of translucent polys blending together in the same priority layer.

Re: Depth sorting

PostPosted: Mon Nov 06, 2017 3:47 pm
by HarryTuttle
Ian wrote:Pass 1, render opaque polygons normally.
Pass 2, render translucent polys but just write depth values
Pass 3, render translucent polys normally.


That's basically what I did time ago for each priority level (ending up to many render passes) fixing, among the others, the breaking glass scene in ECA attract mode. However I messed up 'cause I wrongly included also TextureAlpha() :roll:

But I think that's the right approach.

Re: Depth sorting

PostPosted: Mon Nov 06, 2017 3:52 pm
by Ian
I am not sure how else it could be done. The balloons show it's clearly not using the stencil buffer.
Here is one more example that we have seen before from ECA

Image

There is some specular applied to the glass, but absolutely no blending overlap.

Re: Depth sorting

PostPosted: Sat Nov 18, 2017 9:59 am
by Ian
Not had much time to supermodel this week
I did briefly look into this issue again. I found simple doing a depth pass first for transluent polys is not enough. The reason is because 2 polys drawn at the same depth, will be drawn and blended twice. Ie the shadows in many games.

The solution it to do a depth pass, then change how the stencil buffer and depth test work

So
something like this

Code: Select all
   glStencilFunc   (GL_EQUAL, 0, 0xFF);         // basically stencil test passes if the value is zero
   glStencilOp      (GL_KEEP, GL_KEEP, GL_INCR);   // if the stencil test passes, we incriment the value
   glStencilMask   (0xFF);


What that does is only incriment the stencil value, if the depth test passes

Then we render the scene for opaque polys normally

Then ..

Code: Select all
      glColorMask   (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);         // disable colour writing for a depth pass   
      RenderScene   (pri, false, PolyType::polyAlpa);
      glDepthFunc   (GL_EQUAL);
      glColorMask   (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);            // re-enable again
      glEnable   (GL_STENCIL_TEST);
      RenderScene   (pri, false, PolyType::polyAlpa);
      glDisable   (GL_STENCIL_TEST);


Color mask turns off writing to the colour buffer. So the first render scene only writes depth values.
Then we change the depth function to only pass if the depth values are equal to those in the depth buffer. So this will only draw the topmost polys. It will still z fight with co-planar polys with the same depth values, but we can fix that with the stencil buffer. If the depth test passes, it will increment the value in the stencil buffer, and prevent further co-planar polys from drawing.

This almost totally fixes every z fighting issue in the games. But there are still some minor order related transparency errors