Sign in to follow this  
Butterman

Per-Pixel Point Light GLSL

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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. ;)

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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);

?!

Share this post


Link to post
Share on other sites
Quote:
Honestly, I have no idea half of those terms mean. The code is there, could you check for me?


Sounds like you copy and pasted code and expect to be a pro at openGL. Try updating the position uniform that you have each frame. Allow yourself to move the that position and draw it at run time.

Share this post


Link to post
Share on other sites
Quote:
Original post by dpadam450
Quote:
Honestly, I have no idea half of those terms mean. The code is there, could you check for me?


Sounds like you copy and pasted code and expect to be a pro at openGL. Try updating the position uniform that you have each frame. Allow yourself to move the that position and draw it at run time.


Actually. That's the exact oposite of the truth. First I wrote what I understood about lamberts cosine law from physics, it worked, yay! Then, I started reading through tutorials about per-pixel lights and point lights. I implemented it as I understood it from those tutorials. Obviously, I've done somthing really wrong, because it's not working :D. If I had of copy-pasted it, wouldn't it have worked?

Anyway. Yes, I'm using homogenous co-ordinates, if you read the code you would have realised I'm not even using any fixed function stuff, I can't! This code is targetting ES 2.0, I'm going to have to replace the matricies with my own, because all matrix math is out of ES 2.0, that's why I'm multiplying matrices individually. Anyway, multiplication law, it dosen't make a difference what order I do it in.

The problem is in the multiplication of the matrices, while I understand physics concepts quite well, I'm not so great on maths. I need to pass the light in world-space.

Share this post


Link to post
Share on other sites
Quote:
Original post by Butterman
This code is targetting ES 2.0, I'm going to have to replace the matricies with my own, because all matrix math is out of ES 2.0, that's why I'm multiplying matrices individually. Anyway, multiplication law, it dosen't make a difference what order I do it in.

The problem is in the multiplication of the matrices, while I understand physics concepts quite well, I'm not so great on maths. I need to pass the light in world-space.
Actually, you will find that the order of multiplication *does matter* for matrices, as they are not commutative with respect to multiplication.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this