Advertisement

Cg Per Pixel Lighting - wrong lighting

Started by November 04, 2004 08:46 AM
20 comments, last by RipTorn 19 years, 11 months ago
Quote: Original post by RipTorn
the diffuse also looks correct as if you move the light source a good distance away, the plane fades to grey, which I guess is your ambient colour.

The problem is that it also fades to grey (as you've said, ambient color) if I move the EYE (camera), not just the light.

Roquqkie: I did just as you had said and the result was the same (correct, as it seems now). I pass light and eye position in world-space coordinates anyway, so that shouldn't change things.
ah I see what you mean. I guess I should have noticed.

I think the problem is that you may not have light_pos and eye_pos in camera space. They may still be in world space. So when you rotate your camera, the lighting breaks...

All other values, once they reach the pixel shader, are in camera space. Ideally you still want light_pos and eye_pos to still be uniform variables, so resist the temptation to simply pass them through as texture coords, letting the vertex shader translate them to camera space (mult by modelview)... :)

rotate and translate the values by the modelview matrix before setting them with cgGLSetParameter3fv.
I realise this isn't as easy to do as it sounds.

The camera/matrix/lighting demo I have linked in my signature has a simple matrix class I wrote in there. It would make this sort of thing quite easy, if you want to check it out. (course if you already have a matrix class or whatnot then never mind [smile])

Moral of the story: I should learn to read posts before replying. Twice (I just read your reply again arg you already mention eye-space and the like, so here I go again, patronizing away... *mumbles*)
Advertisement
I think you're right about rotating into TBN-space, RipTorn.

WingMan, if you try this approach and you have any questions on how to do it, please email me :)

Best regards,
Roquqkie
mikkel@cgrender.dk
I've been busy recently, so I haven't posted for quite some time here..sorry.
Arg I should have known that's the problem. Once again, thanks RipTorn (and Roquqkie). Yet, I don't really know how to rotate and translate the values by the modelview matrix. So, could you provide an example (pseudocode or whatever) how to do that? I hope that is the last thing I'm asking for in this thread.
Anyone? How do you do PPL then?

float mat[16];


glGetFloatv(GL_MODELVIEW_MATRIX,mat);


will get the modelview matrix, but it's not all that much use like that. Furthermore, you would really only want the modelview matrix when the camera is setup, because you want your light positions in camera space (not in camera + object space)...


so...


Easy way,
rip the matrix + vector code from the little app in my signature. Or get a matrix class from somewhere else. There are lots and lots around. The one in my sig is pretty simply but does the job...

Unfortunatly, it's likly going to require that you rework how you do cameras, and the like.


code could look something like:


Matrix camera; // in global or class scope..


...

in main loop:

camera.lookAt(...); // or whatever


start rendering:



camera.setGLcamera();


... setup shader

Vector3 lightPosition(5,23,1); // example light pos (random)
Vector3 eyePosition=camera.getPosition();


with my matrix class, if you want to rotate a vector by that matrix, you multiply, if you want to translate by the matrix, you add... So to do both it would be vec*mat+mat.
However, in this case, the matrix that is loaded into the openGL modelview matrix is the inverse of the actual camera matrix. Since the inverse is the same as transpose, when the matrix is not scaled or scewed, then you can divide by the matrix, or subtract. So with my matrix class, (vec-mat)/mat is the same as vec*mat.transpose()+mat.transpose()... So...


Vector3 cameraSpaceEye=(eyePosition-camera)/camera; // THIS SHOULD BE 0,0,0

Vector3 cameraSpaceLight=(lightPosition-camera)/camera;

cgGLSetParameter3fv (light_pos, (float*)&cameraSpaceLight);
cgGLSetParameter3fv (eye_pos, (float*)&cameraSpaceEye);




... render each object one at a time

objectMatrix.pushGL(); //glPushMatrix() and glMultMatrix()


... draw object


objectMatrix.popGL();



... tada



Does this make any sense?


Overall however I'd really recommend you write your own Matrix + Vector classs. You learn a lot doing this.
linky

Eventually you end up soly using only glMultMatrix. No glRotate, glTranslate, etc. Makes this a lot easier to manage, especially highly complex scenes with lots of objects attached to one another (scenegraph style)...
Advertisement
Sorry something odd happened and I wasn't logged in when I posted that above (never happened before, firefox must have had a seizure)...

anyway, the link near the bottom was meant to be this
Great post, thanks. I think I get it now, though I haven't implemented it yet. However, it is much more complicated than I thought.
Quote:
However, it is much more complicated than I thought.


on the surface it looks very complex I'd admit, but when you start to use matrices, especially in object from such as a matrix class, it becomes much, much simpler..

for example,


...

//set camera
glLoadIdentiy();
glLookAt(.. target ..)

... first object

glPushMatrix()..
glTranslate(x,y,z);
glRotate(1,0,0,90);
gl...

.. draw

glPop();

etc

would just simply be:

somewhere else:

camera.lookAt(.. target ..)

object.position() += velocity * time;
object.rotate(rotationalMomentum * time);


then in rendering:

//set camera
glLoadMatrix(camera.inverse());


glPushMatrix();
glMultMatrix(object);

.. draw

glPopMatrix();

etc.

imo much simpler, much easier.

The most important use of this idea, is to make rendering seperate from everything else (say, in a class).

That way, the code that says how an object is positioned and rotated does not need to go with the rendering setup/drawing code. The same for the camera. Some other code can set the camera, not the rendering code.

good old OO. [smile]


Further, if you do use operator overloading like I did in the example code, then things get doubly useful. Being able to rotate 3D and 4D vectors by matrices easily with *,*= and /,/= operators is really, really useful.

a really simple example (that would be really hard any other way)


say you have a space ship, X

it can rotate in any direction any way possible.

instantly you can't do this with glRotate, you need a matrix (some will say a quaternion but I think thats a bad idea).

So there is a class called SpaceShip, and inside there, is a matrix called 'matrix'.

Every frame, if the user is holding down the left arrow, then matrix.rotateZ(..) is called. To rotate the ship left. Simply. From that, pretty much infinite rotation angles are possible.

Say then, you wanted to fire a bullet.
Think about it, how on earth would you get the direction the bullet will travel if using glRotate, etc... You would probably end up using lots and lots and lots of cos/sin combinations. And it wouldn't be accurate still.

Well, in the example, it is:

bullet.velocity = Vector3(0,1,0) * matrix;


Thats it.

In 'ship space' 0,1,0 is forward, so [0,1,0]*matrix is forward in world space. (I'm assuming * won't apply a translation)

btw in this example, bullet.velocity / matrix would equal [0,1,0]
Yes, I think it'll be much more simple when I create matrix class and other things. I'll most likely implement all this within a shader for now, and change it later.

Anyway, I use quaternions rather than glRotate() ;) (must admit I don't understand them fully - but that's another topic).

This topic is closed to new replies.

Advertisement