Fractals - e.g. the Mandelbrot set
Karl Sims - artificial evolution of mathematical formulas
(round (log (+ y (color-grad (round (+ (abs (round (log (+ y (color-grad (round (+ y (log (invert y) 15.5)) x) 3.1 1.86 #(0.95 0.7 0.59) 1.35)) 0.19) x)) (log (invert y) 15.5)) x) 3.1 1.9 #(0.95 0.7 0.35) 1.35)) 0.19) x)
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 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.
To use double-buffering:
def draw(): glClear(GL_COLOR_BUFFER_BIT) ... glutSwapBuffers() glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
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
State includes:
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()
OpenGL includes functions to draw points, lines, and polygons.
All other shapes are made up of these elements.
A basic shape is entirely described by its vertices, which are connected by straight edges.
The graphics hardware fills in all the necessary pixels.
The basic method for drawing a shape is:
glBegin(...) glVertex(...) glVertex(...) glVertex(...) ... glEnd()
Always be sure to have a matching glEnd() for each glBegin()
GL_POINTS | GL_LINES | GL_LINE_STRIP | GL_LINE_LOOP |
---|---|---|---|
GL_TRIANGLES | GL_TRIANGLE_STRIP | GL_TRIANGLE_FAN | |
GL_QUADS | GL_QUAD_STRIP | GL_POLYGON | |
glColor3f(1, 0.5, 0) glBegin(GL_TRIANGLES) glVertex2f(0, 0) glVertex2f(1, 0) glVertex2f(0.5, 0.5) glEnd()
A coordinate system is needed for measuring objects' positions
It allows us to describe any location by a set of numbers - 2 numbers when working in 2 dimensions, 3 numbers for 3 dimensions.
A coordinate system has an origin (a reference point) and coordinate axes
In 2D we have an X axis and a Y axis. In 3D, we add a Z axis.
The axes are perpendicular - they are independent
Some coordinate systems used:
Drawing commands that specify locations:
The default drawing coordinate system can be changed with the function gluOrtho2D
e.g.:
glMatrixMode(GL_PROJECTION) glLoadIdentity() gluOrtho2D(0.0, 10.0, 0.0, 5.0) glMatrixMode(GL_MODELVIEW)
gluOrtho2D is typically used either in the drawing function, or in GLUT's reshape callback.
The reshape callback is called whenever the window changes size.
e.g., to make the window always span -10 to +10 in X, while keeping the aspect ratio 1:1, the coordinate range in Y will depend on the window size:
def reshape(w, h): glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluOrtho2D(-10.0, 10.0, -10.0*h/w, 10.0*h/w) glMatrixMode(GL_MODELVIEW) glutReshapeFunc(reshape)