Per-Pixel Point Light GLSL

Started by
12 comments, last by knighty 15 years ago
Hey, having some real trouble with my shaders, it's been a week and I still can't sort it out, so for me, that's forum time :p. I need a picture to explain what's going wrong. As you can see, light is totally skipping that point. Here are my shaders, I'm doing light stuff in worldspace, because, if not, that strange effect shown in the picture, rotates around the light. *sigh*. Also, ignore "position", it's best not to ask why, but i'm using it to translate just for the minute. Ignore the specular stuff too, (the half vector) I know that's wrong. Vertex:


//TINCS Vertex Shader

varying vec3 normal;
varying vec3 halfV;
varying vec4 lightVertexVec;

uniform vec4 position;

uniform mat4 modelViewMatrix;

//I get my eyeDIR (eye direction vector, for specular) and lightPOS (light position vector) from the APP
uniform vec3 eyeDIR;
uniform vec4 lightPIS;


void main()
{
    
        //I need the world position of the vertex, so i can get a direction vector between it and the light
        vec4 calculatedVertex = gl_Vertex - position;
    
        //I need the light-vertex vector, to grab direction and distance off
        lightVertexVec = ((lightPIS) - (calculatedVertex));

        //Make sure everything that needs to be applied to the normal is
        normal = gl_Normal;
    
        //We only need one set of vertex co-ordinates
        gl_TexCoord[0] = gl_MultiTexCoord0;
    
        //Optmized setting of position
        gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * (gl_Vertex + position);

} 



Fragment:


//TINCS Fragment Shader

//sampler2D for diffuse map and specular map
uniform sampler2D tex, spec;
varying vec3 normal;
varying float Power, lightDistance;
varying vec3 halfV;
uniform vec3 eyeDIR;
varying vec4 lightVertexVec;


void main()
{

        //I store the final specular value in a single float
        float specPower;
        vec4 specular;
        float specFinal;
    
        //Att = multiplyer for light distance stuff
        float att;
    
        //Quick ambient, I'm going to set ambient to uniform when i link it in with TINCS, so map makers can set it
        vec4 ambient = vec4(0.03,0.03,0.03,0.03);
        vec4 color = ambient;

        //Now, I normalize the light-vertex vector to get the direction of the light to the vertex
        vec4 lightDirection = normalize(lightVertexVec);
        //Then I just get the length for distance
        vec4 lightDistance = length(lightVertexVec);

        //Calculate the halfVector, (for specular stuff) I think this code might be dodgey! Take a good look darkblu :P
        halfV = normalize((lightDirection + (vec4(eyeDIR.x,eyeDIR.y,eyeDIR.z,0) * gl_ProjectionMatrix * gl_ModelViewMatrix)) / 2);

        //Cacluate the power of the light, by getting the dot product of the normal and light direction
        Power = max(dot(normalize(normal), normalize(lightDirection)),0.0);

        //Get the diffuse value off the texture and if there is no diffuse, we set it to white
        vec4 diffuse = texture2D(tex,gl_TexCoord[0].st);

        if(diffuse == 0)
        {
            diffuse = vec4(2,1,1,1);
        }
    
        //Get the specular value off the specular texture
        specular = texture2D(spec,gl_TexCoord[0].st);
    
        float specMulti = specular;

        //attenuation equals one over the linear and quadratic power of the light, lower you go, the more powerful the light is
        att = 1 / (0.00001 * lightDistance + 0.1 *  lightDistance * lightDistance);
        //add the diffuse values onto the final color
        color +=  att * (diffuse * Power);
    
        if(specMulti < 1.0 && specMulti > 0.0)
        {
            //I've taken out the spec stuff for now, so we can solve this
            //specPower = max(dot(normal, halfV),0.0);
            //specFinal = 1 * pow(specPower,specMulti);
            //color += att * specFinal;
        }
        

        //Get the final color!
        gl_FragColor = color;
}


Any help is great. Thanks! EDIT: I've circled the light in the picture, the compression seems to make it invisible.
Game Development Tutorials, a few good game development tutorials located on my site.
Advertisement
I don't know how much of a help this is, but when I implemented shaders in one of my games, one user complained of not being able to see anything... and there was a strange red glow, somewhat like what you showed. It was later determined that his graphics card didn't have shader support.

It looked very similar to that, though.

Hope this helps,

adam_o
_______________________My computer stats:Xcode 3.1.2Mac OS 10.5.8---Visual C++ 2008 Express EditionWindows XP---NetBeansUbuntu 9.04---Help needed here!
I've just made it a red light. No problem there. I'm running a 9600GT ;).

GLEW would spew errors if it wasn't supported also.

EDIT: The problem is the fact that the light stops, past an imaginary line cast from the bottom of the light, you see it stops to the right of the light. Yet, it's a point light, so it should be illuminated, but even more strangely, the plane past the area where light should be which is another mesh, has light applied to it. But again with the same strange cut off.

Also, my normals are fine.
Game Development Tutorials, a few good game development tutorials located on my site.
this looks a lot like a spot with an exponent applied to it (the lighting to the left). Are you sure it's a point light & calculated without spot exponent?
Honestly, I have no idea half of those terms mean. The code is there, could you check for me?
Game Development Tutorials, a few good game development tutorials located on my site.
Quote:Original post by Butterman
I've just made it a red light. No problem there. I'm running a 9600GT ;).


Oh ok, scratch my theory then. That's very odd, though. It looked almost the same, although said tester had an ATI Radeon 9000 mobile. ;)
_______________________My computer stats:Xcode 3.1.2Mac OS 10.5.8---Visual C++ 2008 Express EditionWindows XP---NetBeansUbuntu 9.04---Help needed here!
A/ only worry about diffuse lighting first
eg
gl_FragColor.xyz = vec3(dot( normal, light_vector ));

the same relates to any programming excercise when a bug occurs

B/
vec4 calculatedVertex = gl_Vertex - position;
why do u need a vec4 instead of vec3?
I usually use
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);

Besides that I have no idea. I sugest you recreate your math starting with this link

http://www.lighthouse3d.com/opengl/glsl/index.php?pointlight
many times people mess up sending the light data to OpenGL during the fixed function operations.

Make sure you send a 4 component vector to glLightfv( GL_POSITION, vec4 position )

if you are using a point or spot light w = 1 ( because you are transforming point in homogenious coordinates )

and w = 0 if you are transforming a vector.

It seem to me that there is someting wrong with normals. try a debug output.

I also think you can do it with much less expensive length() and normalize()functions.

Oh! why:
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * (gl_Vertex + position);

when you can do simply:

gl_Position= gl_ModelViewProjectionMatrix * (gl_Vertex + position);

?!

This topic is closed to new replies.

Advertisement