Tuesday, December 14, 2010
X-Plane vs. Blender Normal Maps
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.
Friday, November 26, 2010
Using Glass Objects in Planes
- 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.
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.)
Sunday, October 10, 2010
Coping With Variable Rendering Options In X-Plane 10
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 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.
Thursday, September 23, 2010
Performance Tuning and Future Proofing
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.
Use Every Pixel of Your Normal Maps
- 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.
Tuesday, September 21, 2010
Revisiting Texture Compression
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.
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.
Sunday, August 22, 2010
More Global Illumination Video
This is the Cirrus again, with landing lights and strobes; you can see that all of the airplane's lights contribute dynamically to the lighting on the fuselage and doors as they move. (Yes, that is heat blur on the engine; the heat blur still needs a lot of tuning.)
This shows airplane-mounted lights interacting with custom scenery. In this case the standard Cirrus (with global lights attached) casts both strobe and multiple landing light spill on LOWI. One of the powerful results of global illumination is that we get correct lighting interaction between diverse content, including third party content.
Finally, this shows an airport beacon lighting a plane and vice versa. The global lights on the airport beacon are inside an animation group, making them "sweep" the airplane, which can in turn animate the airport beacon. With global illumination, there are no rules about who lights who.
Saturday, August 21, 2010
X-Plane 10 and 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.
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.
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.)
Friday, July 23, 2010
Performance of Panel Texture vs. 3-d Cockpit
The 2-D Way
When you use the panel texture to make an object, X-Plane goes through a lot of steps to create the final result:
- Your panel has to be rendered in 2-d. We atlas your panel textures, but we don't necessarily order them optimally - we don't know the optimal order. Each generic instrument is at least one batch, perhaps even two. Those batches have very low vertex count, and the vertices are stored non-optimally on the CPU. There may be a fair number of texture changes between instruments.
- If you use ATTR_cockpit_region, we then go back and do the same thing...again! Why? Well, we need your panel's raw color ("albedo" to graphics nerds) and the emissive light given off by anything self-lit separately, so that we can do correct 3-d lighting.
- Both of these are rendered to an off-screen texture that the video driver will feeel obligated to preserve at all costs, putting pressure on VRAM.
- Only when all that is done do we begin drawing your object, with the usual batches to change to panel texture and change back, perform animations, etc.
The 3-d Way
What if we want to go 3-d? Well, we're going to "eat" a lot more of what your 3-d pit already has:
- You'll need a lot more animations to move all of those parts.
- You'll need new batches with ATTR_lit_level to dial up and down various lighting levels.
- Geometry in objects is processed about as optimally as we possibly can. All of that work we've done on the rendering engine to make OBJs fast is available in your cockpit. So you can increase 3-d detail 'for free'.
- Your lit geometry can be drawn in a single pass (we don't need to prepare two separate lit textures). So for example a needle would take three batches via the panel-texture route (a batch to rotate the needle for albedo, a second batch to draw the rotated night needle, and a third batch to draw the resulting texture in 3-d) but only one if you use the OBJ directly.
- Since you organize your textures for OBJs, you can guarantee that all of the cockpit stuff is together, saving texture thrash.
- You can use normal maps to add per pixel detail to your cockpit; panel textured geometry cannot be normal mapped.
Given the high cost of panel texture relative to native OBJ drawing, you'd think going native OBJ would be a no-brainer, right? Well, not quite.
A needle is an easy case: you can model a needle using a rotation animation, so your implementation in an OBJ and our generic instrument are quite similar. Same with the throttle lever generic instrument.
But what about a "glass pie indicator"? What about a moving map? What about a rotary?
There are some generic instruments that have "movement" for which there is no equivalent OBJ technique. With these generics, the generic instrument/panel code may be able to render the generic quite a bit more directly than your OBJ can simulate the same effect.
This is my suggestion on a cut-off: if you can directly model a generic instrument with an OBJ (needles, throttles, and other "simple moving things"), consider 3-d. If you would have to use a lot of extra texture space, copies of your mesh, or a lot of show-hides, use the panel texture.
Your goal should not be to eliminate the use of panel texture. But if you can cut panel texture down to a single 1024 x 1024 region from a larger area, you'll probably see a performance win or a reduction in your airplane's system requirements.
Performance Test First
Final thought: before you invest months in a complex cockpit design, mock up the "work-load" X-Plane must do and performance test it! For an OBJ, simply make one moving instrument and duplicate the mesh to get the number of expected animations. For the panel, drag out a bunch of instruments, make custom textures and just paint junk into them with photoshop. The goal is to make X-Plane do the same amount of work as it will in the final version. Then fly your test panel on target computers and observe performance.
Monday, June 28, 2010
DDS Has No Gamma (Which is Very Sad)
- PC and Mac monitors are calibrated differently. Dark tones on a PC appear darker than on a Mac. The curve of how colors are mapped to the monitor is the gamma correction curve, typically expressed as a number like 1.8 for Mac and 2.2 for PC. The higher the number, the more Gothic your dark tones.
- A png file can have a gamma value written into the file, which tells X-Plane (and anyone else) what kind of monitor the png was drawn on. This lets X-Plane brighten a png from a Mac when you are on a PC, and darken a png from a PC when you are on a Mac.
- If you leave off the gamma value on your png, we assume 1.8 (Mac) which can be bad if you're a PC author.
In version 9 we added a gamma correction setting to X-Plane. The setting you enter in the rendering settings is how "dark" your monitor is (bigger number = darker). We then attempt to compensate by lightening the textures more; thus a bigger number results in a lighter looking X-Plane (because you told us your monitor was dark and we tried to "fix it").
There are two other developments since the original png situation which have unfortunately been a step backward in terms of X-Plane color correction.
DDS and Gamma
The handling of DDS and gamma is, to put it mildly, quite problematic. The problem is two-fold:
- DDS doesn't actually have gamma information, so we can't tag DDSes as having originated on Macs and PCs. So we assume a DDS is authored at a gamma of 1.8 (Mac). I think DDSTool correctly does a gamma correction when grinding files at other gammas.
- (If you are a real graphics programmer, please do not read this next sentence.) X-Plane attempts to adjust the color of the DDS in its compressed form. This is a big hack designed to keep framerate high, but it's really not a very good idea. The result can be color distortion when a DDS is viewed at 2.2 gamma.
Apple Goes Gothic
Apple adopted the sRGB color profile for OS X 10.6, which has a gamma curve of about 2.2. So now the situation with DDS is particularly ugly:
- All DDS are authored at a gamma of 1.8.
- All users are moving toward a display gamma of 2.2.
- X-Plane thus has to always color correct, but its color correction is low quality for performance reasons.
There are two things we can do about this:
- In the short term, we can provide post-decompression color correction. This will cost a (hopefully) small amount of framerate and improve color fidelity for users with 2.2 gamma. This is the kind of thing that any user with a modern card would want, but that we might make optional for users with very old hardware.
- In the long term, we can provide a gamma calibration in the text files that wrap DDS files so that authors can mark their DDS as already being 2.2. This will mean that for most users X-Plane won't have to do any color correction at all.
Wednesday, June 09, 2010
What is the Difference between ANIM_hide and ATTR_draw_disable?
- 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).
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.
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.
Tuesday, May 25, 2010
Plugin-Based Prop Discs
Let me draw an analogy: when it comes to systems modeling, using a plugin is to Plane-Maker as using Blender is to using Plane-Maker.
Users who cannot use Blender are frustrated because they cannot make something as nice as those who are building planes out of OBJs. Sometimes they ask for more features in Plane-Maker, like: more stations! This new editing mode! Make the UI better!
But...you tell me: will Plane-Maker's UI ever be as flexible and powerful as Blender? And if it ever did get to be that good, would that have turned out to be a good use of LR's time, when Blender is already available?
The motivation for OBJ-based airplane geometry via third party tools is that what users want to do cannot be easily generalized into a few simple cases. Every plane is different, so a truly flexible platform is needed.
The prop disc (and other systems modeling problems) are the same way. In developing the prop disc graphics, I spoke with a number of third party developers who had already tried to push prop discs as far as they could go, were using plugins, were drawing themselves, as well as 25 other crazy hacks. I also spoke to our internal art team. And what I found was: no one had any consensus on how the prop disc system should work. Everyone wanted to tune a very specific set of behaviors to their peculiar art assets.
That's what drove me to put it into a plugin. When we need an equation or a strategy we reach the point where we need more flexibility than Plane-Maker can exhibit. A plugin can encapsulate a strategy or technique in a way that Plane-Maker radio buttons cannot.
Consider what would happen if custom prop disc parameters were built into Plane-Maker. Everyone would have to wait until Austin implemented the prop disc algorithm they wanted. How would this be bad? Let me count the ways?
- How many algorithms do you think Austin has time to code? Not more than he has fingers on his right hand. Only the five lucky third party developers who get their algorithm coded will be happy with this.
- Austin code exactly what you want? Don't get your hopes up.
- , what you asked for wasn't what you wanted? We can't change the behavior now, that would break compatibility!
- oh...your email got eaten by a spam filter? Too bad...no custom prop disc for you!
- Sorry, we don't have a release vehicle lined up for the next 3 months. You'll have to wait.
Think of the prop disc via plugins situation (and the strobe lights are the same way) as an experiment in generic instruments for systems. By transitioning to a generic abstaction for instruments we've let a lot more users do exactly what they want with a small, high performance piece of code. The original instrument strategy (one of everything) reached a point where we simply couldn't meet user needs in a cost-effective manner.
Sunday, May 23, 2010
Additive Lighting Does Not Require Alpha
- 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.
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.
new_r = old_r + overlay = old_r + 0 = old_rIn other words,when using additive light, adding "black" does nothing, preserving the background.
new_g = old_g + overlay = old_g + 0 = old_g
new_b = old_b + overlay = old_b + 0 = old_b
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.
Monday, May 10, 2010
Why Is My Airplane Slow?
Here are some of the specific tricks I do:
Change views; the panel will be drawn differently in the 2-d view, 3-d cockpit view, external view (when close or far - zoom out and the panel won't be updated) vs. 2-d no HUD.
If the 2-d view is slow but forward-no-HUD is not, your panel is expensive. If the 3-d view is slow but 2-d is not, one of your panels may be more expensive than the other (copy them in Plane-Maker from one to the other to see) or it could be that the preparation of the cockpit texture is slow.
Remove 3-d objects from your plane to test the cost of OBJs. Turn down X-Plane's texture res or shrink your textures to see if texture memory is at issue. (Some airplane textures are not affected by the texture res settings, so you may have to manually shrink them.)
Be sure to play with X-Plane's rendering settings; the GPU-specific options don't always cost "the same". For example, per pixel lighting is more expensive when there is more translucency on screen. If your airplane has a lot of overlapping surfaces or translucency this otherwise manageable setting might become too slow.
If you use panel regions, try switching to regular ATTR_cockpit. Panel regions provide superior lighting effects but can take more CPU time when you have a lot of instruments.
Sunday, May 09, 2010
Zen and the Art of OBJ 2: Performance
- Global properties of the OBJ.
- Raw Mesh Data
- Commands, which in turn set per-batch state and then draw the batches.
Global properties tend to affect OBJ performance on a one-time basis. For example, if you use cockpit regions, you pay a fairly large penalty for having the panel texture be set up even if you only apply that panel texture to a single texture. Sure enough, COCKPIT_REGION is in the global properties section of an OBJ.
Per-batch properties affect the OBJ in two ways:
- Every command you see in the commands section is going to involve some CPU intervention. A very long commands section is more work for an OBJ.
- Every time there are attributes between TRIS commands, it defines a new "batch" - that is, a separate instruction to the graphics card to draw a new and distinct setup. Think of this as shutting down the factory to reconfigure the assembly line.
TRIS 0 300
ATTR_light_level 0 1 some_dataref
ATTR_no_blend 0.5
TRIS 300 12the fact that there are two attributes is less interesting than the fact that there are two batches (the two TRIS commands run with different state). Even if you got rid of the no-blend attribute, you'd still have two batches because of the light-level change.The most powerful aspect of the OBJ format is bulk data handling - that is, you have to add a huge number of triangles before the number of triangles becomes a performance problem.
For this reason, you should never use an attribute to reduce geometry count. A few examples:
- Don't use ATTR_no_cull to reduce triangle count - simply issue the indices of the triangle twice.
- Don't use ATTR_flat_shade to reduce vertex count - simply use more vertices with correct per-vertex normals to simulate flat shading.
- Prefer texturing to materials whenever possible.
By comparison, for scenery, batches matter more; X-Plane will share the global properties of objects across hundreds or thousands of objects, but each batch hurts framerate. So when making autogen-style scenery, batches are most important.
Saturday, May 08, 2010
Zen and the Art of OBJ 1: The Anatomy of an OBJ
The World's Simplest OBJ
Here is a very simple OBJ file, broken up by my annotations. First we have the header and global section:
A
800
OBJ
TEXTURE great_image.dds
POINT_COUNTS 24 0 0 36the global section describes properties universal to the entire OBJ. For example, what textures will be used to draw the object?We picked up a few new global properties in the version 9 run:
- Normal maps are declared globally for the entire OBJ.
- The metrics of any panel regions to be used are declared globally.
Next comes the data section:
VT 0.449997 0.300003 0.860001 1.000000 0.000000 0.000000 0.000000 0.000000
VT 0.449997 0.300003 0.000000 1.000000 0.000000 0.000000 0.000000 1.000000
VT 0.449997 -0.509995 0.860001 1.000000 0.000000 0.000000 1.000000 0.000000
...
IDX10 0 1 2 3 2 1 4 5 6 7
...
IDX 21I have removed a lot of the data section, because there's not much to be said about it. The data section contains the raw data for the meshes in your OBJ, and it hasn't changed since the OBJ 8 format was introduced.The third and final section is the most interesting one: the commands section.
ATTR_LOD 0 3000
ATTR_hard asphalt
TRIS 0 36The commands section describes how the data is used in the form of serial instructions to X-Plane. Most changes to the OBJ format have come in the form of new commands. We can categorize our commands into a few buckets:- Drawing commands create "stuff". There aren't very many drawing commands, and new ones don't appear very frequently. TRIS and LINES are the main commands, but the smoke commands also fall into this category, as do the light billboard commands. The new light billboard command LIGHT_PARAM is the only new drawing command for version 9, and it probably warrants its own blog post.
- Attribute commands change how stuff is drawn - they effectively define properties for drawing on all triangles that can be modified. We picked up a number of new attributes: manipulators (controlling how the mouse works), light level control, solid camera, draw disabling, deck style hard surfaces, and panel regions. (While you must declare the panel region locations globally, a panel region is enabled for a specific batch.)
- ATTR_LOD is sort of an exception, because it defines the structure of the model (e.g. a model with LOD really contains several separate command lists, of which only one is used).
Note that attributes can be thought of as "per mesh" or "per batch" properties, because they affect only the batches of mesh (TRIS commands) between the attribute being turned on and turned back off again.
Where Will New Features Appear?
I try to post some of my crazier ideas regarding OBJ on the scenery system RFCs page. Looking at the extensions, we can see how these extensions will all be either global, drawing primitive, attribute, or OBJ structure extensions. (I am not promising that any of these RFCs will be implemented, just showing how the OBJ format grows.)
- Additive LOD. This is a change to the structure of an OBJ, but it doesn't actually change the format, just the legal LOD values.
- Explicit OBJ Height. This is a global property on the OBJ.
- Global Texture Variants would be a global property on the OBJ's textures.
- Global Object Attributes are new global properties - they move some per-batch attributes to be object-wide.
- Draped Object Geometry would be per batch.
Next: what are the implications on performance of the various sections of an OBJ?
Friday, April 09, 2010
Two-Sided Drawing and Up-Normals
In order to understand why two sided geometry is bad, we must consider the alternative. The alternative to two-sided geometry is to simply create each triangle twice, with one facing in each direction. We can do this in an OBJ without making new vertices - because vertices are referenced by indices, we only need more indices, and indices are cheap.
Thus we have an alternative to two sided geometry, namely "doubled" one-sided geometry.
The first problem with two sided geometry is performance: for a small number of triangles, it is must faster to simply emit additional indices than to change the drawing mode to two-sided drawing on the CPU.
Thus in an object it is virtually never a good idea to use two-sided geometry. That ATTRibute will always be worse.
What about for the other clutter? Forests are currently always two-sided, but that's okay; X-Plane enables two sided drawing just once, then draws a huge number of trees. Same with roads. For facades, there is a cost to using two sided geometry, so only use it for facades that must be two sided, like fences; do not use it for buildings.
Now the second problem with two sided geometry is lighting: X-Plane does not calculate lighting values separately for the two sides of the two-sided geometry. So if you have directionally lit models with two sided geometry, the lighting will look wrong. This is the second reason to use doubled geometry instead.
Things Are Starting To Look Up
There is a work-around to this problem of incorrect lighting on two-sided geometry: "up normals". With up normals, the normal vector for the triangle (which is used to determine how light "bounces" off the triangle) is set to face straight up. The result is a triangle with brightest lighting at high noon, regardless of which way the triangle actually faces.
The good: the triangle looks the same on both sides and has sort of a "flat" lighting - it doesn't look wrong when the sun is setting. The bad: the triangle has "flat" lighting - it looks non-3d.
We use up normals for forests because the forests are made of two-quad trees...the trees look less fake if directional lighting hints don't make the two quads as obvious. You can simulate this in ac3d using the "make up normal" command for vegetation quads you put in your own models.
For roads, the geometry is two-sided, so we use up normals to avoid having the back of a road element look funny. Some day we may do something more sophisticated.
Fixing Facade Lighting
Facade lighting behavior will be changed in the next 950 release candidate. Before 950, facades would receive up normals, always. Starting in 950, facades will get correct normals if they are one sided and up normals if they are two-sided. This avoids artifacts with two-sided facades, but will make one-sided closed buildings look much better.
Friday, April 02, 2010
Mirrored Normal Maps
You can understand this by thinking of your normal map as a physical piece of metal with bumps punched in it. Flipping it horizontally really means rotating it horizontally to see the other side - now you see the back side of the bumps. Same with the vertical flip. Flip both and you have flipped it twice and it's front-side forward again.
In a move that is either just in the nick of time or dangerously reckless, I have tweaked the normal map shader for 950 RC1 (coming out "real soon") to detect and "fix" a flipped normal. In 950 rc1 the bumps in your normal map will always point in the same direction as the normal of your mesh, even if your UV map is flipped horizontally or vertically.
What does this mean to you, the modeler? It means that you can now mirror your normal map from the left to the right side of the airplane and the normal map will still have the bumps "sticking out" like you want.
I crammed this into 950 RC 1 because it looks like it's a useful change that will restore flexibility to authors making highly detailed airplanes. Mirroring a symmetric airplane (which results in a horizontally mirrored normal map) is a pretty common thing to do, and if the text is applied as decals, this can be a big win in texture space savings.
I figured best to get the tweak in here now so people could take advantage of it. Plus, what's an RC1 without an RC2?
Wednesday, March 10, 2010
I Feel Manipulated
If you're just discovering X-Plane (or just discovering that X-Plane's 3-d cockpits can be very interactive), here's X-Plane's "raw" capabilities for manipulation:
- The simplest manipulations are based on mapping the mouse from the 3-d cockpit back to the 2-d panel. This can only be done when the 3-d cockpit is textured using a piece of 2-d panel. This is the oldest way to make a clickable cockpit in X-Plane, dating back to the original X-Plane 3-d cockpits. The advantage of this method is that it's very easy to set up; the disadvantage is that the mouse click gestures tend to be "flat" in their operation.
- As Tom's plane demonstrates, you can manipulate just about any dataref or command via a drag along a specific axis. Axes are subject to animation, so there's a lot of potential for "grabbing" things with this interface.
- X-Plane also supports direct "click" manipulation - this can be handy for buttons where you don't want to require the user to move the mouse around. There are several types of click manipulation.
To create manipulators on your cockpit, you can use the latest plugin for AC3D. A manipulator is a property on a mesh within your object - each mesh can have its own manipulation with its own properties.
X-Plane does not have an IK solver. Rather, movement of "stuff" in your cockpit is indirect.
- Your manipulator changes a dataref as the user drags along an axis.
- The dataref change shows as an animation on your mesh.
Thursday, February 11, 2010
A Few More Lights
X-Plane 940 introduced the concept of parameterized lights to support these features. Here's the basic idea:
Named lights (available for quite a while now) let you add a light billboard to your model that we define. The idea is that since the lights are specified against a real world model (this light billboard should look roughly like a landing light) it lets us upgrade art assets and back the light with the fastest path on the graphics card.
The problem with landing lights is that they are one-size-fits all, and this is particularly problematic for airplanes, where the lights can look quite different in size and angle based on the size of the airplane. Parameterized lights fix this by letting you specify a limited number of parameters in your OBJ. By limiting the parameters that you can set, it means that we can still optimize the light when possible.
I took a few minutes today to round out the list of parameterized lights, and I think there will be 9.46 patch in which we can release them*. When we put 9.46 in beta I'll update the example plane; the new set of lights will give you parameterized control over the navigation and taxi lights, as well as the generics, beacons, strobes and landing lights.
* We have a few small bug fixes we'll roll out in 9.46.