
At the start of spikeout, the text on the map indicator is simply missing. Originally I thought, somehow we could have been missing or skipping this geometry entirely. However in our debugging tool it's clear the polys are there.

Okay, so it must have been depth tested out due to lack of precision. In order to understand this problem need a little background on 3d gfx ..
Almost all 3d apis you define a 'camera'. The camera has a left right, top and bottom clipping planes. The clipping planes basically define your field of view. The closer the planes the smaller the FOV. Visible geometry is anything inside these planes.

In the above image only the blue boxes are visible.
All APIs pass a near and far plane. It's common in games if you get too close to the geometry for holes to appear.

Nvidia has a kind of 'solution' to this problem. Anyway that's beyond the scope of this.
The model3 is an extremely strange architecture. It never seems to exhibit clipping anywhere regardless of how close objects get to the camera. Z fighting except for truly co-planar polys also seems to be completely non existent. How is this happening? Well the model3 doesn't pass near or far planes (unlike virtually every other h/w renderer in existence). In the original renderer we had guessed a set of near/far planes that worked (ish) for most games. Something like 0.25 for a near plane and 1e6 for a far plane. But games were either exhibiting extreme z fighting due to lack of precision or clipping. In order to capture the geometry the ideal near plane starts exactly where the geometry starts, and the ideal far plane extends only just past where the geometry ends. If you set a far plane at 1000, but your geometry only extends to a depth of say 10, you are wasting a good portion of your depth buffer. And your geometry starts at 1000, but your near plane is set to 0.25 you have almost no depth precision at all. The reason is because the depth buffer is 1/z or non linear. Most of the depth precision is at the near plane.
I tried many things to come up with an algorithm to solve this problem. Non linear depth buffer, using the culling node distances to set a near/far plane. A solution always existed in the back of my mind but I avoided it until absolutely everything else had failed, and that was to clip in software every vertex against the view frustum. By doing that we could get the exact z start and z end value, and set the near/far planes accordingly. It sounds very expensive, but actually isn't too bad because we don't have to clip every polygon. All the polygons in the model 3 exists inside culling nodes. And only those nodes that overlap the view frustum need to be sent for clipping. In modern hardware every polygon in the scene would automatically be clipped against the 6 clipping planes. My guess is the hardware clips these polygons, then after the near/far plane calculation is done it then sets the projection matrix and sends the entire polygon set off for rasterisation.
But back to our problem. Even with this solution why don't we have enough z precision? Well I expanded the near/far planes by 5%. You don't want to exactly clip the geometry on the polygons themselves. Anyway, a 5% tolerance was too much. I changed to 1% for the near plane, and all problems gone!

Here is where they are set in the code.
- Code: Select all
CalcViewport(&n.viewport, std::abs(m_nfPairs[priority].zNear*0.99f), std::abs(m_nfPairs[priority].zFar*1.05f)); // make planes 5% bigger
Dirt devils it seems .. also has issues with Z precision.

If you are driving about the sega logo seems to flash like crazy. These are separate polys that draw over the top of the balloon.
We can see the same effect in our debugging tool

Need very precise precision? to render correctly.
Let's take a look at our near/far plane calculations to see what is going on.

Hmmm everything starts at exactly 1.5. Why? What are these polys.
In our debugging tool we can see each viewport seems to have this same poly attached to it.

Literally just 1 polygon, and its an alpha poly. Hmm, what is its alpha value?

The RGBA value is 255,255,255,0. So the alpha is 0 which means it is completely invisible. I wonder if the hardware is simply skipping this polygon entirely (including in the near/far) plane calculation. We can try this ..

Wow that's much better looking numbers. Should have a lot more depth precision! Let's see what the actual render looks like

Nice, skipping this junk alpha poly fixed everything! No more z fighting. Or nearly ...
The yellow light on the back of the car was also still flashing like crazy. Still? Looking at the polygons in the debugger I can see they are 100% co-planar, which means it's impossible for them to draw without z fighting. Must be impossible ..... if the hardware is drawing these correctly I'll probably lose my mind



Nope! Phew. Z fighting here too on the original hardware
