per pix lighting / bump mapping question

Started by
6 comments, last by fragface 19 years, 2 months ago
hi, i've been reading alot of stuff on dot 3 bump mapping recently, and i've got it working...however, a couple of the samples i used as reference almost used the terms dot 3 bump mapping and per pixel lighting interchangeably...i know both operations use the dot 3 product of the texel normal and the light direction, but are they the same? if not, how is per pixel lighting accomplished in d3d9? ps another question...none of the samples actually used a d3d light (just a direction vector)...in an engine, would you have a d3d light and use it's direction vector for dot 3 calculations? many thanks for clearing this stuff up...
Advertisement
When you use a vertex shader, you lose D3D lighting. You could keep using D3DLIGHT9 structures as your own input, or whatever structure with direction and color that you want.

Per pixel lighting is often done as normal mapping, but it's not a necessity. You could just put the normal direction as an output from the vertex shader (scaled and biased to 0..1). In the pixel shader do a dp3 with the light direction and the normal (again, scaled and biased back to -1..1). It will look slightly better than vertex lighting, but not a whole lot. However, if you throw in a simple texture fetch to get a new normal, you've got bump mapping. This small change brings a huge improvement in visual quality, which is why almost nobody would do per pixel lighting without bumpmapping.

Once you're doing per-pixel lighting, you're definately not wanting D3D to do it's own vertex lighting. Whether you pass the direction and color along in your own structures, or use a D3DLIGHT9, is up to you. D3D isn't using the information anymore, so use whatever is more convenient for you.
thank you very much for your reply.

for my bumpmapping, i'm just performing a D3DTOP_DOTPRODUCT3 between the normal map and the light vector (D3DTA_TFACTOR) in the first texture stage, and then modulating this together with the original texture in the second stage. so, if this is the correct way of doing it, i assume the light's color actually has nothing to do with bumpmapping? it's more of a "shading" technique? and about the per pixel lighting - that's basically doing the same operation (for directional lights, at least), but adding a color from the light source somehow?
just looking for a quick answer to my last question here...being how to do per pixel lighting using the dot product 3 operation...i have bumpmapping working via dot 3, but i can't figure out how i'd integrate the light's color factor into the mix (as the bumpmapping only uses the light's direction)

thanks again to Namethatnobodyelsetook and anyone else who can help. :)
Ignoring ambient, specular, and emissive...

Light generally is diffusematerialcolor * diffuselightcolor * dot3(normal, light). So, just do a modulate (or modulate2x to get both brightening and darkening) by the light color.

From your post you aren't using shaders, and are already using TFACTOR, which makes the hard part getting another color into the texture stages to play with. If you have per stage constants (D3DTA_CONSTANT) available, you can try using that. You could program a stage with out of range UVs and set your textureaddressing mode to border, set the border color to your light color, and then modulate by D3DTA_TEXTURE. You could mix in the light color as a seperate pass. You could make a 1x1 texture. You could put the light color as your vertex color. You could use a pixel shader.
again, thanks so much for the help.

so, in your (and anyone else's who might have one) opinion, it would be best to use a pixel shader? i think the 1x1 texture idea is a good one, if i decide to stay this route, i'll try it that way.
The best option is to use a vertex shader, as it can be software emulated on older hardware, and to use tangent space bump mapping.

In the vertex shader, transform the light vector into tangent space. Output as diffuse. Calculate the material * lightcolor for this material on the CPU, and put in TFACTOR.

Stage 0: dot3 texture, diffuse.
Stage 1: modulate current, TFACTOR.

or, if you have 2 textures available, and cubemaps available.

In the vertex shader, transform the light vector into tangent space. Output as uv0. Use normal UVs as UV1 output. Calculate the material * lightcolor * vertex color in shader, output as diffuse.

stage 0: normalization cubemap
stage 1: dot3 texture,current
stage 2: modulate current, diffuse

You could try stuffing an extra color or vector into specular, and leaving specularenable as false, however some cards don't appreciate that level of creativity. Both of these techniques should work on anything worth supporting. Both of these techniques can work on older pre-pixel shader hardware, requiring one pass per light, with an additive alpha blend to mix each pass. When you have pixel shaders you can attempt multiple lights per pass. I've done 3 diffuse only lights in a single pass ps.1.1 shader. I'm sure I've read that Carmack didn't bother trying to sort out multiple lights per pass in 1.1 hardware, and just does 1 light per pass, similar to what I've posted above. Higher shader versions can pretty much do whatever lighting you want in 1 pass.

If you want your app to work on older hardware (or even GeForce4MX cards), like HalfLife 2 does, then you'll need the non pixel-shader approach, but by all means start playing with vertex shaders if you're getting into per-pixel lighting.
you've been a terrific help. i'm going to use the vs/ps approach. :)

This topic is closed to new replies.

Advertisement