Home Utilities Tutorials 3D Demos Graphics Cards Forums About

 GLSL Hacker
Current version: 0.8.2
»GLSL Hacker homepage
»GLSL Hacker Overview

 FurMark
Current version: 1.18.0
»FurMark homepage
»FurMark 1.9.x Submissions

 GPU Caps Viewer
Current version: 1.31.0
»GPU Caps Viewer homepage
»GPU DB Submissions

 GPU Shark
Current version: 0.9.10
»GPU Shark homepage

 Blogs
»JeGX's HackLab

 Geeks3D's Articles
»GPU Memory Speed Demystified

»Multi-Threading Programming Resources

»GeForce and Radeon OpenCL Overview

»How to Get your Multi-core CPU Busy at 100%

»How To Make a VGA Dummy Plug

»Night Vision Post Processing Filter

 PhysX FluidMark
Current version: 1.5.2
»FluidMark homepage
»FluidMark 1.4.x Submissions

 GeeXLab
Current version: 0.4.0
»GeeXLab homepage
»GeeXLab Overview

 TessMark
Current version: 0.3.0
»TessMark homepage

 ShaderToyMark
Current version: 0.3.0
»ShaderToyMark homepage
»ShaderToyMark Scores

 Demoniak3D
Current Version: 1.23.0
»Demoniak3D
»Download
»Libraries and Plugins
»Demos
»Online Help - Reference Guide
»Codes Samples

3D Graphics Search Engine:

Lighting with GLSL
Phong Model

By Jérôme GUINOT aka 'JeGX' - jegx [at] ozone3d [dot] net

Initial draft: February 19, 2006
Update: March 8, 2006

[ Index ]

4 - Lighting Attenuation

Lighting equation coefficients that are dependent on a specific source of light can be optionally multiplied by an attenuation factor. This attenuation factor allows to simulate the light fading with distance.

`If = (As*Am) + ((Al*Am) + Id + Is) * att`

There are several ways to calculate the attenuation factor. We're going to see two of them.

4.1 - The standard method

This method exploits OpenGL coefficients of each light in GLSL:
- gl_LightSource[0].constantAttenuation or Kc
- gl_LightSource[0].linearAttenuation or Kl
- gl_LightSource[0].quadraticAttenuation or Kq

From these coefficients, the attenuation factor can be obtained by:

att = 1.0 / (Kc + Kl*d + Kq*d2)

where d stands for the distance between the position of the light and the currenlty processed vertex:

```lightDir = vec3(gl_LightSource[0].position.xyz - vVertex);
float d = lenght(lightDir);```

In OpenGL terms, attenuation factors are defined by:

```glLightf( GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.0f );
glLightf( GL_LIGHT0, GL_LINEAR_ATTENUATION , 0.0f );
glLightf( GL_LIGHT0, GL_QUADRATIC_ATTENUATION , 0.0002 );```

And in Demoniak3D, these factors are defined in the light node:

```<light name="Light_01"
constant_att="0.0" linear_att="0.0" quadratic_att="0.0002" />```

Here is now our attenuated point light vertex shader:

```[Vertex_Shader]

varying vec3 normal, lightDir, eyeVec;
varying float att;

void main()
{
normal = gl_NormalMatrix * gl_Normal;

vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
lightDir = vec3(gl_LightSource[0].position.xyz - vVertex);
eyeVec = -vVertex;

float d = length(lightDir);

att = 1.0 / ( gl_LightSource[0].constantAttenuation +
(gl_LightSource[0].linearAttenuation*d) +
(gl_LightSource[0].quadraticAttenuation*d*d) );

gl_Position = ftransform();
}```

And here is our attenuated point light pixel shader:

```[Pixel_Shader]

varying vec3 normal, lightDir, eyeVec;
varying float att;

void main (void)
{
vec4 final_color =
(gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) +
(gl_LightSource[0].ambient * gl_FrontMaterial.ambient)*att;

vec3 N = normalize(normal);
vec3 L = normalize(lightDir);

float lambertTerm = dot(N,L);

if(lambertTerm > 0.0)
{
final_color += gl_LightSource[0].diffuse *
gl_FrontMaterial.diffuse *
lambertTerm * att;

vec3 E = normalize(eyeVec);
vec3 R = reflect(-L, N);

float specular = pow( max(dot(R, E), 0.0),
gl_FrontMaterial.shininess );

final_color += gl_LightSource[0].specular *
gl_FrontMaterial.specular * specular * att;
}

gl_FragColor = final_color;
}```

The attenuation factor is computed in the vertex shader and then is passed to the pixel shader through the varying float att; variable.

Fig.5 - The point_light_att.xml demo.

4.2 - Light Radius

This method uses an imaginary sphere in which the light lies in. This sphere represents the light's influence area (i.e the farthest distance an object can be influenced by the light). The attenuation factor decreases along the radius, and becomes equal to zero on the edge of and outside the sphere. This factor is calculated in the pixel shader and assumes that a variable holding the inverse of the radius of the sphere is defined (in order to avoid a division):

```float distSqr = dot(lightDir, lightDir);
float att = clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0);
vec3 L = lightDir * inversesqrt(distSqr);```

This piece of code needs to be explained. The norm of the lightDir vector, is given by:

dist = sqrt(lightDir.x2 + lightDir.y2 + lightDir.z2)

This norm can be written using a dot product:

dist = sqrt( dot(lightDir, lightDir) )
and
distSqr = dot(lightDir, lightDir)

distSqr and invRadius allow to calculate the attenuation factor. The L vector, that is the normalized direction vector, can be obtenaid by the usual normalization formula:

magnitude: |r| = sqrt( x2 + y2 + z2 )
magnitude: |r| = sqrt( distSqr )

unit vector u: u = (1/|r|) * U
unit vector u: u = inversesqrt(distSqr) * U

A value of invRadius=0.001 (i.e 1000.0 units radius) will allow you to start your tests.

The final word: all vertex / pixel shaders previously seen are for all-purposes (i.e they are not bound to Demoniak3D), do not take input parameters (i.e no uniform variables) and so they can be effortless used in any OpenGL application. That said, have a good coding!

5 - Further Resources

6 - Downloads

 Demoniak3D Phong Lighting Source CodesUpdate: February 19, 2006All projects have been successfully tested on a nVidia Geforce 7800GT (with Forceware 81.98) and on an ATI Radeon X700 Pro (with Catalyst 6.1).All projects have been successfully tested on the flollowing configurations: nVidia Geforce 7800GT - Forceware 81.98 ATI Radeon X700 Pro - Catalyst 6.1 ATI Radeon 9800 Pro - Catalyst 6.2 *** These source codes require Demoniak3D to work properly. Demoniak3D is available here: [:: Demoniak3D Demo-System ::].

[ Index ]

 GLSL Hacker demos

GLSL - Mesh exploder

PhysX 3 cloth demo

Normal visualizer with GS

Compute Shaders test on Radeon

Raymarching in GLSL

 Geeks3D latest news

 Geeks3D forum news

 Misc
»Texture DataPack #1
»Asus Silent Knight CPU Cooler
 © 2002-2015 oZone3D.Net - G3D Network - All rights reserved. Last update: May 06, 2015 - 08:46
Page generated in 0.033825874328613 seconds.