At this point I can say with 99% confidence that X-Plane 10 will feature bezier curved roads. In X-Plane 9, a road is a line segment; you can simulate curved roads by using a lot of line segments, but the global scenery roads are pretty chunky.
X-Plane 10 allows for a road to be a bezier curve, allowing the specification of smooth curves with a small amount of data. This sets us up to trade off visual quality and performance using a rendering setting.
A few notes for authors:
- Like all of the new v10 road features (and pretty much all of the new v10 scenery features), you don’t have to use bezier curves in your roads. They are there as an option if you want them.
- X-Plane 10 will not make curves for you; road data that is defined as line segments in the DSF will be rendered as line segments. (This follows the principle that DSFs contain pre-processed scenery data, and the sim shows DSFs exactly as they are written.)
Pay No Attention to the Documentation
The DSF specification alludes to bezier curved roads; this “old way” of encoding curves was never supported in the sim – all versions of X-Plane ignore this data. The “old way” was how we thought we might do curves some day.
The version 10 curve encoding is different; the “old way” will continue to be ignored in version 10. So: do not use the DSF spec to try to make curved roads now. I will post detailed documentation on curved roads once version 10 is available to authors.
I have mentioned a few of the scenery engine features coming in X-Plane 10 that will be of interest to authors: global illumination, conditional parts of OBJs (to cope with variable rendering settings). There is another general feature coming that will make authoring scenery a lot easier, I hope.
X-Plane 9’s rendering engine has the ability to drape geometry. Draped geometry are meshes that are ‘dropped’ onto the terrain and hug the underlying base mesh perfectly. The most common example of this is the runways: because the runways ‘drape’ the ground, the runway shows any curvature and bumps from the underlying base mesh. This is who we create sloping and non-flat runways.
Authors can drape geometry as well, using a draped polygon (.pol) primitive in an overlay. Such draped geometry is useful any time you want to add more “paint” to the ground, e.g. to put down a taxiway, parking markings, dirt, grass, a driveway for a house, you name it.
There is one case in X-Plane 9 where you cannot drape geometry: in an object. In an object, all geometry is aligned to the object, and will only interact nicely with the ground if you get lucky. For example, if you model a house with a sidewalk, the sidewalk won’t “sit” on the ground if the ground turns out to be sloped. You can use ATTR_poly_os to hide the artifacts, but ATTR_poly_os really can’t cope with mismatches between the OBJ and the terrain under it.
X-Plane 10 will introduce a new object attribute: ATTR_draped. Draped geometry in an object is actually draped down onto the terrain when the object is placed in the scenery. This means that the draped part of the object will hug the ground perfectly with no interference or Z thrash. You get all of the quality of a draped polygon with the convenience of an OBJ.
There are a few possible uses for ATTR_draped:
- Any time a 3-d model needs some ground details attached to it, e.g. the driveway near a house, draped geometry provides a good fit with the ground and good alignment with the object.
- Any time you want to include a pre-made ground decal (E.g. a painted parking spot on a taxiway), the ground detail can be modeled as an object using draped geometry.
ATTR_draped will facilitate creating and sharing custom details for airports and streamline the authoring process.
This is my expectation for scenery compatibility in X-Plane 10:
Scenery based on DSFs, OBJs, and other version 8/9 file formats should work with X-Plane 10 unmodified.
This includes orthophoto scenery based on DSFs – we’re not throwing that code out.
The new rendering engine features for version 10 (and there are a lot of them) are extensions – new ways to render things, new types of art assets.
I do believe that we may drop support for ENV scenery files in version 10. We’ve had DSF for six years now, and ENV’s capabilities (a 500m mesh, very limited orthophoto resolution) aren’t useful to today’s users. You can use DSF2Text/XGrinder to extract custom object placements from an ENV for use in a new overlay.
We may also drop support for OBJ version 2. (Yes, we still load OBJs version 2.) OBJ version 2 is the OBJ file format from X-Plane 6, the one before OBJ 7. If you have any old OBJs (version 2 or 700) you can use XGrinder to automatically batch convert them to OBJ8.
X-Plane 10 will have rendering options for global illumination and global shadows. This leaves one question: what if the user has these features disabled?
The plan for version 10 is this: the OBJ file format will have some extensions to allow conditional commands based on rendering settings. A few notes on these conditional commands:
- They will only be based on rendering settings.
- They will be evaluated once when the object is loaded. (If rendering settings change, the object will be reloaded.)
The idea is to be able to change which lit texture you use or remove a set of shadow polygons depending on rendering settings.
The conditionals are evaluated once at load time so that the object can be fully optimized based on the particular set of conditionals used. For example, if your drop shadow (with ATTR_poly_os) is fully removed at load time (because global shadows are on) your object now has fewer attributes, which is good for frame-rate.
This is very different from ANIM_hide. The hide animation may or may not hide depending on datarefs; to keep this fast, you cannot “hide” an attribute, only triangles. This means you “pay” for your atttributes no matter what.
The motivation for both designs is this: if the set of attributes in a file never changes (e.g. they are either conditionally removed at file load once, or they are always present regardless of animation) then we can optimize the attributes of an object once knowing how they relate to each other, to create the leanest, meanest OBJ.
For quite a while now, I have been advocating in favor of DDS compression. I am pretty damned obstinate, but eventually if enough people yell at me, I get a clue. I have come to appreciate that there are some cases where DDS compression is not a net win; this blog post explains when it happens and what we might do in X-Plane 10 to work around this.
DDS – The Good, The Bad, the Ugly
DDS is a file format that contains image data pre-mipmapped (that is, the smaller versions of the image that the video driver needs are included) in a format that may or may not be compressed. DDS is virtually always used with a compressed image format (like DXT1 or DXT5). This has three positive effects for X-Plane:
- Because the image is already compressed, we save CPU time when loading the texture that would be spent compressing while X-Plane is running.
- Because small versions of the image (the “mipmap pyramid”) is already in the file, we save time down-sizing the image with the CPU, another win for load time.
- Because the image is compressed ahead of time, it can be compressed with a slow high quality compressor rather than a fast low quality compressor, so relative to other compressed images we get an image quality improvement.
The bad is that the DDS file does not contain the original uncompressed file. If the user unchecks “compress textures to save VRAM”, DDS files remain compressed. If the image file contains details that don’t compress well, they’re going to get splatted and stay splatted.
What If VRAM Grew On Trees?
My original heavy arguments for DDS were based on the idea that VRAM is a limited commodity; if we don’t compress textures, the user runs out of VRAM faster and has to go down a level of resolution…and once that happens, everything starts to look ugly.
But what if the user has 1 GB of VRAM? At this point, we’ve limited the maximum quality the user can see because we don’t have the original uncompressed image anymore, only the DDS/DXT version. This can be frustrating to authors who spent a lot of time on their textures.
If you ship PNGs with your airplane or scenery, turning off texture compression will reveal this beautiful, uncompressed image, but now when texture compression is on, the compression will be done by the video driver, and that will look extra ugly.
The Best Of Both Worlds
This is my thinking for version 10. (These are just musings, we haven’t coded this yet.) Currently DDS are preferred to PNG files. We could relax the load rules in version 10 to prefer PNG over DDS when texture compression is off and DDS over PNG when it is on. This would allow authors to ship both PNGs and DDS files and have the right one be picked for the scenario: the pre-compressed one when texture compression is on and the uncompressed one when compression is off.
Thanks to my foolish use of unprotected directories, we have basically announced that X-Plane 10 will feature global illumination. Here is some basic information on global illumination.
What Is Global Illumination?
Global illumination is the ability of any part of an airplane or scenery system to cast light on any other part of the scenery system or airplane. In X-Plane 9, the only lights in the sim that ever actually cast cast light anywhere else are:
- The sun.
- The airplane’s landing light. (Even if your plane has many landing light billboards, there is only one spill effect.)
- Three 3-d lights in the 3-d cockpit.
This list was kept short due to the high cost per pixel of each light on all rendering.
When X-Plane 10’s global illumination is enabled, a “spill” light attached to any OBJ can shine light on anything near it. Since any OBJ can have a spill light, this means we can have light sources on airplanes, scenery, cars, whatever you want. The spill effects any 3-d scenery nearby, even from another scenery pack.
This kind of still effect can be simulated in X-Plane 9 by careful use of LIT textures. However, real global illumination works between art assets created by separate authors. You can drive your custom airplane up to a custom airport and the landing and logo lights on the airplane will cast light on the terminal; the apron lights from the terminal will cast light on the airplane.
Furthermore, global illumination is fully dynamic – as objects animate or move, the lighting effects are correctly applied in 3-d. This makes effects possible that cannot easily be created using LIT textures.
Requirements for Global Illumination
Like most new rendering tricks in version 10, global illumination will be a rendering option that can be optionally enabled by users who have a video card meeting hardware requirements. In the case of global illumination, that requirement is a DirectX-10 generation video card, e.g. any Radeon HD , nVidia GeForce 8000 or 9000 series, and “100” series (100,200,300,400 series).
For authors: global illumination is applied using named and parametrized lights on your OBJ. Anywhere you can attach a light billboard, you can attach a spill effect as well, with some tuning constants for how wide you want the light, etc.
It will be possible to create two versions of your LIT textures, one to be used when global illumination is enabled, and one when it is disabled. Thus if you are baking lighting into your textures with a 3-d modeling program, you can simply re-bake the lit texture with some lights disabled and add 3-d lights to your model. The result is an airplane with real 3-d lighting where possible, and a close approximation via baking otherwise.
Global illumination can be added to a model incrementally; existing art content will work normally with global illumination enabled or disabled, so authors can choose to add a few light spill effects or add a large number, as time permits.
The Cost of Global Illumination
Global illumination isn’t going to be free. The main cost is an increase in VRAM use and fill-rate. The cost of global illumination is mostly a one-time cost to put X-Plane into a new rendering mode. (Graphics nerds: global illumination is implemented via deferred rendering.) The incremental cost of lights isn’t that high, although a scene with a lot of lights will have impact.
My expectation is that users with new, highly capable high-end graphics cards will be able to run global illumination easily, but will lose some of the other benefits of fill rate. (For example, running at 2560 x 1024 + 4x FSAA is a lot more painful with global illumination than without.)
Global illumination also introduces two artifacts, both of which I am trying to minimize as best as I can. These artifacts are a function of deferred rendering – all games that use deferred rendering have to address these problems:
- The lighting calculations are shared between multiple translucent surfaces, which can create some strange effects. For example, if a translucent window is in shadow, the scenery behind the window will appear to be in shadow too.
- Traditional full-screen anti-aliasing is not available with deferred rendering. We should be able to offer a simulation of 4x FSAA as well as some kind of cheaper FSAA-approximation, but the cost will be quite a bit higher in fill rate than the 16x-style CSAA available now.
(Hardware-based FSAA can make a number of optimizations like CSAA to optimize throughput; this is how such high multiples as 16x are possible. Since our implementation is similar to “super sampling” and costs a real 4x in performance, 4x will be the highest setting.)
Why Global Illumination
Of the new X-Plane 10 rendering engine features (and there are a fair number of them), global illumination is certainly the one that has the most impact on the structure of the rendering engine. With global illumination, X-Plane effectively has two separate modes (“forward” rendering, which is the only mode X-Plane 9 has, and “deferred” rendering, which produces global illumination).
One of the reasons to get global illumination done earlier than other features was that implementing global illumination required rewriting or modifying nearly every piece of low level rendering code. Now that the work is in place, we can safely add new features and test them in both modes.
Global illumination also meets two requirements:
-
Sergio has long observed the central importance of lighting and shadows in the look of X-Plane; at some point more polygons and better textures still look synthetic without a realistic illumination model. Global illumination makes a more realistic lighting model possible at night. Airports represent an environment that can hopefully take advantage of such capabilities in a big way.
-
As hardware becomes more powerful, authors have to do more work to create content that takes full advantage of the rendering engine. We are reaching a point where artist’s time is going to be a limiting factor as well as hardware and engine capabilities. Global illumination thus kills two birds with one stone: it makes the rendering engine’s output look better, but it also makes the whole scene look better with less work by the artist.
(For example, when baking lighting into a model, the author must plan the model’s texture UV map to guarantee unique texture space for all spill effects. When lighting effects are dynamic, the author can simply texture so the model looks good without worrying about baking requirements.)
I have updated some of the facade documentation on the wiki with new performance tips for using facades.
A few quick notes:
- Your facades must be counter-clockwise (when viewed from above). Do not repeat the first point; X-Plane will “close” your building for you. (A four sided building should have four points, not five.)
- If you turn off two-sided facade drawing and your walls look wrong (and your roof disappears) your facade is wound in the wrong direction.
The performance tips go into a fair amount of detail about saving memory. Most of X-Plane’s rendering fall into two categories:
- Shared meshes (objects), where the geometry of the object is saved once and used lots of times. Objects usually hurt frame-rate by consuming CPU time, because for each drawing of the object, we have to do some setup to draw that shared geometry in a different location. (Version ten should feature some major improvements in object efficiency.)
- Non-shared meshes (everything else), where every single “instance” of a tree, facade, forest, etc. is uniquely constructed in memory. Non-shared messages are very fast (because we can submit a huge pile of non-shared messages to the video card in one shot) but they consume a lot of memory (because we pay for RAM per building/tree, not just once). Typically non-shared meshes are limited by virtual address space, not by framerate.
Facades are non-shared meshes, so the performance tips focus on how to limit the amount of RAM needed to represent your facade.
We have Tyler working for us again for the summer (last summer he did a very nice and much needed rework of the X-Plane manual), and among his projects is cleaning up the mess that is scenery documentation.
We are moving the scenery documentation from their own dedicated site to the X-Plane wiki. As of this writing, as you can tell, it’s a work in progress. There are a few reasons why we decided to consolidate to the wiki:
- The scenery website is the very best of 1995 technology – unmanaged php in a big mess of files. We wanted to get the site under some kind of content management system, and MediaWiki is already working well for us for other docs.
- There is a lot of overlap between modeling techniques for scenery and modeling techniques for airplanes, so having all of the third party authoring docs in one place makes sense.
It’ll be a few more weeks before everything is organized.
Tyler is also reviewing all of the documentation. I have had a lot of trouble trying to document the scenery system, partly because I have been working on it for years, and thus I have no sense of what people don’t know. Since Tyler hadn’t done any scenery work before, he was able to read the documents and go “hey Ben, you keep talking about X but you never defined what it is.” The resulting edits should make the docs a lot clearer.
In order to understand the difference between hiding geometry and disabling drawing, you need to understand that an OBJ triangle can serve many purposes. Broadly, those purposes are:
- Drawing (the most basic use).
- Collision detection, of which we have three flavors: collision of the plane with the object (“hard surfaces”, or “physics”), collision of the mouse with the panel (manipulators, or clickable triangles) and collisions of the camera with the airplane (“solid camera”, which constrains the camera).
Any given triangle can be drawn and/or used to check for any of these collisions*; attributes change what the triangle is used for.
By default, all triangles are drawn; ATTR_draw_disable marks future triangles as not being drawn. This allows you to make a triangle that is used only for collisions. Examples might include a “hot spot” in front of a region on the panel (the hot spot might be easier to click than a small switch) and an invisible simple mesh to constrain the camera.
By comparison, ANIM_hide effectively removes some triangles from your model (temporarily) for all uses – drawing and collision detection of any kind. If a door is hidden, it’s not only not drawn, but it’s not going to stop the camera moving through it either.
Some key points to these distinctions:
- Categorizing what a triangle is used for (drawing, various flavors of collisions) is static – that is, it is always the same for the object and never changes with datarefs or animation. This is intentional for performance reasons!
- Animation to hide triangles affects the triangle in every way consistently – drawing and collisions.
Generally, you will get better performance improvements by removing categories from a triangle than by hiding it. (That is, it is better to not have manipulators on your cockpit, so it isn’t mouse-click collision-checked, than to hide it.) But the purpose of ATTR_draw_disable and ANIM_hide are different enough that which you use will be determined by the effect you are trying to create.
Finally, note that hiding an object completely (that is, the object does no drawing) does not provide the maximum performance benefit of not having an object at all. ANIM_hide was created to allow authors to create clever effects, not as a performance enhancer!
* This is not quite accurate: airplane-object collision checks are only available in scenery objects, and camera/airplane or mouse/panel collision checks are only available in the cockpit object.
In X-Plane there are two fundamental ways that a texture can be painted “over” a background image:
- Blending, whereby the alpha channel of the new top layer decides how much we see the top layer vs. the background.
- Additive Lighting, whereby the new texture makes the background lighter.
Blending is more common. For example, if you build an OBJ, the object appears “in front of” the terrain via blending. With blending, you put the color of your new layer in the RGB channels and use the alpha channel to indicate opacity. 1.0 alpha = 100% opaque, 0.0 alpha = 0% opaque, and alpha in between will create a blend. If you omit an alpha channel, X-Plane will treat the entire layer as 100% opaque.
When a layer is applied using additive lighting, the resulting color is the sum of the background plus the new color, clamped to the maximum brightness we can show on screen. Additive lighting is good for simulating effects that really “add light”. Some examples of additive lighting in X-Plane:
- All lighting billboards are drawn additively.
- Instrument overlays are additive if you pick the appropriate mode in Plane-Maker. (The option is labeled “glass” for generics, since most glass instruments work by adding light to a nearly black screen.)
- The emissive (_lit) texture of an object is added to the albedo (daytime) texture using additive lighting.
Now just a little bit of math. In RGB color terms, black = 0,0,0 and white = 1,1,1. So if we add a pure black texture to a background additively we get:
new_r = old_r + overlay = old_r + 0 = old_r
new_g = old_g + overlay = old_g + 0 = old_g
new_b = old_b + overlay = old_b + 0 = old_b
In other words,when using additive light, adding “black” does nothing, preserving the background.
And this brings me to my main point: any time you have additive lighting you don’t need an alpha channel. You can simply make your additive lighting texture black for the parts you want to be “transparent”.
This is why I generally recommend that emissive _LIT textures for objects not have an alpha channel. In fact, for “back-lit” and “additive” instruments (these are instruments that use a second emissive _LIT texture) Plane-Maker will indicate a warning if the texture has an alpha channel. If you have a texture that is applied additively, you don’t need alpha.
At this point you might be wondering: Ben, if additive lighting doesn’t require alpha, and all lighting billboards are drawn additively, why the heck is there an alpha channel for custom lights?
The short answer is: there probably doesn’t need to be one; the original setup for lighting billboards inherited a number of idioms from older versions of X-Plane, going back to versions where lighting billboards were not additive* (and thus alpha was necessary).
The long answer is: the alpha channel is often as a general “intensity” control to turn the light up and down in amplitude, while the RGB channels are often re-interpreted in strange ways. So while RGBA color is not necessary from a graphics standpoint, it is handy that there are four color channels in the custom lights because that gives us one more parameter to play with when designing really compicated lights (like VASIs).
* Note that lighting billboards that aren’t additive don’t look very good…hence Austin switched to additive billboards.