Making Specular Highlights Per Pixel


To address this issue, you can make the highlights appear per pixel rather than per vertex. Doing so requires a more complicated pixel shader. Back in your KartRacers.fx file, add the new shader functions in Listing 23.3.

Listing 23.3. A Per-Pixel Shader
 //----------------------------------------------------------------------------- // Transformation with single directional light plus per pixel specular //----------------------------------------------------------------------------- struct PER_PIXEL_OUT {     float4 Position : POSITION;     float2 TexCoords : TEXCOORD0;     float3 LightDirection : TEXCOORD1;     float3 Normal : TEXCOORD2;     float3 EyeWorld : TEXCOORD3; }; PER_PIXEL_OUT TransformSpecularPerPixel(float4 pos : POSITION, float3 normal : NORMAL, float2 uv : TEXCOORD0) {     PER_PIXEL_OUT Output = (PER_PIXEL_OUT)0;     // Transform position     Output.Position = mul(pos, worldViewProjection);     // Store uv coords     Output.TexCoords = uv;     // Store the light direction     Output.LightDirection = lightDirection;     // Transform the normals into the world matrix and normalize them     Output.Normal = normalize(mul(normal, worldMatrix));     // Transform the world position of the vertex     float3 worldPosition = normalize(mul(pos, worldMatrix));     // Store the eye vector     Output.EyeWorld = normalize(eyeVector - worldPosition);     // Return the data     return Output; } float4 TextureColorPerPixel(  float2 uvCoords : TEXCOORD0,  float3 lightDirection : TEXCOORD1,  float3 normal : TEXCOORD2,  float3 eye : TEXCOORD3) : COLOR0 {     // Normalize our vectors     float3 normalized = normalize(normal);     float3 light = normalize(lightDirection);     float3 eyeDirection = normalize(eye);     // Store our diffuse component     float4 diffuse = saturate(dot(light, normalized));     // Calculate specular component     float3 reflection = normalize(2 * diffuse * normalized - light);     float4 specular = pow(saturate(dot(reflection, eyeDirection)), 8);     float4 textureColorFromSampler = tex2D(SceneSampler, uvCoords);     // Return the combined color     return textureColorFromSampler * diffuse + specular; }; 

You'll notice here that the code is generally the same as that in the per-vertex version, but this time, it is split across two methods. Because the pixel shader cannot retrieve much of the data that the vertex shader can, you'll notice that the only job the vertex shader has here is to pass the data on to the pixel shader in the form of texture coordinates. The pixel shader then takes that data and performs the same operation the pixel shader did earlier.

Once again, you need a new technique to access this new effect. Because this pixel shader is more complicated, you need at least a 2.0 shader to execute it:

 technique RenderSceneSpecularPerPixel {     pass P0     {         VertexShader = compile vs_1_1 TransformSpecularPerPixel();         PixelShader = compile ps_2_0 TextureColorPerPixel();     } } 

You'll notice that ps_2_0 is used to signify the updated shader required. However, currently you don't know whether your device even supports this shader model. Because you've already decided to support a minimum of vs_1_1 in the IsDeviceAcceptable method, and you already have techniques that use this version, you should only use the 2.0 version if it's supported. It's like an "added feature." Add a new variable to your C# code to decide when to use this version:

 // Can the device use pixel shader 2.0? private bool canUse20Shaders = false; 

This line defaults to false, so the advanced shaders aren't forced on a user that can't support them. However, if the user can support them, you want them to be used, so find the OnCreateDevice method and add this check to the end:

 if (sampleFramework.DeviceCaps.PixelShaderVersion >= new Version(2, 0) ) {     canUse20Shaders = true; } 

Finally, you need to update the rendering method so the kart rendering uses the correct technique, depending on which model is available:

 effect.Technique = canUse20Shaders ? "RenderSceneSpecularPerPixel" :     "RenderSceneSpecular"; 

With that, you should be able to see your kart being rendered with per-pixel specular highlights, as shown in Figure 23.1.

Figure 23.1. Specular highlights.




Beginning 3D Game Programming
Beginning 3D Game Programming
ISBN: 0672326612
EAN: 2147483647
Year: 2003
Pages: 191
Authors: Tom Miller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net