Lighting questions

Started by
11 comments, last by Lord_Evil 17 years, 1 month ago
hi all ! well my plan is to make a soccer simulator, this means I will need lots of lights (stadiums). So my question is. Wich is the best method or aproach for this? I cant use OpenGl lighting because is a resource eater, plus they are limited. So any recomendation is welcome. Also Making some test I coded a spotlight, now the weird thing is that if I set the cutoff angle to something less that 90º I get somekind of weird split on the screen (half of it has light the other half is shadowed) and its always facing the camera... This is the code that activates the light)


Lights.SetPosition(-2022.3320f,	-1185.0239f,	1263.6978f,1.0);
	Lights.SetSpotDirection(82.0830f,	-17.6392f,	0.0000f);
	Lights.SetAmbientColor(0.8980f,	0.1373f,	0.1373f,  0.0f);
//	Lights.SetSpotCutoff(43.0000f);
    Lights.TurnOn(GL_LIGHT1);

void CGL_Light3D::TurnOn ( int light ) {

    
	LIGHT=light;


	glEnable(LIGHT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity(); // comenta esto para ver las bolitas

	glLightfv(LIGHT, GL_POSITION, position);
	glLightfv(LIGHT, GL_AMBIENT, ambient);
    glLightfv(LIGHT, GL_DIFFUSE, ambient);
    glLightfv(LIGHT, GL_SPECULAR, ambient);
	glLightf(LIGHT, GL_SPOT_EXPONENT,spot_exponent);
	glLightfv(LIGHT, GL_SPOT_DIRECTION, spot_direction);
//	glLightf(LIGHT, GL_SPOT_CUTOFF,spot_cutoff);
	glLightf(LIGHT, GL_CONSTANT_ATTENUATION, constant_attenuation);
	glLightf(LIGHT, GL_LINEAR_ATTENUATION, linear_attenuation);
	glLightf(LIGHT, GL_QUADRATIC_ATTENUATION, quadratic_attenuation);

    //glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,1);

}

Advertisement
1.:

Why would you need that many lights for a soccer simulator? From my experience, a stadium only has a few huge spot lights, lets say 4, one at or near each corner. Those huge spots are actually a collection of smaller spots, but can be approximated by a single light, since all small spots have roughly the same position (they are at quite a distance from the players or won't be visible at all).

You could use a directional light to light the soccer field/players etc. This would be a quick approximation that shouldn't be that obvious (for the reasons I explained above). You also could light the stadium with those directional lights or use some other lighting method if it isn't sufficient.

For the players you then could employ a shadowmap for each of the 4 directional lights to get those 4 typical shadows.


2.:
Your "weird" spot light: could you show us a screenshot of what's happening?
Do you apply any camera tranform before rendering?
Why don't you use some simpler values for position, direction, color etc. so that you could check the results more easily?
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
Here is the pic, if I move the camera, the shadow also moves (the thing is that I dont have shadow maps)

http://img213.imageshack.us/img213/2412/lightbt9.jpg

Also yes Im making some camera tranformations, ie moving the camera.
Here is the rendering code, Im also rendering some spheres for reference to see where the light is and where is pointing

void CGL_Light3D::Render(glCamera *Cam){     GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };  //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);    gluLookAt(Cam->m_Position.x, Cam->m_Position.y, Cam->m_Position.z,0.0,0.0,0.0, 0.0, 1.0, 0.0);  glPushMatrix();  glDisable(GL_LIGHTING);//  glRotatef(m_lightAngle, 1.0, 0.0, 0.0);//  glRotatef(m_lightAngle, 0.0, 1.0, 0.0);  glTranslatef(position[0], position[1], position[2]);  glColor3fv(ambient);  gluSphere(m_pSphere, 100.0f, 10, 10);  glEnable(GL_LIGHTING);  glPopMatrix();    glPushMatrix();  glDisable(GL_LIGHTING);//  glRotatef(m_lightAngle, 1.0, 0.0, 0.0);//  glRotatef(m_lightAngle, 0.0, 1.0, 0.0);  glTranslatef(spot_direction[0],spot_direction[1], spot_direction[2]);  glColor3fv(white);  gluSphere(m_pSphere, 100.0f, 10, 10);  glEnable(GL_LIGHTING);  glPopMatrix();}
The light comes from the right of the picture, right? Doesn't seem that bad to me. What do you expect, the model fully lit?

Remember that the direction the spot is pointing to is a *direction* not a position. You should render the second sphere (light "target") at pos = light.position + light.direction.

When do you render your model? Before or after the light's spheres?

Try to mode that gluLookAt to another place, e.g. to the beginning of your top level render function. Also remove that glLoadIdentity() from your light enabling code, since this will result in the light beeing at the same position but the model is moved by the inverse camera movement (remember that OpenGL treats the moving camera as moving the world by the inverse, calling glLoadIdentity() undos that movement, so the light stays at the same relative position to the light).

If you specifiy cutoff = 90 you'll end up with a 180 degree spotlight which would affect you whole model if the light points towards it. Setting cutoff to something between 0 and 90 will result in a smaller spot that may affect only parts of your model. And if you have default attenuation setting (which is constant=1, linear=0, quadratic=0 => "no attenutation") there will be that "sharp" transition from lit to unlit parts of your model.

If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
well from the pic it looks correct, the problem becomes when I move the camera, then light effect moves and the shadow does the same too, its like having a moving flashlight cutted in half.

here you can see what I mean (I just moved the camera)

http://img181.imageshack.us/img181/1062/lightjk4.jpg

And yes I render the model before the lights
Remove that glIdentity() call before setting up the light. The light position has to be given in world space. You set the light in camera space. This is because the world is effectively transformed by the inverse camera matrix, but that glIdentity() undos that transformation and thus your light stays in camera space and moves with the camera.

Do something like this (pseudocode):

start render function
set camera
set light(s) (without glIdentity())
for each model
save modelview matrix
transform model (translate, rotate etc.)
render model
restore modelview matrix (will restore to camera transformation)
render your light spheres (note to use position + direction for the "target" sphere)
end render function
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
thats how Im doing it atm,except for the identity error.
I think my problem is that Im using a Quaternion based camera.

This is what I do with the camera.

glCamera::glCamera(){	outs("glCamera::glCamera()",0);	// Initalize all our member varibles.	m_MaxPitchRate			= 0.0f;	m_MaxHeadingRate		= 0.0f;	m_HeadingDegrees		= 0.0f;	m_PitchDegrees			= 0.0f;	m_MaxForwardVelocity	= 0.0f;	m_ForwardVelocity		= 0.0f;}void glCamera::SetPrespective(){	GLfloat Matrix[16];	glQuaternion q;	// Make the Quaternions that will represent our rotations	m_qPitch.CreateFromAxisAngle(1.0f, 0.0f, 0.0f, m_PitchDegrees);	m_qHeading.CreateFromAxisAngle(0.0f, 1.0f, 0.0f, m_HeadingDegrees);		// Combine the pitch and heading rotations and store the results in q	q = m_qPitch * m_qHeading;	q.CreateMatrix(Matrix);	// Let OpenGL set our new prespective on the world!	glMultMatrixf(Matrix);		// Create a matrix from the pitch Quaternion and get the j vector 	// for our direction.	m_qPitch.CreateMatrix(Matrix);	m_DirectionVector.j = Matrix[9];	// Combine the heading and pitch rotations and make a matrix to get	// the i and j vectors for our direction.	q = m_qHeading * m_qPitch;	q.CreateMatrix(Matrix);	m_DirectionVector.i = Matrix[8];	m_DirectionVector.k = Matrix[10];	// Scale the direction by our speed.	m_DirectionVector *= m_ForwardVelocity;	// Increment our position by the vector	m_Position.x += m_DirectionVector.i;	m_Position.y += m_DirectionVector.j;	m_Position.z += m_DirectionVector.k;	// Translate to our new position.	glTranslatef(-m_Position.x, -m_Position.y, m_Position.z);}void glCamera::ChangePitch(GLfloat degrees){	if(fabs(degrees) < fabs(m_MaxPitchRate))	{		// Our pitch is less than the max pitch rate that we 		// defined so lets increment it.		m_PitchDegrees += degrees;	}	else	{		// Our pitch is greater than the max pitch rate that		// we defined so we can only increment our pitch by the 		// maximum allowed value.		if(degrees < 0)		{			// We are pitching down so decrement			m_PitchDegrees -= m_MaxPitchRate;		}		else		{			// We are pitching up so increment			m_PitchDegrees += m_MaxPitchRate;		}	}	// We don't want our pitch to run away from us. Although it	// really doesn't matter I prefer to have my pitch degrees	// within the range of -360.0f to 360.0f	if(m_PitchDegrees > 360.0f)	{		m_PitchDegrees -= 360.0f;	}	else if(m_PitchDegrees < -360.0f)	{		m_PitchDegrees += 360.0f;	}}


And this is where I set the rotaion for the mouse and the render

void CheckMouse(void){	GLfloat DeltaMouse;	POINT pt;	GetCursorPos(&pt);		MouseX = pt.x;	MouseY = pt.y;		if(MouseX < CenterX)	{		DeltaMouse = GLfloat(CenterX - MouseX);		Cam->ChangeHeading(-0.2f * DeltaMouse);			}	else if(MouseX > CenterX)	{		DeltaMouse = GLfloat(MouseX - CenterX);		Cam->ChangeHeading(0.2f * DeltaMouse);	}	if(MouseY < CenterY)	{		DeltaMouse = GLfloat(CenterY - MouseY);		Cam->ChangePitch(-0.2f * DeltaMouse);	}	else if(MouseY > CenterY)	{		DeltaMouse = GLfloat(MouseY - CenterY);		Cam->ChangePitch(0.2f * DeltaMouse);	}	MouseX = CenterX;	MouseY = CenterY;	SetCursorPos(CenterX, CenterY);}void CameraMovement(void){	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer	glLoadIdentity();	    Cam->SetPrespective();	CheckMouse();}
I still cant find an answer... Anyone got an idea?

Thanks!
Just to clarify:

Perspective means "How is the 3D content that is visible to the camera projected into 2D space?", i.e. it should not have anything to do with your camera direction. You did use the MODELVIEW matrix mode, didn't you?

Also, why do you check the mouse AFTER setting the camera?

I don't see an error in your SetPerspective() method (except for the name). Unless your Quaternion code is correct it should work.
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
well the camera works, there is no problem with that. Btw I use the checkmouse because I lock the mouse at the center of the app so when I move I change the camera view, ie mouse hoes left cam goes left.

But I cant find why the light acts weird when I move the camera.

When you told me to use cam position + cam direction, you mean do something like this?

glTranslatef(spot_direction[0]+position[0],spot_direction[1]+position[1], spot_direction[2]+position[2]);

If thats the case, it dosent work, both balls are almost one next to the other, when one (ambient) should be the source of the light and the white one the spot where the light is pointing...

Atm Im just rendering the light and the model, this is how I render the model
 void ASE::render() {    if (! loaded)   return;   glPushMatrix();   glScalef(currentScale, currentScale, currentScale);   glCallList(dlist);   glPopMatrix(); } 

This topic is closed to new replies.

Advertisement