• Advertisement
Sign in to follow this  

[OpenGL] spot light

This topic is 4286 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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;
}

Share this post


Link to post
Share on other sites
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;
}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement