🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

[OpenGL] spot light

Started by
2 comments, last by TNDenton 18 years, 1 month ago
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;
GLfloat     ty=0;
GLfloat     tz=-9;
GLint     tt=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;
}
Advertisement
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 VALUES
GLfloat 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 view		glCallList(list_cubes);				glTranslatef(90,20,-120); // not a must, just positions the light nearer		glLightfv(GL_LIGHT0+i,GL_SPOT_DIRECTION,dir_light); // it is a must		glLightfv(GL_LIGHT0+i,GL_POSITION,pos_light); // it is a must	glPopMatrix();


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]

This topic is closed to new replies.

Advertisement