Re: [Algorithms] It looks terrible (was: Lightmap Terrain)
Brought to you by:
vexxed72
From: Klaus H. <k_h...@os...> - 2000-08-29 06:11:54
|
Mark, From: Mark Wilczynski <mwi...@cy...> > Hi Niki, > > You could also try the trick that many people used when > making outdoor levels for Quake based games. They create a > 2D grid of lightsources on a plane in the sky. The > brightness of each light is adjusted based on the sun > position. This method approximates an area light source > (sky/clouds) instead of just a point light (sun). This would be another option, but if I understand it correctly, then you lose the properties of a directional light source. I'll have a look at the modeling sites, though. > Search > around the Quake modeling sites for more details. By the > way... I think your lightmap looks fine. Lightmaps never > look very good when viewed alone. I disagree. I have tried the method I described, and the results look great (including the dark sides of the mountains). The method has all the features I was looking for, except that the shadows are still sharp (didn't take care about this, yet). My current implementation of this is sort of brute force, though: I specify the position of the sun as a point on a unit sphere (longitude, latitude). Then for each vertex of the surface, I calculate the vertex normal, and then use this normal to calculate a second point on the unit sphere (longitude, latitude). Then I compute the shortest distance between the two points on the sphere (that is along the great circle). This gives a distance in the range [0; PI]. I divide this distance by PI to get a distance in the range [0; 1], and then I apply a bias-function to the distance in order to compute the light intensity. I'm sure there's cheaper methods to compute this, but here's some help for those who'd like to try this: float GreatCircleDistance(float lon1, float lat1, float lon2, float lat2) { float theta = lon2 - lon1; float dist = acos(sin(lat2) * sin(lat1) + cos(lat1) * cos(lat2) * cos(theta)); if (dist < 0) dist += PI; return dist / PI; } A vertex normal can be converted into (lonVertex, latVertex) as follows (y-component represents elevation): lonVertex = atan2(normal.z, normal.x) latVertex = atan2(normal.y, sqrt(normal.x^2 + normal.z^2)) For the shadow casting you may also need to convert the light source's (lonLight, latLight) into a unit vector: lightDir.x = cos(lonLight) * cos(latLight); lightDir.y = sin(latLight); lightDir.z = sin(lonLight) * cos(latLight); The intensity is computed as follows: I = GreatCircleDistance(lonLight, latLigh, lonVertex, latVertex); I = 1.0f - pow(I, log(b) / log(0.5)); Where b is the bias. In this case, b is some value > 0.5 (I used 0.6). This basically defines the gradient of the intensity over the sphere. I'll probably try a couple of other functions, too, and see what yields the best results. > You have to blend them > with a noisy base texture to get a decent effect. The noisy base texture will further enhance the quality, yes. Thanks, Niki |