Lecture1 v2
Lecture1 v2
• Non–Real-Time 3D
– Given more processing time, you can generate higher quality 3D
graphics.
– Rendering a single frame for a movie such as Toy Story or
Shrek could take hours on a very fast computer.
A popular OpenGL-based flight
simulator from Flight Gear
3D graphics used for computer-
aided design (CAD)
3D graphics used for architectural
or civil planning
3D graphics used for medical
imaging applications
3D graphics used for scientific
visualization
3D graphics used for entertainment
Shaders
• Graphics cards are no longer dumb rendering chips, but
highly programmable rendering computers
– Note:
In order for someone else on a different machine to run your
application you must include the glut32.dll file with the program.
If they do not have this file in the same directory as your
application or in their C:\Windows\System folder and error will
occur and the program will not run.
YourFirstProgram.c
#include <GL/glut.h>
void RenderScene(void) {
glClear(GL_COLOR_BUFFER_BIT);
glFlush(); // Flush drawing commands
}
• and
• glClear(GL_COLOR_BUFFER_BIT);
• glClear(GL_DEPTH_BUFFER_BIT);
// Check bounds. This is in case the window is made smaller while the rectangle is
//bouncing and the rectangle suddenly finds itself outside the new clipping volume
glMatrixMode(GL_MODELVIEW); glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(800,600);
glutCreateWindow("Bounce");
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
glutTimerFunc(33, TimerFunction, 1);
SetupRC();
glutMainLoop();
return 0;
}
glutTimerFunc
• void glutTimerFunc(unsigned int msecs, void
(*func)(int value), int value);
glEnable(GL_DEPTH_TEST);
...
while (1) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
get_viewing_point_from_mouse_position();
draw_3d_object_A();
draw_3d_object_B(); }
• We want to see only those surfaces in
front of other surfaces
• OpenGL uses a hidden-surface method
called the z-buffer algorithm that saves
depth information as objects are rendered
so that only the front objects appear in the
image
• Z-buffering (depth-buffering) is a visible
surface detection algorithm
• Requires data structure (z-buffer) in
addition to frame buffer.
• Z-buffer stores values [0 .. ZMAX]
corresponding to depth of each point.
• If the point is closer than one in the
buffers, it will replace the buffered values
Z-buffering with front clipping
for (y = 0; y < YMAX; y++)
for (x = 0; x < XMAX; x++) {
F[x][y] = BACKGROUND_VALUE;
Z[x][y] = -1; /* Back value in NPC */
}
for (each polygon)
for (each pixel in polygon’s projection) {
pz = polygon’s z-value at pixel coordinates (x,y)
if (pz < FRONT && pz > Z[x][y]) { /* New point is behind front
plane & closer than previous point */
Z[x][y] = pz;
F[x][y] = polygon’s color at pixel coordinates (x,y)
}}
Using the z-buffer algorithm
1. Requested in main.c
glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB|
GLUT_DEPTH)
2. glEnable(GL_DEPTH_TEST)
3. Cleared in the display callback
glClear(GL_COLOR_BUFFER_BIT|
GL_DEPTH_BUFFER_BIT)
OpenGL Errors
• Internally, OpenGL maintains a set of error flags. Each flag
represents a different type of error. Whenever one of these errors
occurs, the corresponding flag is set. To see whether any of these
flags is set, call glGetError:
– Glenum glGetError(void);
// Rotation amounts
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
z = -50.0f;
for(angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f)
{
//C runtime functions sin() and cos() accept angle values measured in radians
x = 50.0f*sin(angle);
y = 50.0f*cos(angle);
// Restore transformations
glPopMatrix();
return 0;
}
Setting the Point Size
• To control the size of a rendered point, use
glPointSize() and supply the desired size in
pixels as the argument.
glVertex2f(0.0, 0.0);
glVertex2f(0.0, 3.0);
glVertex2f(3.0, 3.0);
glVertex2f(4.0, 1.5);
glVertex2f(3.0, 0.0);
glEnd();
Geometric Primitive Types
Restrictions on Using glBegin()
and glEnd()
• You can also supply additional vertex-specific data for each vertex -
a color, a normal vector, texture coordinates, or any combination of
these - using special commands.
– glColor*( ) set current color
– glIndex*( ) set current color index
– glNormal*( ) set normal vector coordinates
– glEvalCoord*( ) generate coordinates
– glCallList(), glCallLists( ) execute display list(s)
– glTexCoord*( ) set texture coordinates
– glEdgeFlag*( ) control drawing of edges
– glMaterial*( ) set material properties
z = -50.0f;
for(angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f){
x = 50.0f*sin(angle);
y = 50.0f*cos(angle);
// Specify the point and
//move the z value up a little
glVertex3f(x, y, z);
z += 0.5f;
}
// moved up Z axis
// to produce a cone instead of a circle
glVertex3f(0.0f, 0.0f, 75.0f);
// Loop around in a circle and specify even points along the circle
// as the vertices of the triangle fan
for(angle = 0.0f; angle < (2.0f*GL_PI); angle += (GL_PI/8.0f)) {
// Calculate x and y position of the next vertex
x = 50.0f*sin(angle);y = 50.0f*cos(angle);
glVertex2f(x, y); // Specify the next vertex for the triangle fan
}
glBegin(GL_TRIANGLE_FAN);
glVertex2f(x, y); // Specify the next vertex for the triangle fan
}
// Done drawing the Circle
glEnd();
Add Menu
void ProcessMenu(int value) {
switch(value) {
case 1: iDepth = !iDepth; break;
default: break;
}
glutPostRedisplay();
}
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow("Triangle Culling Example");
if(bOutline)
glPolygonMode(GL_BACK,GL_LINE);
else
glPolygonMode(GL_BACK,GL_FILL);
• You should request a depth buffer when you set up your OpenGL window with GLUT.
For example, you can request a color and a depth buffer like this:
• glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
if(bDepth) glEnable(GL_DEPTH_TEST);
else glDisable(GL_DEPTH_TEST);
• With the preceding example and the pattern 0x3F07 (which translates to 0011111100000111
in binary), a line would be drawn with 3 pixels on, then 5 off, 6 on, and 2 off.
• If factor had been 2, the pattern would have been elongated: 6 pixels on, 10 off, 12 on, and 4
off.
A stipple pattern is used to
construct a line segment
void display(void)
{
int i;
glClear (GL_COLOR_BUFFER_BIT);
/* draw all lines in white */
glColor3f (1.0, 1.0, 1.0);
/* in 1st row, 3 lines, each with a different stipple */
glEnable (GL_LINE_STIPPLE);
glLineStipple (1, 0x0101); /* dotted */
drawOneLine (50.0, 125.0, 150.0, 125.0);
glLineStipple (1, 0x00FF); /* dashed */
drawOneLine (150.0, 125.0, 250.0, 125.0);
glLineStipple (1, 0x1C47); /* dash/dot/dash */
drawOneLine (250.0, 125.0, 350.0, 125.0);
void RenderScene(void) {
...
// Begin the stop sign shape,
// use a standard polygon for simplicity
glBegin(GL_POLYGON);
glVertex2f(-20.0f, 50.0f);
glVertex2f(20.0f, 50.0f);
glVertex2f(50.0f, 20.0f);
glVertex2f(50.0f, -20.0f);
glVertex2f(20.0f, -50.0f);
glVertex2f(-20.0f, -50.0f);
glVertex2f(-50.0f, -20.0f);
glVertex2f(-50.0f, 20.0f);
glEnd();
...
glutSwapBuffers ();
}
Polygon Construction Rules
• When you are using many polygons to
construct a complex surface, you need to
remember two important rules:
– The first rule is that all polygons must be
planar. That is, all the vertices of the polygon
must lie in a single plane
• Here is yet another good reason to use triangles.
• The second rule of polygon construction is
that the polygon’s edges must not
intersect, and the polygon must be
convex.
– If any given line enters and leaves the
polygon more than once, the polygon is not
convex.
• Even though OpenGL can draw only
convex polygons, there’s still a way to
create a nonconvex polygon: by arranging
two or more convex polygons together.
Polygons as Points, Outlines, or Solids
For example, you can have the front faces filled and the
back faces outlined with two calls to this routine:
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_LINE);
Culling Polygon Faces
• By convention, polygons whose vertices appear in
counterclockwise (CCW) order on the screen are called
front-facing.
• You can swap what OpenGL considers the back face by
using the function void glFrontFace(GLenum mode);
• By default, mode is GL_CCW. If mode is GL_CW, faces
with a clockwise orientation are considered front-facing.
• In a completely enclosed surface constructed from
polygons with a consistent orientation, none of the back-
facing polygons are ever visible. You can maximize
drawing speed by having OpenGL discard polygons as
soon as it determines that they're back-facing.
• Similarly, if you are inside the object, only back-facing
polygons are visible.
• To instruct OpenGL to discard front- or back-
facing polygons, use the command
glCullFace(GLenum mode); and enable culling
with glEnable().
• Indicates which polygons should be discarded
(culled) before they're converted to screen
coordinates.
• The mode is either GL_FRONT, GL_BACK, or
GL_FRONT_AND_BACK
• Culling must be enabled using glEnable() with
GL_CULL_FACE; it can be disabled with
glDisable() and the same argument.
Marking Polygon Boundary Edges
glBegin (GL_POLYGON);
glNormal3fv(n0);
glVertex3fv(v0);
glNormal3fv(n1);
glVertex3fv(v1);
glNormal3fv(n2);
glVertex3fv(v2);
glNormal3fv(n3);
glVertex3fv(v3);
glEnd();
Calculating Normal Vectors
sin_theta = z/r;
cos_theta = sqrt(1-sin_theta*sin_theta);
//C runtime functions sin() and cos() accept angle values measured in radians
x = r*sin(angle)*cos_theta;
y = r*cos(angle)*cos_theta;
angle += 0.1f;
// Specify the point and move the Z value up a little
glVertex3f(x, y, z);
}
// Done drawing points
glEnd();