   [OpenGL] spot light
  Hi!I'm trying to create a spot light. Please help me to find error.Thanks.#include <windows.h>#include <gl\glut.h>#pragma comment(lib, "opengl32")#pragma comment(lib, "glut32")GLfloat  rx=0;GLfloat  ry=0;GLfloat  tx=0;GLfloatty=0;GLfloattz=-9;GLinttt=0;int mx,my;bool ldown=false;bool rdown=false;int WinWidth=640;int WinHeight=480;GLfloat light_Ka[]={.1, .1, .1, 1};GLfloat light_Kd[]={.3, .3, .3, 1};GLfloat light_Ks[]={.1, .1, .1, 1};GLfloat light_model_Ka[]={.2, .2, .2, 1};GLfloat pos_light[4]={10,4,10,1},    dir_light[4]={0,-1,0,1};GLfloat material_Ka[]={.5, .5, .5, 1};GLfloat material_Kd[]={.4, .6, .8, 1};GLfloat material_Ks[]={.5, .5, .5, 1};GLfloat material_Ke[]={0, 0, 0, 1};GLfloat material_Se=10;GLuint list_cubes;void Init(){    glShadeModel(GL_SMOOTH);    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);    glClearDepth(1.0f);    glEnable(GL_DEPTH_TEST);    glDepthFunc(GL_LEQUAL);    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    glEnable(GL_TEXTURE_2D);    glEnable(GL_LIGHTING);    glEnable(GL_NORMALIZE);    int i=3;    glEnable(GL_LIGHT0+i);    glLightfv(GL_LIGHT0+i,GL_AMBIENT,light_Ka);    glLightfv(GL_LIGHT0+i,GL_DIFFUSE,light_Kd);    glLightfv(GL_LIGHT0+i,GL_SPECULAR,light_Ks);    glLightf(GL_LIGHT0+i,GL_SPOT_CUTOFF,60);    glLightf(GL_LIGHT0+i,GL_SPOT_EXPONENT,100);    glLightfv(GL_LIGHT0+i,GL_POSITION,pos_light);    glLightfv(GL_LIGHT0+i,GL_SPOT_DIRECTION,dir_light);    glLightModelfv(GL_LIGHT_MODEL_AMBIENT,light_model_Ka);    glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,1);    glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1);    glMaterialfv(GL_FRONT,GL_AMBIENT,material_Ka);    glMaterialfv(GL_FRONT,GL_DIFFUSE,material_Kd);    glMaterialfv(GL_FRONT,GL_SPECULAR,material_Ks);    glMaterialfv(GL_FRONT,GL_EMISSION,material_Ke);    glMaterialf(GL_FRONT,GL_SHININESS,material_Se);    list_cubes=glGenLists(1);    glNewList(list_cubes, GL_COMPILE);    for(int y=0;y<200;y++){    for(int x=0;x<200;x++){   glutSolidCube(.1);   glTranslatef(1,0,0);    }    glTranslatef(-200,0,0);    glTranslatef(0,0,1);    }    glEndList();}void Display(){    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);    glLoadIdentity();    glTranslatef(tx,ty,tz);    glTranslatef(0,0,-20);    glRotatef(rx,1,0,0);    glRotatef(ry,0,1,0);    glRotatef(180,0,1,0);    glPushMatrix();   glTranslatef(-100,0,0);   glTranslatef(0,0,-100);   glTranslatef(0,1,0);   glCallList(list_cubes);    glPopMatrix();    glutSwapBuffers();}void Reshape(int Width,int Height){    glViewport(0,0,Width,Height);    WinWidth=Width;    WinHeight=Height;    glMatrixMode(GL_PROJECTION);    glLoadIdentity();    gluPerspective(45,GLdouble(WinWidth)/WinHeight,1,1000);    glMatrixMode(GL_MODELVIEW);    glLoadIdentity();    glutPostRedisplay();}void Mouse(int button, int state, int x, int y){    if (button==GLUT_LEFT_BUTTON)    {   switch (state)   {  case GLUT_DOWN: ldown=true; mx=x; my=y; break;  case GLUT_UP: ldown=false; break;   }    }    if (button==GLUT_RIGHT_BUTTON)    {   switch (state)   {  case GLUT_DOWN: rdown=true; mx=x; my=y; break;  case GLUT_UP: rdown=false; break;   }    }}void MouseMotion(int x, int y){    if (ldown)    {   rx+=0.5*(y-my);   ry+=0.5*(x-mx);   mx=x;   my=y;   glutPostRedisplay();    }    if (rdown)    {   tx+=0.01*(x-mx);   if (tt)  tz+=0.01*(y-my);   else  ty+=0.01*(my-y);   mx=x;   my=y;   glutPostRedisplay();    }}int main(int argc, char* argv[]){    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);    glutInitWindowSize(WinWidth,WinHeight);    glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH)-WinWidth)/2,  (glutGet(GLUT_SCREEN_HEIGHT)-WinHeight)/2);    glutCreateWindow("gl_lights");    Init();    glutDisplayFunc(Display);    glutReshapeFunc(Reshape);    glutMouseFunc(Mouse);    glutMotionFunc(MouseMotion);    glutMainLoop();    return 0;}
  Generally you should copy 'glLightfv(GL_LIGHT0+i,GL_POSITION,pos_light);' code line from Init() to Display() and make 'i' a global variable, but I have added some attractions :)  -for other users to watch quite cool efect your program generates.(and i hope you will forgive me entering the hole code once more)#include <windows.h>#include <gl\glut.h>#pragma comment(lib, "opengl32")#pragma comment(lib, "glut32")GLfloat  rx=0;GLfloat  ry=0;GLfloat  tx=0;GLfloat  ty=0;GLfloat  tz=-9;GLint    tt=0;int mx,my;int i=3;// NEW - now 'i' must be a global variable // but why are you using it instead of // simple GL_LIGHT0? me don't know...bool ldown=false;bool rdown=false;int WinWidth=640;int WinHeight=480;GLfloat light_Ka[]={.6, .6, .6, 1};  // NEW VALUESGLfloat light_Kd[]={.3, .3, .3, 1};GLfloat light_Ks[]={.5, .5, .5, 1};GLfloat light_model_Ka[]={.2, .2, .2, 1};GLfloat pos_light[4]={10,10,10,1}, /// NEW POS.Y VALUE - for better effect:) ///    dir_light[4]={0,-1,0,1};GLfloat material_Ka[]={.5, .5, .5, 1};GLfloat material_Kd[]={.4, .6, .8, 1};GLfloat material_Ks[]={.5, .5, .5, 1};GLfloat material_Ke[]={0, 0, 0, 1};GLfloat material_Se=10;GLuint list_cubes;void Init(){    glShadeModel(GL_SMOOTH);    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);    glClearDepth(1.0f);    glEnable(GL_DEPTH_TEST);    glDepthFunc(GL_LEQUAL);    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    glEnable(GL_TEXTURE_2D);    glEnable(GL_LIGHTING);    glEnable(GL_NORMALIZE);    ///  note that 'int i=3;' is moved to global definitions ///    glEnable(GL_LIGHT0+i);    glLightfv(GL_LIGHT0+i,GL_AMBIENT,light_Ka);    glLightfv(GL_LIGHT0+i,GL_DIFFUSE,light_Kd);    glLightfv(GL_LIGHT0+i,GL_SPECULAR,light_Ks);    glLightf(GL_LIGHT0+i,GL_SPOT_CUTOFF,60);    glLightf(GL_LIGHT0+i,GL_SPOT_EXPONENT,100);    glLightfv(GL_LIGHT0+i,GL_POSITION,pos_light);    glLightfv(GL_LIGHT0+i,GL_SPOT_DIRECTION,dir_light);//glEnable(GL_COLOR_MATERIAL);  // NEW, but not necessary /////////////////////// delete the slashes if want to see the effect, // otherwise, when color tracking is disabled,// you will see only these cubes which// are lightened by the spot light glLightModelfv(GL_LIGHT_MODEL_AMBIENT,light_model_Ka);    glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,1);    glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1);    glMaterialfv(GL_FRONT,GL_AMBIENT,material_Ka);    glMaterialfv(GL_FRONT,GL_DIFFUSE,material_Kd);    glMaterialfv(GL_FRONT,GL_SPECULAR,material_Ks);    glMaterialfv(GL_FRONT,GL_EMISSION,material_Ke);    glMaterialf(GL_FRONT,GL_SHININESS,material_Se);    list_cubes=glGenLists(1);    glNewList(list_cubes, GL_COMPILE);    for(int y=0;y<200;y++){    for(int x=0;x<200;x++){   glutSolidCube(.5);  /// NEW RADIUS VALUE - for better effect:) ///   glTranslatef(1,0,0);    }    glTranslatef(-200,0,0);    glTranslatef(0,0,1);    }    glEndList();}void Display(){    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);    glLoadIdentity();    glTranslatef(tx,ty,tz);    glTranslatef(0,0,-20);    glRotatef(rx,1,0,0);    glRotatef(ry,0,1,0);    glRotatef(180,0,1,0);glLightfv(GL_LIGHT0+i,GL_POSITION,pos_light);  /// NEW - copied from Init() function ///    glPushMatrix();   glTranslatef(-100,0,0);   glTranslatef(0,0,-100);   glTranslatef(0,1,0);   glCallList(list_cubes);    glPopMatrix();    glutSwapBuffers();}void Reshape(int Width,int Height){    glViewport(0,0,Width,Height);    WinWidth=Width;    WinHeight=Height;    glMatrixMode(GL_PROJECTION);    glLoadIdentity();    gluPerspective(45,GLdouble(WinWidth)/WinHeight,1,1000);    glMatrixMode(GL_MODELVIEW);    glLoadIdentity();    glutPostRedisplay();}void Mouse(int button, int state, int x, int y){    if (button==GLUT_LEFT_BUTTON)    {   switch (state)   {  case GLUT_DOWN: ldown=true; mx=x; my=y; break;  case GLUT_UP: ldown=false; break;   }    }    if (button==GLUT_RIGHT_BUTTON)    {   switch (state)   {  case GLUT_DOWN: rdown=true; mx=x; my=y; break;  case GLUT_UP: rdown=false; break;   }    }}void MouseMotion(int x, int y){    if (ldown)    {   rx+=0.5*(y-my);   ry+=0.5*(x-mx);   mx=x;   my=y;   glutPostRedisplay();    }    if (rdown)    {   tx+=0.01*(x-mx);   if (tt)  tz+=0.01*(y-my);   else  ty+=0.01*(my-y);   mx=x;   my=y;   glutPostRedisplay();    }}int main(int argc, char* argv[]){    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);    glutInitWindowSize(WinWidth,WinHeight);    glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH)-WinWidth)/2,  (glutGet(GLUT_SCREEN_HEIGHT)-WinHeight)/2);    glutCreateWindow("gl_lights");    Init();rx=55; ry=-50;  // NEW but not necessary - adjusting camera view; now you don't have // to look after the spot light - it's in the centre of GLwindow    glutDisplayFunc(Display);    glutReshapeFunc(Reshape);    glutMouseFunc(Mouse);    glutMotionFunc(MouseMotion);glutMainLoop();    return 0;}   ;  Hi!Thanks a lot for your answer!!One little thing left: I whant a spotlight to be static. Placing line glLightfv(GL_LIGHT0 + i,GL_POSITION,pos_light); /// NEW - copied from Init() function ///into Display() after world (camera) transformations makes spotlight dependant from camera position. How this can be avoided?I use GL_LIGHT0 + i beacause I have 8 lights in my scene and one of them was taken for this example.Thaks again for your help.   ;  You have almost resolved this problem.Let's forget about all i have written ealier - it was my first post on the forum and i was a bit excited, but now i am quite fine ;). Let's get back to your version. Now you know that in Display() the light must be positioned once again (because of transformations). You expect the spot light to be static, so copy 'glLightfv(GL_LIGHT0+i,GL_POSITION,pos_light);' between Push and Pop Matrix, for example after glCallList(). But that's not enough to do the trick - spot light direction is always (0,-1,0,1) as you definied at the code begining, no matter that you pushed the matrix after transformations. So you should copy in here a code which is related to the direction, that is 'glLightfv(GL_LIGHT0+i,GL_SPOT_DIRECTION,dir_light);'.Changed code lines from Display() are below:glPushMatrix();glTranslatef(-100,-4,-100); // a little optimisation// This way is cheaper, and I changed Pos.Y for// better viewglCallList(list_cubes);glTranslatef(90,20,-120); // not a must, just positions the light nearerglLightfv(GL_LIGHT0+i,GL_SPOT_DIRECTION,dir_light); // it is a mustglLightfv(GL_LIGHT0+i,GL_POSITION,pos_light); // it is a mustglPopMatrix();And remember to make an 'i' a global variable, if you haven't done it yet.Good luck![Edited by - TNDenton on June 3, 2006 3:53:24 AM]