Some coding problems are stubborn – I find myself looking back at a week of working realizing that all I really did was prove that a bunch of theoretical improvements don’t work in practice.
Improving OBJ throughput is one of those problems. On a high-end machine, even drastic changes to the OBJ engine make only the slightest difference in throughput – 2 or 3% at best. Every improvement counts, but a 3% improvement doesn’t change the game for how we draw scenery.
There is at least one route I haven’t had time to go down yet: object instancing. The theory is that by making many objects appear with only one object drawn, we get a multiplier, e.g. a 2x or 4x or larger amplification of the number of objects we can have.
In practice it won’t be that simple:
- To get such an amplification we have to recognize groups of the exact same object. Grouped objects will have to be culled together. So we might get a hit in performance as we draw more objects that are off-screen, just to use instancing.
- It may be that the grouping requirement is so severe that it is not practical to find and group objects arbitrarily (instead we would have to group objects that are built together, like clusters of runway lights). That might limit the scope of where we can instance.
- The objects have to look more or less the same, so some categories of very complex objects won’t be subject to instancing. (E.g. objects with animation where each object might look different.)
- I have already coded some experiments with geometry shaders, and the results are just dreadful – geometry shaders simply don’t output a huge number of vertices efficiently, so they don’t help us increase our total vertex throughput. The experience has left me with a “prove it” attitude toward GL extensions that are supposed to make things faster.
When will we know whether instancing can help? I don’t know — I suspect that I won’t be able to find time for code experiments for a bit, due to other work, particularly on scenery creation and tools.
A hidden detail of my previous post on variation and terrain textures: variation for flat textures was implemented using more triangles in the DSF in X-Plane 8, but is implemented in a shader in X-Plane 9. This means that you don’t get this feature in X-Plane 9 if shaders are off.
My guess is that this is perfectly acceptable to just about every user.
- If you don’t have shaders, you have something like a GeForce 4 or Radeon 8500, and are fighting for frame-rate. In this case, not paying the price of layer-based variation is a win.
- If you have shaders, you’re getting better performance because the shader creates variation more efficiently than the old layering scheme did.
This kind of move of a feature to the GPU can only happen at major versions when we recut the global scenery, because (to utilize the benefit) the DSFs are recut with fewer (now unneeded) layers. So features aren’t going to mysteriously disappear mid-version.
I do have a goal to move more layering-type features to the GPU for future global scenery renders. There are a number of good reasons:
- DSF file size is limited – we have distribution requirements on the number of DVDs we ship. So DSF file size is better spent on more detailed meshes than on layers.
- GPU power is increasing faster than anything else, so it’s good to put these effects on the GPU – the GPU is still hungry for more!
- If a feature is run on the GPU, we can scale it up or down or turn it on or off, for more flexible rendering settings on a wide variety of hardware. A feature baked into the DSF is there for everyone, no way to turn it off.
My hope for the next render is to (somehow) move the cliff algorithm (which is currently done with 2-4 layers) to the GPU, which would shrink DSFs, improve performance, and probably create nicer looking output.
In my previous post I discussed variation as a way to hide the artifacts of land use texturing. Now we can talk about this bug.
What are these weird artifacts that show up over the terrain when shaders are on? Well, they should (and will in 930) look like this:
But what’s going on? The answer is auto-variation.
In X-Plane 8, variation is created by using multiple layers, each one applying a texture at a different offset. This technique works on a wide range of hardware, but is inefficient – it causes overdraw (which we know is
very bad).
So in X-Plane 9 I replaced this layer-based variation with a pixel shader algorithm. This means less information in the DSF (which means smaller DSFs, faster loading and less RAM use), but it also means variation is only visible to those with shaders. Having the pixel shaders create variation dynamically on the GPU is called “auto-variation” (and is invoked via the AUTO_VARY command in a .ter file).
The artifact above was a bug in the auto-variation shader. With the code now fixed (the 930 patch will contain the fix), here are some images of how it is supposed to work:
Here we have the texture in question, at two different offsets.
This black and white texture is the “mixing mask” used to select which offset to use.
And this is the final result.
There is a little bit more disruption in the columns of green park.
I was going to post some pictures of the newly fixed “auto-vary” feature, but before I can do that in a way that makes any sense, I need to explain how X-Plane deals with texture repetition.
Texture repetition is the inevitable result of using “landuse-style” texturing (that is, a repeating single texture representing a type of land). Typical X-Plane land use textures are 1024 x 1024 at max res and repeat about every 3-5 km. Unfortunately, our brains are pattern-recognizing machines, and the result of this texturing scheme is that the “grid lines” of texture placement become apparent over wide views.
We use a number of techniques to minimize this problem.
Lots of Land Uses
Our main tool to combat repetition is to not use a given land use for too large of an area. This has the advantage of efficiently using the entire set of textures, and (because terrain textures change based on an irregular grid, based on elevation) the changes to textures are both irregular in shape and “plausible” in placement.
In this picture, you can see that the urban residential land use has been interrupted by various forest and grass textures. This is intentional – Sergio tuned hte land use rules to make sure that we wouldn’t have large regions of one land use type. Those blobs match the irregular grid, which gets its shape from the terrain’s elevation.
Variation
In the above picture, you can still see the repeating grid of the residential terrain; observe the right side – you’ll see the same repeating vertical pattern of road repeating over and over. In order to further hide repetition, we use the same texture multiple times, but in offset locations.
Here you can see that the vertical line on the right side has been broken up a bit.
More VRAM
In some cases, a terrain covers such large areas despite the rule set (e.g. for really flat areas) that we use two separate textures and can vary between them. Here you can see both input textures for our dry square crop land use, as well as the combined results.
In summary, we have three techniques:
- Add more rules to prevent large spans of a single land-use.
- Use a texture with multiple offsets (variation)
- Use two textures and vary between them.
I saw a post about this on X-Plane.org…authors sometimes try to make a vehicle (a car, truck, etc) modeled via an OBJ “drive around” using animation translate commands. The problem is that sometimes the objects disappear. Here’s what is going on:
X-Plane uses a bounding sphere to decide whether to draw an object. The bounding sphere is the smallest sphere X-Plane can fit around the entire object; if the sphere is on screen, the object is drawn (even if the object itself isn’t on screen). We do this because we can test whether the sphere is on screen very quickly.
But what if the object has animation? X-Plane attempts to guess how animation might affect the sphere by looking at animation commands and making the sphere a bit bigger where animation might move the object outside the sphere. This process works, well, rather poorly. In particular, X-Plane doesn’t know exactly how your datarefs will change. This results in two error cases:
- If X-Plane assumes the animation is more drastic than it really is, we make the sphere too big. The object will then be drawn even when it is not on screen (because the sphere is on screen because it is too big). This case hurts fps but does not cause objects to disappear.
- If X-Plane assumes the animation is less drastic than it really is, we do not make the sphere big enough, and sometimes the object “disappears” because the object is on screen but the (too small) sphere is not.
Now let’s apply this to objects that are driving around. Usually this is done via a translate animation command where datarefs feed the object’s position.
X-Plane estimates the effects of a translate animation using the largest and smallest key frame values. But the animation engine will extrapolate beyond these key frames. So consider these three cases:
- As your dataref goes from -1 to 1, you translate by +/- 1 meter. In this case, the bounding sphere will be increased in radius by one meter.
- As your dataref goes from -25 to 25, you translate by +/- 25 meters. In this case, the bounding sphere is increased in radius by twenty five meters.
- As your dataref goes from -1000 to 1000, you translate +/- 1 kilometer. In this case, the bounding sphere is increased in radius by 1000 meters.
Note that in all three of these cases, the animation works exactly the same! But by using different dataref and value extremes, X-Plane’s estimate of the effects of the animation (and its change to the boundign sphere) can be quite different.
So…if you animate an object and it disappears, it is probably because the bounding sphere has not been increased, perhaps because a translation animation is being sent values outside its minimum and maximum values.
The problem is of course that to have an object “roam” over a large area, it must have a very large bounding sphere, which means it is being drawn a lot more than necessary.
More ranting on the question of whether a file format is based on factual information or not. For the sake of taxonomy, let’s call this:
- Factual. The file format aims to capture “real world” information. The file spec is thus written against real world norms. Example: a runway is described by the location of its centerline at its threshholds, the type of aproach lighting fixtures, and the material it is built out of. This is all fact that can be verified by going to the runway and measuring it (while trying to avoid 747s).
- Artistic. The file format gives authors a creative platform to create “stuff”, e.g. an image, a model; the file format dictates how client applications might interpret that “stuff”. Example: OBJs are artistic – it describes what affect on drawing the various bits of the OBJ file have.
Apt.dat is actually a hybrid format – most of it is factual, with one glaring exception: pavement surface areas.
Pavement surface areas are simply an overlapping pile of bezier polygons with holes. There are multiple ways to create a given layout, and you couldn’t make an argument that one is “more factually correct” than the other.
Artistic file formats give us a way to be open-ended, and so they are particularly useful for problems that we cannot solve in a practical manner using factual file formats. When we worked on the apt.dat 850 format, I clung to a 100% factual approach for as long as I could, hoping to be able to truly describe “ground truth” about airport pavement. What I found in the end was that real world instances of airport pavement are so varying and weird in real life that almost any factual approach would fail to correctly model important real-world airports. So we punted and simply said “put pavement wherever you want, make it look nice.”
The result of going artistic instead of factual is two-fold:
- The taxiway data in the apt.dat file is less broadly useful to a wide range of client applications; you might be able to infer some aspects of the real taxiways from the data, but the taxiway shape has very little structure to it.
- You can model just about anything you can dream of – there really aren’t any limits.
That taxiways are “artistic” will probably always bug me a little bit from a theoretical viewpoint, but I think there is no question that this was the only practical standpoint.
Final thought: factual file formats are usually not precomputed – that is, if we have a list of runways described by their real-world properties (and not modeled as a collection of textured triangles) then there is probably work that still needs to be done to make the file useful for X-Plane. (That work is done by X-Plane’s file loading code.)
Okay – I’m OOTO for a while – see you before thanksgiving!
/ben
Previously I have blogged about a key choice in file format and scenery system design: will the file format be “specification based” or “reality based”.
Specification based: the format has an exact interpretation of the data. OBJ is an example of this…the format describes triangles and there is only one interpretation of what that triangle could be.
Reality based: the format models real-world concepts; the correct interpretation is “as close to the real world as possible.” The nav.dat file is like that.
I have been reading the OpenStreetMap Wiki and hit upon something I didn’t realize: you can’t use copyright to protect a derived work from a file that simply contains a list of facts!
Now I am a programmer – I am used to writing code, slapping a copyright notice up top, and assuming that it’s now mine…heck, I’m the one getting carpel tunnel from typing it out. But consider the nav.dat file; it contains a giant list of frequencies for navaids. It’s a fact that the BOS VOR is 112.7. Is my mentioning of that fact in this blog a derived work of the nav.dat file? Of course not, and it’s a good thing too because otherwise we wouldn’t be able to state facts without IP conflicts.
The OSM guys believe that they need to change their license to something weirder than the CC-BY-SA license they have now because the CC license uses copyright, you can’t copyright facts, and OpenStreetMap is really just a huge collection of facts.
Now at this point I’ve written six paragraphs too many without the obligatory “I am not a lawyer.” I am not one. And I must admit, my biggest concern with all of this is that it gets confusing and hard to interpret, and I’d be perfectly happy if there were only 3 or 4 licenses out there for everyone, you’d pick your favorite flavor, and everyone would know what it means.
Suffice it to say, it never occurred to me that a criteria of a file format might be “protectability” – that is, does the file format allow an author to specify something other than facts, so that it is elligible for copyright protection?
If you are an author, the good news is: pretty much all of our file formats would meet that criteria:
- OBJ and DSF are essentially 3-d modeling containers (DSF is just a damned wierd one).
- Images are copyrightable, so that takes care of your textures.
- Plugins are code, clearly copyrightable.
- ACF files contain, among other things, 3-d models, see the first point.
- Apt.dat would be the format most at risk of “factualization”, but I think you could argue that the arrangement of bezier curves and attributes is more of an artistic 3-d model than a statement of fact.
But who knows, I am not a lawyer.
(Oh yeah, this whole article is written from an entirely US-centric viewpoint…I am even less qualified to speak of such things outside the US than I am here at home.)
Starting Wednesday I will be out of the office – Lori and I are going on a 2+ week trip to India!
So first, the obvious: your comments to the blog won’t show up until I get back and can moderate them. Similarly, I will be even less on email than I am now. I am trying to dig out my tech support emails as much as possible before I go!
I will announce this before I go: I finally got an end-to-end render of a global scenery tile using CGAL 3.3.1. Andrew did the original work on this, modifying parts of the scenery generation code to handle his NZ scenery. I’ve been working on the rest of the algorithms and finished it today.
This doesn’t mean very much immediately, but it…
- Will fix the instability bugs in MeshTool.
- Will address missing antennas and obstacles in the global scenery.
- Provides a solid basis for building scenery out of just about any kind of data.
- Provides a bunch of nice tools for writing better algorithms, which means nicer looking scenery.
The next steps will probably be to create a new release of the tool set, including perhaps a bug-fixed Mesh Tool, etc.
The apt.dat 850 file format defines a polygonal “airport boundary”. But what exactly does it do? It does different things when creating DSFs and when rendering them.
Inside X-Plane it has relatively little effect:
- It is one of many elements that counts toward the land area that will be flattened. (Runways and taxiways are also used.)
- We do not actually render any special terrain or fences.
The airport boundary has more of an effect during scenery creation.
- If an airport has an airport boundary, we do not calculate the airport’s boundary ourselves – instead f we use the specified boundary.
- All land intersecting the airport boundary is turned to airport terrain.
- The DEM is flattened within the airport boundary to reduce the slope of high frequency bumps.
There is one aspect of airport creation that the airport boundary is not involved in: filling in water to make land under runways. When we create an airport, we actually calculate three boundary polygons:
- The inner ring is closest to runways and taxiways (very close) with very little simplification. It is filled in with land if it is wet.
- A second ring slightly farther from runways and taxiways is also filled in with land if it is wet.
- The outermost ring is a lot farther out, but does not fill in Water. This is the ring that the airport boundary can replace.
Why do we need two inner rings? Well, if an airport is next to the water but not at sea level, we need to induce two sets of mesh points, the outer ones which drop down to sea level and the inner ones which are at airport level. You can see the importance of this at KLGA, where one of the runways dropped to sea level at its midpoint in version 8, but not version 9.
Since the airport boundary polygon provides only one ring, it cannot be used for this purpose. At some point in the future, we might use the airport boundary for rings 2 and 3, or use a smaller version of the airport polygon for rings 1 and 2.
For now, my recommendation is: the airport boundary should trace out the entire airport premesis, not including water.
I’m never quite sure about naming names. There are users whose contributions to X-Plane and its scenery system have been immense – we wouldn’t have what we have without them.
But I don’t want to make the decision to blog for anyone else – this blog is part of Laminar Research’s communications to our users, and I don’t want to set up content that leads our paying customers toward third parties who may not want the extra questions/attention.
So I guess for now what I’ll say is this: the work I discuss here on this blog is not a solo effort – I have had the good fortune to collaborate with some really good people, and it has made X-Plane that much better of a flight simulator.
To everyone who has helped me with the scenery system: thank you!!