Written: 26th January 2002
of this lesson
2. How it actually works
back to the 5th extended Direct3D8 feature...
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!
How it actually works
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...
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...
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...
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
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.
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.
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:
D3DRS_SPECULARENABLE, 1 ' set to 0 to disable
optionally, you can use this following render
state to allow more accurate specular lighting
(at a further speed cost):
D3DRS_LOCALVIEWER, 1 ' set to 0 to disable
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
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,
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG1,
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG2,
stage-0 is the normal texture, and stage-2 is
the RGB lightmap.
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...
Lighting Enabled, power = 0
Lighting Enabled, power = 10
Lighting Enabled, power = 35
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.
work the Sample code:
Bar - turns specular lighting on/off
Return - turns local-viewer on/off
+ (numpad) - increases the power of the specular
- (numpad) - decreases the power of the specular
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).
can get the file from the top of the page, or
from the downloads
feedback or improvements can be emailed to me
- I'm always interested...