Você está na página 1de 46

15-462 Computer Graphics I Lecture 8

Shading in OpenGL
Polygonal Shading Light Source in OpenGL Material Properties in OpenGL Normal Vectors in OpenGL Approximating a Sphere [Angel 6.5-6.9]

September 23, 2003 Doug James Carnegie Mellon University

Polygonal Shading
Curved surfaces are approximated by polygons How do we shade?
Flat shading Interpolative shading Gouraud shading Phong shading (different from Phong illumination)

Two questions:
How do we determine normals at vertices? How do we calculate shading at interior points?

09/23/2003

15-462 Graphics I

Flat Shading
Normal: given explicitly before vertex
glNormal3f(nx, ny, nz); glVertex3f(x, y, z);

Shading constant across polygon Single polygon: first vertex Triangle strip:Vertex n+2 for triangle n

09/23/2003

15-462 Graphics I

Flat Shading Assessment


Inexpensive to compute Appropriate for objects with flat faces Less pleasant for smooth surfaces

09/23/2003

15-462 Graphics I

Flat Shading and Perception


Lateral inhibition: exaggerates perceived intensity Mach bands: perceived stripes along edges

09/23/2003

15-462 Graphics I

09/23/2003

15-462 Graphics I

09/23/2003

15-462 Graphics I

Interpolative Shading
Enable with glShadeModel(GL_SMOOTH); Calculate color at each vertex Interpolate color in interior Compute during scan conversion (rasterization) Much better image (see Assignment 1) More expensive to calculate

09/23/2003

15-462 Graphics I

Gouraud Shading
Special case of interpolative shading How do we calculate vertex normals? Gouraud: average all adjacent face normals

Requires knowledge about which faces share a vertexadjacency info

09/23/2003

15-462 Graphics I

Data Structures for Gouraud Shading


Sometimes vertex normals can be computed directly (e.g. height field with uniform mesh) More generally, need data structure for mesh Key: which polygons meet at each vertex

09/23/2003

15-462 Graphics I

10

Phong Shading
Interpolate normals rather than colors Significantly more expensive Mostly done off-line (not supported in OpenGL)

09/23/2003

15-462 Graphics I

11

Phong Shading Results


Michael Gold, Nvidia

Single pass Phong Lighting Gouraud Shading


09/23/2003

Two pass Phong Lighting, Gouraud Shading


15-462 Graphics I

Two pass Phong Lighting, Phong Shading


12

Polygonal Shading Summary


Gouraud shading
Set vertex normals Calculate colors at vertices Interpolate colors across polygon

Must calculate vertex normals! Must normalize vertex normals to unit length!

09/23/2003

15-462 Graphics I

13

Outline
Polygonal Shading Light Sources in OpenGL Material Properties in OpenGL Normal Vectors in OpenGL Example: Approximating a Sphere

09/23/2003

15-462 Graphics I

14

Enabling Lighting and Lights


Lighting in general must be enabled
glEnable(GL_LIGHTING);

Each individual light must be enabled


glEnable(GL_LIGHT0);

OpenGL supports at least 8 light sources

09/23/2003

15-462 Graphics I

15

Global Ambient Light


Set ambient intensity for entire scene
GLfloat al[] = {0.2, 0.2, 0.2, 1.0}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, al);

The above is default

Also: local vs infinite viewer


glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

More expensive, but sometimes more accurate

Angel Typo: (p.296)


glLightModeli(GL_LIGHT_MODEL_TWO_SIDED, GL_TRUE)

09/23/2003

15-462 Graphics I

16

Defining a Light Source


Use vectors {r, g, b, a} for light properties Beware: light source will be transformed!
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[] = {1.0, 1.0, 1.0, 1.0}; GLfloat light_position[] = {-1.0, 1.0, -1.0, 0.0}; glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT0, GL_POSITION, light_position);

09/23/2003

15-462 Graphics I

17

Point Source vs Directional Source


Directional light given by position vector
GLfloat light_position[] = {-1.0, 1.0, -1.0, 0.0}; glLightfv(GL_LIGHT0, GL_POSITION, light_position);

Point source given by position point


GLfloat light_position[] = {-1.0, 1.0, -1.0, 1.0}; glLightfv(GL_LIGHT0, GL_POSITION, light_position);

09/23/2003

15-462 Graphics I

18

Spotlights
Create point source as before Specify additional properties to create spotlight
GLfloat sd[] = {-1.0, -1.0, 0.0}; glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, sd); glLightf (GL_LIGHT0, GL_SPOT_CUTOFF, 45.0); glLightf (GL_LIGHT0, GL_SPOT_EXPONENT, 2.0);

[Demo: Lighting Position Tutor]


09/23/2003 15-462 Graphics I 19

Outline
Polygonal Shading Light Sources in OpenGL Material Properties in OpenGL Normal Vectors in OpenGL Example: Approximating a Sphere

09/23/2003

15-462 Graphics I

20

Defining Material Properties


Material properties stay in effect Set both specular coefficients and shininess
GLfloat mat_a[] = {0.1, 0.5, 0.8, 1.0}; GLfloat mat_d[] = {0.1, 0.5, 0.8, 1.0}; GLfloat mat_s[] = {1.0, 1.0, 1.0, 1.0}; GLfloat low_sh[] = {5.0}; 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);

Diffuse component is analogous [Demo: Light material Tutor]


09/23/2003 15-462 Graphics I 21

GL_COLOR_MATERIAL Mode
Can shortcut material properties using glColor Must be explicitly enabled and disabled
glEnable(GL_COLOR_MATERIAL);
/* affect front face, diffuse reflection properties */

glColorMaterial(GL_FRONT, 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);

E.g., highlighting picked faces


09/23/2003 15-462 Graphics I 22

Outline
Polygonal Shading Light Sources in OpenGL Material Properties in OpenGL Normal Vectors in OpenGL Example: Approximating a Sphere

09/23/2003

15-462 Graphics I

23

Defining and Maintaining Normals


Define unit normal before each vertex
glNormal3f(nx, ny, nz); glVertex3f(x, y, z);

Length changes under some transformations Ask OpenGL to re-normalize (all tfms)
glEnable(GL_NORMALIZE);

Ask OpenGL to re-scale normal


glEnable(GL_RESCALE_NORMAL);

Works for uniform scaling (and rotate, translate)


09/23/2003 15-462 Graphics I 24

Example: Icosahedron
Define the vertices
#define X .525731112119133606 #define Z .850650808352039932 static GLfloat vdata[12][3] = { {-X, 0, Z}, {X, 0, Z}, {-X, 0, -Z}, {X, 0, -Z}, {0, Z, X}, {0, Z, -X}, {0, -Z, X}, {0, -Z, -X}, {Z, X, 0}, {-Z, X, 0}, {Z, -X, 0}, {-Z, -X, 0} };

For simplicity, avoid the use of vertex arrays

09/23/2003

15-462 Graphics I

25

Defining the Faces


Index into vertex data array
static GLuint tindices[20][3] = {1,4,0}, {4,9,0}, {4,9,5}, {1,10,8}, {10,3,8}, {8,3,5}, {3,10,7}, {10,6,7}, {6,11,7}, {10,1,6}, {11,0,9}, {2,11,9}, }; { {8,5,4}, {3,2,5}, {6,0,11}, {5,2,9}, {1,8,4}, {3,7,2}, {6,1,0}, {11,2,7}

Be careful about orientation!

09/23/2003

15-462 Graphics I

26

Drawing the Icosahedron


Normal vector calculation next
glBegin(GL_TRIANGLES); for (i = 0; i < 20; i++) { icoNormVec(i); glVertex3fv(&vdata[tindices[i][0]]); glVertex3fv(&vdata[tindices[i][1]]); glVertex3fv(&vdata[tindices[i][2]]); } glEnd();

Should be encapsulated in display list

09/23/2003

15-462 Graphics I

27

Calculating the Normal Vectors


Normalized cross product of any two sides
GLfloat d1[3], d2[3], n[3]; void icoNormVec (int i) { for (k = 0; k < 3; k++) { d1[k] = vdata[tindices[i][0]] vdata[tindices[i][1]] d2[k] = vdata[tindices[i][1]] vdata[tindices[i][2]] } normCrossProd(d1, d2, n); glNormal3fv(n); }
09/23/2003 15-462 Graphics I

[k] [k]; [k] [k];

28

The Normalized Cross Product


Omit zero-check for brevity
void normalize(float v[3]) { GLfloat d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); v[0] /= d; v[1] /= d; v[2] /= d; } void normCrossProd(float u[3], float v[3], float out[3]) { out[0] = u[1]*v[2] u[2]*v[1]; out[1] = u[2]*v[0] u[0]*v[2]; out[2] = u[0]*v[1] u[1]*v[0]; normalize(out); }
09/23/2003 15-462 Graphics I 29

The Icosahedron
Using simple lighting setup

09/23/2003

15-462 Graphics I

30

Sphere Normals
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();

09/23/2003

15-462 Graphics I

31

Icosahedron with Sphere Normals


Interpolation vs flat shading effect

09/23/2003

15-462 Graphics I

32

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 Approximate sphere by subdividing icosahedron

09/23/2003

15-462 Graphics I

33

Methods of Subdivision
(a) Bisecting angles (b) Computing centroid (c) Bisecting sides

Here: bisect sides to retain regularity


09/23/2003 15-462 Graphics I 34

Teaser: Loop Subdivision

09/23/2003

15-462 Graphics I

35

Sphere Subdivision: Bisection of Sides


Draw if no further subdivision requested
void subdivide(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int depth) { GLfloat v12[3], v23[3], v31[3]; int i; if (depth == 0) { drawTriangle(v1, v2, v3); return; } 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; } ... 09/23/2003 15-462 Graphics I }

36

Sphere Subdivision: Extrusion of Midpoints


Re-normalize midpoints to lie on unit sphere
void subdivide(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int depth) { ... normalize(v12); normalize(v23); normalize(v31); subdivide(v1, v12, v31, depth-1); subdivide(v2, v23, v12, depth-1); subdivide(v3, v31, v23, depth-1); subdivide(v12, v23, v31, depth-1); }
09/23/2003 15-462 Graphics I 37

Sphere Subdivision: Start with Icosahedron


In sample code: control depth with + and -
void display(void) { ... for (i = 0; i < 20; i++) { subdivide(&vdata[tindices[i][0]][0], &vdata[tindices[i][1]][0], &vdata[tindices[i][2]][0], depth); } glFlush(); }

09/23/2003

15-462 Graphics I

38

Icosahedron Unsubdivided

09/23/2003

15-462 Graphics I

39

One Subdivision

09/23/2003

15-462 Graphics I

40

Two Subdivisions
Each time, multiply number of faces by 4

09/23/2003

15-462 Graphics I

41

Three Subdivisions
Reasonable approximation to sphere

09/23/2003

15-462 Graphics I

42

Example Lighting Properties


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);

09/23/2003

15-462 Graphics I

43

Example Material Properties


GLfloat mat_specular[] GLfloat mat_diffuse [] GLfloat mat_ambient [] GLfloat mat_shininess glMaterialfv(GL_FRONT, glMaterialfv(GL_FRONT, glMaterialfv(GL_FRONT, glMaterialf (GL_FRONT, = {0.0, 0.0, 0.0, 1.0}; = {0.8, 0.6, 0.4, 1.0}; = {0.8, 0.6, 0.4, 1.0}; = {20.0}; GL_SPECULAR, mat_specular); GL_AMBIENT, mat_ambient); GL_DIFFUSE, mat_diffuse); GL_SHININESS, mat_shininess);

glShadeModel(GL_SMOOTH); /* enable smooth shading */ glEnable(GL_LIGHTING); /* enable lighting */ glEnable(GL_LIGHT0); /* enable light #0 */

09/23/2003

15-462 Graphics I

44

Summary
Polygonal Shading Light Sources in OpenGL Material Properties in OpenGL Normal Vectors in OpenGL Example: Approximating a Sphere

09/23/2003

15-462 Graphics I

45

Preview
Either
Basic texture mapping Curves and surfaces

09/23/2003

15-462 Graphics I

46

Você também pode gostar