Atmosphere & Terrain Rendering System

Atmospheric scattering of light is important in outdoor scenes. It changes sunlight from the pale red of dawn to the bright yellow of midday and back again. It determines the color and brightness of the sky throughout the day, and it cues us to the distance of objects by shifting their colors.

Atmosphere & Terrain rendering system consist of two shader files (effects\scattering\ScatteringTer.fx, effects\scattering\ScatteringSky.fx) and two script files (scripts\Scattering\Sun.lua, scripts\Scattering\Atmosphere.lua). The shader file 'ScatteringTer.fx'  is for terrain and 'ScatteringSky.fx' is for sky; the script files provides two classes: Sun and Atmosphere to control various parameters.

Script classes reference:

Sun

Atmosphere

Workflow:

1. Models

Sky is a big sphere; and terrain is a wavy square. Import them to Awakening as static mesh (or use the Terrain object). (clue: use terragen or World Machine to create terrain then import to Awakening by .ter file)

2. Textures

decal map

normal map

horizon map

Horizon map only needed for self-shadow, can store in normal map's alpha channel.
To handle shadows well for all 0~180 degree horizon angles, you need two horizon maps: one for angle<90 and another for angle >=90 .

3. Materials

One for sky, load shader file 'ScatteringSky.fx', no texture.
One for terrain, load shader file 'ScatteringTer.fx', decal map set to the 1st texture, normal map set to the 2nd texture.

4. Light

One point light named 'sunlight'.

5. User Script File

First, define script variables in Awakening:



Then in user script file:

1). Add below codes to the start:
require 'scripts\\Scattering\\Sun'
require 'scripts\\Scattering\\Atmosphere'

local materlist={sky,terrain}
sun=Sun.new( materlist )
atmo=Atmosphere.new( materlist )



2). In FrameMove() function, add below codes:
sun.setColor(sunlight.getDiffuse())
sun.setIntensity(40)

local vsundir=sunlight.getPosition()
vsundir.normalize()
sun.setDirection(vsundir,vec.new(vsundir.x,vsundir.y,vsundir.z))

if (vsundir.z>0) then -- assume your sun light circles x-axis
      terrain.setTexture(1,terrain_nh_tga)
else
     terrain.setTexture(1,terrain_nh2_tga)
end

Troubleshooting:

1. If you failed to use the shader files, try to start Awakening as "safe mode".
2. If you use terragen to create terrain, please set terrain size to 129 x 129, otherwise terrain mesh will too big due to the limit of 65536 vertices.
3. The sun is too big? Try to set the G value in Henyey Greenstein approximation function to a bigger number. Or use Atmosphere.setDistanceScale() to adjust.

Tutorial:

Sweet Canyon Mesas