I have updated the OBJ8 specification with the new X-Plane 10.10 commands. This blog post explains why we added some of these commands.
Pixel-Space Drag Manipulator
The pixel-space drag manipulator is a new axis manipulator whose drag length is measured in screen pixels instead of meters; its drag axes are always screen aligned, but it works both horizontally and vertically.
The goal of this manipulator is to make draggable knobs that:
- Have a good response speed for both slow and fast drags via a non-linear curve and
- Have the same drag sensitivity no matter what camera angle.
The axis manipulator has the problem that it works in 3-d; depending on how you look at the manipulation target (both position and rotation) the sensitivity of the drag can change radically.
Recommendation: use the regular drag-axis manipulator for levers and other physically moving items. Use the pixel-space drag manipulator for drags where the underlying target does not move, like knobs. Use button-type clicks for anything that just toggles – it’s easier on the user.
Three new attributes (GLOBAL_no_shadow, ATTR_no_shadow, and ATTR_shadow) allow you to exclude part or all of your object from shadow casting. Shadows can make certain types of geometry, like grass billboards, look silly; excluding them from shadows fixes artifacts.
Note that ATTR_no_shadow is different from ATTR_shadow_blend..
- ATTR_no_shadow: the geometry simply does not cast a shadow! This is meant to exclude objects like vegetation.
- ATTR_shadow_blend: the geometry does cast a shadow, but only if the alpha is greater than a certain ratio. This is meant to make windows with tint cast shadows correctly.
Recommendation: fix shadowing bugs using ATTR_no_shadow for non-instanced objects, and GLOBAL_no_shadow for instanced objects. Use the Plane-Maker check-box for parts on aircraft.
This attribute lets you have your cake and eat it. In X-Plane 9, ATTR_cockpit gives you alpha blending, but ATTR_cockpit_region gives you correct 3-d lighting. You have to pick one or the other.
In X-Plane 10.10, GLOBAL_cockpit_lit gives you both. It makes ATTR_cockpit use 3-d lighting (while maintaining translucency) and it makes ATTR_cockpit_region respect alpha translucency (while maintaining cockpit lighting).
You can add this attribute to any airplane. This attribute should make it easier for authors to adopt correct 3-d lighting in their airplanes.
Recommendation: use GLOBAL_cockpit_lit on any airplane that uses ATTR_cockpit to change to 3-d lighting for your panel texture. Also see here for more guidance.
At this point the only thing holding up a public beta of 10.10 is, well, me. I am currently working on a set of related aircraft rendering bugs, and as soon as I can get the car off of jacks, we can go beta.
One of my goals or 10.10 is to close out the issues that stop payware authors from releasing final conversions of their aircraft to 10.10. By final, I mean conversions that won’t need any additional future editing. Right now X-Plane 10.05r1 has a few bugs that cause v10 to look different from v9, different depending on rendering settings, or just wrong. I want to fix those problems in a permanent manner so that authors can release aircraft and not worry about having to update.
Here are my goals for 10.10, roughly in priority order:
- Rendering should be consistent from X-Plane 10.10 onward through the rest of the v10 version run.
- Rendering should be consistent between HDR and non-HDR mode. Authors should not have to create two versions of textures where the HDR and non-HDRs offer the same capabilities. (In other words, while you might have to make two textures to bake lights when in non-HDR mode, you shouldn’t have to make two textures to correct for differences in color-correction between the two renderers.)
- Where possible, non-HDR mode should match X-Plane 9.
The switch of priority between item 2 and 3 is a fundamental change in priority from what I originally intended for X-Plane 10.
Originally I thought that the best thing to do would be to keep non-HDR rendering as close to v9 as possible, so that at least content would look correct with HDR off.
My new thinking for 10.10 is that we should aim for consistency between HDR and non-HDR modes. Realistically, an author is going to have to make at least a few adjustments in moving v9 content to v10; better to have the cost of rendering engine changes be borne out in a v9->v10 upgrade than to have every v10 airplane require double authoring to cope with HDR vs. non-HDR differences. In the long term, it’s best to not have v9 haunt v10 like a ghost years after authors are making exclusive v10 content.
Why is HDR Mode So Weird
This begs the question: why is HDR rendering so weird? Why does it look different from non-HDR rendering, and why doesn’t it look the same as v9? What did you guys do?
There are a number of changes to how we render in X-Plane 10, some specific to HDR rendering, and some sim-wide.
- The entire sim now works with a linear lighting equation. Basically when the sim performs lighting calculations on the GPU, it thinks in terms of photons and not colors, which produces more realistic results in most cases. With lots of light sources, linear lighting is absolutely necessary for combining those lights.
- The order of rendering operations is very different between HDR and non-HDR mode, and the formats that they render into (24-bit RGB vs. floating point, etc.) are very different. HDR is fundamentally a two-pass format.
X-Plane maintains two separate rendering paths for HDR vs. non-HDR and they are quite different in both what happens at each stage and when the stages occur.
Fixing some of the authoring bugs has required further changing the HDR pipeline to allow for correct rendering. The up-side of this change in pipeline is that the new one supports better HDR tone mapping and possibly even better fill rate performance. The down-side is that it’s a lot of complex code to touch and it may take a few betas to work out the bugs.
I finally finished up an update to the OBJ8 specification, as well as the forest specification – see here for the documents. These specifications are mostly of interest only to developers who are working on scenery exporters.
The OBJ specification is very thick – here are some of the hilights of what’s new.
In X-Plane 10, you create global spill lights by attaching a light to an object. (Thus, spill can come from any object-bearing part of the sim – an airplane, custom scenery, etc.)
One way to do this is with the existing named and parameterized lights – these features existed in version 9, but in version 10 there are some spill lights added to the light list.
What may be of more interest to custom authors is the new LIGHT_SPILL_CUSTOM command. This lets you build a completely customized spill light. You control its size, color, shape and direction. You can even optionally run the light through a dataref, giving a plugin custom control of the light.
In X-Plane 10, an object can contain geometry that is “draped” on the ground – that is, X-plane will subdivide, bend and modify part of your object mesh so it sits perfectly on the ground even if the ground is sloped. ATTR_draped makes this happen.
This feature is a much better alternative to using ATTR_poly_os to make marks on the ground. Draping produces objects with better performance, and the geometry always sits on the ground with no artifacts.
As an added bonus, you can optionally use a second, different texture for the draped part of your object from your regular object. (Internally the draped geometry actually becomes something like a .pol file – this is why it can have its own texture.)
Draped geometry makes it much easier to make airport markings. If you want a parking spot, simply draw it on a quad, make it draped, and drop it into place with WED. Tom uses this heavily in our airport library.
Draped geometry also makes it easier to have ground markings that match the object they come with. For example, if you want a house and the house comes with a driveway texture, you can make the driveway texture a draped quad and when you place the object, the draped driveway is always in the right place.
Global Attributes and Instancing
In X-Plane 10, it is possible to set a few key attributes (blending and shininess, among others) globally for the entire OBJ, rather than using an ATTR_ to change part of the object.
These global attributes make hardware instancing possible. In hardware instancing, X-Plane draws many objects with a single instruction to the CPU. In order for this to happen, X-Plane must be able to draw the entire object without needing CPU intervention mid-object. This means an instanced object has to be free of animation, attributes, and a few other features.
The global attributes let you set things like shininess and still have a single-call draw object, ready for instancing. Alex uses these heavily in the urban autogen, and it really helps performance.
My fear is that global attributes are going to be a source of confusion for authors. When should you use them? How do you add them? This is my thinking:
- Modeling program exporters should allow an author to identify an object as “for instancing” or not.
- Authors should check “for instancing” for any object that is heavily repeated. (A car or a single tree or a static airplane, for example.)
- The modeling program can then try to prefer global attributes for instancing objects but not for regular ones, which should come very close to optimal behavior.
Conditionals are simple logic statements that include or ignore parts of an art file based on the rendering settings. In particular, they let you change an OBJ based on whether HDR is on or shadows are on. For example:
In this example, which LIT texture the OBJ uses will depend on HDR.
Because the conditionals can be used anywhere in the OBJ, you can change any aspect of the OBJ to customize for HDR. You can replace a texture, remove lights, add more geometry, etc.
I don’t know how heavily people will use conditionals, but they give authors the option to make one file tuned for both HDR and non-HDR, shadows and non-shadows.
I think the two most common uses of conditionals will be:
- Providing alternative LIT textures when HDR is on or off. Note that only one texture is ever loaded (when the HDR rendering setting is changed, X-Plane unloads one and reloads the other) so this does not increase VRAM.
- Removing drop shadows that are baked into a model when shadows are on.
That second case would look like:
IF NOT GLOBAL_SHADOWS
# This is the shadow geometry
TRIS 300 6
When global shadowing is turned on, the entire set of draped geometry disappears, removing baked vs. real shaodw conflicts.
This is a screenshot of Javier’s new version of the X-15 for X-Plane 10. In this case I have hacked the rendering engine to show the specular channel* (the alpha channel) of Javier’s normal map as the texture of the airplane. In other words, that is the per pixel shininess that Javier “drew into” the normal map. there isn’t any lighting on the airplane; the bright edges are simply parts of the plane that are completely glossy.
Just look at how gnarly and detailed and full of goo it is! When you look at the plane under normal lighting conditions you simply see the regular texture. But when the sun reflects off of the plane, the reflection is messed up by this complex specularity pattern. The fact that the sun reflections change unpredictably and dynamically is what sells the illusion.
I mention this because normal maps are expensive – they aren’t compressed and can chew up 4 or 16 MB of VRAM easily – they have to be at high resolution to get the subtle bump details. As long as you’re going to have the resolution, make use of it by putting “texture” into the specular channel – it’ll make your materials seem a lot more complex.
X-Plane 10: X-Plane 10 will allow you to use a gray-scale PNG as a specular-only image, for this kind of “texture” at 1/4 of the VRAM cost, in case you don’t need the actual bump mapping.
* 3-d nerd: X-Plane’s terminology is different from what you’d see in a typical 3-d modeler materials editor. What we call “shininess” is the specular level – that is, how bright specular hilights appear to be. In a 3-d editor this is usually an RGB color, but X-Plane only gives you a single level control; the specular hilights take on the tint of the sun instead.
The “shininess ratio” or “specular exponent” you’d see in a 3-d editor isn’t available in X-Plane – it is set to a fixed exponent by the sim. The unconventional names is a historical artifact.
Propsman pointed this one out to me yesterday: apparently Blender tangent-space normal maps run from a value of Z=-1 (no blue) to Z=1 (100% blue). This is not how X-Plane normal maps work; our normals go from Z=0 (no blue) to Z=1 (100% blue).
This difference is easy to miss because X-Plane has to renormalize the normal map as the last step of processing the normal map. This turns a big artifact into a small one. The general effect of using the Blender convention rather than X-Plane’s is that your normal map will look ‘less bumpy’ for fairly extreme amounts of bump.
To fix this, simply remap the colors of your blue channel in PhotoShop or some other image editing program. Basically you’ll want to set what was 50% blue to 0% blue, and keep 100% blue the same. This will extend the lighter half of the blue channel over the entire blue channel.
If you have any blue less than 50% in the image, um, that’s a normal that points backward, and X-Plane doesn’t support that.
X-Plane 9 allows you to categorize objects as being on the plane’s outside, inside, or glass. X-Plane depends on these flags being right for a few things:
- The draw order of the airplane is determined by the object types – glass is drawn last to avoid translucency artifacts.
- Interior light from the plane is only spilled on the “inside” objects.
- Glass objects are excluded from shadow calculations to avoid having opaque windows in the airplane shadow.
It is important that you use these flags as intended; X-Plane 10 depends on this information as well, and X-Plane 10’s global spill and global shadowing algorithms are more sensitive to incorrect categorization of objects than X-Plane 9’s forward renderer.
In particular, you should have glass for the airplane windows in an attached object tagged as type ‘glass’; do not attach your glass to the cockpit object, which cannot be categorized as glass. If you have an old plane with glass in the cockpit, consider cutting the object in half in a 3-d editor and attaching the glass separately.
(You should also use our prop disc animation, rather than use an OBJ for prop discs; the OBJ format doesn’t contain the z-buffer tricks necessary to make the prop look right.)
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.
I wrote up some performance tuning notes for OBJs on the wiki. A few notes on how these rules will change with version 10:
Everything on that note applies to version 10 too. If you’ve tuned your model for version 9, that effort will be worth it in version 10.
A few rules are even more important in version 10 than before. In particular, I’ve done a lot of performance tuning for OBJ drawing, but you don’t get those wins if you use ATTRibutes. Clean your objects out for maximum speed.
One special case: objects with very small vertex count are sometimes extra fast in version 10. For example, in version 9, a tree with 8 vertices and no attributes is horribly slow. In version 10, this tree will be quite fast. So in version 9 you might make the tree have 64 vertices and look nicer; in version 10 by keeping the tree lean and mean, you get a speed improvement.
Normal maps are expensive. A 2048 x 2048 normal map takes 22 MB of VRAM! So make sure you get every bit of image quality you can out of it. Two things to consider:
- Normal maps are uncompressed (because texture compression really screws up the normal map). So per-pixel detail will be preserved. Use it!
- VRAM is allocated for an alpha channel whether you use one or not. This is because the cards need 32-bit pixels for performance. So include an alpha channel in your normal maps and use it to modulate shininess; this can help create the illusion of different materials.
For scenery objects, do not include an alpha channel if you don’t need it. When textures are compressed, the alpha channel does take more VRAM, and X-Plane will hit a faster rendering path for textures with no alpha channel.
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.