Flashlight mit GLSL

Liebes Forum!

Ich arbeite seit einiger Zeit an einem Shader der einen Taschenlampeneffekt produzieren soll und erziele leider keine zufriedenstellenden Ergebnisse.

Ich verwende mehr oder weniger modifiziert den Quellcode von diesem Tutorial:
http://www.lighthouse3d.com/opengl/glsl/index.php?sp…

Grundsätzlich bewege ich mich in einer Landschaft. Genauer gesagt in der map cs_assault von CS. Die Taschenlampe soll bei Aktivierung einfach einen Lichtkegel von der Kamera ausgehend werfen. Das ganze mache ich mit einem Spotlight:

 glEnable(GL\_LIGHT0);

 // set light position
 GLfloat lightPos[]={0.0f,0.0f,0.0f,1.0f};
 glLightfv(GL\_LIGHT0,GL\_POSITION,lightPos);

 // set spot light parameters
 GLfloat spotDir[]={0.0f,0.0f,-1.0f}; // define spot direction
 glLightfv(GL\_LIGHT0, GL\_SPOT\_DIRECTION, spotDir);
 glLightf(GL\_LIGHT0, GL\_SPOT\_CUTOFF,25.0f); // set cutoff angle
 glLightf(GL\_LIGHT0, GL\_SPOT\_EXPONENT,1.0f); // set focusing strength
 glLightf(GL\_LIGHT0, GL\_CONSTANT\_ATTENUATION, 0.0f);
 glLightf(GL\_LIGHT0, GL\_LINEAR\_ATTENUATION, 0.0f);
 glLightf(GL\_LIGHT0, GL\_QUADRATIC\_ATTENUATION, 0.0001f);

Das Per-Pixel-Lighting funktioniert leider nur auf sehr große Distanzen. (Die Figur, die auf der Wand entsteht ist kreis/ellipsenähnlich) Wenn ich jetzt aber sehr nahe zur Wand gehe, wird diese Figur immer unförmiger, was wahrscheinlich mit der Interpolation der varying Variablen zu tun hat.

Hat irgendjemand von euch eine Idee, wie man das besser implementieren könnte oder hat jemand schon einmal eine Taschenlampe als Shader implementiert oder kennt ein Tutorial oder einen Code dafür?

Wäre für jede Hilfe dankbar.
mfg dixxi

Hier mein derzeitiger Code:

shader.vert

varying vec4 diffuse,ambientGlobal, ambient;
varying vec3 normal,lightDir,halfVector;
varying float dist;

void main()
{
 vec4 ecPos;
 vec3 aux;

 /\* first transform the normal into eye space and normalize the result \*/
 normal = normalize(gl\_NormalMatrix \* gl\_Normal);

 /\* now normalize the light's direction. Note that according to the
 OpenGL specification, the light is stored in eye space.\*/
 ecPos = gl\_ModelViewMatrix \* gl\_Vertex;
 aux = vec3(gl\_LightSource[0].position-ecPos);
 lightDir = normalize(aux);

 /\* compute the distance to the light source to a varying variable\*/
 dist = length(aux);

 /\* Normalize the halfVector to pass it to the fragment shader \*/
 halfVector = normalize(gl\_LightSource[0].halfVector.xyz);

 /\* Compute the diffuse, ambient and globalAmbient terms \*/
 diffuse = gl\_FrontMaterial.diffuse \* gl\_LightSource[0].diffuse;
 ambient = gl\_FrontMaterial.ambient \* gl\_LightSource[0].ambient;
 ambientGlobal = gl\_LightModel.ambient \* gl\_FrontMaterial.ambient;


 gl\_Position = ftransform();

 gl\_TexCoord[0] = gl\_MultiTexCoord0;
 gl\_TexCoord[1] = gl\_MultiTexCoord1;
}

shader.frag

uniform sampler2D tex1;
uniform sampler2D tex2;

uniform bool bFlashlight;

void Flashlight();

void main()
{
 vec4 cColor1 = texture2D(tex1, gl\_TexCoord[0].st);
 vec4 cColor2 = texture2D(tex2, gl\_TexCoord[1].st);

 gl\_FragColor = cColor1 \* cColor2;

 if (bFlashlight)
 {
 Flashlight();
 }

}

varying vec4 diffuse,ambientGlobal, ambient;
varying vec3 normal,lightDir,halfVector;
varying float dist;

void Flashlight()
{
 vec3 n,halfV;
 float NdotL,NdotHV;
 vec4 color = /\*ambientGlobal\*/ gl\_FragColor;
 float att,spotEffect;

 /\* a fragment shader can't write a verying variable, hence we need
 a new variable to store the normalized interpolated normal \*/
 n = normalize(normal);

 /\* compute the dot product between normal and ldir \*/
 NdotL = max(dot(n,normalize(lightDir)),0.0);

 if (NdotL \> 0.0)
 {

 spotEffect = dot(normalize(gl\_LightSource[0].spotDirection), normalize(-lightDir));
 if (spotEffect \> gl\_LightSource[0].spotCosCutoff)
 {
 spotEffect = pow(spotEffect, gl\_LightSource[0].spotExponent);
 att = spotEffect / (gl\_LightSource[0].constantAttenuation +
 gl\_LightSource[0].linearAttenuation \* dist +
 gl\_LightSource[0].quadraticAttenuation \* dist \* dist);

 color += att \* (diffuse \* NdotL + ambient);


 halfV = normalize(halfVector);
 NdotHV = max(dot(n,halfV),0.0);
 color += att \* gl\_FrontMaterial.specular \* gl\_LightSource[0].specular \* pow(NdotHV,gl\_FrontMaterial.shininess);
 }
 }

 gl\_FragColor = color;
}