PDA

View Full Version : Vertex lighting shader - black dot at rendering



Smoove
07-19-2011, 03:02 AM
Good morning,

I am doing my first steps in shader coding using GLSL. For a start I wanted to create a lighting algorithm, so I browsed the internet and found some fairly simple examples. To suit my need I only changed the lights by adding my own custom ones, as uniform variables. Here the code:

// The shader is creating the light effects on a sphere
// from several light sources.
uniform vec3 Sphere_Position;
uniform int Light_Counter;
uniform vec3 Light_Position[20];
uniform vec3 Light_Color [20];
uniform float Light_Factor [20];

// Main function
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_FrontColor = gl_Color;

for(int i = 0; i < Light_Counter; i ++)
{
vec3 Light_Direction = -normalize(gl_Position.xyz - Light_Position[i].xyz);
vec3 Vertex_Normal = normalize(gl_NormalMatrix * gl_Normal);
float Dot_Product = max(dot(Vertex_Normal, Light_Direction), 0.0);

float Light_Distance = length(gl_Position.xyz - Light_Position[i].xyz);
float Final_Factor = (Dot_Product * Light_Factor[i]) / (Light_Distance * Light_Distance);

gl_FrontColor.xyz = gl_FrontColor.xyz * Light_Color[i].xyz * Final_Factor;
}

Now as the title suggest, when rendering, this produces a nice light/shadow effect, except for a small black circle zone in the middle of the sphere... Sounds to me like a very basic geometry principle, but I can't figure it out!

Any help would be very much appreciated!

Thank you,

Philippe

EDIT: I forgot to mention that to first keep it simple, I am testing with a single light. So the 'for' loop can be neglect for the moment!

mobeen
07-19-2011, 03:24 AM
You need to make sure all of your vectors are in the same coordinate space. Your vertex positions are in clipspace but I am not sure which space your light position is (usually it is in eye space) but I cant tell.

Smoove
07-19-2011, 03:59 AM
Thank you for your answer Mobeen. I think I understand what you're saying, but I am not yet familiar enough with those concepts: my light position is sent by the program (hence the uniform variable). So as you can imagine, I have a 'Light' class with a 'Position' property sent to the shader before rendering.
Same principle is applied for the Sphere position (or center) used by my shader.

What coordinate space would that be?

Typical I am testing with the following code:

gluLookAt(0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

// Draw the lamp without shader
glPushMatrix();
glTranslatef(3.0f, 3.0f, 5.0);
// Draw light source
glPopMatrix();

// Activate the shader and set variables
vshader.Activate();
// Define the current sphere properties
vshader.SetUniform3f("Sphere_Position", -1.0f, 0.0f, 0.0f);
vshader.SetUniform3f("Light_Position[0]", 3.0f, 3.0f, 5.0f);
vshader.SetUniform3f("Light_Color[0]", 1.0f, 1.0f, 0.8f);
vshader.SetUniform1f("Light_Factor[0]", 50.0f);
// Activate lights
vshader.SetUniform1i("Light_Counter", 1);

glPushMatrix();
glTranslatef(-1.0f, 0.0f, 0.0);
// Draw sphere
glPopMatrix();

EDIT: Your remark made me tried something: I used the 'gl_Vertex' instead of the transformed 'gl_Position'. Render obviously change and I would need to analyse it more further to understand, but interesting points are:
- I still have a nice shadow/light gradient effect (might be an unrealistic one, but still)
- The black circle has turned into a white one, but is still there

Smoove
07-19-2011, 09:37 AM
I found my mistake:

In my vertex shader, first instruction was this:
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

This is the correct transformation to finally apply on gl_position, however, I am first using it to calculate the lighting effect... And that is where your remark makes sense, Mobeen!

Solution is therefore this:

// First calculate de position in the correct coordinate space
gl_Position = gl_ModelViewMatrix * gl_Vertex;

// ... Lighting calculation using gl_Position

// Then apply the final transformation on the point
gl_Position = gl_gl_ModelViewProjectionMatrix * gl_Vertex;


Thanks again for having pointed me in the right direction.

Philippe