GLART week 4: Light and Material

Lighting is both an art and science and there is much debate about the best way to create convincing light in computer graphics. The OpenGL lighting system is designed to approximate light behavior in a relatively simple and efficient fashion. It is not ray tracing (a much more expensive method for rendering light). It does not actually calculate reflections and scattering of light. The light properties are very open, and can be used in completely irrational ways, whether intentionally or unintentionally. These properties are not 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. I'll clarify what I can in the details below. Light has meaning only when there is a surface to reflect light. Even if you don't define a material OpenGL uses default material values until you specify your own settings. You can modify material settings to define how surfaces reflect light. Assigment: Light a sphere Reading: Redbook pages 173-210 "Chapter 5: Lighting" Examples: Calculate a Normal Light one triangle Light a curved surface Smooth the normals Light a sphere Light and Materials Move a light (and glow) Spotlight The examples require these two classes to work: Vector3D.java GLMaterial.java Images: Examples of light in painting See also: nate robbins light tutorial: http://www.xmission.com/~nate/tutors.html Normal Mathematics http://www.euclideanspace.com/maths/algebra/vectors/normals/ NOTES: ================================================================= Normals ---------------------------- 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 to the surface. Given three points (the vertices of a triangle) we can calculate a normal for that triangle (see Vector3D.getNormal()). The glNormal() command tells OpenGL what normal to use for all the following glVertex() calls. If you call glNormal() once 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 instance, 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 models 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 glEnable(GL11.GL_NORMALIZE) to tell OpenGL to force all normals to have a length of 1. If normals are different lengths then lighting will fall unevenly across the surface. Light ---------------------------- There are two main components to lighting: Light color Surface color and reflectivity (material) Light properties define how light propagates from a source. There are three components of light color: Diffuse light -- the light rays coming directly from source Specular light -- the light reflected off a shiny surface Ambient light -- the light scattered 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 light. 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 **reflected** 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 percentage 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-intuitive 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 color. 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, OpenGL 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 set ambient to 1/4 of diffuse. set specular to diffuse To define a material: set diffuse to the color you want, set ambient to 1/4 of diffuse, set specular to a gray (white is brightest reflection, black is no reflection) 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 eye 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 model 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 positional (light radiates from a point,ie. a light bulb) or directional (light rays are parallel and illuminate entire scene evenly, ie. from the sun). The fourth position value sets positional/directional. * Remember, once you enable GL_LIGHTING there is a default 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(GL11.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.