Tag: modeling

Draping Part 2: Draping a Polygon

In my previous post I described Z thrash and how polygon offset is used to fix it.  Now we can look at draping and runways.

The fundamental problem with sloped runways is that a runway is made up of tiles, but the ground underneath it may change slopes in unrelated locations.  The following diagram illustrates the problem.

This is a side view of a sloped runwy: the green line is the underlying bumpy terrain and the black line is the runway, divided into multiple tiles.  Recall from last time that we can only avoid Z-thrash using polygon offset if the two polygons are truly coplanar.  Therefore, we can look at four ways to handle the situation and evaluate them for quality:

  1. In the top picture, the runway simply runs right through the terrain.  This case won’t work, with or without polygon offset.  In some cases the terrain is on top, and in some cases the runway is on top.  The gap between the runway and terrain might be quite large for a significantly sloped runway.
  2. In the second picture, we move the runway up to clear all but the tallest part of the terrain.  This won’t Z-thrash, but it will look pretty bad.  There can be a large gap between the runway and the terrain; if you run your airplane off the side of the runway, you’re going to fall.  The gap between the runway and terrain will be quite noticeable.
  3. The third picture is close – each runway tile is clamped to the terrain.  But this still isn’t good enough; while most runway tiles now sit on the ground perfectly, a few will take a ‘short cut’ over or under the ground, like the case I have circled in red.  So we’ll have less Z thrash, but some parts of the runway will still be broken.
  4. The last picture is what we really need: we break the runway tiles up into even smaller pieces where the terrain makes a change.  The last tile on the right is now two tiles, each of which can sit perfectly on part of the terrain.  Only in this last case can we apply polygon offset and get a nice clean runway.

This last case is exactly what X-Plane does.  This technique is called draping – the sim ‘drapes’ the overlaid runway tiles on top of the runway like a rug.  The sim breaks the tiles into pieces so that each tile can sit perfectly on the underlying terrain.

The real work of draping is not just in figuring out where the terrain below the tile is, it is in cutting the tile into the appropriate pieces that can ‘sit right’.  The following pictures show this process in 3-d.

This is a screen-shot of a small piece of taxiway at KSAN.  I have drawn in the outline of the draped polygon in yellow and the terrain triangles in blue.  (The terrain triangles are quite large, so we can only see part of them running through the scene.

This is a wire frame of the problem at hand: we need to insert the yellow polygon into X-Plane, but we need to make sure that no triangles that we generate cross the blue line.  The blue lines essentially represent “ridge lines” in the underlying mesh.

If we just had to draw the yellow polygon, we could triangulate it using the thick gray lines shown in this picture.  However, this would not be good; the big gray triangle in the middle of this picture runways right across a blue line – there’s no way that this big gray triangle can “drape” properly across the ridge line.

This is what actually ends up happening.  The gray lines are cuts we need to triangulate the polygon; the red line are cuts we need to not cross the ridge line, and the purple lines are cuts we need to ensure that everything is broken down into triangles (since that’s what the video card really wants).  Once we have this triangulation, we can place every vertex on the ground and it will “drape” the way it should.

In my next post I’ll describe how you can use draping in your scenery to create images on the ground without Z thrash.

Posted in Scenery by | 13 Comments

Draping Part 1: Z Thrash

I think I have mentioned draping repeatedly, as well as Z thrash, without ever clearly explaining what either of these things are.  I happen to have some pictures from recent work on draping, so here’s the basic situation.

What Is Thrash?

Warning to OpenGL purists: I’m going to play fast and loose with a number of OpenGL rules.  Basically what I say here is the worst case.  Sometimes things work out better than I describe, but if you don’t handle the worst case, you’re going to have problems some times.  Nitpickers, consider yourself “on notice”.

When drawing 3-d polygons in OpenGL, if two polygons are coplanar, most of the time they will experience “Z thrash” – that is, the hidden surface removal hardware on the graphics card removes some parts of one polygon and some parts of the other, often removing different parts on each frame in a flickering pattern.  The results look like this:

In this picture on the left, we see the raw result of coplanar airport polygons on top of the sandy desert terrain that is the airport surface area.  As you can see, the graphics card has been a bit random in deciding whether the runways are “hidden” by the ground or not.  If you could see the camera moving, you would see that the pattern of missing taxiways ‘flickers’ as the camera moves.

If there is an overall take-away point so far, it’s this: you can’t just layer coplanar triangles without getting a mess.

(What about moving the runway slightly higher than the pavement?  This would have several problems.  First, the amount we’d have to move them is horribly dependent on camera angle and video card Z-buffer performance.  Second, we’d see the gap between layers; for markings that really do need to be coplanar, like a rubber mark on a taxiway, this would appear as a bug.)

The Cure is Worse Than the Disease

Fortunately if we have truly coplanar geometry, OpenGL gives us a weapon to fight this: polygon offset.  Polygon offset is a cheat that tells the video card: “listen, if you ever have doubts about the runway and the ground, favor the runways by a little bit.”  It’s a little bit like putting a spread on a football game: the ground would have to be closer than the runway by a margin before we stop seeing.

When we have coplanar geometry, we can use polygon offset to handicap the geometry we want on top.  Problem solved, right?  So why do I keep writing blog posts with titles like: The Sordid History of ATTR_poly_os or The road to hell is paved with ATTR_poly_os?

Polygon offset has three problems that can bite you:

  1. The amount of ‘margin’ you get depends on the camera angle.  This can make for some truly bizarre effects.  The only way to safely manage this is to carefully minimize the margin.  (This is a problem for the programmer, not the artist.)
  2. Because the margin must be minimized, the geometry really has to be coplanar – small cheats can exceed the margin.
  3. The margin you give your top polygon applies to anything else that is nearby, which can cause even more weird artifacts.  For example, if you polygon offset a taxiway, it can start appearing through the nose wheels of airplane.  That’s another aspect that must be carefully controlled.

If there’s a take-away to polygon offset, it’s this: polygon offset can help fight Z-thrash, but it must be used in a very narrow set of cases, and it must be used very carefully.

In my next post I’ll describe how X-Plane uses draping to fight Z-thrash for sloped runways.

Posted in Scenery by | 7 Comments

X-Plane vs. Blender Normal Maps

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.

Posted in Development, Modeling by | 1 Comment

Using Glass Objects in Planes

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.)

Posted in Aircraft, Development, Modeling, News by | 4 Comments

Coping With Variable Rendering Options In X-Plane 10

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.

Posted in Development, File Formats, Modeling, News, Scenery by | 3 Comments

Performance Tuning and Future Proofing

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.

Posted in Development, Modeling by | 2 Comments

Use Every Pixel of Your Normal Maps

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.

Posted in Development, Modeling by | 1 Comment

Revisiting Texture Compression

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:

  1. Because the image is already compressed, we save CPU time when loading the texture that would be spent compressing while X-Plane is running.
  2. 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.
  3. 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.

Posted in Aircraft, Development, File Formats, Modeling, News by | 3 Comments

More Global Illumination Video

I realized I have slightly better test shots of global illumination than the ones that got out a week ago. These are from only a day or two after the last shots.

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.

Posted in Aircraft, Development, Modeling, News, Scenery by | 17 Comments

X-Plane 10 and Global Illumination

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.)

Posted in Aircraft, Development, File Formats, Modeling, News, Scenery by | 5 Comments