Per Vertex Lighting with terrain textures.

Say i have a terrain texture which i stretch over the terrain mesh, and i multitexture over that a detail texture repeatedly. Anyway, how can i get per vertex lighting? Because what i currently do is when calculating the terrain texture, i also multiply the value of each texel of the texture buy the dot product of the vertex normal of the curresponding point on the mesh. But then i get plane lighting and the shading is VERY flat and is not smooth and ugly. I cannot simply use glColor3f for the verteces because im using single pass multitexturing. Anyone have any ideas? Ive seen per vertex lighting in terrain engines before that use a single terrain texture and a detail texturew, but i dont know how to do this.

How do you send your terrain mesh to OpenGL?
I recommend you use glDrawElements. It’s a lot faster than glBegin/glEnd and it makes specifying attributes per vertex very easy.

To do per vertex normals with glDrawElements, you do something like this:

glEnableClientState(GL_NORMAL_POINTER);
glEnableClientState(GL_VERTEX_POINTER);

glNormalPointer(GL_FLOAT, 0, normals);
glVertexPointer(3,GL_FLOAT,0,vertices);

glDrawElements(GL_TRIANGLES, numverts, GL_UNSIGNED_SHORT, indices);

That’s how you render. Calculating the normals is the hard part though. This is how you do it:

-for each vertex
-find all of the facets(polygons) which use it.
-Average the surface normals of all of those polys, and store the average normal as the normal for this vertex.
-repeat

Then send it to GL like I said above.
Check out my engine at http://home.earthlink.net/~ioquan/x3d.htm. It does all of this and it comes with the source code.

ALl my normals and stuff are pre claculated, thats easy. What i do is strecth the texture over the terrain, so each polygon of the terrain is textured with a tiny fraction of the terrain texture, and also with the detail tetxure. I do not want to use OpenGL lighting, i think that thats what your suggesting. Im using a kind of lightmapping method, im basically combining a lightmap with teh terrina texture putting it all into one texture.

Use opengl lighting and specify normals - thats my advice.

Cant, opengl lighting doesnt work when using multitexturing, plus i want to have shadows and stuff thats why im precalculating the lighting.

The lighting system and multitexturing are two completely separated operations. They work independent of each other. It’s just a matter of setting up the correct texture combine function to get lighing “working” with multitexturing.

The lighting system is not disabled once you enable a second texture unit. You can access the lighting in the textrure evironment as the primary color. Lighting “replaces” calls to glColor when enabled.

Ok then, how do i make it so that i can still call glColor3f for every vertex in the mesh and multitexture in single pass?? because currently OpenGL simply ignores my calls to glColor3f. If i could get this to work all my problems would be solved :slight_smile:

Shoe, I’m doing it following way in my engine and it looks VERY good. I don’t use any complex calculations for this at all to keep the FPS high. The limitation of my algorithm is that the light has to be directed along any of the axis, but well, that’s in most engines the case, in X-isle as well. I simply check the height difference to the next field on the right. Limitate the value to 100 and add this to 150, so that the brightness “swings” between 50 and 250. After this simple shading I check, how much this field is covered in direction to the sun by other fields through tracing up to a set value into the direction of the sun, counting through how much “earth” I have to go. This way the hills and mountains throw additional soft shadows onto the landscape. When calculating the lightmap of this data then I interpolate the shadow/lighting intensity by all surrounding fields of the pixel then.

BlackJack

“Normal” lighting on a texture is texture * light. With multitexturing, there are a few different ways to achieve a lighting effect, depending on what the two textures represent.

Since you mentioned detail texture, I assume the first texture is a base texture (grass, sand, rock, whatever makes the base of the terrain), and a detail texture added ontop of this. So I assume you want something like this: (base texture + detail texture) * light.

This would require three texture units with using ARB_texture_env_combine, where the last unit is only used to modulate the light. However, if your detail texture does not contain very bright and dark areas (i.e. affecting the base alot), you can get away with a simpler formula; base texture * light + detail texture.

The last formula can be realized as follows.

glActiveTexture(GL_TEXTURE0);
glBindTexture(base texture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glActiveTexture(GL_TEXTURE1);
glBindTexure(detail texture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD_SIGNED);

Bob, 3 texture units are totally unneeded. I’ve also got detail+base+light, but simply preblend it for each visible getting cell (8x8 squares in my case) and keep them in textue memory while they’re visible. New ones are preblended in PBuffer. To use combiners is a “sin”, to use 3 texture units anyway, because with this you would cut off all cards below GeForce 3.

Texture 0: basemap
Texture 1: colormap+shadow/lightmap
http://www.lyxion.com/images/landcap.jpg

BlackJack

[This message has been edited by BlackJack (edited 06-28-2002).]

Well, three texture units is needed if you want (base texture + detail texture) * light without any precalculations. Even if the light is comming from the primary color instead of a texture. Assuming you use ARB_texture_env_combine that is. Not sire about other vendor specific extensions, but I assume you can cut it to two then.

Sure, with ARB_texture_env_combine you can still cut it to two, if you make some assumtions and precalculations.

I currently do (base map * light) + detail with one texture texture unit. They key is to use a little higher resolution on the terrain mesh, so you can put the base texture in the vertex color instead of burning a texture unit. Looks very good if used with a proper detail texture.

base*light + detail… yeah, sounds nice… and i wondered all time why my landscape looked so dark when using xisle’s texture for testings … well… am doing it the multiplicative way now… i think if i would want to change it to ADD now our graphicians would beat me , but looks nice nevertheless, doesn’t it?

Well… in our old engine we stored the color in the vertices too, but that looked so… monotone. But I simply precompute the lightmap and basetexture, so two units are enough.

BlackJack

Ok, ive just done this: modulate the first texture unit, the base texture, with teh colour, and modulte the second texture unit with the previous texture. And yer, works. Now i just use color3f for each vertex to get per vertex lighting.