OpenGL Lightingx - Computer Engineering and Computer ...

sploshtribeΛογισμικό & κατασκευή λογ/κού

14 Δεκ 2013 (πριν από 4 χρόνια και 5 μήνες)

117 εμφανίσεις


OpenGL Lighting , Material and Shading

Lighting is both an art and science and there are many techniques

to create convincing light in computer graphics. The OpenGL lighting

system is designed to approximate light behavior in a relatively simple


efficient fashion. It is good at rendering light in real
time, for

example in a computer game. Other more expensive approaches to light

rendering that you find in Maya or 3DS Max, such as ray tracing,

require higher end hardware or are meant for use in s
till images or video

output. OpenGL lighting does not calculate reflections and scattering of

light and does not produce shadows. There are ways to approximate more

subtle lighting effects using textures, shadow mapping, and shaders.

OpenGL light proper
ties are very flexible, and may not be immediately

intuitive, but, like brush and pigment, they provide a wide range of

options for creating the illusion of light and reflection in a scene.

Light works with Materials. Light has meaning only when there is

surface to reflect the light and OpenGL has functions to define the

properties of a surface: what color the surface is and how much or how

little it reflects light. These "material properties" describe the

surface. Once you enable lighting, OpenGL uses

default material values

until you specify your own settings.


For OpenGL to calculate light on a surface, it needs to know which way

the surface is facing. The surface "normal" is a vector perpendicular


the surface. Given three points (the vertices of a triangle) we can

calculate a normal for that triangle (see Vector3D.getNormal()).


command tells OpenGL what normal to use for all the

following glVertex() calls. If you call glNormal() o
nce for each triangle

in a sphere, each triangle will appear to be flat and distinct from the

others (faceted).

To create a smooth continuous surface, you need to assign normals

to each vertex, and average the normals across the triangles. For

if a vertex is on the border between two triangles, you

would average the normals for the two triangles and assign that

average to the vertex.

It's good to understand normals, though you usually won't have to

calculate them yourself. In most cases the mo
dels you load (from Maya

or 3DS Max) will have normals already calculated for you. You may need

to calculate normals yourself if you're generating your own geometry


in your code.

Normals should have a length of 1. Call

to tell Open
GL to force all normals to have a length of 1. If normals

are different lengths then lighting will fall unevenly across the surface.


There are two main components to lighting:

Light color

Surface color (aka. the material color)

properties define how light propagates from a source.

There are three

components of light color:



the light rays coming directly from source



the light reflected off a shiny surface



the light scatter
ed off the environment

Usually all three colors are similar. A red light will illuminate

a surface with red, the reflection will be red, and the scattered

light in the environment will be a dim red.

Material properties define how a surface reflects ligh

They do this by

defining color values much the same way that lights do. A material has

color value for diffuse (direct) light, ambient (scattered) light,

and specular (reflected) light, but these values define how the

components of light are **reflect
ed** off the material surface.

The incoming light colors are combined with the corresponding material

color and the resulting color is what we see on screen.

These material values have meaning only in relation to the light source(s).

For instance if your
material reflects ambient light (ie. the material AMBIENT

setting has a color value), it will still appear as black if there is

no AMBIENT light coming from the light source. Similarly, the diffuse material

color may be yellow but it will appear greenish

if the diffuse light color

is green.

The material specular value is usually white, gray or black,

because it has no hue of it's own, it is reflecting the hue of the

light that is shining on it. Think of this color value as defining the


of light that will be reflected.

There is an additional material setting, shininess, that defines the

size of the surface reflection.


A Simple Approach to Lighting:

There is much room for fudging in the lighting system. You can invent

very un
e light conditions that have no relationship to

actual light conditions in the real world. Here is a simple way

to think of light and material.

Diffuse is the direct light

color, and
specular is the reflected light


In reality these two are usually

the same (a green light will cast greenish

light on a surface, and the reflection will be green).

Ambient describes how the light is scattered

by the environment, which

isn't really a property of the light at all, it's a property of the

environment. For
example, sunlight directly striking an object appears

white/yellow, but sunlight scattered in the atmosphere takes on a bluish hue.

In outer space there would be no ambient light because there is no

atmosphere to scatter the sunlight. For simplicity, Open
GL folds this

property into the light.

Materials describe how these different light components (diffuse,

ambient. specular), reflect off a surface. In reality

a material reflects the same way whether it's reflecting direct or

scattered light.

How to simplify light and material:

To define a light:

set diffuse to the color you want the light to be

set specular equal to diffuse

set ambient to 1/4 of diffuse.

To define a material:

set diffuse to the color you want the m
aterial to be,

set specular to a gray (white is brightest reflection, black is no reflection)

set ambient to 1/4 of diffuse,

Some things to remember:


Once lighting is enabled, the vertex colors are ignored. OpenGL

calculates it's own color

values for each vertex, based on the color

of the light and the degree of illumination.


Normals are critical to correct lighting. The vertex normals

tell OpenGL what angle a plane is at. Based on the angle of the plane

with respect to the light and e
ye positions, OpenGL calculates the

reflected light.


Normal lengths matter! They should all be length of 1, or


light will fall unevenly. The easiest way to do this is to enable

GL_NORMALIZE. The Sphere object provides normals for us, as will

many mod
el file formats.


Distance matters! When a positional light comes close to a surface,

the angle of light becomes very acute and the vertices get very

different light values. This will look like rippling on the surface.


A light can be

(light radiates from a point,ie. a

light bulb) or

(light rays are parallel and illuminate

entire scene evenly, ie. from the sun). The fourth position value sets



Remember, once you enable GL_LIGHTING there is a defau
lt light

and default material in effect. You can change material properties,

but there will always be some sort of material in effect.


Spheres may be buggy at some sizes. Watch out for complex shapes

at very low sizes (.2, .3, etc.).


Lights are points in the space like vertices and can be transformed

just like vertices. Use glLight(GL.GL_POSITION...) after

glTranslate() glRotate() to change light position.


Emissive material property typically overrides diffuse, ambient, specular

unless the glow is very faint). Emissive light is not radiant, doesn't

cast light on other objects. You use another light source to do that.



turn on lighting



on a single light source. There are seven light sources in OpenGL.

glLight(GL_LIGHT1, GL_DIFFUSE, RGB_color_values)

define the color of a light source. The RGB values define the color, and

are passed into the function as a FloatBuffer.

There are fou
r color values we can define for a light: GL_DIFFUSE,


glLight(GL_LIGHT1, GL_POSITION, XYZ_Position_values)

define the light position. We pass four values. The first three are XYZ.


If the fourth value is a 1
then the XYZ values are treated as a position

of the light source (positional light). Positional lights are a point

light source that will fade if the light position is very far from the

surface (ie. a light bulb).

If the fourth value is a 0 then

e the XYZ values describe the direction of the light (directional light).

Directional light shines at the same intensity and from the same direction

on all surfaces (ie. the sun).

glLightModel(GL_LIGHT_MODEL_AMBIENT, RGB_color_values)

define overall pr
operties of the lighting environment, such as Ambient

light for the entire scene.


defines the normal value for the following vertices.

used inside a glBegin() ... glEnd() block

affects the glVertex() commands that follow


With this huge range of options, it can be hard to pick sensible default values for these things.

My advice for a starting point is to:

Set GL_LIGHT_0's position to something like 45 degrees to the 'vertical'. Coordinate
(1,1,0) should work nic
ely in most cases.

Set GL_LIGHT_0's Ambient color to 0,0,0,1

Set GL_LIGHT_0's Diffuse color to 1,1,1,1

Set GL_LIGHT_0's Specular color to 1,1,1,1

Set the glLightModel's global ambient to 0.2,0.2,0.2,1 (this is the default).

Don't set any other glLight

or glLightModel options

just let them default.


Enable GL_COLOR_MATERIAL and set glColorMaterial to
GL_AMBIENT_AND_DIFFUSE. This means that glMaterial will control the polygon's
specular and emission colours and the a
mbient and diffuse will both be set using glColor.

Set the glMaterial's Specular colour to 1,1,1,1

Set the glMaterial's Emission colour to 0,0,0,1

Set the glColor to whatever colour you want each polygon to basically appear to be. That
sets the Ambient
and Diffuse to the same value which is what you generally want.