c++openglmfc

Unexpected behavior of GL_SPOT_CUTOFF


Good day all,

I am exploring Lighting in OpenGL with the small MFC app that draws a cube centered in (0,0,0) and a single light source.

However, light source (if I may say - unexpectedly) turns off when I set GL_SPOT_CUTOFF.

This is the code for cube:

void CGLRenderer::DrawCube(float a)
{
GLfloat mat_ambient[] = { 0.5, 0.5, 0.5, 1.0 };
GLfloat mat_diffuse[] = { 0.8, 0.8, 0.8, 1.0 };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_emission[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat mat_shininess = 64.0;

glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess);

//glShadeModel(GL_FLAT);

glEnable(GL_NORMALIZE);

glBegin(GL_QUAD_STRIP);

//front
glColor3f(1.0, 0.0, 0.0);
glNormal3f(0.0, 0.0, 1.0);
glVertex3f(-a / 2, -a / 2, a / 2);
glVertex3f(-a / 2, a / 2, a / 2);
glVertex3f(a / 2, -a / 2, a / 2);
glVertex3f(a / 2, a / 2, a / 2);

//right
glColor3f(0.0, 1.0, 0.0);
glNormal3f(1.0, 0.0, 0.0);
glVertex3f(a / 2, -a / 2, -a / 2);
glVertex3f(a / 2, a / 2, -a / 2);

//back
glColor3f(0.0, 0.0, 1.0);
glNormal3f(0.0, 0.0, -1.0);
glVertex3f(-a / 2, -a / 2, -a / 2);
glVertex3f(-a / 2, a / 2, -a / 2);

//left
glColor3f(0.0, 1.0, 1.0);
glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(-a / 2, -a / 2, a / 2);
glVertex3f(-a / 2, a / 2, a / 2);

glEnd();

glBegin(GL_QUADS);
//top
glColor3f(1.0, 1.0, 0.0);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-a / 2, a / 2, a / 2);
glVertex3f(a / 2, a / 2, a / 2);
glVertex3f(a / 2, a / 2, -a / 2);
glVertex3f(-a / 2, a / 2, -a / 2);

//bottom
glColor3f(1.0, 0.0, 1.0);
glNormal3f(0.0, -1.0, 0.0);
glVertex3f(-a / 2, -a / 2, a / 2);
glVertex3f(a / 2, -a / 2, a / 2);
glVertex3f(a / 2, -a / 2, -a / 2);
glVertex3f(-a / 2, -a / 2, -a / 2);

glEnd();

}

And for the light:

void CGLRenderer::SetUpLight()
{
GLfloat mod_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, mod_ambient);

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

GLfloat light0_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
GLfloat light0_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light0_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat light0_position[] = { mLight0_x, mLight0_y, mLight0_z, 1.0 };
GLfloat light0_direction[] = { 0.0, 0.0, 0.0}; //at the center of the cube

glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);

glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0_direction);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0);
//glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

  }

No matter what value (0.0-90.0) I set for GL_SPOT_CUTOFF, light0 simply goes off. Any clue why is this happening? I am very new to OpenGL, so I believe there's something my code is missing or is doing wrong.

This is without setting GL_SPOT_CUTOFF SPOT_CUTOFF is not set

This is when GL_SPOT_CUTOFF is set to 45.0 SPOT_CUTOFF is 45

White point is representing GL_POSITION of light0.


Solution

  • For a spotlight to work, you need some light direction. However,

    GLfloat light0_direction[] = { 0.0, 0.0, 0.0}; //at the center of the cube
    

    is not going to work. You need a direction vector, not the position of some object you want the light to be directed at. The null vector is just no direction at all.

    Use the difference between the target point and the light position as the direction vector. But be careful: the light position is set in the local object space defined by the current GL_MODELVIEW matrix at the call of glLight().

    If you are learning OpenGL now, I strongly recommend that you do not learn that stuff at all. OpenGL lighting is part of the fixed function pipeline and deprecated since OpenGL 3.0. You should use the programmable pipeline ("shaders") nowadays.