Thursday, June 2, 2011

Light shafts

Light shafts are seen in nature when a light soure like the sun is occluded by an object like a tree. We can then observe some rays spreading from the occluder which are in fact volumetric shadows in the atmosphere. This effect can be implemented in games as a post-process, which makes it easy to add into a 3D engine. Here is a screenshot of my implementation:


I am still working on this one, there is still minor tweaks required to enhance both quality and performances, and I will post it here as soon as I am done with it. I will then post a bit more explanation on how it is done. 


Preliminary version of the code:

[Vertex_Shader]
varying vec3 lightPos;
void main(void)
{
   vec4 v = (gl_ProjectionMatrix * gl_ModelViewMatrix
      gl_LightSource[0].position);
   lightPos = v.xyz / v.w;
   gl_Position = ftransform();
   gl_TexCoord[0] = gl_MultiTexCoord0;
}

[Pixel_Shader]
uniform sampler2D sceneTex;
varying vec3 lightPos;
void main()
   int NUM_SAMPLES = 100;
   float density = 0.9;
   float illuminationDecay = 1.0;
   float weight = 0.010;
   float decay = 0.99;
 
   vec2 uv = gl_TexCoord[0].xy;
   lightPos.xy = (lightPos.xy + vec2(1.0, 1.0)) / 2.0;
   vec2 deltaTexCoord = uv - lightPos.xy;
 
   deltaTexCoord = deltaTexCoord / (float(NUM_SAMPLES) * density);
     
   vec3 color = texture2D(sceneTex, uv).xyz;
 
   for(int i=0; i<NUM_SAMPLES; ++i)
   {
      uv -= deltaTexCoord;
      vec3 sample = texture2D(sceneTex, uv).xyz;
      sample = sample * illuminationDecay * weight;
      color += sample;
      illuminationDecay = illuminationDecay * decay;
   }
 
   gl_FragColor = vec4(color, 1.0);
}


Don't hesitate to post any comment, advice or improvement ideas!

No comments:

Post a Comment