L3DT documentation
Large 3D terrain generator

Differences

This shows you the differences between two versions of the page.

l3dt:algorithms:lm [2017/08/31 05:17] (current)
Line 1: Line 1:
 +====== Light mapping algorithms ======
  
 +===== Overview =====
 +
 +The L3DT lighting routine includes the following features:
 +
 +  * Different RGB spectra for direct and ambient lighting, allowing afternoon sun or full moon effects.
 +  * Anisotropic ambient lighting (discussed below).
 +  * Physically realistic light absorption by water.
 +  * Light refraction in water (shadows, lighting directions, etc).
 +  * Fast shadow casting.
 +  * Bump mapping.
 +
 +===== Calculating light intensity =====
 +
 +The RGB intensity of a pixel in the light map is given by:
 +
 +<html><p class = "wikiex_p_eqn">
 +I<sub>rgb</sub> = Sun<sub>rgb</sub> × N·v + Amb<sub>rgb</sub> × (N<sub>z</sub> + 1) ÷ 2
 +</p></html>
 +
 +Where:
 +  * //Sun// = the RGB intensity (spectrum) of the sun / moon / whatever.
 +  * //Amb// = the spectrum of ambient light.
 +  * //I// = the resulting RGB intensity on the light map pixel.
 +  * //N// = the normal vector from the surface (unit length).
 +  * //N<sub>z</sub>// = is the vertical component of the normal vector (from the [[l3dt:reference:maps:tn|normals map]]).
 +  * //v// = the light vector to the sun (unit length).
 +  * · = the scalar product operator for two vectors.
 +
 +==== Effect of shadows, anisotropic ambient lighting ====
 +
 +If the pixel has been shadowed, then the direct sunlight term (<html><span class = "wikiex_font_eqn">Sun<sub>rgb</sub> × N·v</span></html>) is ignored and only the ambient light term (<html><span class = "wikiex_font_eqn">Amb<sub>rgb</sub> × (N<sub>z</sub> + 1) ÷ 2)</span></html> is considered. 
 +
 +Note that the //N<sub>z</sub>// component in the ambient light term implies ambient lighting is anisotropic. Thus, steep terrain does not receive light from the whole sky hemisphere, and in the limiting case that the land is tilted at 90 degrees (thus //N<sub>z</sub>// = 0) the terrain will see only half of the sky dome, in which case the ambient term becomes <html><span class = "wikiex_font_eqn">Amb<sub>rgb</sub> ÷ 2</span></html>. This hack that assumes the sky dome is a uniformly bright Lambertian shell, which it most certainly is not, but the effect is still better than not doing it.
 +
 +==== Light absorption by water ====
 +
 +If the heightfield pixel is under water, then both //Sun<sub>rgb</sub>// and //Amb<sub>rgb</sub>// are modified by [[http://scienceworld.wolfram.com/physics/LambertsLaw.html|Beers' / Lambert's law]] [link: Wolfram Research] to give physically accurate light maps for the seafloor / lake bottom. The equation goes a little something like this:
 +
 +<html><p class = "wikiex_p_eqn">
 +I / I<sub>0</sub> = T<sub>x</sub>e<sup>-&lambda;x</sup>
 +</p></html>
 +
 +where the ratio //I / I<sub>0</sub>// is the intensity of the light at a depth of //x// as a fraction of the intensity that was incident on the surface, for a medium with an attenuation coefficient of //&lambda;//, and a surface transmission coefficient of //T<sub>x</sub>// (discussed below). This equation is applied to each colour individually, as red, green and blue light are absorbed differently by water. In the '[[l3dt:userguide:ops:lm#light_absorption_by_water|Light/water effects]]' wizard you set the depths at which these colours are attenuated to 1/2 of the original transmitted light.
 +
 +The relationship between half-depth (//x<sub>1/2</sub>//) and absorption coefficient (<html>&lambda;</html>) is:
 +
 +<html><p class = "wikiex_p_eqn">
 +x<sub>1/2</sub> = - loge(2) / &lambda;
 +</p></html>
 +
 +The transmission coefficient //T<sub>x</sub>// is calculated using the [[http://hyperphysics.phy-astr.gsu.edu/hbase/phyopt/freseq.html|Fresnel relations]] [link: Georgia State University]. Second-year university optics at its very best.
 +
 +Anyhoo, I'm sure you get the idea.
 +
 +<html><div align = "center"></html>
 +|  {{l3dt:algorithms:lm:lm2.jpg?250}}  |
 +^  A typical light-map.  ^
 +|  {{l3dt:algorithms:lm:lm2w.jpg?250}}  |
 +^  The same light map, with absorption and refraction by water.  ^
 +<html></div></html>
 +
 +<note>
 +The heightfield is this case was 'wrapping', so shadows were cast across map edges.
 +</note>
 +
 +
 +===== Shadow ray-casting =====
 +
 +The basic approach of shadow casting is described by Mircea Marghidanu in [[http://www.gamedev.net/reference/articles/article1817.asp|this GameDev article]].
 +
 +The method described in that article involves a raycast from the sun to every pixel in the heightfield (or vice versa) to test if each pixel is shadowed. The L3DT routine is a little different insofar as it casts a 'shadow ray'((Yes, I do understand that no such thing exists. It's simply a convenient geometric construct.)) from each heightfield pixel in the direction away from the sun, shadowing all heightfield pixels that lie beneath the ray. The effect is the same, but with less raycasts through empty space. The raycasting terminates when the ray intersects the terrain, which is immediate for any non-shadowing pixel (which is to say, almost all of them). Furthermore, we do not cast shadows from pixels that have been shadowed. This routine is rather fast because it minimises the number of ray-casts.
 +
 +==== Shadows in water ====
 +
 +In L3DT, the 'shadow rays' in the casting routine are refracted when they enter water, in accordance with [[http://scienceworld.wolfram.com/physics/SnellsLaw.html|Snell's Law]] [link: Wolfram Research]. The effect is subtle, but I sleep better knowing it's there.
 +
 +
 +===== High-resolution light mapping =====
 +
 +<note important>
 +This option is only available in [[http://www.bundysoft.com/L3DT/downloads/professional.php|L3DT Professional]].
 +</note>
 +
 +For pretty terrain rendering, it is common to use a 'high-resolution' terrain texture that has a finer pixel size than the terrain heightmap (see [[l3dt:algorithms:tx#high_resolution_textures|high-resolution textures]]). To get the best out of this practice, you need to also generate a high-resolution light map, so that features like shadows don't get washed out. This is exactly what //L3DT Professional// does:
 +
 +<html><div align = "center"></html>
 +|  {{l3dt:algorithms:lm:lm_hires.jpg?350}}  |
 +^  4<html>&times;</html> high-res light map, L3DT Professional (click for larger image).  ^
 +|  {{l3dt:algorithms:lm:lm_lores.jpg?350}}  |
 +^  Regular 1<html>&times;</html> light map, L3DT Standard (click for larger image).  ^
 +<html></div></html>
 +
 +The process is a simple extension of the lightmapping algorithm, whereby the heightfield is interpolated for the shadow-casting and the normals map is interpolated for the bilinear lighting. Additionally, the shadow edges are cleaned using a 3×3 [[wp>Anti-aliasing|anti-aliasing filter]] to remove pixellation. This filter only applies to the shadow state, and thus other lighting data retains its normal sharpness.
 +
 +
 +
 +
 +
 +===== Bump mapping =====
 +
 +<note important>
 +This option is only available in [[http://www.bundysoft.com/L3DT/downloads/professional.php|L3DT Professional]].
 +</note>
 +
 +Bump mapping, as described by [[wp>Bump_mapping|Wikipedia]], is a process by which the [[l3dt:reference:maps:tn|normals map]] of a surface is perturbed during light rendering, typically by an image, to produce more detailed and realistic surface relief. In L3DT, each [[l3dt:algorithms:cli:material|material]] may have its own bump map(s) that are overlayed during the generation of the light map. Below you can see the texture and corresponding bump map for a rock land type:
 +
 +<html><div align = "center"></html>
 +| {{l3dt:algorithms:lm:rock1.jpg}} | {{l3dt:algorithms:lm:rock1_bump.jpg}} |
 +^  Rock texture  ^  Rock bump map  ^
 +<html></div></html>
 +
 +The cliffs in the left image below shows the effect of bump mapping, where the apparent surface relief is enhanced when compared to the non-bump-mapped image (click for larger view):
 +
 +<html><div align = "center"></html>
 +| {{l3dt:algorithms:lm:bumpshot3.jpg?350}} | {{l3dt:algorithms:lm:bumpshot2.jpg?350}} |
 +^  With bump mapping  ^  Without bump mapping  ^
 +<html></div></html>
 +
 +Note that the effect of bump mapping is most noticeable when the light is at glancing angles to the surface. When the light direction is perpendicular to the surface, bump mapping has a lessened effect. 
 +
 +Here is another example, using bump mapping to apply the appearance of sand dunes:
 +
 +<html><div align = "center"></html>
 +^  With bump mapping  ^  Without bump mapping  ^
 +| {{:l3dt:algorithms:lm:desert_bumped_2d.jpg?350}} | {{:l3dt:algorithms:lm:desert_nobump_2d.jpg?350}} |
 +| {{:l3dt:algorithms:lm:desert_bumped.jpg?350}} | {{:l3dt:algorithms:lm:desert_nobump.jpg?350}} |
 +<html></div></html>
 +
 +<note>
 +There are even prettier bump mapping screenshots in the [[bundynews>blog:2006-may-26|development blog]].
 +</note>
 
l3dt/algorithms/lm.txt · Last modified: 2017/08/31 05:17 (external edit)
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki