• FEATURED

View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# Z-buffer and the clip planes-- help me understand them

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

10 replies to this topic

### #1Hawkblood  Members

Posted 27 January 2014 - 09:08 AM

I have a complex render engine that requires the rendering of objects that are spaced apart on the order of magnitude of an entire solar system. If I was rendering just planets and moons, this would be relatively simple, but I have ships and space stations that can be anywhere. Currently I am rendering in stages from far-to-near order, clearing the z-buffer (almost) each stage and changing the near and far clip planes. I’m not clearing the z-buffer each object, just each range chunk.

This is working fine, but this reduces the effectiveness of depth optimization. I tried going in the other direction and not clearing the z-buffer, but it doesn’t work.

The question is: How does the z-buffer work? I have read some technical articles on this, but I don’t understand them. How do the near and far clip planes affect the z-buffer?

### #2Husbjörn  Members

Posted 27 January 2014 - 12:21 PM

The Z buffer records depth in screen-space (normalized floats [0..1], where 0 is equivalent to the near and 1 to the far plane).

As such it will not work if you change your clipping planes as you go along.

### #3Hawkblood  Members

Posted 27 January 2014 - 12:37 PM

So if I render an object with 0.0 as near and 1000.0 as far and it sets z-buff[0,0] to 0.5 (meaning the pixil is at 500.0 depth), then any attempts to render another pixil at +500.0 will fail…. So if I change the clip planes to 500Near and 1500Far and try to render an object at, say 1100.0 then it should still fail, but a render at 999.0 should pass?

### #4Husbjörn  Members

Posted 27 January 2014 - 01:12 PM

The depth axis isn't linear like that (it prioritizes so you get higher resolution near the near plane and less further away towards the far plane), but if your range is 1000.0, your starting point 0.0 and you attempt to draw something at 1000.0 it will be (partially, the parts that lie inside the view frustum will be rendered) clipped.

Your second example is wrong though; if your near plane is at 500, far at 1500, and the object at 1100 (in world space then) it should end up between the planes and not be clipped. The range is between the planes, not from the point of origin.

### #5Hawkblood  Members

Posted 27 January 2014 - 01:52 PM

Ok. Not being linear is not a problem. Is there a correlating relationship between z-depths when the difference between near and far are the same; i.e. 0-100 &amp;amp;500-1500 (both having a difference of 1000)?

Basically, I want to be able to render objects right near the camera and objects at distances of 100Mkm+ without z-fighting. I have already done this by rendering far-to-near, but as I said before, this negates the z-depth optimization….

### #6Husbjörn  Members

Posted 27 January 2014 - 06:35 PM

What is the smallest unit you need to be able to discern between?

If your Z buffer uses 32-bit floats, it has limited precision and if by 100 000 000 000 meters you mean a billion space units too that just won't work out well.

I would recommend finding the smallest size that you need (maybe some asteroid of 10 km or something?) and then divide all your units by that; it should help a good deal and might just be enough that you can pull it off in a single normal pass.

Otherwise you can just sort them by distance (if that is possible, ie. no overlapping objects) and draw them in that order, never minding the Z buffer. Of course you will have to essentially draw everything then since there will be no sense to a depth test if you draw everything from back to front. It depends on your application which approach is best I guess, but that would be my first two approaches to look into.

### #7Hawkblood  Members

Posted 27 January 2014 - 08:57 PM

I've already figured out how to extend it. I created a vector structure with __int64 and float. It works well for a coordinate system. I sort all the objects by distance and find the relative vector to the camera (stored in a float vector). I can't have an infinite (or even very large) far clip plane, so the objects that are REALLY FAR, like distant planets, are scaled using a formula and placed just before the FCP. All the near objects are rendered normally, but still in far-to-near order. I break up the distances several times, changing the far and near best suited for those distances and clear the z-buffer. This works well, but I was hoping to get some optimization by not having to do that.

The game is in real units of 1unit==1meter. I don't have any "zones" except the solar system.

### #8frob  Moderators

Posted 28 January 2014 - 01:42 AM

Any time you start getting objects that are "really far" you might instead consider just rendering them to a texture similar to a skybox. Few things will be visible at very large distances, and often when they are visible (like a nearby star) a skybox is more than enough. Something in the "really far" distance is unlikely to visibly change during a scene, but based on your numbers it still might change occasionally. Even if it does need an update every few minutes, it can conserve a lot of processing power to render it once per minute rather than every frame.

Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I occasionally write about assorted stuff.

### #9Hawkblood  Members

Posted 28 January 2014 - 07:20 AM

Thanks. That is the best explanation of the z-buffer I have seen. As far as using W-buffer, I am concerned about video cards that don’t support RHW clipping. As this is new to me, it may be that this info is out of date, and that all modern cards support it.

The objects that will be visible at great distances will be the local star and relatively nearby planets. The idea of making that into a skybox is not so good because of the way the player can travel in the solar system. Most ships will have a near-light-speed drive (NLS) which makes travel between planets within a star system trivial (and fast). So the amount of change the star and planets relative to the player can be great and quick. Nearby stars (that are visible) are represented using billboards. The number of “visible” stars isn’t that many, so this is not a problem. Even so I could make a skybox for those….

### #10frob  Moderators

Posted 28 January 2014 - 12:49 PM

The game is in real units of 1unit==1meter. I don't have any "zones" except the solar system.

The objects that will be visible at great distances will be the local star and relatively nearby planets.

In that case expect all kinds of nasty evil problems. Your scales are not compatible.

Because you say you are relying on traditional rendering systems you will need to ultimately use floating point math. That means you normally get six decimal digits of precision. When you do operations that involve different scales the small numbers are promoted up to the big numbers.

A star is anywhere from 1,000,000,000 to 500,000,000 meters in radius, double for diameter. Our sun is about 1,391,000,000 meters in diameter (thanks Google). So with six digits, you have 1.39100e9.

The radius of the Earth is 6,378,100 meters in radius, or once promoted to the same scale, 0.012275e9

And of course your space ship is probably around 100 meters, or promoted to the same scale, 0.00000e.

Uh-oh.

When you are operating at the scale of stars and planets a spaceship will either cease to exist (actually round to zero) or be the same size as a numeric rounding error.

This isn't to say you cannot have a world at those scales. That type of thing has been done in advanced numeric simulations. It certainly can be done, but the math involved is quite involved and will require you to essentially rewrite the entire rules for rendering in your own notation and then transform your custom rendering system to something compatible to graphics hardware.

You can write it, but you won't spend your time actually making a game.

Most ships will have a near-light-speed drive (NLS) which makes travel between planets within a star system trivial (and fast).

Either you don't understand the distances involved, or your concept of "trivial and fast" as it applies to games is very different than mine.

The travel time from Earth to Sun is just over eight minutes. You could complete a speed run of the entire Super Mario Bros during that time, with enough time left over to fix yourself a sandwich before entering orbit.

The maximum travel time from Earth to Mars is about 25 minutes when we are at opposite ends of the sun. You could complete a speed run of Zelda: Ocarina of Time while you wait to travel.

Or perhaps Earth to Pluto, which can reach 7 hours. You could watch the original star wars trilogy as you travel. Or you could play through all of Portal 1 and Portal 2 as you travel between the two planets.

If you need to travel between two distant planets, such as Pluto and Eris (Eris is the planet that helped Pluto get reclassified as a dwarf planet), you might have a journey of 20 hours. I wouldn't call that "trivial and fast" unless your game is designed around one brief play session every day.

While many games involve interplanetary and interstellar travel, and a few of those games have scripts that hint at things like traveling near light speed, the games internally do not have anything even remotely resembling accurate scales.

Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I occasionally write about assorted stuff.

### #11Hawkblood  Members

Posted 28 January 2014 - 01:55 PM

I created a vector structure with __int64 and float. It works well for a coordinate system.

This video (includes sound this time) shows the scaling ability of objects in the game:

Either you don't understand the distances involved, or your concept of "trivial and fast" as it applies to games is very different than mine.

I understand exactly how large the solar system is. This is one of the features I have included in my engine. That is why I need a special render loop with several stages for various distances.

The maximum travel time from Earth to Mars is about 25 minutes when we are at opposite ends of the sun. You could complete a speed run of Zelda: Ocarina of Time while you wait to travel.

This is where "relativistic" space travel comes into play. This formula:

TD=1.0F/sqrt(1.0F-(Vel*Vel)/SOLsq);


is used for the "time dilation effect". The closer you get to the speed of light the slower your perception of time is. This means that the 25 actual time it would take for an object going SOL (or very near since nothing but light can go that fast by normal means) would SEEM, to the occupants of such a craft, to only be less than a minute or two (depending on how close to SOL).

EDIT:

As far as size goes, with the coordinate system I use, you could go 1559846446.2801920865888719769998 times the distance from the Sun to Pluto before wrapping around the coordinates.

Another way to look at it:
The star Hip 96088 is ~154 parsecs from Sol. This is the farthest of the 30,000 nearest stars.
A parsec is 3x10^13 km
That would be 4620,000,000,000,000 km from Sol.
With a max distance of travel on any axis being 9,223,372,036,854,775,808 km for my coordinate system.
The ship could travel ~1996.4 x that distance before wrapping around.

Edited by Hawkblood, 28 January 2014 - 02:48 PM.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.