📄 chapter06.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-2">
<META NAME="GENERATOR" CONTENT="Mozilla/4.07 [en] (Win98; I) [Netscape]">
<META NAME="Author" CONTENT="Goran UnreaL Krajnovic">
<TITLE>Chapter 6 - OpenGL Programming Guide (Addison-Wesley Publishing Company)</TITLE>
</HEAD>
<BODY BGCOLOR="#EFEFEF" LINK="#0000FF" VLINK="#551A8B" ALINK="#FF0000">
<DIV ALIGN=right><IMG SRC="figures/SGI_ID.gif" ALT="Silicon Graphics" NOSAVE HEIGHT=43 WIDTH=151 ALIGN=TEXTTOP></DIV>
<PRE>
<HR></PRE>
<H1>
Chapter 6<BR>
Lighting</H1>
<B>Chapter Objectives</B>
<P>After reading this chapter, you'll be able to do the following:
<UL>Understand how real-world lighting conditions are approximated by OpenGL
<BR>
<P>Render illuminated objects by defining the desired light sources and
lighting model
<BR>
<P>Define the material properties of the objects being illuminated
<BR>
<P>Manipulate the matrix stack to control the position of light sources</UL>
As you saw in Chapter 5 , OpenGL computes the color of each pixel in a
final, displayed scene that's held in the framebuffer. Part of this computation
depends on what lighting is used in the scene and on how objects in the
scene reflect or absorb that light. As an example of this, recall that
the ocean has a different color on a bright, sunny day than it does on
a gray, cloudy day. The presence of sunlight or clouds determines whether
you see the ocean as bright turquoise or murky gray-green. In fact, most
objects don't even look three-dimensional until they're lit. Figure 6-1
shows two versions of the exact same scene (a single sphere), one with
lighting and one without.
<P><IMG SRC="figures/Fig6-1.gif" ALT="[IMAGE]" >
<P><B>Figure 6-1 : </B>A Lit and an Unlit Sphere
<BR>
<BR>
<P>As you can see, an unlit sphere looks no different from a two-dimensional
disk. This demonstrates how critical the interaction between objects and
light is in creating a three-dimensional scene.
<P>With OpenGL, you can manipulate the lighting and objects in a scene
to create many different kinds of effects. This chapter explains how to
control the lighting in a scene. It discusses OpenGL's conceptual model
of lighting, and it describes in detail how to set the numerous illumination
parameters to achieve certain effects. Toward the end of the chapter, the
mathematical computations that determine how lighting affects color are
presented.
<P>This chapter contains the following major sections:
<UL>"Real-World and OpenGL Lighting" explains in general terms how light
behaves in the world and how OpenGL models this behavior.
<BR>
<P>"A Simple Example: Rendering a Lit Sphere" introduces OpenGL's lighting
facility by presenting a short program that renders a lit sphere.
<BR>
<P>"Creating Light Sources" explains how to define and position light sources.
<BR>
<P>"Selecting a Lighting Model" discusses the elements of a lighting model
and how to specify them.
<BR>
<P>"Defining Material Properties" explains how to describe the properties
of objects so that they interact with light in a desired way.
<BR>
<P>"The Mathematics of Lighting" presents the mathematical calculations
used by OpenGL to determine the effect of lights in a scene.
<BR>
<P>"Lighting in Color-Index Mode" discusses the differences between using
RGBA mode and color-index mode for lighting.</UL>
<HR>
<H2>
Real-World and OpenGL Lighting</H2>
When you look at a physical surface, your eye's perception of the color
depends on the distribution of photon energies that arrive and trigger
your cone cells, as described in "Color Perception." Those photons come
from a light source or combination of sources, some of which are absorbed
and some of which are reflected by the surface. In addition, different
surfaces may have very different properties - some are shiny, and preferentially
reflect light in certain directions, while others scatter incoming light
equally in all directions. Most surfaces are somewhere in between.
<P>OpenGL approximates light and lighting as if light can be broken into
red, green, and blue components. Thus, the color of light sources is characterized
by the amount of red, green, and blue light they emit, and the material
of surfaces is characterized by the percentage of the incoming red, green,
and blue components that are reflected in various directions. The OpenGL
lighting equations are just an approximation, but one that works fairly
well and can be computed relatively quickly. If you desire a more accurate
(or just different) lighting model, you have to do your own calculations
in software. Such software can be enormously complex, as a few hours of
reading any optics textbook should convince you.
<P>In the OpenGL lighting model, the light in a scene comes from several
light sources that can individually be turned on and off. Some light comes
from a particular direction or position, and some light is generally scattered
about the scene. For example, when you turn on a light bulb in a room,
most of the light comes from the bulb, but some light comes after bouncing
off one, two, three, or more walls. This bounced light (called <I>ambient</I>)
is assumed to be so scattered that there is no way to tell its original
direction, but it disappears if a particular light source is turned off.
<P>Finally, there might be a general ambient light in the scene that comes
from no particular source, as if it had been scattered so many times that
its original source is impossible to determine.
<P>In the OpenGL model, the light sources have an effect only when there
are surfaces that absorb and reflect light. Each surface is assumed to
be composed of a material with various properties. A material might emit
its own light (like headlights on an automobile), it might scatter some
incoming light in all directions, and it might reflect some portion of
the incoming light in a preferential direction like a mirror or shiny surface.
<P>The OpenGL lighting model considers the lighting to be divided into
four independent components: emitted, ambient, diffuse, and specular. All
four components are computed independently, and then added together.
<H3>
Emitted, Ambient, Diffuse, and Specular Light</H3>
<I>Emitted</I> light is the simplest - it originates from an object and
is unaffected by any light sources.
<P>The <I>ambient</I> component is the light from that source that's been
scattered so much by the environment that its direction is impossible to
determine - it seems to come from all directions. Backlighting in a room
has a large ambient component, since most of the light that reaches your
eye has bounced off many surfaces first. A spotlight outdoors has a tiny
ambient component; most of the light travels in the same direction, and
since you're outdoors, very little of the light reaches your eye after
bouncing off other objects. When ambient light strikes a surface, it's
scattered equally in all directions.
<P><I>Diffuse</I> light comes from one direction, so it's brighter if it
comes squarely down on a surface than if it barely glances off the surface.
Once it hits a surface, however, it's scattered equally in all directions,
so it appears equally bright, no matter where the eye is located. Any light
coming from a particular position or direction probably has a diffuse component.
<P>Finally, <I>specular</I> light comes from a particular direction, and
it tends to bounce off the surface in a preferred direction. A well-collimated
laser beam bouncing off a high-quality mirror produces almost 100 percent
specular reflection. Shiny metal or plastic has a high specular component,
and chalk or carpet has almost none. You can think of specularity as shininess.
<P>Although a light source delivers a single distribution of frequencies,
the ambient, diffuse, and specular components might be different. For example,
if you have a white light in a room with red walls, the scattered light
tends to be red, although the light directly striking objects is white.
OpenGL allows you to set the red, green, and blue values for each component
of light independently.
<H3>
Material Colors</H3>
The OpenGL lighting model makes the approximation that a material's color
depends on the percentages of the incoming red, green, and blue light it
reflects. For example, a perfectly red ball reflects all the incoming red
light and absorbs all the green and blue light that strikes it. If you
view such a ball in white light (composed of equal amounts of red, green,
and blue light), all the red is reflected, and you see a red ball. If the
ball is viewed in pure red light, it also appears to be red. If, however,
the red ball is viewed in pure green light, it appears black (all the green
is absorbed, and there's no incoming red, so no light is reflected).
<P>Like lights, materials have different ambient, diffuse, and specular
colors, which determine the ambient, diffuse, and specular reflectances
of the material. A material's ambient reflectance is combined with the
ambient component of each incoming light source, the diffuse reflectance
with the light's diffuse component, and similarly for the specular reflectance
and component. Ambient and diffuse reflectances define the color of the
material and are typically similar if not identical. Specular reflectance
is usually white or gray, so that specular highlights end up being the
color of the light source's specular intensity. If you think of a white
light shining on a shiny red plastic sphere, most of the sphere appears
red, but the shiny highlight is white.
<H3>
RGB Values for Lights and Materials</H3>
The color components specified for lights mean something different than
for materials. For a light, the numbers correspond to a percentage of full
intensity for each color. If the R, G, and B values for a light's color
are all 1.0, the light is the brightest possible white. If the values are
0.5, the color is still white, but only at half intensity, so it appears
gray. If R=G=1 and B=0 (full red and green with no blue), the light appears
yellow.
<P>For materials, the numbers correspond to the reflected proportions of
those colors. So if R=1, G=0.5, and B=0 for a material, that material reflects
all the incoming red light, half the incoming green, and none of the incoming
blue light. In other words, if an OpenGL light has components (LR, LG,
LB), and a material has corresponding components (MR, MG, MB), then, ignoring
all other reflectivity effects, the light that arrives at the eye is given
by (LR*MR, LG*MG, LB*MB).
<P>Similarly, if you have two lights, which send (R1, G1, B1) and (R2,
G2, B2) to the eye, OpenGL adds the components, giving (R1+R2, G1+G2, B1+B2).
If any of the sums are greater than 1 (corresponding to a color brighter
than the equipment can display), the component is clamped to 1.
<P>
<HR>
<H2>
A Simple Example: Rendering a Lit Sphere</H2>
These are the steps required to add lighting to your scene:
<OL>Define normal vectors for each vertex of all the objects. These normals
determine the orientation of the object relative to the light sources.
<BR>
<P>Create, select, and position one or more light sources.
<BR>
<P>Create and select a <I>lighting model</I>, which defines the level of
global ambient light and the effective location of the viewpoint (for the
purposes of lighting calculations).
<BR>
<P>Define material properties for the objects in the scene.</OL>
Example 6-1 accomplishes these tasks. It displays a sphere illuminated
by a single light source, as shown earlier in Figure 6-1 .
<P><B>Example 6-1 : </B>Drawing a Lit Sphere:
<PRE>#include <GL/gl.h>
#include <GL/glu.h>
#include "aux.h"
void myinit(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 };
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);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
auxSolidSphere(1.0);
glFlush();
}
void myReshape(GLsizei w, GLsizei h)
{
glViewport(0, 0, w, 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)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGBA | AUX_DEPTH);
auxInitPosition (0, 0, 500, 500);
auxInitWindow (argv[0]);
myinit();
auxReshapeFunc (myReshape);
auxMainLoop(display);
}</PRE>
The lighting-related calls are in the <B>myinit()</B> command; they're
discussed briefly in the following paragraphs and in more detail later
in the chapter. One thing to note about Example 6-1 is that it uses RGBA
color mode, not color-index mode. OpenGL's lighting calculation is different
for the two modes, and in fact the lighting capabilities are more limited
in color-index mode. Thus, RGBA is the preferred mode when doing lighting,
and all the examples in this chapter use it. See "Lighting in Color-Index
Mode" for more information about lighting in color-index mode.
<H4>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -