- 1 Graphics In X-Plane
- 1.1 About Graphics
- 1.2 X-Plane's Graphics Environment and Architecture
- 1.3 Text In X-Plane
- 1.4 Drawing Callbacks
- 1.5 Using Graphics
- 1.6 Installing a Drawing Callback
- 1.7 Working with OpenGL State
- 1.8 Working with Textures
- 1.9 Working with Local Coordinates
- 1.10 Working with Text
- 1.11 Graphics Reference
Graphics In X-Plane
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:
- Fog - Fog may be enabled or disabled depending on the drawing. During 3-d rendering fog is set up to cause a fade-to-fog effect at the visibility limit.
- Lighting - Lighting may be disabled or enabled. OpenGL sets up one light during 3-d rendering for the sun.
- Alpha Testing - We may enable or disable the alpha test. The alpha test stops pixels from being rendered to the frame buffer if their alpha is zero.
- Alpha Blending - We may enable or disable alpha blending. Alpha blending causes pixels to be blended with what is already in the frame buffer based on their alpha value. Note two limitations of blending vs testing:
- Blending always writes a pixel to the buffer even if its alpha is zero.
- Also, alpha blending can decrease frame rate since some cards have limited alpha blended pixel fill rate.
- Depth Testing - We may enable or disable a test for depth. If depth testing is on, the geometry will be tested against the depth buffer, which is useful for drawing in the 3-d world.
- Depth Writing - We may enable or disable write-back to the depth buffer. If we are rendering multiple polygons on top of each other at the same location, we may want to disable write-back of texturing to keep from thrashing the Z buffer.
Attribute OpenGL Settings Typical State during Typical State during 3D Drawing 2D 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
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 south. 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 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:
- The screen is redrawn perpetually; there is no need to schedule this.
- OpenGL state is managed and set by the simulator.
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.
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.
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 >
See the XPLMGraphics documentation for complete graphics reference.