OpenGL State
GL rendering consists of geometry + state
Both are passed to graphics hardware via function calls
To draw something, the necessary state attributes (e.g. color) are set first
Then, the geometry (e.g. triangle data) is passed
State is retained until changed
State changes do not affect any geometry already drawn
OpenGL State
State includes:
- Color
- Drawing style
- Material properties
- Light sources
- Texture
- Transformations
Example:
glColor3f(1, 1, 0) # Set current color
glBegin(GL_TRIANGLES)
glVertex2f(0.0, 0.0) # This triangle is yellow
glVertex2f(0.4, 0.0)
glVertex2f(0.8, 0.8)
glColor3f(1, 0, 1) # Change current color
glVertex2f(0.0, 0.0) # This triangle is magenta
glVertex2f(-0.4, 0.0)
glVertex2f(-0.8, -0.8)
glEnd()
Flicker
Signal from rods & cones to brain is smoothed - there is a several millisecond
ramp-in or out after light hits or stops hitting the rod/cone.
Light flashing at > ~60 Hz appears to be continuous.
Called the Critical Flicker Frequency (CFF)
Below the CFF, flashing is perceptible
~ 45 Hz is usually good enough -> film flickers at 48 Hz; PAL TV at 50 Hz; NTSC TV at 60 Hz
Animation
Illusion of motion produced by rapidly displaying still frames that change
Does not need to be at CFF
Animation frame rate can be independent of video display frequency
Traditional animation often works at 12 frames per second.
But faster rates will yield smoother motion.
Below ~ 10 fps, animation looks like a slide show, rather than motion
GLUT Timers
Animation in OpenGL is achieved by calling the "Display" function repeatedly,
drawing a single frame each time.
In GLUT, this requires calling glutPostRedisplay() regularly.
An "Update" function is also typically used, to compute changes for each frame.
Use GLUT timers to call functions at a fixed rate:
def update(v):
glutTimerFunc(16, update, 0) # Schedule a new call in 16 ms,
# yielding 60 fps
newposition = moveObject()
# etc.
glutPostRedisplay()
glutTimerFunc(0, update, 0) # Schedule the first "update" call
Frame Buffer
The frame buffer is a chunk of graphics card memory that contains what is displayed on the screen.
Like an image, but for each pixel there can be additional data besides color - depth, masking, etc.
OpenGL renders shapes, images, etc. into pixels of the frame buffer.
rasterizing it - converting it into raster form in the frame buffer.
Double Buffering
Double-buffering hides the image being drawn until it is finished.
The previously completed image is displayed while the new one is drawn.
The frame buffer is split into two buffers - front buffer (displayed) and back buffer (drawn into).
Useful for smooth animation.
Double Buffering
Double Buffering
To use double-buffering:
Pass GLUT_DOUBLE flag to glutInitDisplayMode, instead of GLUT_SINGLE
Call glutSwapBuffers() at end of frame (replaces glFlush())
def draw():
glClear(GL_COLOR_BUFFER_BIT)
...
glutSwapBuffers()
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
In-class Exercise
Write a program that animates a bouncing triangle.
If you have time, enhance it - add multiple triangles, allow the user to
change the speed by hitting keys, etc.
This document is by Dave Pape, and is released under a Creative Commons BY-2.0 License.