Yet another CG-related thread by me, I know... :)
I couldn't find a better-suited forum than this one here at gamedev.net, I tried the official NVidia one, but they don't even have a subcategory for CG. And help has been great so far!
Anyways,
to the problem:
I have a very simple pixel shader that is supposed to calculate lighting values for each pixel. But it just renders blackness. I use OpenGL and CG 2.0. Take a look:
lighting.cg
float4 main ( uniform sampler2D texture : TEXUNIT0,
float2 texture_coordinates : TEXCOORD0,
uniform float3 light_vector,
uniform float3 normal_vector ) : COLOR
{
// look the color of our pixel up from the texture
float3 texture_color = tex2D ( texture, texture_coordinates ).rgb;
// calculate diffuse-factor
float diffuse = dot ( normal_vector, light_vector );
// return calculated rgb and full alpha
return float4 ( diffuse * texture_color, 1.0f );
}
This shader compiles fine. Let's see how I implement it:
main.cpp
void draw ( void )
// draws everything - called every frame
{
// do unrelated stuff here (ie. camera movement)
// activate texture
glActiveTextureARB ( GL_TEXTURE0_ARB );
glEnable ( GL_TEXTURE_2D );
glBindTexture ( GL_TEXTURE_2D, texture[0].id );
glBegin ( GL_TRIANGLES );
for ( int i = 0; i < 2; i++ )
// loop through both triangles in the scene
{
// calculate and pass normal of triangle to shader
cvector triangle_normal = triangle.return_normal ( );
normalize ( triangle_normal );
cgGLSetParameter3f ( normal_vector_parameter, triangle_normal.x, triangle_normal.y, triangle_normal.z );
// calculate and pass vector from the middle of the triange to the light to the shader
cvector light_vector;
light_vector.set ( triangle.return_midpoint ( ), light_position );
normalize ( light_vector );
cgGLSetParameter3f ( light_vector_parameter, light_vector.x, light_vector.y, light_vector.z );
for ( int j = 0; j < 3; j++ )
// loop through each vertex of the triangle
{
// print debug information
printf ( "t: %d v: %d lv.x: %f lv.y: %f lv.z: %f nv.x: %f nv.y: %f nv.z: %f\n", i, j, light_vector.x, light_vector.y, light_vector.z, triangle_normal.x, triangle_normal.y, triangle_normal.z );
// bind first texture
glMultiTexCoord2fARB ( GL_TEXTURE0_ARB, triangle.vertex[j].u, triangle.vertex[j].v );
// Specify the vertex coordinates
glVertex3f ( triangle.vertex[j].x, triangle.vertex[j].y, triangle.vertex[j].z);
}
}
glEnd ( );
}
Seems logical, doesn't it? I calculate the normal of the triangle and the vector from the middle of the triangle to the light, normalize both and pass them to the shader. The shader then takes the dot-product of both values and multiplies that to the color from the texture. That's the theory that should work if I'm not mistaken. Since I've been done with school my math has been somewhat rusty and I'm working on refreshing it at the moment.
As you probably noticed, I print debug information. With that, I can tell that my math works perfectly fine. I have two triangles in the scene and the output that is created looks like this:
t: 0 v: 0 lv.x: -0.471759 lv.y: 0.319579 lv.z: 0.821774 nv.x: 0.000000 nv.y: 0.000000 nv.z: -1.000000
t: 0 v: 1 lv.x: -0.471759 lv.y: 0.319579 lv.z: 0.821774 nv.x: 0.000000 nv.y: 0.000000 nv.z: -1.000000
t: 0 v: 2 lv.x: -0.471759 lv.y: 0.319579 lv.z: 0.821774 nv.x: 0.000000 nv.y: 0.000000 nv.z: -1.000000
t: 1 v: 0 lv.x: -0.592559 lv.y: 0.471628 lv.z: 0.653024 nv.x: 0.000000 nv.y: 0.000000 nv.z: -1.000000
t: 1 v: 1 lv.x: -0.592559 lv.y: 0.471628 lv.z: 0.653024 nv.x: 0.000000 nv.y: 0.000000 nv.z: -1.000000
t: 1 v: 2 lv.x: -0.592559 lv.y: 0.471628 lv.z: 0.653024 nv.x: 0.000000 nv.y: 0.000000 nv.z: -1.000000
The values for each vertex in the triangle are the same because I do the calculations for light_vector and normal only once for each triangle. So that's right - for real per-pixel lighting I would have to move these so they are being done for each vertex. I know that, but it's not the problem now. With that, the debug will return individual values which are still correct.
I also know that the shader works right, because when I add a " + 0.4f" for example in the last line of the shader where I return the float4 for the pixel-color it displays it in all gray - similar to an ambient color.
Thus I conclude that the problem lies in the calculation of the float diffuse in the shader. It seems to be zero always and canceling out the texture (if I comment the diffuse-term out in the last line, it renders the unlit texture, so that part is also working - it really has to be the diffuse-term). What's wrong with it?
Thanks a bunch ahead of time!
[Edited by - d h k on January 12, 2008 7:16:07 AM]