View Full Version : per pixel attenuation

05-28-2003, 09:20 PM
I got a problem of implementing dynamic lighting across planar surfaces by per pixel attenuation method without using gl extensions.I actually know how to do it with Quake levels with lightmaps,but I just want to do the lighing without lightmaps.Is there any other way?

05-29-2003, 12:22 AM
If you don't want to use extensions, you can either use conventional OpenGL lighting or use lightmaps. One solution with multitexturing could be using a attenuation map with a intensity map, generate texture coords for every vertex/light and use some sort of alpha-interpolation.
BTW, if you want to implement dynamic lighting you should use extensions. DL is nothing for old graphic cards.

05-29-2003, 01:17 AM
So there is a method only using multitexture to do it?But I think multitexture could be easily replaced right?So what is it anyway?BTW,do you know how Quake3 does for dynamic lighting across bezier patches?


05-29-2003, 01:49 AM
Quake3 tesselates the beziar patches into standard triangles when it loads its maps, so it treats them as any other surface when doing dynamic lighting

05-29-2003, 03:58 AM
Yes,I know that.But I just wondered if there are some optimizations or other ways for it.And also not all of the surfaces in Quake3 have lightmaps,but they still gets distance attenuated lighting effects on dynamic lighting.

05-29-2003, 04:05 AM
The best way is to use per-pixel lighting but that mean use extensions. You can emulate it with textures. For example, attenuation map is a 1D texture with alpha values for which you generate texture coord based on dinstance and blend it with color of fragment.
B.T.W. Conventional lighting in GL has attenuation! What are you willing to do? I don't understand your problem.

05-29-2003, 04:46 AM
Well I just want to do the dynamic lighting without q3's lightmap scheme.Say I got a triagle,and all of its details,the vertex coords,texcoords and normal,the tangent space details, then a point light.Then how do you do attenuation?If there is no way of doing it without extensions I will just give it up.

05-29-2003, 10:03 AM
as far as i know, the problem is that for per-pixel lighting, a dot product between two vectors has to be computed to get the brightness of a fragment (light vector * normal vector), and it is not possible to do that per fragment in standard opengl. there are at least three ways to do it with extensions (as far as i know), but no one without them.


05-29-2003, 04:11 PM
A dot product is simply the sum of three products, which you can do in unextended opengl... if you are willing to do three passes for each dot product.

05-30-2003, 07:33 AM
Actually, OpenGL can't do subtract directly, so you have to do 6 passes with an approximation of subtraction... I believe Cass's thesis was about doing bump mapping in unextended OpenGL, you could search for that.

05-30-2003, 08:01 AM
How does per pixel attenuation work if theres a big triangle and the light is right in the middle of it? The attentuation values for the vertices will be very high since the light is far away. Interpolating this value across the triangle results in a very dark triangle even tough the light is standing right in front of it!

05-30-2003, 10:02 AM
That's per-vertex attenuation you described, not per-pixel.

05-30-2003, 10:14 AM
Simple solution: tesselation with the standard GL lighting model. I think this would be faster than using six passes.

05-30-2003, 10:24 AM
Well how do you calculate per pixel attentuation then? I think you'd need to store the vertex position in a texcoord that gets interpolated for the pixel shader. Then you could calculate the distance from the pixel pos and the lightpos ( which you also need to pass to the pixel shader ) in order to calculate the attentuation. Now if you wanted to do it properly so everything is per pixel, you would also need to calculate the light and the halfvector this way because otherwise the center of light is not interpolated properly across the triangle. To do this, you'd also need to interpolate the objToTangentSpace 3x3 Matrix, which is where I get stuck, since i dont know whether it is at all possible to, correctly interpolate this matrix across the triangle

05-30-2003, 05:20 PM
Thanks for suggestions,but I would not be bothered to do it that way now.Use dynamic lightmapping for quake style lighting or use rc and stencil without quake's lightmap for better effects performance.

05-30-2003, 11:37 PM
Can anyone explain where the error in my theory lies?

05-31-2003, 01:31 AM
Your theory is too complicated? And how you gonna compute subtraction of texcoords without DX9 hardware? Or at least without extensions(It could be possible to do with NV_texture_shader, I guess, but I woudn't bother).

05-31-2003, 01:45 AM
Well how do you do per pixel attentuation and per pixel light vector calculation properly then? ( BTW: Where did I tell anything about TexCoord substraction? You dont need that for what i described above ( if it would at all work, what i described since i dont know if its possible to interpolate the tangent binormal normal properly across the triangle )

[This message has been edited by Dtag (edited 05-31-2003).]

05-31-2003, 04:37 AM
The iddea is to compute per-pixel attenuation without extensions.
Say 'a' is attenuation factor(0 to 1)

a = attfunc(distance)

r is the radius of the light sphere(point at distance r will have a 0)

Then we compute a 1D map with GL_INTENSITY format. It will be our attenuation map. We activate clamping and fill our map with attfunc values, so that map(dist/r) will give us attenuation factor.

The rest is simple: you compute distance at every vertex and pass distance/r as s texture coordinate for attenuation map. There you got it.

This is the common way to compute attenuation(on <DX9 hardware).

05-31-2003, 05:10 AM
Hmmm I still dont understand in what way this solves the problem that i explained before. If the light is in front of a big triangle the attenuation will still be interpolated which will again result in a high att all over the triangle.

"The rest is simple: you compute distance at every vertex and pass distance/r as s texture coordinate for attenuation map. There you got it."

Example: if the light is in the center of the triangle ... say we have a dist to all verts of 100. The vertex shader will compute the same texcoord for all 3 vertices. Interpolated across the tri, this is again the same coord for all pixels. This is not a true per pixel thing!

05-31-2003, 05:49 AM
Well,maybe I'm completely wrong or trivial,but if we got a precaculated attenuation map,with the surf tangent space details we blend the map with a quad of constant dimension,using stencil to make sure quad only blend within the surface,and use glColor to filter the atten map color according to the light color and distance. So what's wrong with it?

05-31-2003, 06:17 AM
"we got a precaculated attenuation map,with the surf tangent space details we blend the map with a quad of constant dimension"

How do you blend an 1D Attentuation Map with a 2D Texture?

"using stencil to make sure quad only blend within the surface"

Hmm ive heard of a per pixel lighting/attenuation technique that needs the stencilbuffer

"and use glColor to filter the atten map color according to the light color and distance"

Distance to what?

05-31-2003, 06:52 AM
no,I mean 2d attenuation map,just like a lightmap.

"Distance to what?"
Distance to surface.The further the distance,the lower a variable k to be mutiplied by the rgb params glColor recieve.

Maybe even if it does work,it's unpractical,and may not work well.

05-31-2003, 07:04 AM
Well you cant use the distance to a surface in a per pixel program because every point of the triangle has probably a different distance to the light.
What you describe really seems to be a lightmap only. Iam talking about real per pixel lighting with per pixel attenuation and per pixel light vector calculation.

06-01-2003, 06:38 AM
Dtag, the question(as far as I understood) was to make attenuation without extensions, so, without real per-pixel lighting. Your example is good, but it's an extreme case. If you use such algorithm as I proposed, you should take relativ small triangles to avoid interpolation issue(like per-vertex specular lighting).

06-01-2003, 07:39 AM
I never said anything about extensions. In fact iam using pixel/vertexshaders ( cg ). What Iam doing IS real per pixel lighting, because the final diffuse value is calculated per pixel and not per vertex. The only problem i have is that the light/half vector and the attenuation is not interpolated properly across the triangle in situations like the one i mentioned before.

Ah and btw: about your suggestion to tesselate the surface. I cant do that because its provided by the map format which i dont want to change. Tesselating the surface at runtime is something i dont really want to do.

[This message has been edited by Dtag (edited 06-01-2003).]

06-01-2003, 07:56 AM
The simplest way in vanilla GL that I have found is, to use a combination of two textures. One 2D texture holds a radial gradient that represents your attenuation function in 2D, the other is a 1D texture that holds the attenuation function for the 3rd dimension. You can either render in two passes or multiply the two using texture environment combiners. The resulting color is your 3D attenuation function, with the texture coordinates as input. Simple object space or eye space texgen can generate the necessary texture coordinates for you, and then you can even move and scale the light source using the texture matrix.

06-01-2003, 09:12 AM
Dtag, vertex/pixel shaders are extensions http://www.opengl.org/discussion_boards/ubb/smile.gif

Oh, at DX9 hardware you can pass vertex and light coordinate per texture coords and compute the dist vector in your fragment shader. On GF3-4 ... hm.. I think it's just impossible to do perfectly. Maybe you can use some texture shaders tricks. Or use attenuation maps http://www.opengl.org/discussion_boards/ubb/smile.gif