Outline
CSCI 420 Computer Graphics
Lecture 10 • Normal Vectors in OpenGL
• Polygonal Shading
Shading in OpenGL • Light Sources in OpenGL
• Material Properties in OpenGL
Normal Vectors in OpenGL • Example: Approximating a Sphere
Polygonal Shading
Light Source in OpenGL
Material Properties in OpenGL
Approximating a Sphere
[Angel Ch. 6.5-6.9]
Jernej Barbic
University of Southern California
1 2
Defining and Maintaining Normals Normalization
• Define unit normal before each vertex • Length of normals changes under some
modelview transformations (but not under
translations and rotations)
glNormal3f(nx, ny, nz); glNormal3f(nx1, ny1, nz1); • Ask OpenGL to automatically re-normalize
glVertex3f(x1, y1, z1); glVertex3f(x1, y1, z1);
glVertex3f(x2, y2, z2); glNormal3f(nx2, ny2, nz2); glEnable(GL_NORMALIZE);
glVertex3f(x3, y3, z3); glVertex3f(x2, y2, z2);
glNormal3f(nx3, ny3, nz3); • Faster alternative (works only with translate,
same normal glVertex3f(x3, y3, z3); rotate and uniform scaling)
for all vertices
different normals glEnable(GL_RESCALE_NORMAL);
3 4
Outline Enabling Lighting and Lights
• Normal Vectors in OpenGL • Lighting “master switch” must be enabled:
• Light Sources in OpenGL glEnable(GL_LIGHTING);
• Material Properties in OpenGL • Each individual light must be enabled:
• Polygonal Shading
• Example: Approximating a Sphere glEnable(GL_LIGHT0);
• OpenGL supports at least 8 light sources
5 6
1
What Determines Vertex Color in OpenGL Reminder: Phong Lighting
Is OpenGL lighting enabled? • Light components for each color:
– Ambient (La), diffuse (Ld), specular (Ls)
NO YES • Material coefficients for each color:
– Ambient (ka), diffuse (kd), specular (ks)
• Distance q for surface point from light source
Color determined Color determined by
by glColor3f(...) Phong lighting which uses:
Ignored: • normals
• normals • lights l = unit vector to light r = l reflected about n
• lights • material properties n = surface normal v = vector to viewer
• material properties
See also: http://www.sjbaker.org/steve/omniv/opengl_lighting.html 7 8
Global Ambient Light Defining a Light Source
• Set ambient intensity for entire scene • Use vectors {r, g, b, a} for light properties
GLfloat al[] = {0.2, 0.2, 0.2, 1.0}; • Beware: light positions will be transformed by
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, al); the modelview matrix
• The above is default GLfloat light_ambient[] = {0.2, 0.2, 0.2, 1.0};
• Also: local vs infinite viewer GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0};
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,
GLfloat light_position[] = {-1.0, 1.0, -1.0, 0.0};
GL_TRUE);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
– Local viewer: Correct specular highlights glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
• More expensive, but sometimes more accurate glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
– Non-local viewer: Assumes camera is far from object glLightfv(GL_LIGHT0, GL_POSITION, light_position);
• Approximate, but faster (this is default)
9 10
Point Source vs Directional Source Spotlights
• Directional light given by “position” vector • Create point source as before
GLfloat light_position[] = {-1.0, 1.0, -1.0, 0.0}; • Specify additional properties to create spotlight
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
GLfloat sd[] = {-1.0, -1.0, 0.0};
• Point source given by “position” point glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, sd);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0);
GLfloat light_position[] = {-1.0, 1.0, -1.0, 1.0}; glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
11 12
2
Outline Defining Material Properties
• Normal Vectors in OpenGL
GLfloat mat_a[] = {0.1, 0.5, 0.8, 1.0};
• Light Sources in OpenGL
GLfloat mat_d[] = {0.1, 0.5, 0.8, 1.0};
• Material Properties in OpenGL GLfloat mat_s[] = {1.0, 1.0, 1.0, 1.0};
• Polygonal Shading GLfloat low_sh[] = {5.0};
• Example: Approximating a Sphere glMaterialfv(GL_FRONT, GL_AMBIENT, mat_a);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_d);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_s);
glMaterialfv(GL_FRONT, GL_SHININESS, low_sh);
OpenGL is a state machine:
material properties stay in effect until changed.
13 14
Color Material Mode Outline
• Alternative way to specify material properties • Normal Vectors in OpenGL
• Uses glColor • Light Sources in OpenGL
• Must be explicitly enabled and disabled • Material Properties in OpenGL
• Polygonal Shading
glEnable(GL_COLOR_MATERIAL); • Example: Approximating a Sphere
/* affect all faces, diffuse reflection properties */
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glColor3f(0.0, 0.0, 0.8);
/* draw some objects here in blue */
glColor3f(1.0, 0.0, 0.0);
/* draw some objects here in red */
glDisable(GL_COLOR_MATERIAL);
15 16
Polygonal Shading Polygonal Shading
• Now we know vertex colors • Curved surfaces are approximated by polygons
– either via OpenGL lighting,
– or by setting directly via glColor3f if lighting disabled • How do we shade?
– Flat shading
• How do we shade the interior of the triangle ? – Interpolative shading
– Gouraud shading
– Phong shading (different from Phong illumination!)
17 18
3
Flat Shading Flat Shading Assessment
• Enable with glShadeModel(GL_FLAT); • Inexpensive to compute
• Shading constant across polygon • Appropriate for objects with flat faces
• Color of last vertex determines interior color • Less pleasant for smooth surfaces
• Only suitable for very small polygons
v2
v0 v1
19 20
Interpolative Shading Gouraud Shading
Invented by Henri Gouraud, Univ. of Utah, 1971
• Enable with glShadeModel(GL_SMOOTH); • Special case of interpolative shading
• How do we calculate vertex normals for a polygonal
• Interpolate color in interior surface? Gouraud:
• Computed during scan conversion (rasterization) 1. average all adjacent face normals
• Much better than flat shading
• More expensive to calculate
(but not a problem for modern graphics cards)
2. use n for Phong lighting
3. interpolate vertex colors
into the interior
• Requires knowledge about
which faces share a vertex
21 22
Data Structures for Gouraud Shading Phong Shading (“per-pixel lighting”)
Invented by Bui Tuong Phong, Univ. of Utah, 1973"
• Sometimes vertex normals can be computed • At each pixel (as opposed to at each vertex) :
directly (e.g. height field with uniform mesh) 1. Interpolate normals (rather than colors)
• More generally, need data structure for mesh 2. Apply Phong lighting to the interpolated normal
• Key: which polygons meet at each vertex
• Significantly more expensive
• Done off-line or in GPU
shaders (not supported
in OpenGL directly)
23 24
4
Phong Shading Results Polygonal Shading Summary
• Gouraud shading
Michael Gold, Nvidia – Set vertex normals
– Calculate colors at vertices
– Interpolate colors across polygon
• Must calculate vertex normals!
• Must normalize vertex normals to unit length!
Single light Two lights Two lights
Phong Lighting Phong Lighting Phong Lighting
Gouraud Shading Gouraud Shading Phong Shading
25 26
Outline Example: Icosahedron
• Normal Vectors in OpenGL • Define the vertices
• Light Sources in OpenGL #define X .525731112119133606
• Material Properties in OpenGL #define Z .850650808352039932
• Polygonal Shading
• Example: Approximating a Sphere static GLfloat vdata[12][3] = {
{-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z},
{0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
{Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}
};
• For simplicity, this example avoids the use of
vertex arrays
27 28
Defining the Faces Drawing the Icosahedron
• Index into vertex data array • Normal vector calculation next
static GLuint tindices[20][3] = { glBegin(GL_TRIANGLES);
{1,4,0}, {4,9,0}, {4,9,5}, {8,5,4}, {1,8,4}, for (i = 0; i < 20; i++) {
{1,10,8}, {10,3,8}, {8,3,5}, {3,2,5}, {3,7,2}, icoNormVec(i);
{3,10,7}, {10,6,7}, {6,11,7}, {6,0,11}, {6,1,0}, glVertex3fv(&vdata[tindices[i][0]] [0]);
{10,1,6}, {11,0,9}, {2,11,9}, {5,2,9}, {11,2,7} glVertex3fv(&vdata[tindices[i][1]] [0]);
}; glVertex3fv(&vdata[tindices[i][2]] [0]);
}
• Be careful about orientation! glEnd();
• Should be encapsulated in display list
29 30
5
Calculating the Normal Vectors The Normalized Cross Product
• Normalized cross product of any two sides • Omit zero-check for brevity
GLfloat d1[3], d2[3], n[3]; void normalize(float v[3]) {
GLfloat d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
void icoNormVec (int i) { v[0] /= d; v[1] /= d; v[2] /= d;
for (k = 0; k < 3; k++) { }
d1[k] = vdata[tindices[i][0]] [k] – vdata[tindices[i][1]] [k];
d2[k] = vdata[tindices[i][1]] [k] – vdata[tindices[i][2]] [k]; void normCrossProd(float u[3], float v[3], float out[3]) {
} out[0] = u[1]*v[2] – u[2]*v[1];
normCrossProd(d1, d2, n); out[1] = u[2]*v[0] – u[0]*v[2];
glNormal3fv(n); out[2] = u[0]*v[1] – u[1]*v[0];
} normalize(out);
}
31 32
The Icosahedron Sphere Normals
• Using simple lighting setup • Set up instead to use normals of sphere
• Unit sphere normal is exactly sphere point
glBegin(GL_TRIANGLES);
for (i = 0; i < 20; i++) {
glNormal3fv(&vdata[tindices[i][0]][0]);
glVertex3fv(&vdata[tindices[i][0]][0]);
glNormal3fv(&vdata[tindices[i][1]][0]);
glVertex3fv(&vdata[tindices[i][1]][0]);
glNormal3fv(&vdata[tindices[i][2]][0]);
glVertex3fv(&vdata[tindices[i][2]][0]);
}
glEnd();
33 34
Icosahedron with Sphere Normals Recursive Subdivision
• General method for building approximations
• Research topic: construct a good mesh
– Low curvature, fewer mesh points
– High curvature, more mesh points
– Stop subdivision based on resolution
– Some advanced data structures for animation
– Interaction with textures
• Here: simplest case
flat shading interpolation
• Approximate sphere by subdividing
icosahedron
35 36
6
Methods of Subdivision Bisection of Sides
• Bisecting angles • Draw if no further subdivision requested
• Computing center void subdivide(GLfloat v1[3], GLfloat v2[3],
• Bisecting sides GLfloat v3[3], int depth)
{ GLfloat v12[3], v23[3], v31[3]; int i;
if (depth == 0) { drawTriangle(v1, v2, v3); }
for (i = 0; i < 3; i++) {
v12[i] = (v1[i]+v2[i])/2.0;
v23[i] = (v2[i]+v3[i])/2.0;
v31[i] = (v3[i]+v1[i])/2.0;
}
...
• Here: bisect sides to retain regularity
37 38
Extrusion of Midpoints Start with Icosahedron
• Re-normalize midpoints to lie on unit sphere • In sample code: control depth with ‘+’ and ‘-’
void subdivide(GLfloat v1[3], GLfloat v2[3], void display(void)
GLfloat v3[3], int depth) { ...
{ ... for (i = 0; i < 20; i++) {
normalize(v12); subdivide(&vdata[tindices[i][0]][0],
normalize(v23); &vdata[tindices[i][1]][0],
normalize(v31); &vdata[tindices[i][2]][0],
subdivide(v1, v12, v31, depth-1); depth);
subdivide(v2, v23, v12, depth-1); }
subdivide(v3, v31, v23, depth-1); glFlush();
subdivide(v12, v23, v31, depth-1); }
}
39 40
One Subdivision Two Subdivisions
• Each time, multiply number of faces by 4
flat shading interpolation flat shading interpolation
41 42
7
Three Subdivisions Example Lighting Properties
• Reasonable approximation to sphere
GLfloat light_ambient[]={0.2, 0.2, 0.2, 1.0};
GLfloat light_diffuse[]={1.0, 1.0, 1.0, 1.0};
GLfloat light_specular[]={0.0, 0.0, 0.0, 1.0};
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
flat shading interpolation
43 44
Example Material Properties Summary
GLfloat mat_specular[]={0.0, 0.0, 0.0, 1.0}; • Normal Vectors in OpenGL
GLfloat mat_diffuse[]={0.8, 0.6, 0.4, 1.0}; • Polygonal Shading
GLfloat mat_ambient[]={0.8, 0.6, 0.4, 1.0}; • Light Sources in OpenGL
GLfloat mat_shininess={20.0}; • Material Properties in OpenGL
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); • Example: Approximating a Sphere
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess);
glShadeModel(GL_SMOOTH); /*enable smooth shading */
glEnable(GL_LIGHTING); /* enable lighting */
glEnable(GL_LIGHT0); /* enable light 0 */
45 46