MULTIMEDIA

# DirectX 10 Game Programming : Shaders and Effects - Pixel Shaders, Lighting (part 2) - Lighting Calculations

11/21/2013 7:47:42 PM
##### #### 2.2 Lighting Calculations In previous versions of Direct3D, the fixed function pipeline included support for a fixed number of built-in lights. With Direct3D10, that support is gone, giving you the freedom to handle as many lights as you care to do the math for. In most situations, this is beneficial as the previous pipeline couldn’t take into account the myriad options people really wanted with lighting. Regardless of the type of lights you choose to employ, they can affect your scene however you want because you have the ability to directly control them in the shader. Ambient Ambient light is an all powerful light. It doesn’t have a fixed source and seems to come from all around you. Calculating lighting based on ambient light is the simplest of the lighting calculations. Ambient lighting is determined by multiplying the object’s material color by the color of the ambient light. `outputColor = objectColor * ambientColor` Note An object’s material is used to describe how light coming off the object behaves. The material can affect the color of the light being reflected or even the amount of light. For instance, a red ball being lit by a blue light will have its reflected color a combination of the two. The following function shows how you would determine the output color based on ambient lighting in a shader. `/********************************** CalculateAmbient -* inputs -* vKa material's reflective color* lightColor - the ambient color of the lightsource* output - ambient color*********************************/float3 CalculateAmbient(float3 vKa, float3 lightColor){ float3 vAmbient = vKa * lightColor; return vAmbient;}` Diffuse Diffuse lighting calculates the color of an object based on any directional lights within your scene. Directional lights don’t have a fixed position but definitely have a direction. Because directional lights come from a single direction, this means that they will be brighter on one side of your objects and dimmer on the other side. This effect will give your objects that sense of depth. The CalculateDiffuse function shown next demonstrates how this is calculated. The CalculateDiffuse function takes four parameters: the base color of the object, the color of the directional light, the surface normal, and the light vector. The first step is taking the dot product using the normal and the light vector. This value is then clamped between 0 and 1 using the saturate function. The resulting value is then multiplied by the object’s base color and the color of the directional light. As a reminder, this will calculate the angle between the incoming light and the surface of the object. `/********************************** CalculateDiffuse* inputs -* material color* The color of the direct light* the local normal* the vector of the direct light* output - diffuse color*********************************/float3 CalculateDiffuse(float3 baseColor, float3 lightColor, float3 normal,float3 lightVector){ float3 vDiffuse = baseColor * lightColor * saturate(dot(normal, lightVector)); return vDiffuse;}` Specular Highlights Specular is the shininess of an object. Take a lamp and place it next to a glossy object like a piece of glass. Notice not only how the object is lit, but you’ll probably also see what looks like light spots on the object; this is an example of a specular highlight. Specular highlights add that little bit of extra realism to a scene and help show how the light really affects the items in your scene. Calculating the specular highlight requires a few things from your application. First, you need the view vector. This is a vector that describes the camera’s location in relation to the object. Second is the light vector. This is the vector that describes where the light is coming from. Lastly is the surface normal. The first step is creation of the reflection vector using the reflect function. This gives you the direction the light is coming off the surface of the object. Next, the specular value is determined by first taking the dot product of the reflection vector and the view vector. This value is then clamped between 0 and 1 using the saturate function. Finally, the specular value is raised to a power value specified in the specpower variable. This value is tunable and can be changed until you obtain the look you like. `float specpower = 80.0f;/********************************** CalculateSpecular -* inputs -* viewVector* the light vector* the normal* output - specular highlight*********************************/float CalculateSpecular(float3 viewVector, float3 lightVector, float3 normal){ float3 vReflect = reflect(lightVector, normal); float fSpecular = saturate(dot(vReflect, viewVector)); fSpecular = pow(fSpecular, specpower); return fSpecular;} ` Combining the Lighting Now that you have the three lighting values, you need to combine them. This will give you an object that takes into account ambient, diffuse, and specular lighting. Be aware that the lighting in this case in not dependent on the camera’s point of view. The LightingCombine function shown next demonstrates how the lighting methods are brought together. `/********************************** LightingCombine -* inputs -* ambient component* diffuse component* specular component* output - final color*********************************/float3 LightingCombine(float3 vAmbient, float3 vDiffuse, float fSpecular){ float3 vCombined = vAmbient + vDiffuse + fSpecular.xxx; return vCombined;}` All four of these calculations can be placed into a utility shader file and included when needed in your own effect files. These functions contain the generic lighting calculations that you’ll be using over and over. These calculations are just one of many ways that lighting can be implemented within your application and are by no means perfect for every instance.
 Other

 video

 Video tutorials