Skip to main content
GameDev.net gamedev.net
🔒 Locked

Lighting terrain

Started by sirSolarius Feb 22, 2005 at 5:09 PM 8 replies 1.6k views
Original Post
sirSolarius
sirSolarius
My game engine is going to precompute lighting on a terrain, but I don't know a good algorithm to use. Right now I'm just making the sun a directional light and doing:

for(int x=0; x < h->m_mapWidth; ++x)
	{
		for(int z=0; z < h->m_mapLength; ++z)
		{
			float innerProduct=lightpos.dot(h->m_normals[x+z*h->m_mapWidth]);
			if(innerProduct < MIN_LIGHT_PERCENTAGE)
					innerProduct=MIN_LIGHT_PERCENTAGE;

			for(int pixelX=0; pixelX < pixelsPerVert; ++pixelX)
			{
				for(int pixelZ=0; pixelZ < pixelsPerVert; ++pixelZ)
				{
					tex[3*(x*pixelsPerVert+pixelX+((z*pixelsPerVert+pixelZ)*sizeX))]*=lightR*innerProduct;
					tex[3*(x*pixelsPerVert+pixelX+((z*pixelsPerVert+pixelZ)*sizeX))+1]*=lightG*innerProduct;
					tex[3*(x*pixelsPerVert+pixelX+((z*pixelsPerVert+pixelZ)*sizeX))+2]*=lightB*innerProduct;
				}
			}
		}
	}

I get some _really_ dark (ie black) areas of the terrain though, and it doesn't look very realistic. Is there a better lighting model I can use? Thanks!
JohnBolton
JohnBolton
Add an ambient value.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
The Scytheman
The Scytheman
What you need is to account for indirect lighting (atmosphere and surrounding terrain). Otherwise, the areas in full shadow relative to the sun will be black. You can approximate indirect lighting by adding an ambient lighting term. Actually that clamping (MIN_LIGHT_PERCENTAGE) code of yours should ensure that there's always some lighting.

You can get more accurate results by constructing an environment map M(theta,phi) out of the sky texture and calculating the reflection integral at each point (u,v) on the terrain texture. Assuming ideally diffuse reflections on the terrain, this involves representing the environment map and per-texel visibility function V_u,v(theta,phi) in a suitable basis (e.g. spherical harmonics). The reflection integral can then be computed per-texel as a dot product between the coefficient vectors corresponding to the functions M and V. This does not take into account terrain-terrain interreflections, but does take the contribution of the whole sky in so far it is not occluded by the terrain.

-- Jani



sirSolarius
sirSolarius
Ok, clamping the light value has helped a bit. I put in some terrain self-shadowing, but I'm getting some random dots here and there. I'm going to render the terrain at a ratio of 4 pixels:1 vertex and I'll see if that helps at all.
The Scytheman
The Scytheman
By the way, that 'lightpos' vector and the normal vectors should be normalized. Otherwise your code will produce values greater than 1 for that dot product (I suspect this is not what you want).

-- Jani
The Scytheman
The Scytheman
It would be interesting to see a terrain engine dynamically lighting the terrain with an environment map representing the sky. You could get very nice results that way. It'd probably take quite a lot of memory, but who cares? I don't. :)

Of course, just to be able to do real-time shadowing due to a typically very slowly changing sky might be considered a waste of clock cycles. :)

-- Jani
sirSolarius
sirSolarius
Yeah, I'm going to keep things static and precomputed for the terrain.

My question is, once I've generated a lightmap, how do I apply it to the objects in the scene? Shading the terrain is fine, but when something steps into the shadows how do I know to darken the object?
The Scytheman
The Scytheman
Assuming you haven't baked the lightmap into the texture, you could approximate that by checking the lightmap values at the current position of an object. Of course, this only produces acceptable results if the objects lie on the ground..

-- Jani
sirSolarius
sirSolarius
Right now I am baking the lightmap, but for obvious reasons I would like to avoid this. Is there an efficient way to apply this global lightmap to every object?
The Scytheman
The Scytheman
Some ideas from the top of my head:

1. Do a lightmap look-up at the position of the object to get an estimate of lighting at that position and just shade the whole object with that. Isn't robust (e.g. doesn't work for flying objects too well), but is simple.

2. Do a visibility test on the sun. This information could be cached in a PVS of some sort. This option supports flying objects as well.

3. Project the lightmap texture on top of the terrain and the objects. Not robust either.

4. Use shadow buffering. Gives shadowing for objects easily, but is prone to visual artifacts unless you use high resolution shadow buffers or do some fancy sampling magik.

5. Create some kind of shadow volumes for the hills (stencil shadows).

Just ideas.. don't take them too seriously. :)

-- Jani

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.