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...
|