Advertisement Jump to content
Sign in to follow this  
Fibonacci One

Atmospheric scattering (preetham)

This topic is 4588 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I'm trying to implement the atmospheric scattering method described by preetham here or here. While I have something that looks somewhat like what I would expect the final result to look like, there are still several things that are clearly wrong. The sun is tinted teal, there is no sunset effect when I move the light near the horizon, and the opposite side of the skysphere is less bright than around the sun, but more bright than the rest of the sky. I'm sure that all of these problems are from my misunderstanding of some part of the theory, but other than the way I'm separating calculations for each of the wavelengths I don't see what I'm missing. Here is the shader source:
float4x4 worldViewProj  : WORLDVIEWPROJECTION;
float4x4 world            : WORLD;
float3   camPos;            // The camera's position
float3   sunVec;            // The sun's direction

const float3    invWaveLength4 = {5.602045, 9.473285, 19.643818}; // 1 / (wavelength^4) for each channel
const float        Br = 0.0025;
const float        Bm = 0.001;
const float        Esun = 1.0;
const float        g = 0.80;

struct SkyDomeOutput
    float4 position : POSITION;
    float3 inscattering : TEXCOORD0;

SkyDomeOutput VS_SkyDomePass(float4 position : POSITION)
    float3 worldpos = mul(position, world).xyz;
    float3 viewDir = worldpos - camPos;
    float distFromCamToVert = length(viewDir);
    viewDir /= distFromCamToVert;
    sunVec = normalize(sunVec);
    float costheta = dot(viewDir, sunVec);
    float BrTheta = (3.0 / (16.0 * 3.14159)) * Br * (1 + costheta*costheta);
    float BmTheta = (1.0 / (4.0 * 3.14159)) * Bm * ( (1 - g)*(1 - g) / pow(1 + g*g - 2*g*costheta, 3.0/2.0) );
    float extinction = exp(-(Br + Bm) * distFromCamToVert);
    float inscattering = (BrTheta + BmTheta) / (Br + Bm) * Esun * (1 - extinction);
    SkyDomeOutput sdo;
    sdo.position = mul(position, worldViewProj);
    sdo.inscattering = invWaveLength4 * inscattering;
    return sdo;

float4 PS_SkyDomePass(float3 inscattering : TEXCOORD0) : COLOR
    return float4(, 1.0);

Here are a few screenshots that might help diagnose the problem. The jpg compression and the shrinking mess the image up a decent amount, but you can still see what I think you need to see. Image of the sun with the shader set as above. An image where you can see from the sun to the horizon. (The scattering has not yet been applied to the terrain) Image of the sun with the inscattering multiplied by float3(5.0, 5.0, 5.0) rather than invWaveLength4 If anyone has an idea about what I'm doing wrong I'd appreciate the help. As usual, thanks in advance for your help. P.S. Please, no comments about the (lack of) naming convention or the terrain erosion. I know they suck, thank you. =)

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!