This module implements a trivial framework for OpenGL demonstration. It is appropriate for the interactive presentation of rendering techniques and animations, but provides few facilities for mapping user input onto application control. A demo implementation using this module need only provide a function to perform rendering and, optionally, functions for setup, shutdown, and animation.
The module maintains several pieces of internal state including the position, orientation, and zoom value of the camera, and the direction toward the primary light source. Upon rendering, the camera zoom is loaded into the OpenGL projection matrix, the position and orientation are loaded into the OpenGL model-view matrix, the primary light source direction is loaded into
GL_LIGHT0, and the mouse pointer vector is loaded into
The demo module is implemented using GLUT, and applications are free to co-opt any GLUT features not used internally. Notably, this includes GLUT's menu functions, which applications may use for interactive feature selection and configuration.
cc -o program program.c demo.c image.c -lpng -lz -lm
int demo(int mode, int argc, char **argv, demo_init_f init, demo_tilt_f tilt, demo_quit_f quit, demo_draw_f draw, demo_step_f step)
The demo API consists of one primary entry point that receives pointers to all pertainant information. This function initializes the OpenGL context and executes the main application loop, calling the provided functions as needed. It does not return until the application is closed. Any of the function arguments may be
NULLto disable the related callback. The arguments are as follows:
This argument selects the application's control style, determining how keyboard and mouse events map onto view state. In general:
- Mouse drag maps onto camera orientation.
- Shift-drag maps onto camera zoom.
- Alt-drag maps onto light source direction.
- The keyboard maps onto camera position in the traditional first-person style.
However, the meaning of the camera position and orientation depends upon the selected mode. The following modes are defined:
The camera is locked in place.
The camera zooms and moves forward or back, but does not rotate.
The camera zooms and moves normally, and rotates with an inward-looking object tumble.
The camera zooms and moves normally, and rotates with an outward-looking first-person view.
int argc, char **argv
These arguments should receive the command line argument count and array as passed to the C or C++
mainfunction. This allows options to be passed to GLUT, most notably to control window position and size.
int (*demo_init_f)(int argc, char **argv)
initfunction is called after the OpenGL context is created, but before the application main loop begins. This provides an opportunity for the application to initialize any necessary OpenGL state. The
argvarguments give the command line arguments remaining after GLUT has finished processing the values passed to
demo. All arguments left by GLUT remain for use by the application.
tiltfunction is called when the user presses the "tilt" key. If needed, applications should respond by flushing and reloading all OpenGL resources. This allows changes to be made to assets without requiring that the entire demo state be reset. For example, the user may modify a shader or texture, save it to disk, and reload it in the demo application without disturbing the current view state.
quitfunction is called just prior to application exit. It provides an opportunity to release resources and store state as needed.
drawfunction is called each time the display is repainted. Applications should perform rendering here, but should not swap buffers, as the
demomodule does this as part of the performance monitoring mechanism.
void (*demo_step_f)(float dt)
stepfunction is called as often as possible, usually whenever there are no other events to be serviced. The
dtargument gives the amount of time passed in seconds since the previous call. Applications may use this value to update time-varying values and animations. Applications need not request a repaint of the display, as this is automatic due to the free-running nature of all demos.
const GLfloat *demo_get(int token)
demo_getfunction allows the application to query the internal state of the demo. Values are returned as a pointer to an array of floats. Valid
tokenvalues and their meanings are as follows:
The current world-space position (x, y, z) of the camera.
The current orientation (φ, θ) of the camera.
The current orientation (φ, θ) of the light source.
The current eye-space vector (x, y, z) of the mouse pointer.
The current zoom value of the camera.
void demo_clear(const GLfloat *top, const GLfloat *bottom)
demo_clearfunction clears the screen using a linear gradient from
bottom. If the underlying hardware supports programmable fragment shading then an ordered dither is applied in an effort to smooth the gradient across high-resolution or low bit depth displays.
If the environment variable
DEMO_STATE is defined at startup then the
demo module will load camera and light source state from the file named there, if it exists. It will also store camera and light source state to that file upon normal exit.
The following keys are bound, though their effect is limited to specific modes:
|Tab||"Tilt" the application, triggering a reload of assets.|
|Return||Capture a screenshot and write it to the file `out.png`.|
|Escape||Exit the demo.|
Dvorak equivalents for all keys are simultaneously bound, without conflict. Screenshots are written in 8-bit RGBA format, with the alpha channel masking the color buffer as rendered.