Sign in to follow this  
csuguy

Creating a Spot Light

Recommended Posts

Hey all, So I've just started messing with lighting. I've got a simple scene with a couple pool tables, some billiard balls, and a flat floor (which I actually made invisible so I could better get this lighting down). I'm using Light1 and I've disable Light0. I set the global ambient light to (0,0,0,0) and the Light1's ambient is set to (.1,.1,.1,1.0). I also set Light1's diffuse light to (.8,.8,.8,1.0). I also have set Light1's position to (0,30,0,1). Now - this looks awesome! Other than where the diffused light hits - it's super dark like I want. The only trouble I am having is getting the light to rotate so that instead of facing down the Z axis - it aims directly down the Y axis. While I have no trouble moving the light - I can't figure out how to get it to aim down. I'm calling a function every frame called positionLight() - and this is called after I do the camera transformations but before my objects are placed.Here is the function: GLfloat lightPosition[] = { 0.0f, 30.0f, 0.0f, 1.0f }; ... void positionLight() { glPushMatrix(); glRotatef(90.0f,0.0f,1.0f,0.0f); glLightfv(GL_LIGHT1,GL_POSITION,lightPosition); glDisable (GL_LIGHTING); glColor3f(1.0f,1.0f,0.0f); glutSolidCone(4.0f,5.0f,15,15); glEnable (GL_LIGHTING); glPopMatrix(); } I've also tried values other than 90 for the rotation - but they don't seem to make any difference to the light (though the solid cone does rotate properly). Any and all help is greatly appreciated! Ryan

Share this post


Link to post
Share on other sites
In OpenGL lights are relative to the current modelview matrix, i.e. if you set the position it will be multiplied with the current matrix.

So set your lights before setting the camera in order to make them keep their position/orientation (and don't forget to call either glLoadIdentity() or glLoadMatrix() at the beginning of each new frame).

Share this post


Link to post
Share on other sites
Quote:
Original post by Lord_Evil
In OpenGL lights are relative to the current modelview matrix, i.e. if you set the position it will be multiplied with the current matrix.

So set your lights before setting the camera in order to make them keep their position/orientation (and don't forget to call either glLoadIdentity() or glLoadMatrix() at the beginning of each new frame).


Thank you for the information! Here's my modified function (now called before camera placement):

void positionLight()
{
//Light Position: 0,75,0
glLightfv(GL_LIGHT1,GL_POSITION,light1Position);
//Spot Direction: 0,-1,0
glLightfv(GL_LIGHT1,GL_SPOT_DIRECTION, spot1Direction);
//Spot CutOff: 90.0f
glLightfv(GL_LIGHT1,GL_SPOT_CUTOFF,&spotCutOff);
//Spot Exponent: 0.0f
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT,spotExponent);
}

It kinda of works now. I have a really annoying problem where when I look at it from the -Z axis it gets really bright, and it dims when I look from the +Z axis... It should light both sides equally, shouldn't it? It's directly above the middle of the table! wdf...

Share this post


Link to post
Share on other sites
Ok - so I've been messing with it some more to try to solve the problem. First, I switched it back to being positioned after the camera view was set - because it was not being placed in the scene properly until i did so. Second - in order to test it out and make sure it was working I set it up to rotate around the x and z axis. the xRot and zRot variables are mapped to the directional keys.

It works perectly in that regard - it is definitely IN the scene as a spot light should be and everything's lighting changes as expected when I rotate it around.

I guess my problem, then, is the spot_direction setting. Right now I have it set to (0,-1,0). I thought this would make it point directly downard along the Y axis from the spot lights position (0,75,0) and light up the table directly underneath. However, it still lights up the front half (the half that runs along the positive Z) much more than the back half. Please help! Here's my current code:

void positionLight()
{
glPushMatrix();
glRotatef(xRot,1.0f,0.0f,0.0f);
glRotatef(zRot,0.0f,0.0f,1.0f);

glLightfv(GL_LIGHT1,GL_POSITION,light1Position);
glLightfv(GL_LIGHT1,GL_SPOT_DIRECTION, spot1Direction);
glLightfv(GL_LIGHT1,GL_SPOT_CUTOFF,&spotCutOff);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT,spotExponent);

glTranslatef(light1Position[0],light1Position[1],light1Position[2]);
glPushAttrib(GL_LIGHTING_BIT);
glDisable(GL_LIGHTING);
glColor3f(1.0f,1.0f,0.0f);
glutSolidCone(4.0f,5.0f,15,15);
glPopAttrib();
glPopMatrix();
}

Share this post


Link to post
Share on other sites
Quote:
Original post by csuguy
Anyone? :(



im not an expert but :

1) it has been answered before but id like to reminder. Light position are in eye-coord. That mean its relative to ur camera. 0, 75, 0 mean the light is 75 units over the camera.

2) Spot direction is the coord where it point relative to the light.
if you put the light a 0, 75, 0 and you want it to point at 0, 0, 0 then the spot direction will be 0, -75, 0

3) Light is calculated for each vertex of a surface. You will get a better result with a plane made of a lot of small polygon than a simple big quad.

4) I always have problem using translate when it also involve light. Like if i draw a gluSphere and then translate it, the light will be shown on the sphere like if it still was at 0,0,0.

hope it helps.

EDIT : make sure your normals are properly calculated

Share this post


Link to post
Share on other sites
Thank you for your reply. But you are incorrect - you can insert a light into a scene as if it were an object (positionally speaking). It will stay in the same place in your scene and not move around with the eye coordinates.

This is done with the GL_POSITION param. As you probably know it takes an array of 4 floats. The first three are the x,y,z coords. The last one - an optional one - is w. If w = 0.0 then the first three values represent a vector - meaning the light will come from that direction! However, if you set w to 1.0 (or any value above 0 i think) then the three values serve as an actual position!

I've experimented and confirmed this, I can place the light in the scene and it will stay in the same spot. I can even map the light to the keyboard to move it around. I can also kind of rotate it, but that's where I am having trouble. I can't seem to get it to rotate how I want it to :/.

Share this post


Link to post
Share on other sites
Quote:
Original post by csuguy
Thank you for your reply. But you are incorrect - you can insert a light into a scene as if it were an object (positionally speaking). It will stay in the same place in your scene and not move around with the eye coordinates.

This is done with the GL_POSITION param. As you probably know it takes an array of 4 floats. The first three are the x,y,z coords. The last one - an optional one - is w. If w = 0.0 then the first three values represent a vector - meaning the light will come from that direction! However, if you set w to 1.0 (or any value above 0 i think) then the three values serve as an actual position!

I've experimented and confirmed this, I can place the light in the scene and it will stay in the same spot. I can even map the light to the keyboard to move it around. I can also kind of rotate it, but that's where I am having trouble. I can't seem to get it to rotate how I want it to :/.


nice find i always wondered what was that w value.

to rotate it ull have to do just like a fps camera. Act like if there was a sphere around ur light and make ur light point on a coord on that sphere.

Do u even get it to move or it act like a directionnal ?

here the lil part you may need from a FPSCamera class i made
Quote:

if(buttonViewUp)
{
if (zAngle < (Math.PI/2.0) - 0.1)
zAngle += sensibility * 10.0;
}
if(buttonViewDown)
{
if (zAngle > -(Math.PI/2.0) + 0.1)
zAngle -= sensibility * 10.0 ;
}
if(buttonViewLeft)
yAngle += sensibility * 10.0;
if(buttonViewRight)
yAngle -= sensibility * 10.0;


.....................

public void update()
{
double zVirtual = z - (Math.cos(yAngle) * (Math.cos(zAngle) * 1000.0));
double xVirtual = x - (Math.sin(yAngle) * (Math.cos(zAngle) * 1000.0));
double yVirtual = y + (Math.sin(zAngle) * 1000.0);
glu.gluLookAt(x, y, z, xVirtual, yVirtual, zVirtual, 0, 1, 0);
}

Share this post


Link to post
Share on other sites
Quote:
Original post by csuguy
hm... I can't seem to get the glRotatef to work correctly on it, but the glTranslatef works perfectly, I can make it zip all around my scene... wdf...


you have to rotate before and translate after in that order.

glTranslate.....
glRotate........

if its not the confusing order of the stack, i absolutely have no idea,
i use light shaders instead and before i was calculating coords myself instead of using translate n rotate.

Share this post


Link to post
Share on other sites
No, I've got that in the right order. I actually have all the settings good now and it rotates around, I think I just need to fine tune my rotation algorithm 'cus I can't seem to get it to point straight down.

How do you do light shaders?

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