Javier posted a video of his CRJ on the dev list today. I have not tried the plane, but there is no question from the video that it looks really good. What makes the video look so nice is the careful management of light. Part of this comes from careful modeling in 3-d, and part of it comes from maxing out all of X-Plane’s options for light.
But…what are the options for light on an airplane? I don’t know what Javier has done in this case, but I can give you a laundry list of ways to get lighting effects into X-Plane.
Model In 3-D
To really have convincing light, the first thing you have to do is model in 3-d. There is no substitute – for lighting to look convincing, X-Plane needs to know the true shape of the exterior and interior of the plane, so that all light sources are directionally correct. X-Plane has a very large capacity for OBJ triangles, so when working in a tight space like the cockpit, use them wisely and the cockpit will look good under a range of conditions.
You can augment this with normal maps in 940. Normal maps may or may not be useful for bumpiness, but they also allow you to control the shininess on a per-pixel basis. By carefully controlling the shininess of various surfaces in synchronization with the base texture, you can get specular hilights where they are expected.
The 2-D Panel
First, if you want good lighting, you need to use panel regions. When you use a panel texture in a 3-d cockpit with ATTR_cockpit, X-Plane simply provides a texture that exactly matches the 2-d cockpit. Since the lighting on the 2-d cockpit is not directional, this is going to look wrong.
When you use ATTR_cockpit_region, X-Plane uses new next-gen lighting calculations, and builds a daytime panel texture and a separate emissive panel texture. These are combined taking into account all 3-d lighting (the sun and cockpit interior lights – see below). The result will be correct lighting in all cases.
Even if you don’t need more than one region and havea simple 1024×1024 or 2048×1024 3-d panel, use ATTR_cockpit_region – you’ll need it for high quality lighting.
The 2-d panel provides a shadow map and gray-scale illumination masks. Don’t use them for 3-d work! The 2-d “global lighting” masks are designed for the 2-d case only. They are optimized to run on minimal hardware. They don’t provide the fidelity for high quality 3-d lighting – they can have artifacts with overlays, there is latency in applying them, and they eat VRAM like you wouldn’t believe. I strongly recommend against using them as a source of lighting for a 3-d cockpit.
To put this another way, you really want to have all global illumination effects be applied “in 3-d”, so that the relative position of 3-d surfaces is taken into account. You can’t do this with the 2d masks.
The 2-d panel lets you specify a lighting model for every overlay of every instrument – either:
- “Mechanical” or “Swapped” – this basically means the instrument provides no light of its own – it just reflects light from external sources.
- “Back-Lit” or “Additive” – this means the instrument has two textures. The non-lit texture reflects external light, and the lit texture glows on its own.
- “Glass” – the instrument is strictly emissive.
You can use 2-d overlays not only for instruments but also to create the lighting effect within instruments, e.g. the back-lighting on a steam gauge’s markings, or the back-lighting on traced labels for an overhead panel.
2-d overlays take their lighting levels from one of sixteen “instrument brightness” rheostats. You can carefully allocate these 16 rheostats to provide independent lighting for various parts of the panel.
The 3-d Cockpit
The 3-d cockpit allows you to specify 3 omni or directional lights. These can be placed anywhere in the plane, affect all interior objects, and can be tinted and controlled by any dataref. Use them carefully – what they give you is a real sense of “depth”. In particular, the 3-d lights are applied after animation. If a part of the cockpit moves from outside the light to into the light, the moving mesh will correctly change illumination. This is something you cannot do with pre-baked lighting (e.g. a _LIT texture).
Finally, ATTR_light_level is the secret weapon of lighting. ATTR_light_level lets you manually control the brightness of _LIT texture for a given submesh within an OBJ. There are a lot of tricks you can do with this:
- If you know how to pre-render lighting, you can pre-render the glow from a light onto your object into your _LIT texture, and then tie the brightness of the _LIT texture to a dataref. The result will be the appearance of a glow on your 3-d mesh as the light brightens. Because the lighting effect is pre-calculated, you can render an effect that is very high quality.
- You can create back-lit instruments in 3-d and link the _LIT texture to an instrument brightness knob.
- You can create illumination effects on the aircraft fuselage and tie them to the brightness of a beacon or strobe.
There are two limitations of ATTR_light_level to be aware of:
- Any given triangle in your mesh can only be part of a single ATTR_light_level group. So you can’t have multiple lighting effects on the same part of a mesh. Plan your mesh carefully to avoid conflicts. (Example: you can’t have a glow on the tail that is white for strobes and red for beacons – you can only bake one glow into your _LIT texture.)
- ATTR_light_level is not available on the panel texture. For the panel texture, use instrument brightness to control the brightness of the various instruments.
I have a sample plane that demonstrate a few of these tricks; I will try to post it on the wiki over the next few days.
Let me set the record straight on this: you should not need to re-save an airplane to have it work in a newer version of X-Plane. If you have to do this, X-Plane is broken … please report a bug!
(In the case of 940 – there is a big fat bug – see the end of the post.)
Here’s a little bit more about what’s going on under the hood.
When Austin creates a new revision of the acf format (which happens in virtually every major patch), he handles backward compatibility with old aircrafts in one of two ways:
- He sets the default value of a setting to match the “unused” value in the old ACF file and sets this default value to match the legacy behavior. This naturally initializes all newly introduced functionality to its “backward compatible default” for old airplanes.
- Where this is not possible, he writes some conversion code that maps old ACF values to new ACF values. This mapping tries to re-create the old systems functionality as closely as possible.
This forward conversion code runs in two cases:
- When you open the airplane in Plane-Maker.
- When you open the airplane in X-Plane.
Plane-Maker will resave the plane in the newest format, with the automatic system updates in place. But this should not be necessary because X-Plane applies the same automatic process on airplane load. This is why you should not need to resave – X-Plane will do the upgrade “on the fly”.
Now about that bug…it turns out that 940 incorrectly updates 930 airplanes – the generator amperage is not correctly initialized. This is why 930 planes will run their batteries down in 940. (This bug was fixed in 941 beta 2, btw.)
What was strange was that, because of the way Plane-Maker’s code was structured, this code was failing in X-Plane but succeeding in Plane-Maker. This doesn’t happen very often (usually the code fails everywhere) but the result was authors noticing that their planes would start working if resaved in PM.
And that brings me back to the beginning of the post. If Plane-Maker can update the airplane but X-Plane cannot, that’s a bug! Please report it as such.
I want to make sure people realize that auto-update should work, and that resaving in Plane-Maker should not be necessary. Otherwise authors will start silently resaving their airplane instead of reporting the bugs, and we’ll never find them.
(Systems bugs sometimes only show up with a particular combination of systems settings. So while I do hope that we can catch all such bugs in beta, it is always possible that one peculiar model will induce a bug once the sim is released.)
Yesterday I blogged about Order Independent Transparency (OIT). That robot is very shiny, but what does this fix in X-Plane itself? Here are two pictures that show the problem in an X-Plane context.
This is the Cirrus jet in X-Plane 9.22.
Pretty, eh? But…look through the right two windows – look at the passenger door on the other side. Note that through the middle window the passenger door is visible. Through the right window, the entire passenger door is gone!
This is the same shot from X-Plane 940, where the problem has been corrected.
The bug you see here is incorrect draw order. In X-Plane 922, the right door (which contains the right-most near window) is drawn before the left door – hence its translucent part destroys the door.
Max fixed this by changing the draw order of the model – the new cirrus draws the inside view of both doors before the outside view of either doors; because the geometry is one-sided he can draw the ‘inside’ first and outside ‘second’.
These two
blog posts explain translucency in a lot more detail.
What X-Plane has now is “order dependent” transparency – if translucent surfaces are not drawn from far to near, you get artifacts like the missing door.
What OIT promises (and that robot demonstrates) is the ability to have translucent geometry and not have the objects behind the translucent parts disappear.
If you have ever textured an airplane, then you know that you can’t use the same texture for both sides of the plane if there is writing on the fuselage. The writing will be horizontally mirrored on one side.
The same thing goes for normal maps – you can’t mirror a normal map without getting bogus results. Think of your normal map as a real 3-d (slightly extruded) piece of metal. If you are seeing the text go the wrong way, the metal must be facing with the exterior side pointing to the interior of the airplane.
Having your normal map flipped does more than just “inset” what should be “extruded” – it completely hoses the lighting calculations. In some cases this will be obvious (no shiny where there should be shiny) but in others you will see shine when the sun is in a slightly wrong position.
The moral of the story is: you can’t recycle your textures by flipping if you want to use normal maps.
The rule is very simple: if you want to put a marking on the ground, your results will be much better if you use a .pol (draped polygon) or .lin (draped line) than if you use an OBJ. In fact, an OBJ is probably the worst way to put markings on the ground.
Requirements for Good Looking Markings
In order for markings to look good you need to have three things happen:
- You need to make sure your markings are at the exact same level as the ground itself.
- You need to use polygon offset to tell X-Plane to tell the video card that these are “coplanar” (at the same height) triangles that must be managed in a special way.
- You must guarantee that the draw order is: the stuff under your markings, your markings, then the 3-d buildings and other 3-d stuff.
With these requirements we can compare .pol/.lin files to OBJs:
- .pol and .lin files always “drape” to the ground, so they always meet rule 1 perfectly. With an OBJ you can set the height of your OBJ to 0 but on sloped terrain this won’t be correct.
- .lin and .pol files are always “polygon offset” automatically, so they always meet rule 2 perfectly. With an OBJ you need to use ATTR_poly_os.
- ATTR_layer_group (or LAYER_GROUP) tell the OBJ or pol/lin in what order to draw, so you can set this correctly in all cases. The default values if you don’t specify a layer group are more appropriate to the task of markings on the ground when you use a pol/lin – that is, by default they meet rule 3 perfectly. By comparison, an OBJ may not be in the right draw order.
So we can see from these 3 rules that you will always get the rules right just by using a pol or lin, but you have to be very careful and may still not get the rules right when using an OBJ.
Performance? Think .pol
When you have a large number of small markings, the performance of a .pol is going to be significantly superior to the performance of an OBJ. For example, imagine an airport where you want to draw on-pavement signs for all taxiways and runways. With an OBJ, to get the height right, you’d need to use a large number of small objects. (With one large object, it will be nearly impossible to make the OBJ markings be on the ground when far from the object center.)
When you use a large number of .pol markings that share one common texture and all have the same .pol file, X-Plane merges them behind the scene into one huge object-like pile of triangles. The cost of drawing all of those polygons will be similar to the cost of drawing just one object! That’s a huge speed win.
Floating Objects Are Wrong
What I see most commonly in scenery packs that are sent to me and have thrashing problems are OBJs that have a height other than 0. This is simply the wrong way to create overlaid geometry in X-Plane, and it will produce artifacts in a wide variety of situations. At best, the “floating” objects will cause airplanes driving over the marking to look like they “sink in”. At worst, the offset you pick will be too small for the video card’s resolution and you’ll get thrash anyway.
There is no one right vertical offset for all scenarios, and even if there was, it would still look ugly! See the above rules for what an OBJ really has to do.
How Do I Get a .pol into my scenery.
Well that is the $10,000 question. I must admit that I don’t know what Overlay Editor’s capabilities are in this regard. WED 1.1 will be able to add draped polygons, including texture coordinate editing of the polygons. I’ve been working on the texture coordinate editor in WED this weekend and am hoping to get some kind of WED 1.1 preview built this week.
With WED 1.1 the process is fairly simple:
- Create your texture.
- Create a single .pol text file that names the texture, so you can use it.
- In WED 1.1 you can select the .pol from the list of resources for your scenery pack, and then use the “polygon create tool” to simply draw the draped polygons into place.
- Once the draped polygons are created, you can select the polygon and open the “texture coordinate editor” tab to edit the way the texture is applied to the polygon.
My hope is that this process will be easier than creating markings using a 3-d editor – you can still edit the texture coordinates, but you can do so directly in WED.
There are a few changes to 940 regarding airplane lights…I will try to get some permanent documentation on the Wiki, but here’s the basic ideas:
There is a new “type” of light in the OBJ8 format, called a parameterized light. A parameterized light is somewhere between a named light (totally as-is, can’t be modified, simple to use) and a custom light (totally complex, can do anything, requires a lot of work). In a parameterized light, you control just one or two aspects of the light.
Parameterized lights are aimed at airplanes, not scenery, because typically parameterized lights are customizable and slow.* The goal is to give airplane authors some flexibility without having to invent a huge number of named lights.
Consider, for example, landing lights. A landing light could vary based on what switch controls it (we have 16 now), how big it is (many authors have pointed out that one size does not fit all) or how wide it’s view angle should be. (Lights that are inset in a structure might not be easily viewable from the side.) With a parameterized light, we can provide one light definition with 3 parameters instead of a huge matrix of lights.
Generic lights are a new collection of 64 lights that can be used for any purpose, sort of like misc wings, misc bodies, and sliders. The main difference between a landing light and a generic light is that the landing light halo won’t show up on the runway when a misc light is turned on. They are meant to be used for logo lights, inlet lights, etc. A series of new named lights will “listen” to the generic switches.
(Tip: combine ATTR_light_level with generic lights to have a light turn on and your lit texture appear at the same time.)
Finally, there is now a plugin override for the beacons and strobes (and in the systems model there can be up to 4 separate sets of beacons and strobes flashing at different times). With parameterized lights you can make two sets of strobes and use a plugin to control when they flash.
The combination of these three things let an author create an airliner that models all of the various lights and their behaviors.
* Slow needs some qualifications here. There are two code paths for lights, the fast and slow path. The slow path IS pretty fast, just not as fast as the fast path. The fast path is expected to be able to draw at least 10,000 lights in a single frame on low-end hardware, while the slow path is expected to be able to draw at least 500 lights per frame on low-end hardware.
500 lights is a lot for one airplane, especially if you have to place them by hand. And most modern computers will easily do thousands of slow lights.
Basically slow lights are not appropriate for scenery objects in the library that might be placed a huge number of times: OBJs attached to roads (e.g. street lights), OBJs used for buildings, taxiway lights. The are plenty fast for airplanes. In the X-Plane world, slow doesn’t really means slow, just slower than something else.
A quote from the .org:
I actually did try the demo before I bought it, and I found it sorta arcadish as I took off with a King Air 200 and performed barrel rolls on t/o lol! That kind of tuned me out!
I don’t mean to pick on that particular poster – we hear that a lot, particularly from people who use MSFS. Andy Goldstein points to Bob Hoover as a counterpoint.
More generally, the criticism is that since X-Plane will allow you to do things in commercial airliners that you’ve never seen in real life, X-Plane must not be realistic. And phrased like that, you can see the possible flaws in the reasoning:
- How do you know your control inputs match real life?
- How do you know the real plane is physically incapable of doing such a thing?
The first is the age-old problem of consumer joysticks – to really maneuver an airliner hard you have to put a lot of pressure on the controls – they put up a lot more resistance than a $20 SideWinder.
The second is an issue of falsifiability again – the absence of evidence is not evidence of absence.
Now in truth there are things that X-Plane models and X-Plane does not model. If you load up the airframe too much with fail-on-over-G on and the G limits are set correctly, X-Plane will start removing parts as you try to fly a 747 like an F-16. But we don’t necessarily simulate some of the internal things that might go wrong. For example, accelerations on the fuel system might potentially cause flow to the engines to fail, stalling an engine. I don’t know how much of this Austin simulates, but we certainly don’t simulate the geometry of the fuel lines and the fuel as a fluid flow. So there may be cases where a maneuver is impossible for logistic but not aerodynamic reasons (e.g. you could do it but you’d lose your engines).
With that in mind, here are a few youtube links:
- Bob Hoover flies a Commander like an aerobatic glider – thanks Andy!
- Roll an airliner? It’s safe, really!
- The 757 has a lot of power – thanks Andrew.
- I have no idea what happened here…I thought the Airbus computer prevents you from doing this kind of thing.
On that last video: the first time I flew with Austin in his Cirrus (this is before he traded it for a Columbia) he pulled the same maneuver: take-off, very slow rate of climb to pick up speed, and then: yank. Our climb rate was well over 2000 fpm in a single-engine prop for a while.
(Logistic note: please don’t interpret this post as an invitation to contact me regarding any aspect of the flight model – when it comes to the physics engine I am just another user, with no special insight. Physics is Austin’s domain, definitely not mine!)
Two warnings about normal maps:
-
Make sure that the RGB color underneath transparent sections does not turn black or white! Some image editing programs (in particular Photoshop) will lose the color beneath a transparent area.
With a normal map, this is very bad – black and white are not legitimate normal map colors, and the result will be bogus normal vectors under the non-shiny part. Normal maps affect more than just specular shiny hilights – the normal map affects all lighting, so having black or white under your transparent (non-shiny) parts is bad news.
To check whether this has happened, I recommend Graphics Converter, which will show you your alpha and RGB channels separately, exactly as they are in the file.
-
Make sure your RGB value are normalized. The “length” of the normal (as encoded in RGB) must come out to a distance of 1. This is virtually impossible to do using PhotoShop or an image-oriented program…I suggest you use a real plugin to PhotoShop or Blender to create normal maps that are correctly “normalized”.
It is also very possible that X-Plane’s gamma correction is distorting normal maps, but that’s one for me to fix.
X-Plane 940 has a new electrical systems model and it has a few important differences from 930:
- You must specify exactly how many buses your plane has. 930 provided two buses but then did a bunch of cross-tying behind the scenes in case you didn’t have enough power sources.
- X-Plane 940 requires that each battery and generator be on exactly one bus.
- X-Plane 940 will not allow systems to be powered by non-existent buses.
Now this can have some strange side effects. Consider the default king-air with two generators and one battery:
- In 930 it has two buses, battery feeds both buses, and each generator feeds one. You could have systems split by bus and they would work unless you lost one generator and the battery.
- 940 defaults this plane to one bus, because on battery power only one bus will be fed.
- This means that in 940 all of your systems will be reset to bus 1.
But wait…if you import into Plane-Maker, the import will trash your system bus selections before you can increase the number of buses to 2. What can you do?
Here’s a work-around: before you update your plane, make sure you have two battery and two generator switches on your panel. Then open in 940. The import will set 2 buses and your systems will be preserved.
Of course, by the next few betas this may all be moot because we may get something less crazy in there.
When Sergio first proposed generic instruments, his model was “lego bricks”. The idea was to provide a number of very basic parts for panel makers and let panel makers mix and match. The result would be huge flexibility for airplane authors without code bloat.
The problem with non-generic instruments is that there is such a huge variety of behavior among airplanes…if Plane-Maker were to have options for every possible plane, the “special equipment” screen would require 3000 tabs and be completely unusable. Hence the need for a smaller unit of modeling: the lego brick.
The prop disc is the first feature I have done that is meant to be used only by a plugin, e.g. “lego brick” code. The X-Plane systems code sometimes suffers from the same “code bloat” problem as the instruments: a ton of very specific, very tweaky behaviors that interact in strange ways and become very difficult to manage. It’s not that the systems code is bad code – it’s that the scope of the problem is simply too large. That is, you can’t expect X-Plane to cleanly simulate the systems of every airplane ever in a ton of detail through an a la carte menu of check-boxes.
The idea of the prop disc is: someone (LR or otherwise) can write a plugin that encodes a certain style of prop disc. That plugin can then be picked up and moved around like a generic instrument between planes (perhaps with a corresponding text file to control it).
If someone else comes up with a different/better prop-disc algorithm, compatibility isn’t an issue…that person writes a new prop disc plugin and the airplane author selects the one desired. Think of it as sort of a portable flight model that stays with your plane.
So we win in three ways:
- Anyone can write the prop disc algorithm, not just LR.
- The code lives with the plane, to avoid compatibility problems.
- More than one plugin can exist, giving authors an a la carte menu.
That’s the theory at least.