Attenuation

Iam trying to add attenuation to my scene.
Iam doing this in a vertex program, and register combiners. But its just wont work right, i got attenuation, but not like intended.

“DP4 o[HPOS].x, c[0], v[OPOS] ;”
“DP4 o[HPOS].y, c[1], v[OPOS] ;”
“DP4 o[HPOS].z, c[2], v[OPOS] ;”
“DP4 o[HPOS].w, c[3], v[OPOS] ;”
//c[5]=lightpos
“MOV R1,c[5];”
“ADD R2.xyz, -R1, v[OPOS];”

//Transform light vec to tangentspace
“DP3 R4.x, R2, v[1];”
“DP3 R4.y, R2, v[2];”
“DP3 R4.z, R2, v[3];”
//c[4].w = 1/light radius
//c[4].z = 0.5
“MUL R2.xyz, R4, c[4].w;”
“MAD R3,R2, c[4].z, c[4].z ;”
//Tex0 = radial map 2D
“MOV o[TEX0].xyz,R3 ;”
“MOV o[COL0].xyz,R3;”
“END”;

"{
"
" rgb {
"
" discard = tex0;
"
" discard = col0.b;
"
" spare0 = sum();
"
" }
"
"}
"
"out.rgb=lerp(spare0,zero,unsigned_invert(zero));
"
"out.a = unsigned_invert(zero);
"

I have read Ron Frazier’s very nice paper and trying to do the same but cant see what is wrong.

PLEASE help
/Marcus

Originally posted by Tandy:
[b]Iam trying to add attenuation to my scene.
Iam doing this in a vertex program, and register combiners. But its just wont work right, i got attenuation, but not like intended.

“DP4 o[HPOS].x, c[0], v[OPOS] ;”
“DP4 o[HPOS].y, c[1], v[OPOS] ;”
“DP4 o[HPOS].z, c[2], v[OPOS] ;”
“DP4 o[HPOS].w, c[3], v[OPOS] ;”
//c[5]=lightpos
“MOV R1,c[5];”
“ADD R2.xyz, -R1, v[OPOS];”

//Transform light vec to tangentspace
“DP3 R4.x, R2, v[1];”
“DP3 R4.y, R2, v[2];”
“DP3 R4.z, R2, v[3];”
//c[4].w = 1/light radius
//c[4].z = 0.5
“MUL R2.xyz, R4, c[4].w;”
“MAD R3,R2, c[4].z, c[4].z ;”
//Tex0 = radial map 2D
“MOV o[TEX0].xyz,R3 ;”
“MOV o[COL0].xyz,R3;”
“END”;

"{
"
" rgb {
"
" discard = tex0;
"
" discard = col0.b;
"
" spare0 = sum();
"
" }
"
"}
"
"out.rgb=lerp(spare0,zero,unsigned_invert(zero));
"
"out.a = unsigned_invert(zero);
"

I have read Ron Frazier’s very nice paper and trying to do the same but cant see what is wrong.

PLEASE help
/Marcus[/b]

I haven’t read the Frazier paper but one way to do it is as follows:

l = vector from light to vertex
a = constant attenuation term (how far from light source must you be to get full attenuation)

v = l/a

send the v vector to the pixel shader (as a texture coordinate) and compute dot3(v, v). this is a scalar and you can use it to lookup into a 1D attenuation texture.

the trick is that dot3(v,v) is the normalized distance squared. you should account for this when creating the 1D attenuation map. the 1D map should be white at one end and black (or ambient) at the other. also, make sure you enable clamping for objects that are very far away (further than a units away).

ie.

vertex shader
{
a = 30.0f // full atten @ distance of 30
l = vertex - light
tex_coord = l/a
}

pixel shader
{
r1 = dot3(tex_coord, tex_coord)
r2 = sample_1D_map(r1)
.
.
.
output_color = base_map * r2
}

[This message has been edited by chrisATI (edited 04-01-2002).]

[This message has been edited by chrisATI (edited 04-01-2002).]

Wow Chris!
That was really nice of you to answer a nvidia orientated question (vertexprograms/regcombiners) with a good generic bit of pseudo-code
Now its nvidia’s turn to answer a vertex_object question, or something…

Thanx for the tips Chris, i will give it a try!

/Marcus

there is only one problem: what the atiguy suggests is a way very logical, but only possible on an ati radeon 8500 with fragmentshaders. on nvidia-hardware you can’t dot a texcoord with itself and then use it as texturelookup in a 1d tex, as i asked some posts before (texture shader coord length, i think…)

you have to workaround… and you’ll eighter loose memory (using a 3d-texture) or texture stages (2 stages and 1 1d-texture will work…)