Sign in to follow this  
TheSeb

problem with per fragment lighting (pictures inside) (problem not resolved)

Recommended Posts

TheSeb    144
Hi, My loader seems to work without the shaders. The per fragment shader works perfectly under renderMonkey. But when i activate this shader the model isn't lighted... i just can see the material's color and this shader works for one of my models but not with the others. I have had a similar problem before i have tought that it was an attenuation problem. I have changed the value of the quadratic factor (1.0, 0.00035,...) but i don't know what to use because nothing works (except for one model). Can you help me to choose the attenuation factor(s) ? or tell me if it comes from something else ? [Edited by - TheSeb on July 5, 2005 10:37:56 AM]

Share this post


Link to post
Share on other sites
Toji    535
The shader works for one model, but not another? That would suggest to me a problem with the model itself. Maybe the normals on that model are malformed? Are all of it's triangles front facing? Does it have the appropriate texture stages (normal, specular, whatever you need)? Basic stuff, but often times people can miss 'em.

Also, you said it works in Render Monkey, but were you testing it with a default (teapot or somthing) model, or your actual in game models? Also, Render Monkey takes care of a lot of state changes on it's own in the background (although it let's you tweak them quite a bit.) I would suggest making sure that the state settings in your engine match the Render Monkey settings as closely as possible.

Share this post


Link to post
Share on other sites
TheSeb    144
in fact, it looks that that there are two problem :
1)Attenuation is not correct for some models
2)my lighting is correct(when attenuation is correct too) only for the part of the object which is firstly lighted by the light. But when i turn the model on itself, the parts which were hidden are either not lighted or lighted incorrectly.
Do you see what i mean ? and do have an idea ?

Share this post


Link to post
Share on other sites
TheSeb    144
i have swapped the y and z normals coordinates and the part which wasn't lighted is lighted now, except for the sides of the model which i display(the lighting is stange).
The orientation of the faces are apparently the same, therefore i don't understand why it works for some parts of the mesh and not with the others.
if i multiply the normals of this mesh with the transformation matrix i have the same results (in this case).
i'm a little lost so if you can help me, i would be glad

Share this post


Link to post
Share on other sites
Toji    535
Quote:
my lighting is correct(when attenuation is correct too) only for the part of the object which is firstly lighted by the light. But when i turn the model on itself, the parts which were hidden are either not lighted or lighted incorrectly.


This suggests to me that you may not be rotating yourn normals properly, or may not be calculating them correctly in the first place.

It would be very helpful to have screenshots of the issue or a simple demo to show what's wrong.

Share this post


Link to post
Share on other sites
Toji    535
Since Seb doesn't have a web host, I'll host these for him till he can get this sorted out:

(Linked due to size - 1024x768)

Pic 1
Pic 2

I'll take a closer look later and see what suggestions I have, but for now I'm off to work!

Share this post


Link to post
Share on other sites
zedzeek    529
after u set up the camera eg glulookat(..) then reposition the light , get it working first with a directional light (ie dont worry about attenuation)

Share this post


Link to post
Share on other sites
zedzeek    529
see here http://www.opengl.org/resources/faq/technical/lights.htm
hmm just see at the top "The per fragment shader works perfectly under renderMonkey" u mean this is a shader + not gl lighting in that case
r u doing bumpmapping?
my suggestion is do it first without bumpmapping

use this as the fragment shader

float diffuse_amount = dot( vec3(0,0,1), normal ) );
gl_FragColor = vec4(diffuse_amount,diffuse_amount,diffuse_amount,1.0)

pass the normal from the vertex shader to the fragment shader, if it doesnt wotrk then youre normals are buggered

Share this post


Link to post
Share on other sites
TheSeb    144
(i'm not doing bump mapping, it's just per pixel lighting)

it's really a problem a normals (i have the same problem with your shader), but i don't understand, i don't manage to find the error (the code is not so complex) and i find strange that some parts are lighted correctly and not the others knowing that the computations are the same for all the vertices.
i put my code (it's long but a lot is simple) can you take a look at it and tell me if you find (or not) errors ?

file.read((char*) &(myObjects[counterObj].nbPoly), sizeof (unsigned short int));

for (polyCounter = 0 ; polyCounter< myObjects[counterObj].nbPoly ; polyCounter++)
{

file.read((char*) &(myObjects[counterObj].myIndices[polyCounter][0]), sizeof (unsigned short int));
file.read((char*) &(myObjects[counterObj].myIndices[polyCounter][1]), sizeof (unsigned short int));
file.read((char*) &(myObjects[counterObj].myIndices[polyCounter][2]), sizeof (unsigned short int));
file.read((char*) &(faceInfo), sizeof (short int));
cout<<"face info "<<faceInfo<<endl ;
oFile2<<"face info "<<faceInfo<<endl ;


int Va = myObjects[counterObj].myIndices[polyCounter][0] ;
int Vb = myObjects[counterObj].myIndices[polyCounter][1] ;
int Vc = myObjects[counterObj].myIndices[polyCounter][2] ;

//on se sert de ab et ca pour le produit vectoriel, ça et le reste servent uniquement pour la normal weight
float Vab[] = {(myObjects[counterObj].myVertices[Vb][0] - myObjects[counterObj].myVertices[Va][0]),
(myObjects[counterObj].myVertices[Vb][1] - myObjects[counterObj].myVertices[Va][1]),
(myObjects[counterObj].myVertices[Vb][2] - myObjects[counterObj].myVertices[Va][2])};

float Vac[] = {(myObjects[counterObj].myVertices[Vc][0] - myObjects[counterObj].myVertices[Va][0]),
(myObjects[counterObj].myVertices[Vc][1] - myObjects[counterObj].myVertices[Va][1]),
(myObjects[counterObj].myVertices[Vc][2] - myObjects[counterObj].myVertices[Va][2])};

float Vba[] = {(myObjects[counterObj].myVertices[Va][0] - myObjects[counterObj].myVertices[Vb][0]),
(myObjects[counterObj].myVertices[Va][1] - myObjects[counterObj].myVertices[Vb][1]),
(myObjects[counterObj].myVertices[Va][2] - myObjects[counterObj].myVertices[Vb][2])};

float Vbc[] = {(myObjects[counterObj].myVertices[Vc][0] - myObjects[counterObj].myVertices[Vb][0]),
(myObjects[counterObj].myVertices[Vc][1] - myObjects[counterObj].myVertices[Vb][1]),
(myObjects[counterObj].myVertices[Vc][2] - myObjects[counterObj].myVertices[Vb][2])};

float Vca[] = {(myObjects[counterObj].myVertices[Va][0] - myObjects[counterObj].myVertices[Vc][0]),
(myObjects[counterObj].myVertices[Va][1] - myObjects[counterObj].myVertices[Vc][1]),
(myObjects[counterObj].myVertices[Va][2] - myObjects[counterObj].myVertices[Vc][2])};

float Vcb[] = {(myObjects[counterObj].myVertices[Vb][0] - myObjects[counterObj].myVertices[Vc][0]),
(myObjects[counterObj].myVertices[Vb][1] - myObjects[counterObj].myVertices[Vc][1]),
(myObjects[counterObj].myVertices[Vb][2] - myObjects[counterObj].myVertices[Vc][2])};


switch (faceInfo)
{
case 0x3 :crossProduct(&myObjects[counterObj].perFaceNormals[polyCounter], Vac, Vbc) ;
break ;
case 0x7 :crossProduct(&myObjects[counterObj].perFaceNormals[polyCounter], Vab, Vbc) ;
break ;
case 0x6 :crossProduct(&myObjects[counterObj].perFaceNormals[polyCounter], Vab, Vbc) ;
break ;
case 0x5 :crossProduct(&myObjects[counterObj].perFaceNormals[polyCounter], Vac, Vab) ;
break ;
case 0x4 :crossProduct(&myObjects[counterObj].perFaceNormals[polyCounter], Vab, Vcb) ;
break ;
case 0x2 :crossProduct(&myObjects[counterObj].perFaceNormals[polyCounter], Vca, Vbc) ;
break ;
case 0x1 :crossProduct(&myObjects[counterObj].perFaceNormals[polyCounter], Vac, Vcb) ;
break ;
case 0x0 :crossProduct(&myObjects[counterObj].perFaceNormals[polyCounter], Vba, Vcb) ;
break ;
}
normalize(&myObjects[counterObj].perFaceNormals[polyCounter]) ;


}//fin de la boucle for

cout<<"face info "<<hex<<faceInfo<<endl ;

for (polyCounter = 0 ; polyCounter< myObjects[counterObj].nbVertices ; polyCounter++)
{
myObjects[counterObj].perVertexNormals[polyCounter][0] = 0 ;
myObjects[counterObj].perVertexNormals[polyCounter][1] = 0 ;
myObjects[counterObj].perVertexNormals[polyCounter][2] = 0 ;
}

for(nIndice=0 ; nIndice < myObjects[counterObj].nbVertices ; nIndice++)
{
for(i=0 ; i < myObjects[counterObj].nbPoly ; i++)
{
for(j=0 ; j< 3; j++)
{
if(myObjects[counterObj].myIndices[i][j]==nIndice)
{
myObjects[counterObj].perVertexNormals[nIndice][0] += myObjects[counterObj].perFaceNormals[i].x/**angle[i][j]*/ ;
myObjects[counterObj].perVertexNormals[nIndice][1] += myObjects[counterObj].perFaceNormals[i].y/**angle[i][j]*/ ;
myObjects[counterObj].perVertexNormals[nIndice][2] += myObjects[counterObj].perFaceNormals[i].z/**angle[i][j]*/ ;
myObjects[counterObj].nbFace[nIndice]++ ;
}
}
}
}

/*multiplyMatrixVertices(myObjects[counterObj].localAxisMatrix,
&myObjects[counterObj].myVertices[0][0],
&myObjects[counterObj].nbVertices) ;*/


multiplyMatrixNormals(myObjects[counterObj].localAxisMatrix,
&myObjects[counterObj].perVertexNormals[0][0],
&myObjects[counterObj].nbVertices) ;

float tempSwap, tempSwap2 ;

for(counter=0 ; counter < myObjects[counterObj].nbVertices ; counter++)
{
tempSwap = myObjects[counterObj].myVertices[counter][1] ;
myObjects[counterObj].myVertices[counter][1]= myObjects[counterObj].myVertices[counter][2] ;
myObjects[counterObj].myVertices[counter][2]= -tempSwap ;

tempSwap2 = myObjects[counterObj].perVertexNormals[counter][1] ;
myObjects[counterObj].perVertexNormals[counter][1]= myObjects[counterObj].perVertexNormals[counter][2] ;
myObjects[counterObj].perVertexNormals[counter][2]= -tempSwap2 ;
}

//average
for(counter=0 ; counter < myObjects[counterObj].nbVertices ; counter++)
{
myObjects[counterObj].perVertexNormals[counter][0] /= myObjects[counterObj].nbFace[counter] ;
myObjects[counterObj].perVertexNormals[counter][1] /= myObjects[counterObj].nbFace[counter] ;
myObjects[counterObj].perVertexNormals[counter][2] /= myObjects[counterObj].nbFace[counter] ;
}

cout.flush() ;

Share this post


Link to post
Share on other sites
James Trotter    432
You should first try a simple mesh, a cube, for instance. It seems like it's just a problem with the way the normals are calculated.

I'm afraid I found your code terribly hard to read. But, here is the usual approach to calculating per-vertex normals for a mesh:

1. Calculate the normals for each face. (The normal vector N of a triangle with three points p1, p2, and p3 is given by: (p0 - p1) × (p0 - p2).)
2. Now, add the face normal to the vertex normal for any vertex that the triangle indexes.
3. After you've calculated all the vertex normals, they need to be normalized.

Hope this helps.

Share this post


Link to post
Share on other sites
James Trotter    432
Quote:
Original post by TheSeb
otherwise, what i should i do to make a code more easy to read ?


There are a few things that might make it easier for outsiders to read your code.

Look at this:

file.read((char*) &(myObjects[counterObj].myIndices[polyCounter][0]), sizeof (unsigned short int));


Two things spring to mind immediately. First, typecasting like that is nasty. I'm not sure if it's necessary in this case. (In any case, since you're coding C++, there are specific type casting mechanisms for C++ that you should use rather than C-style casting. Type casting in C++).

The other thing is the way you're referencing that variable. Writing
myObjects[counterObj].myIndices[polyCounter][0]
is very ugly. It might also be slow in certain time critical situations, (in this case I don't think it's a problem). One way around this is to use a reference, for instance:


for (int i = 0; i < numObjects; i++) {
CObject *object = &myObjects[i];
for (int j = 0; j < object->nbPoly; j++) {
file.read((char*) &(object->myIndices[j][0]), sizeof (unsigned short int));
}
}


That might be just a little prettier to look at, and a little simpler to read. (Note that I also used int i and int j as variables in the for loops. That is just a coding practice that I use, (I've seen alot of other people use it as well). It can make the code shorter and usually just as comprehensive as when using variables named polyCounter or objectCounter.)

Also, I don't read french, so the comments weren't exactly helpful [wink]. It's perfectly alright to comment your code in french, but if you're going to show your code to an audience like here at gamedev, where you're not guaranteed that everyone will understand.

If I'm not mistaken, with this code snippet:

float Vab[] = {(myObjects[counterObj].myVertices[Vb][0] - myObjects[counterObj].myVertices[Va][0]),
(myObjects[counterObj].myVertices[Vb][1] - myObjects[counterObj].myVertices[Va][1]),
(myObjects[counterObj].myVertices[Vb][2] - myObjects[counterObj].myVertices[Va][2])};

float Vac[] = {(myObjects[counterObj].myVertices[Vc][0] - myObjects[counterObj].myVertices[Va][0]),
(myObjects[counterObj].myVertices[Vc][1] - myObjects[counterObj].myVertices[Va][1]),
(myObjects[counterObj].myVertices[Vc][2] - myObjects[counterObj].myVertices[Va][2])};

...


I believe you're trying to calculate the normal of the triangle by using the cross product. If you find that you're using vectors and vector operations alot in your code, you might want to create a vector class. This will make code like above much shorter, easier to read, and more maintainable.
A vector class that implements the cross product operation would allow you to write the above code like so:

Vector3f normal = cross(myObjects[counterObj].myVertices[Va] - myObjects[counterObj].myVertices[Vb], myObjects[counterObj].myVertices[Va] - myObjects[counterObj].myVertices[Vc]);


Hope this helps.

[Edited by - James Trotter on July 4, 2005 9:20:57 AM]

Share this post


Link to post
Share on other sites
TheSeb    144
Quote:
Original post by James Trotter
You should first try a simple mesh, a cube, for instance. It seems like it's just a problem with the way the normals are calculated.

I'm afraid I found your code terribly hard to read. But, here is the usual approach to calculating per-vertex normals for a mesh:

1. Calculate the normals for each face. (The normal vector N of a triangle with three points p1, p2, and p3 is given by: (p0 - p1) × (p0 - p2).)
2. Now, add the face normal to the vertex normal for any vertex that the triangle indexes.
3. After you've calculated all the vertex normals, they need to be normalized.

Hope this helps.


Hi,
i have done the 2) of your answer (the 1 was ever done in my code above) and i have exactly the same problem than on the screenshots.
Do you have an idea ?

Share this post


Link to post
Share on other sites
TheSeb    144
i have displayed my normals with another model than on the captures (the model is too complex to see something) and the normals are oriented to the bottom of the screen. What can i do ?

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