Main Site Links Resources Tutorials
News VB Gaming Code Downloads DirectX 7
Contact Webmaster VB Programming Product Reviews DirectX 8
  General Multimedia Articles DirectX 9
      Miscellaneous

DirectXGraphics: Specular Lighting
Author: Jack Hoxley
Written: 26th January 2002
Contact: [EMail]
Download: GR_Specular.Zip (48kb)


Contents of this lesson
1. Introduction
2. How it actually works


1. Introduction

Welcome back to the 5th extended Direct3D8 feature...

It's been quite a while since I've written anything for this website, so I decided to allocate this weekend to doing something interesting! Which, in this particular instance is specular lighting. As you're probably aware, all geometry rendered through the Direct3D API (by default) is very matte in appearance, which whilst fine for most scenes leaves some things to be desired. In particular, "Shiny" objects. There are several possible cases where shiny objects will come in useful - windows/glass, water, polished metals... In most cases they wont be that noticable, but if you're a perfectionist, adding a little shine to some objects is a definite plus!


2. How it actually works

Specular lighting works by adding highlights to geometry based on the angle between the light, object and viewer - if you take a polished piece of aluminium and a bright spot-light, it is the bright-white reflection that is going to be simulated...

There are some limitations however, Direct3D is a realtime API, so it does "cheat" in some respects to get better performance. Whether these limitations hinder you will only be found out through testing...

1. Direct3D (without any tricks) does not project shadows from geometry, therefore you will still get lighting artifacts with shiny materials - if they are very shiny it is quite possible that they will draw the attention of your user, and therefore emphasizing this defect...

2. As detailed in many academic white papers, it is not proper specular lighting - it is mearly a representation of the effect; real specular lighting is due to reflection properties of materials (and reflected diffuse lighting), which is too complicated to simulate in realtime on todays machines.

3. It is quite slow - whilst the sample code ran at 180-200fps on my machine (GeForce 256 + AMD Athlon 700mhz), the general fact that a specular light source requires more calculations per vertex, per light indicates that it will be slower than if there were no specular lighting. I haven't had the time to test it in a real-world game scenario, but it is quite possible it will knock a considerable number of frames-per-second off your total.

4. This method only reflects colour, not pixel data of any kind. Whilst it is simulating reflected light, your objects will not act like mirrors and reflect other parts of your scene/object.

Specular lighting itself is very easy to use - Once you have configured the D3DMATERIAL8 object (the .specular and .power parameters) and the D3DLIGHT8 (.specular parameter) you need only set this render state:

D3DDevice.SetRenderState D3DRS_SPECULARENABLE, 1 ' set to 0 to disable

And optionally, you can use this following render state to allow more accurate specular lighting (at a further speed cost):

D3DDevice.SetRenderState D3DRS_LOCALVIEWER, 1 ' set to 0 to disable

To my knowledge (and research in the SDK help files), specular lighting should be present on all systems - although, given the very nature of the API it would not surprise me if many of the older systems did not support this feature very well; and given the performance overhead, it would not surprise me if you need to disable this effect on older/slower systems.

Specular lighting through Direct3D only works when you are using Direct3D's lighting engine, if you want to use lightmaps/blending to achieve specular lighting you must pre-process a grey-scale specular lighting texture to be added to the texture cascade with the following properties:

D3DDevice.SetTextureStageState 1, D3DTSS_COLOROP, D3DTOP_ADD
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG1, D3DTA_TEXTURE
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG2, D3DTA_CURRENT

Where stage-0 is the normal texture, and stage-2 is the RGB lightmap.

The following are a set of screenshots from the sample program to show you what things should appear as. Different values for ".Power" in the D3DMATERIAL8 object result in different levels of specular lighting...

No Specular Lighting

Specular Lighting Enabled, power = 0

Specular Lighting Enabled, power = 10

Specular Lighting Enabled, power = 35

As you can see from the above screenshots, the power of the specular lighting is very important - between 10-25 has proven to be quite good in most of my tests, and as you can see, power=0 is pretty useless. and power=35 is starting to show up the per-vertex nature of the calculations.

To work the Sample code:

Space Bar - turns specular lighting on/off
Return - turns local-viewer on/off
+ (numpad) - increases the power of the specular lighting
- (numpad) - decreases the power of the specular lighting


You'll need to download the source code for this article to see what this effect really looks like (the torus rotates around the sphere, which shows the effect much better than the screenshots).

You can get the file from the top of the page, or from the downloads page

any feedback or improvements can be emailed to me - I'm always interested...

DirectX 4 VB 2000 Jack Hoxley. All rights reserved.
Reproduction of this site and it's contents, in whole or in part, is prohibited,
except where explicitly stated otherwise.
Design by Mateo
Contact Webmaster