Graphics In X-Plane

About Graphics

This chapter describes the graphics environment for X-Plane.  If we need to draw in a window and the existing user interface routines and libraries are not adequate, or if we need to draw 3-d graphics in X-Plane, read this chapter.

We may be able to create user interfaces without writing any graphics code at all.  The widgets API contains premade user interface elements for windows, buttons, text entry fields, etc.  This code is cross-platform, feature-rich and does not affect the simulator's frame rate.

X-Plane's Graphics Environment and Architecture

X-Plane uses OpenGL as its graphics package.  X-Plane creates one full-screen system-native window that is entirely rendered by OpenGL.  All X-Plane user interfaces are implemented via OpenGL.

The X-Plane window is double-buffered for flicker-free drawing.  It is fully refreshed every time it is drawn, and it is drawn perpetually.  X-Plane's OpenGL environment features a 32-bit ARGB drawing plane and a depth buffer of (preferably) 32 bits.  The X-Plane window does not feature a stencil buffer.

Standard X-Plane Graphics State

X-Plane manages OpenGL's graphics states to optimize rendering.  OpenGL performs best when the graphics state is not unnecessarily switched.  The plugin SDK provides facilities to coordinate graphics state with X-Plane.

Managed OpenGL State

X-Plane manages six OpenGL properties constantly:
Attribute
OpenGL Settings
Typical State during 3-d Drawing
Typical State during 2-d drawing
Fog
GL_FOG
On
Off
Lighting
GL_LIGHTING, GL_LIGHT0
On
Off
Alpha Test
GL_ALPHA_TEST
On or Off
On or Off
Alpha Blending
GL_BLEND
On or Off
On or Off
Depth Reading
GL_DEPTH_TEST
On or Off
Off
Depth Writing
glDepthMask(GL_TRUE)
On or Off
Off

Texture State

X-Plane tracks a number of texture state-related variables.  X-Plane tracks how many texture units are enabled (0 for no texturing, 1 for the first, 2 for multitexturing, etc.) and which textures are bound to which.  Use the plugin API to bind textures to texture units and enable a certain number of texture units.  X-Plane allows a maximum of four texture units to be used at once.

Default OpenGL State

During normal operation, the scizzors and stencil tests will be off.  Polygon offset is usually set to 0.

Do not alter the use of the blending operation or the values of light 0.

Coordinates in X-Plane

X-Plane uses two coordinate systems: one for 3-d drawing and one for 2-d drawing.

During 3-d drawing the OpenGL origin is positioned on the surface of the earth at the latitude and longitude reference point (which may be found via data access).  The X axis runs east-west from the origin with positive X being east.  The Y axis points straight up from the earth, normal to the earth's surface at the origin, with positive Y being up.  The Z axis runs north-south, with positive Z being north.  One OpenGL unit will render as one meter.

< Picture, OGL axes >

Important: Since the world is round, the correspondence of the OpenGL axes with north, south, east, west, and up/down with gravity is only true at the origin.  For example, as we go east from the origin in the northern hemisphere, the axis pointing to the north pole (north) rotates counterclockwise from the Z axis.  Similarly, gravity and the Y axis change.  If we are doing 3-d drawing, remember to transform the drawing if we need the X, Y, and Z axes to point in specific directions at the local point.

As the aircraft flies far enough from the origin, the OpenGL axes will shift and new scenery will be loaded.  Do not expect the origin to be in the same place between two frames.  We can detect this by tracking the reference latitude and longitude variables.

Do not position the camera during 3-d drawing.  Use the camera control APIs if we need to change where the viewer is looking.  X-Plane will set up the scale and various matrices based on the field of view the user sets, the camera position, etc.  We can determine the field of view, camera position, and visibility for culling the drawing by using the data access and camera control APIs.

During 2-d drawing, X-Plane is set to render orthographically.  The X axis is left-right with positive X going right and the Y axis is up-down with positive Y going up.  0, 0 is the lower left corner of the screen.  One OpenGL unit is one screen pixel.  We can use the XPLMDisplay APIs to determine the screen size.

X-Plane Textures

X-Plane binds its textures to fixed texture object IDs.  X-Plane does not load all of its textures at startup; some are loaded as needed.  However, X-Plane will only load a finite number of total textures.

If we need to allocate texture object IDs, do not use glTexGen.  OpenGL may allocate texture IDs that X-Plane will use when loading new scenery or airplanes.  Instead, use the routines provided in the graphics API.  These will allocate unused texture IDs that are above the range that X-Plane reserves.

We can also use a series of constants to find the bindings of certain textures loaded by X-Plane.  This allows the use of X-Plane's texture-mapped fonts directly, or window graphics, for example.  But do not assume that any texture besides the main graphics style sheet is loaded.

The graphics API  provides a convenience routine to load textures from .bmp files.

Differences Between X-Plane and GLUT

Running under X-Plane is similar to running under GLUT except for a few differences:

Text In X-Plane

X-Plane uses bitmap images of letters loaded onto textures to render text.  The graphics APIs provide access to these fonts to draw strings.  Currently the strings are monospaced, but they may become proportionally spaced in future versions of the simulator.

We may use different fonts and colors to draw text and can access the measurements of text.

Drawing Callbacks

To draw in X-Plane we register a drawing callback.  The drawing callback is called from the render loop to add the graphics to the simulator.

Using Graphics

Installing a Drawing Callback

To draw in 3-d, register a drawing callback.  The drawing callback will be called during the simulator rendering loop.

< Example code : registering a drawing callback.   Call subroutines below. >

Working with OpenGL State

Use the graphics APIs to setup OpenGL state.  Note: we need to set up OpenGL state whenever the callback is called; the drawing state will not be left as it last was when the callback returned.

< Example code : setting up drawing state >

Working with Textures

Use the graphics APIs to allocate objects for and load the textures when the plugin initializes.

< Example: loading a bitmap. >

In the drawing callback, bind the texture we want to draw with and use XPLMSetGraphicsState to enable or disable texturing.

< Example: setting up the texture. >

Working with Local Coordinates

Use the graphics APIs to convert between latitude/longitude/elevation and local OpenGL coordinates.

< example: drawing a grid using these routines. >

Working with Text

Use the text APIs to draw text.  Text drawing should be done in 2-d windows, not on the 3-d screen.

< Example: text overlay >

Graphics Reference

See the XPLMGraphics documentation for complete graphics reference.