View Full Version : Standard lighting with ARB vertex program.

02-03-2006, 07:17 AM
Hi all, I'm trying the following ARB vertex program:


# Performs transformation and ambient, diffuse
# and specular lighting with a directional light souce

ATTRIB iPos = vertex.position;
ATTRIB iNormal = vertex.normal;
ATTRIB iTxCoord = vertex.texcoord;

PARAM mvinv[4] = { state.matrix.modelview.invtrans };
PARAM mvp[4] = { state.matrix.mvp };
PARAM lightDir = state.light[0].position;
PARAM halfDir = state.light[0].half;
PARAM specExp = state.material.shininess;
PARAM ambCol = state.lightprod[0].ambient;
PARAM diffCol = state.lightprod[0].diffuse;
PARAM specCol = state.lightprod[0].specular;

OUTPUT oPos = result.position;
OUTPUT oColor = result.color;
OUTPUT oTxCoord = result.texcoord;

TEMP eyeNormal, temp, dots;

# Transform the vertex to clip coordinates
DP4 oPos.x, mvp[0], iPos;
DP4 oPos.y, mvp[1], iPos;
DP4 oPos.z, mvp[2], iPos;
DP4 oPos.w, mvp[3], iPos;

# Transform the normal into eye space
DP3 eyeNormal.x, mvinv[0], iNormal;
DP3 eyeNormal.y, mvinv[1], iNormal;
DP3 eyeNormal.z, mvinv[2], iNormal;

# Compute diffuse and specular dot products
# and use LIT to compute lighting coefficients
DP3 dots.x, eyeNormal, lightDir;
DP3 dots.y, eyeNormal, halfDir;
MOV dots.w, specExp.x;
LIT dots, dots;

# Accumulate color contributions and pass alpha
MAD temp, dots.y, diffCol, ambCol;
MAD oColor.xyz, dots.z, specCol, temp;
MOV oColor.w, diffCol.w;
MOV oTxCoord, iTxCoord;

ENDBut I can only make it work if light[0] is a directional light, and seems to work only on eye coordinates (as if the light were attached to the view).

Please.. where can I find examples of how to perform a standard shading with a point light source in world coordinates? How distance falloff should be treated?

Also, how can I do a COS(x) in a vertex program? :eek:

02-04-2006, 03:57 PM
Some things to remember when doing lighting:

1. Point lights have position.w = 1, directional lights have position.w = 0.

2. OpenGL transforms your light position with the current modelview matrix (just like points).

3. Make sure all the vectors used in lighting are in the same space. (You say you want to perform lighting in world space but your normal transform is view dependent.)

You can approximate cos and many other functions by using the first few terms of the Taylor series expansion.

cos x = 1 - x^2/2! + x^4/4! - x^6/6! + ...

You'll want to range reduce x for best results (closer to 0 the better).


02-04-2006, 04:22 PM
In case you didn't know, the NVIDIA-specific extension has the SIN and COS instructions built in:

If you're into that sort of thing.


02-04-2006, 04:32 PM
#define Cos(x) (float)cos(x)

Like that? or;

#include <math.h>

02-04-2006, 07:23 PM
Thanks to all.

I figured out the problem with lighting was that I was using vectors in different CSs.

As for the cos(x) I used Taylor series:

# Constants to aproximate cos() using taylor method
PARAM cpow = { 2, 4, 6, 8 };
PARAM cden = { -0.5, 0.04166667, -0.00138889, 2.48015873e-5 };

MOV r1.x, one.x; # Compute cosine of angle.x
POW r0.x, angle.x, cpow.x;
POW r0.y, angle.x, cpow.y;
POW r0.z, angle.x, cpow.z;
POW r0.w, angle.x, cpow.w;
MUL r0, r0, cden;
DP4 r1.x, one, r0;For sin(x) I did cos(x-PI/2) as sin() approximation lacks precission compared to cos() approximation.

Is the above code ok? Any performance suggestion?