590 likes | 636 Views
Lighting. Mathematics of Lighting. light.c. #include <GL/glut.h> void init(void) { GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 50.0 }; GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; glClearColor (0.0, 0.0, 0.0, 0.0);
E N D
light.c #include <GL/glut.h> void init(void) { GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 50.0 }; GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); }
void display(void) { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glutSolidSphere (1.0, 20, 16); glFlush (); }
void reshape (int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode (GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0); else glOrtho (-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoop(); return 0; }
The total color from all lighting color = color_from_light0 + color_from_light1 + color_from_light2 + ... + material_ambient * lightmodel_ambient + material_emission
Global Ambient Light • GLfloat lmodel_ambient[ ]= { 0.2, 0.2, 0.2, 1.0 }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); • In this example, the values used for lmodel_ambient are the default values for GL_LIGHT_MODEL_AMBIENT. • Since these numbers yield a small amount of white ambient light, even if you don't add a specific light source to your scene, you can still see the objects in the scene. • GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 }; glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
Material emission • By specifying an RGBA color for GL_EMISSION, you can make an object appear to be giving off light of that color. • you'll probably use this feature mostly to simulate lamps and other light sources in a scene. GLfloat mat_emission[] = {0.3, 0.2, 0.2, 0.0}; glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
Enabling Lighting • With OpenGL, you need to explicitly enable (or disable) lighting. If lighting isn't enabled, the current color is simply mapped onto the current vertex • glEnable(GL_LIGHTING); • glDisable(GL_LIGHTING); • You also need to explicitly enable each light source that you define • glEnable(GL_LIGHT0); • GL_LIGHT0, GL_LIGHT1, ... , or GL_LIGHT7
The total color from a single light color = attenuation factor * spotlight effect * ( diffuse * material_diffuse * light_diffuse + specular * material_specular * light_specular + material_ambient * light_ambient )
Directional and Positional lights • directional light source; • infinite location is that the rays of light can be considered parallel by the time they reach an object. • An example of a real-world directional light source is the sun. • positional light source, since its exact position within the scene determines the effect it has on a scene and, specifically, the direction from which the light rays come.
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; glLightfv(GL_LIGHT0, GL_POSITION, light_position); you supply a vector of four values (x, y, z, w) for the GL_POSITION parameter. • If the last value, w, is zero, the corresponding light source is a directional one, and the (x, y, z) values describe its direction. • This direction is transformed by the modelview matrix. • By default, GL_POSITION is (0, 0, 1, 0), which defines a directional light that points along the negative z-axis. • If the w value is nonzero, the light is positional, and the (x, y, z) values specify the location of the light. • Remember that the colors across the face of a smooth-shaded polygon are determined by the colors calculated for the vertices. Because of this, you probably want to avoid using large polygons with local lights. break up the large polygon into smaller ones.
attenuation factor where d = distance between the light's position and the vertex kc = GL_CONSTANT_ATTENUATION kl = GL_LINEAR_ATTENUATION kq = GL_QUADRATIC_ATTENUATION If the light is a directional one, the attenuation factor is 1. glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 2.0); glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 1.0); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.5);
Spotlight Effect • The spotlight effect evaluates to one of three possible values: • =1 if the light isn't a spotlight (GL_SPOT_CUTOFF is 180.0). • =0 if the light is a spotlight but the vertex lies outside the cone of illumination produced by the spotlight. v dot d = cos(a) < cos(t) • =(max {v dot d, 0 } )GL_SPOT_EXPONENT where • v = (vx, vy, vz) is the unit vector that points from the spotlight (GL_POSITION) to the vertex. • d = (dx, dy, dz) is the spotlight's direction (GL_SPOT_DIRECTION) • The dot product of the two vectors v and d varies as the cosine of the angle between them; hence, objects directly in line get maximum illumination, and objects off the axis have their illumination drop as the cosine of the angle.
Spotlight • By default, the spotlight feature is disabled because the GL_SPOT_CUTOFF parameter is 180.0. • This value means that light is emitted in all directions • The value for GL_SPOT_CUTOFF is restricted to being within the range [0.0,90.0] (unless it has the special value 180.0). glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0); • You also need to specify a spotlight's direction, which determines the axis of the cone of light: GLfloat spot_direction[] = { -1.0, -1.0, 0.0 }; glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION, spot_direction); By default, the direction is (0.0, 0.0, -1.0), so if you don't explicitly set the value of GL_SPOT_DIRECTION, the light points down the negative z-axis. glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0);
Ambient Lighting • R = light.r * material.r • G = light.g * material.g • B = light.b * material.b • (light.r is the red value of the GL_AMBIENT color of the light source, etc.)
Diffuse Lighting diffuse_intensity = max(normal dot light_dir, 0) = normal.x * light_dir.x + normal.y * light_dir.y + normal.z * light_dir.z R = diffuse_intensity * light.red * material.red G = diffuse_intensity * light.green * material.green B = diffuse_intensity * light.blue * material.blue (light.red is the red value of the GL_DIFFUSE color of the light source, etc.)
Specular Lighting s_vector (half)= normalize( light_dir + view_dir ) specular_intensity = (s_vector dot normal)shininess× 128 R = specular_intensity * light.r * material.r G = specular_intensity * light.g * material.g B = specular_intensity * light.b * material.b (light.r is the red value of the GL_SPECULAR color of the light source, etc.)
Color and Light Distribution for a Red Laser Light Source • You could interpret this table as saying that the red laser light in some scenes has a very high specular component, a small diffuse component, and a very small ambient component. • Wherever it shines, you are probably going to see a reddish spot.
void glLight{if}[v](GLenum light, GLenum pname, TYPEparam); • Default Values for pname Parameter of glLight*() Parameter NameDefault ValueMeaning GL_AMBIENT (0.0, 0.0, 0.0, 1.0) ambient RGBA intensity GL_DIFFUSE (1.0, 1.0, 1.0, 1.0) diffuse RGBA intensity GL_SPECULAR (1.0, 1.0, 1.0, 1.0) specular RGBA intensity GL_POSITION (0.0, 0.0, 1.0, 0.0) (x, y, z, w) position GL_SPOT_DIRECTION (0.0, 0.0, -1.0) (x, y, z) direction GL_SPOT_EXPONENT 0.0 spotlight exponent GL_SPOT_CUTOFF 180.0 spotlight cutoff angle GL_CONSTANT_ATTENUATION 1.0 constant attenuation GL_LINEAR_ATTENUATION 0.0 linear attenuation GL_QUADRATIC_ATTENUATION 0.0 quadratic attenuation • The default values listed for GL_DIFFUSE and GL_SPECULAR apply only to GL_LIGHT0. For other lights, the default value is (0.0, 0.0, 0.0, 1.0) for both GL_DIFFUSE and GL_SPECULAR.
GLfloat light1_ambient[] = { 0.2, 0.2, 0.2, 1.0 }; GLfloat light1_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light1_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light1_position[] = { -2.0, 2.0, 1.0, 1.0 }; GLfloat spot_direction[] = { -1.0, -1.0, 0.0 }; glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular); glLightfv(GL_LIGHT1, GL_POSITION, light1_position); glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.5); glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.5); glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.2); glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 45.0); glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction); glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 2.0); glEnable(GL_LIGHT1);
glMaterial{if}[v](GLenum face, GLenum pname, TYPEparam); • Default Values for pname Parameter of glMaterial*() Parameter Name Default Value Meaning GL_AMBIENT (0.2, 0.2, 0.2, 1.0) ambient color GL_DIFFUSE (0.8, 0.8, 0.8, 1.0) diffuse color GL_AMBIENT_AND_DIFFUSE ambient and diffuse color GL_SPECULAR (0.0, 0.0, 0.0, 1.0) specular color GL_SHININESS 0.0 specular exponent GL_EMISSION (0.0, 0.0, 0.0, 1.0) emissive color
GLfloat no_mat[ ] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat mat_diffuse[ ] = { 0.1, 0.5, 0.8, 1.0 }; GLfloat no_shininess[ ] = { 0.0 }; glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
Local or Infinite Viewpoint • Specular Lighting: s_vector (half)= normalize( light_dir + view_dir ) specular_intensity = (s_vector dot normal)shininess× 128 R = specular_intensity * light.r * material.r • … • With an infinite viewpoint, the direction between it and any vertex in the scene remains constant (i.e; view_dir =constant = (0, 0, 1) ) • A local viewpoint tends to yield more realistic results, but since the direction has to be calculated for each vertex, overall performance is decreased with a local viewpoint. • glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
Two-sided Lighting • Lighting calculations are performed for all polygons, whether they're front-facing or back-facing. • Since you usually set up lighting conditions with the front-facing polygons in mind, however, the back-facing ones typically aren't correctly illuminated. • e.g., If a sphere was going to be cut away so that its inside surface would be visible • glLightModeli(LIGHT_MODEL_TWO_SIDE, GL_TRUE); • OpenGL reverses the surface normals • As a result, all polygons are illumnated correctly. • To turn two-sided lighting off, pass in GL_FALSE as the argument in the preceding call.
scene.c void init (void){ GLfloat light_ambient[ ] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat light_diffuse[ ] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light_specular[ ] = { 1.0, 1.0, 1.0, 1.0 }; /* light_position is NOT default value */ 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); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); glEnable(GL_DEPTH_TEST); } void display (void){ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix (); glRotatef (20.0, 1.0, 0.0, 0.0); glPushMatrix (); glTranslatef (-0.75, 0.5, 0.0); glRotatef (90.0, 1.0, 0.0, 0.0); glutSolidTorus (0.275, 0.85, 15, 15); glPopMatrix (); …….
material.c void init(void) { GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat position[] = { 0.0, 3.0, 2.0, 0.0 }; GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 }; GLfloat local_view[] = { 0.0 }; glClearColor(0.0, 0.1, 0.1, 0.0); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_POSITION, position); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); }
* Draw twelve spheres in 3 rows with 4 columns. * The spheres in the first row have materials with no ambient reflection. * The second row has materials with significant ambient reflection. * The third row has materials with colored ambient reflection. * * The first column has materials with blue, diffuse reflection only. * The second column has blue diffuse reflection, as well as specular * reflection with a low shininess exponent. * The third column has blue diffuse reflection, as well as specular * reflection with a high shininess exponent (a more concentrated highlight). * The fourth column has materials which also include an emissive component.
GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat mat_ambient[] = { 0.7, 0.7, 0.7, 1.0 }; GLfloat mat_ambient_color[] = { 0.8, 0.8, 0.2, 1.0 }; GLfloat mat_diffuse[] = { 0.1, 0.5, 0.8, 1.0 }; GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat no_shininess[] = { 0.0 }; GLfloat low_shininess[] = { 5.0 }; GLfloat high_shininess[] = { 100.0 }; GLfloat mat_emission[] = {0.3, 0.2, 0.2, 0.0}; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* draw sphere in first row, first column * diffuse reflection only; no ambient or specular */ glPushMatrix(); glTranslatef (-3.75, 3.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); glutSolidSphere(1.0, 16, 16); glPopMatrix();
/* draw sphere in first row, second column * diffuse and specular reflection; low shininess; no ambient */ glPushMatrix(); glTranslatef (-1.25, 3.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); glutSolidSphere(1.0, 16, 16); glPopMatrix(); • As you can see, glMaterialfv() is called repeatedly to set the desired material property for each sphere.
Color Tracking • With color tracking, you can tell OpenGL to set material properties by only calling glColor. • To enable color tracking, call glEnable with the GL_COLOR_MATERIAL parameter • Then the function glColorMaterial specifies the material parameters that follow the values set by glColor. • For example, to set the ambient and diffuse properties of the fronts of polygons to track the colors set by glColor, call glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); // Enable color tracking glEnable(GL_COLOR_MATERIAL); // Front material ambient and diffuse colors track glColor glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); ... ... glcolor3f(0.75f, 0.75f, 0.75f); glBegin(GL_TRIANGLES); glVertex3f(-15.0f,0.0f,30.0f); glVertex3f(0.0f, 15.0f, 30.0f); glVertex3f(0.0f, 0.0f, -56.0f); glEnd();
color tracking minimizes performance costs associated with changing material properties is to use • glColorMaterial(GLenum face, GLenum mode); • Causes the material property (or properties) specified by mode of the specified material face (or faces) specified by face to track the value of the current color at all times. A change to the current color (using glColor*()) immediately updates the specified material properties. • The face parameter can be GL_FRONT, GL_BACK, or GL_FRONT_AND_BACK (the default). • The mode parameter can be GL_AMBIENT, GL_DIFFUSE, GL_AMBIENT_AND_DIFFUSE (the default), GL_SPECULAR, or GL_EMISSION. • Note that glColorMaterial() specifies two independent values: the first specifies which face or faces are updated, and the second specifies which material property or properties of those faces are updated. • You should use glColorMaterial() whenever you need to change a single material parameter for most vertices in your scene.
Ambient.cpp (ch5) void SetupRC( ){ // Light values // Bright white light GLfloat ambientLight[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glEnable(GL_DEPTH_TEST); // Hidden surface removal glEnable(GL_CULL_FACE); // Do not calculate inside of jet glFrontFace(GL_CCW); // Counterclockwise polygons face out // Lighting stuff glEnable(GL_LIGHTING); // Enable lighting // Set light model to use ambient light specified by ambientLight[] glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientLight); glEnable(GL_COLOR_MATERIAL); // Enable material color tracking // Front material ambient and diffuse colors track glColor glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); // Nice light blue background glClearColor(0.0f, 0.0f, 05.f,1.0f);}
void RenderScene(void) { // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Save the matrix state glPushMatrix(); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); // Nose Cone ///////////////////////////// // Bright Green glColor3ub(0, 255, 0); glBegin(GL_TRIANGLES); glVertex3f(0.0f, 0.0f, 60.0f); glVertex3f(-15.0f, 0.0f, 30.0f); glVertex3f(15.0f,0.0f,30.0f); ………..
The final output is not much different from the image before we had lighting. However, if we reduce the ambient light by half, we get the image shown in the following figure. • To reduce it by half, we set the ambient light RGBA values to the following: GLfloat ambientLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
colormat.c GLfloat diffuseMaterial[4] = { 0.5, 0.5, 0.5, 1.0 }; void init(void) { GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH); glEnable(GL_DEPTH_TEST); glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseMaterial); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialf(GL_FRONT, GL_SHININESS, 25.0); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glColorMaterial(GL_FRONT, GL_DIFFUSE); glEnable(GL_COLOR_MATERIAL); } void display(void){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glutSolidSphere(1.0, 20, 16); glFlush (); }
void mouse(int button, int state, int x, int y) { switch (button) { case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) { diffuseMaterial[0] += 0.1; if (diffuseMaterial[0] > 1.0) diffuseMaterial[0] = 0.0; glColor4fv(diffuseMaterial); glutPostRedisplay(); } break;
movelight.c void display(void) { GLfloat position[ ] = { 0.0, 0.0, 1.5, 1.0 }; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix (); gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glPushMatrix (); glRotated ((GLdouble) spin, 1.0, 0.0, 0.0); glLightfv (GL_LIGHT0, GL_POSITION, position); glTranslated (0.0, 0.0, 1.5); glDisable (GL_LIGHTING); glColor3f (0.0, 1.0, 1.0); glutWireCube (0.1); glEnable (GL_LIGHTING); glPopMatrix (); glutSolidTorus (0.275, 0.85, 8, 15); glPopMatrix (); glFlush (); }
LitJet.cpp (ch5) void SetupRC() { // Light values and coordinates GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f }; GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f }; glEnable(GL_DEPTH_TEST); // Hidden surface removal glFrontFace(GL_CCW); // Counterclockwise polygons face out glEnable(GL_CULL_FACE); // Do not calculate inside of jet // Enable lighting glEnable(GL_LIGHTING); // Set up and enable light 0 glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight); glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight); glEnable(GL_LIGHT0); // Enable color tracking glEnable(GL_COLOR_MATERIAL); // Set material properties to follow glColor values glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // Light blue background glClearColor(0.0f, 0.0f, 1.0f, 1.0f ); // Rescale normals to unit length glEnable(GL_NORMALIZE);}
void RenderScene(void) { M3DVector3f vNormal; // Storeage for calculated surface normal { M3DVector3f vPoints[3] = {{ 15.0f, 0.0f, 30.0f}, { 0.0f, 15.0f, 30.0f}, { 0.0f, 0.0f, 60.0f}}; // Calculate the normal for the plane m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]); glNormal3fv(vNormal); glVertex3fv(vPoints[0]); glVertex3fv(vPoints[1]); glVertex3fv(vPoints[2]); }
The most obvious way to improve the performance of this code is to calculate all the normal vectors ahead of time and store them for use in the RenderScene function. • Display lists and vertex arrays provide a means of storing calculated values not only for the normal vectors, but for the polygon data as well. • Remember, these examples are meant to demonstrate the concepts. They are not necessarily the most efficient code possible.
Specular lighting and material properties add needed gloss to the surface of your objects. • This shininess has a brightening effect on an object’s color and can produce specular highlights when the angle of incident light is sharp in relation to the viewer. // Light values and coordinates GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f }; GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f }; GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f}; ... ... // Enable lighting glEnable(GL_LIGHTING); // Set up and enable light 0 glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight); glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight); glLightfv(GL_LIGHT0,GL_SPECULAR,specular); glEnable(GL_LIGHT0); • If this were the only change you made to LITJET, you wouldn’t see any difference in the jet’s appearance. We haven’t yet defined any specular reflectance properties for the material properties.
Adding specular reflectance to material properties // Light values and coordinates GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f }; ... ... // Enable color tracking glEnable(GL_COLOR_MATERIAL); // Set material properties to follow glColor values glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // All materials hereafter have full specular reflectivity // with a high shine glMaterialfv(GL_FRONT, GL_SPECULAR,specref); glMateriali(GL_FRONT,GL_SHININESS,128); //The range of this parameter is 1–128 for all conformant implementations of OpenGL.
Spot.cpp (ch5) • This program places a blue sphere in the center of the window. • It also creates a spotlight that you can move vertically with the up- and down-arrow keys and horizontally with the leftand right-arrow keys. • As the spotlight moves over the surface of the sphere, a specular highlight follows it on the surface. • The pop-up menu contains items to set flat and smooth shading and to produce a sphere for low, medium, and high approximation. • Surface approximation means to break the mesh of a curved surface into a finer mesh of polygons (more vertices). • A drawback of vertex lighting (not necessarily OpenGL!). • By lighting the vertices and then interpolating between them, we get a crude approximation of lighting.
GLfloat lightPos[] = { 0.0f, 0.0f, 75.0f, 1.0f }; GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f}; GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat ambientLight[] = { 0.5f, 0.5f, 0.5f, 1.0f}; GLfloat spotDir[] = { 0.0f, 0.0f, -1.0f }; void SetupRC() { glEnable(GL_DEPTH_TEST); // Hidden surface removal glFrontFace(GL_CCW); // Counterclockwise polygons face out glEnable(GL_CULL_FACE); // Do not try to display the back sides // Enable lighting glEnable(GL_LIGHTING); // Set up and enable light 0 // Supply a slight ambient light so the objects can be seen glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight); // The light is composed of just diffuse and specular components glLightfv(GL_LIGHT0,GL_DIFFUSE,ambientLight); glLightfv(GL_LIGHT0,GL_SPECULAR,specular); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); // Specific spot effects. This line what makes a positional light source into a spotlight: glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,60.0f); // Enable this light in particular glEnable(GL_LIGHT0);
CAN YOU SEE THE LIGHT? • No. • Lights in OpenGL cannot be seen by themselves. • Spotlights do not create cones of light, and beams of sunlight streaming in a window do not create beams or shafts of light. • To create these effects in OpenGL, you will actually have to draw geometry, such as real cones or shafts, often using the blending operations covered later. • Lights also go through objects and do not cast shadows. • One technique for drawing shadows will be presented soon.
void RenderScene(void) { if(iShade == MODE_FLAT) glShadeModel(GL_FLAT); else // iShade = MODE_SMOOTH; glShadeModel(GL_SMOOTH); // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // First place the light // Save the coordinate transformation glPushMatrix(); // Rotate coordinate system glRotatef(yRot, 0.0f, 1.0f, 0.0f); glRotatef(xRot, 1.0f, 0.0f, 0.0f); // Specify new position and direction in rotated coords glLightfv(GL_LIGHT0,GL_POSITION,lightPos); glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spotDir);