基本的光照计算公式
The Basic Lighting Model
OpenGL and Direct3D provide almost identical fixed-function lighting models. In our example, we will use a simplified version that we will refer to as the "Basic" model. The Basic model, like the OpenGL and Direct3D models, modifies and extends the classic Phong model. In the Basic model, an object's surface color is the sum of emissive, ambient, diffuse, and specular lighting contributions. Each contribution depends on the combination of the surface's material properties (such as shininess and material color) and the light source's properties (such as light color and position). We represent each contribution as a float3 vector that contains the red, green, and blue color components.
This high-level equation describes the Basic model mathematically:
surfaceColor = emissive + ambient + diffuse + specular
The Emissive Term
The emissive term represents light emitted or given off by a surface. This contribution is independent of all light sources. The emissive term is an RGB value that indicates the color of the emitted light. If you were to view an emissive material in a completely dark room, it would appear to be this color. The emissive term can simulate glowing. Figure 5-2 illustrates the emissive term conceptually, and Figure 5-3 shows a rendering of a purely emissive object. The rendering is understandably boring, because the emissive color is the same all over the object. Unlike in the real world, an object's emissive glow does not actually illuminate other nearby objects in the scene. An emissive object is not itself a light source—it does not illuminate other objects or cast shadows. Another way to think of the emissive term is that it is a color added after computing all the other lighting terms. More advanced global illumination models would simulate how the emitted light affects the rest of the scene, but these models are beyond the scope of this book.
Figure 5-2 The Emissive Term
Figure 5-3 Rendering the Emissive Term
Here is the mathematical formulation we use for the emissive term:
emissive = Ke
where:
- Ke is the material's emissive color.
The Ambient Term
The ambient term accounts for light that has bounced around so much in the scene that it seems to come from everywhere. Ambient light does not appear to come from any particular direction; rather, it appears to come from all directions. Because of this, the ambient lighting term does not depend on the light source position. Figure 5-4 illustrates this concept, and Figure 5-5 shows a rendering of an object that receives only ambient light. The ambient term depends on a material's ambient reflectance, as well as the color of the ambient light that is incident on the material. Like the emissive term, the ambient term on its own is just a constant color. Unlike the emissive color, however, the ambient term is affected by the global ambient lighting.
Figure 5-4 The Ambient Term
Figure 5-5 Rendering the Ambient Term
Here is the mathematical formulation we use for the ambient term:
ambient = Ka x globalAmbient
where:
- Ka is the material's ambient reflectance and
- globalAmbient is the color of the incoming ambient light.
The Diffuse Term
The diffuse term accounts for directed light reflected off a surface equally in all directions. In general, diffuse surfaces are rough on a microscopic scale, with small nooks and crannies that reflect light in many directions. When incoming rays of light hit these nooks and crannies, the light bounces off in all directions, as shown in Figure 5-6.
Figure 5-6 Diffuse Light Scattering
The amount of light reflected is proportional to the angle of incidence of the light striking the surface. Surfaces with a dull finish, such as a dusty chalkboard, are said to be diffuse. The diffuse contribution at any particular point on a surface is the same, regardless of where the viewpoint is. Figure 5-7 illustrates the diffuse term, and Figure 5-8 shows a rendering of a diffuse object.
Figure 5-7 The Diffuse Term
Figure 5-8 Rendering the Diffuse Term
Here is the mathematical formulation we use for the diffuse term (illustrated in Figure 5-9):
diffuse = Kd x lightColor x max(N · L, 0)
where:
- Kd is the material's diffuse color,
- lightColor is the color of the incoming diffuse light,
- N is the normalized surface normal,
- L is the normalized vector toward the light source, and
- P is the point being shaded.
![fig5_9.jpg](http://http.developer.nvidia.com/CgTutorial/elementLinks/fig5_9.jpg)
Figure 5-9 Calculating Diffuse Lighting
The vector dot product (or inner product) of the normalized vectors N and L is a measure of the angle between the two vectors. The smaller the angle between the vectors, the greater the dot-product value will be, and the more incident light the surface will receive. Surfaces that face away from the light will produce negative dot-product values, so the max(N · L, 0) in the equation ensures that these surfaces show no diffuse lighting.
The Specular Term
The specular term represents light scattered from a surface predominantly around the mirror direction. The specular term is most prominent on very smooth and shiny surfaces, such as polished metals. Figure 5-10 illustrates the concept of specular reflection, and Figure 5-11 shows a rendering of a completely specular object.
Figure 5-10 The Specular Term
Figure 5-11 Rendering the Specular Term
Unlike the emissive, ambient, and diffuse lighting terms, the specular contribution depends on the location of the viewer. If the viewer is not at a location that receives the reflected rays, the viewer will not see a specular highlight on the surface. The specular term is affected not only by the specular color properties of the light source and material, but also by how shiny the surface is. Shinier materials have smaller, tighter highlights, whereas less shiny materials have highlights that are more spread out. Figure 5-12 shows some examples of shininess, with the shininess exponent increasing from left to right.
Figure 5-12 Examples of Different Shininess Exponents
Here is the mathematical formulation we use for the specular term (illustrated in Figure 5-13):
specular = Ks x lightColor x facing x (max(N · H, 0)) shininess
where:
- Ks is the material's specular color,
- lightColor is the color of the incoming specular light,
- N is the normalized surface normal,
- V is the normalized vector toward the viewpoint,
- L is the normalized vector toward the light source,
- H is the normalized vector that is halfway between V and L,
- P is the point being shaded, and
- facing is 1 if N · L is greater than 0, and 0 otherwise.
![fig5_13.jpg](http://http.developer.nvidia.com/CgTutorial/elementLinks/fig5_13.jpg)
Figure 5-13 Calculating the Specular Term
When the angle between the view vector V and the half-angle vector H is small, the specular appearance of the material becomes apparent. The exponentiation of the dot product of N and H ensures that the specular appearance falls off quickly as H and V move farther apart.
Additionally, the specular term is forced to zero if the diffuse term is zero because N · L (from diffuse lighting) is negative. This ensures that specular highlights do not appear on geometry that faces away from the light.
基本的光照的ps代码:
void C5E3f_basicLight(float4 position : TEXCOORD0,
float3 normal : TEXCOORD1,
out float4 color : COLOR,
uniform float3 globalAmbient,
uniform float3 lightColor,
uniform float3 lightPosition,
uniform float3 eyePosition,
uniform float3 Ke,
uniform float3 Ka,
uniform float3 Kd,
uniform float3 Ks,
uniform float shininess)
{
float3 P = position.xyz;
float3 N = normalize(normal);
// Compute the emissive term
float3 emissive = Ke;
// Compute the ambient term
float3 ambient = Ka * globalAmbient;
// Compute the diffuse term
float3 L = normalize(lightPosition - P);
float diffuseLight = max(dot(N, L), 0);
float3 diffuse = Kd * lightColor * diffuseLight;
// Compute the specular term
float3 V = normalize(eyePosition - P);
float3 H = normalize(L + V);
float specularLight = pow(max(dot(N, H), 0),
shininess);
if (diffuseLight <= 0) specularLight = 0;
float3 specular = Ks * lightColor * specularLight;
color.xyz = emissive + ambient + diffuse + specular;
color.w = 1;
}