Jump to content
  • Advertisement
Sign in to follow this  

help with atmospheric scattering

This topic is 2053 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


I'm trying to implement atmospheric scattering (Sean O'Neil style). For the sky I can get good enough results, but I have problems with terrain. This is the GLSL vertex shader I use for terrain, can someone help me find the problem?

// Atmospheric scattering vertex shader

// Author: Sean O'Neil

// Copyright (c) 2004 Sean O'Neil

#version 120

uniform vec3 v3CameraPos;            // The camera's current position

uniform vec3 v3LightPos;            // The direction vector to the light source

uniform vec3 v3InvWavelength;        // 1 / pow(wavelength, 4) for the red, green, and blue channels

uniform float fInnerRadius;            // The inner (planetary) radius

uniform float fKrESun;                // Kr * ESun

uniform float fKmESun;                // Km * ESun

uniform float fKr4PI;                // Kr * 4 * PI

uniform float fKm4PI;                // Km * 4 * PI

uniform float fScale;                // 1 / (fOuterRadius - fInnerRadius)

uniform float fScaleDepth;            // The scale depth (i.e. the altitude at which the atmosphere's average density is found)

uniform float fScaleOverScaleDepth;    // fScale / fScaleDepth

uniform int Samples;

float scale(float fCos)


    float x = 1.0 - fCos;

    return fScaleDepth * exp(-0.00287 + x * (0.459 + x * (3.83 + x * (-6.80 + x * 5.25))));


void main(void)


    vec3 radius = vec3(0.0, fInnerRadius, 0.0 );

    vec3 trueCameraPos = v3CameraPos + radius;

    // Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere)

    vec3 v3Pos = gl_Vertex.xyz + radius;    

    vec3 v3Ray = v3Pos - trueCameraPos;

    float fFar = length(v3Ray);

    v3Ray /= fFar;

    if (trueCameraPos.y < v3Pos.y)


        vec3 t = v3Pos;

        v3Pos = trueCameraPos;

        trueCameraPos = t;

        v3Ray = -v3Ray;


    v3Pos = normalize(v3Pos);

    // Calculate the ray's starting position, then calculate its scattering offset

    vec3 v3Start = trueCameraPos;        

    float depth = exp((fInnerRadius - trueCameraPos.y) * (1.0 / fScaleDepth));

    float fStartAngle = 1.0;

    float fLightAngle  = dot(v3LightPos,v3Pos) / length(v3Pos);

    float fCameraScale  = scale(fStartAngle);

    float fLightScale = scale(fLightAngle);

    float fCameraOffset = depth*fCameraScale;

    float fTemp = (fLightScale + fCameraScale);

    float fSampleLength = fFar / float(Samples);

    float fScaledLength = fSampleLength * fScale;

    vec3 v3SampleRay = v3Ray * fSampleLength;

    vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;

    // Now loop through the sample rays

    vec3 v3FrontColor = vec3(0.0);

    vec3 v3Attenuate;

    for(int i = 0; i < Samples; i++)


        float fHeight = length(v3SamplePoint);

        float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));

        float fLightAngle = dot(v3LightPos, v3SamplePoint) / fHeight;

        float fScatter = fDepth*fTemp - fCameraOffset;

        v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));

        v3FrontColor += v3Attenuate * (fDepth * fScaledLength);

        v3SamplePoint += v3SampleRay;


    // Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader

    gl_FrontSecondaryColor.rgb = v3Attenuate;//  v3FrontColor * fKmESun;

    gl_FrontColor.rgb = v3FrontColor * (v3InvWavelength * fKrESun + fKmESun);    

    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;


Share this post

Link to post
Share on other sites

How is your terrain scaled with respect to the sky? Be aware that the distances for the sky calculation are of much higher order of magnitude as compared to distances from terrain to observer. Is your camera position given in the same units as the other parameters (e.g. planet radius)? For the in-scatter integral from terrain to observer, you can also make several simplifying approximations, if you only consider a small "flat" portion of the ground (as suggested by your picture) and if the camera is not too high off the ground.

Share this post

Link to post
Share on other sites

Thanks jmakitalo, can you point me where to make those modifications? I' ve tryied to make some scaling, but nothing changes..

Share this post

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

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net 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!