directional works, positional only draws 1st time through

I posted this in the beginner area but no luck.

Below is the complete program so you can have something to copy/paste/compile/run if you’d like to try it yourself and see if you can help.

The program draws glColor3d()'d coordinate axes, a single lit shaded triangle in the x-z plane (y is up), with a light circling around the triangle, about the (+) z axis, in the x-y plane. I draw a little glColor3d()'d GL_POINT where the light is.

The problem is, the little dot is only drawn in the first frame. After that it’s not drawn, but everything else works fine. I put in an SDL_Delay( 500 ) to make this effect more obvious.

If I change the last arg in the glLightfv() call (in draw(), where the // XXX is) from light_pos to light_dir, the problem goes away. Am I using glLightfv() incorrectly?

// tiny_sdl_gl
//
// main.cpp

#include
#include

#include <gl.h>
#include <glu.h>

#include <SDL.h>
#include <SDL_video.h>

using std::exit;
using std::cout;
using std::endl;

//------------------------------
GLfloat radius = 2.5;
GLfloat light_pos = { 0.0, radius, 0.0, 1.0 }; // positional
GLfloat light_dir = { 0.0, radius, 0.0, 0.0 }; // directional
GLfloat theta = 0; // rotation of light about the z-axis.

//---------------------------------------------------------------------
void processEvents()
{
SDL_Event event;

while( SDL_PollEvent( &event ) )
{
    if ( event.type == SDL_QUIT )
    {
        cout << "quit has been requested via ctrl-c or close window"
             << endl;
        SDL_Quit();
        exit( 0 );
        break;
    }
}

}

//---------------------------------------------------------
void initSDL(int width, int height)
{
if ( SDL_Init( SDL_INIT_VIDEO ) != 0 )
{
cout << "couldn’t initialize SDL: " << SDL_GetError() << endl;
SDL_Quit();
exit(1);
}

const SDL_VideoInfo * vid_info = SDL_GetVideoInfo();
int bpp = vid_info->vfmt->BitsPerPixel;
cout << "Found bpp = " << bpp << endl;

unsigned int vid_flags =
    SDL_DOUBLEBUF |
    SDL_OPENGL |
    SDL_HWPALETTE |
    SDL_HWACCEL;

if ( vid_info->hw_available )
{
    cout << "Found hw_available. Setting vid_flags |= SDL_HWSURFACE." << endl;
    vid_flags |= SDL_HWSURFACE;
}
else
{
    cout << "Didn't find hw_available. Setting vid_flags |= SDL_SWSURFACE." << endl;
    vid_flags |= SDL_SWSURFACE;
}

if ( vid_info->blit_hw )
{
    cout << "Found blit_hw. Setting vid_flags |= SDL_HWACCEL." << endl;
    vid_flags |= SDL_HWACCEL;
}
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_RED_SIZE,     8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE,   8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE,    8 );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE,   8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE,   24 ); // default anyway.

SDL_Surface * surf = SDL_SetVideoMode( width, height, bpp, vid_flags );

if ( surf == NULL )
{
    cout << "unable to set video mode: " << SDL_GetError() << endl;
    SDL_Quit();
    exit(1);
}

SDL_WM_SetCaption( "sdl_ast", "sdl_ast" );

}

//---------------------------------------------------------
void initGL(int width, int height)
{
glPolygonMode( GL_FRONT, GL_FILL );

glShadeModel( GL_SMOOTH );

glCullFace( GL_BACK );
glEnable( GL_CULL_FACE );

glClearColor( 0.0, 0.0, 0.0, 0.0 );
glPointSize( 4.0 );
glLineWidth( 2.0 );

glEnable( GL_DEPTH_TEST );

GLfloat mat_spec[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shin = 50.0;
GLfloat mat_emerald[] = { 0.0, 0.8, 0.1, 1.0 };

GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat amb_light[] = { 0.2, 0.2, 0.2, 1.0 };

glMaterialfv( GL_FRONT, GL_SPECULAR, mat_spec );
glMaterialf( GL_FRONT, GL_SHININESS, mat_shin );
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_emerald );

glLightfv( GL_LIGHT0, GL_AMBIENT, amb_light );
glLightfv( GL_LIGHT0, GL_DIFFUSE, white_light );
glLightfv( GL_LIGHT0, GL_SPECULAR, white_light );

glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );

glViewport( 0, 0, width, height );

glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 40.0, 1.0, 4.0, 16.0 );

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

}

//------------------------------------------------
void draw()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glPushMatrix();
    gluLookAt( 2.0, 4.0, 7.0,
               0.0, 0.0, 0.0,
               0.0, 1.0, 0.0 );

    glPushMatrix();
        glRotated( theta, 0.0, 0.0, 1.0 );
        glLightfv( GL_LIGHT0, GL_POSITION, light_pos ); // XXX

        // Draw the dot representing the light.
        glDisable( GL_LIGHTING );
        glBegin( GL_POINTS );
            glColor3d( 1.0, 1.0, 1.0 );
            glVertex4fv( light_pos );
        glEnd();
        glEnable( GL_LIGHTING );
    glPopMatrix();

    // Draw the x y z coordinate axes.
    glDisable( GL_LIGHTING );
    glBegin( GL_LINES );
        glColor3d( 1.0, 0.0, 0.0 );
        glVertex3d( 0.0, 0.0, 0.0 );
        glVertex3d( 2.0, 0.0, 0.0 );

        glColor3d( 0.0, 1.0, 0.0 );
        glVertex3d( 0.0, 0.0, 0.0 );
        glVertex3d( 0.0, 2.0, 0.0 );

        glColor3d( 0.0, 0.0, 1.0 );
        glVertex3d( 0.0, 0.0, 0.0 );
        glVertex3d( 0.0, 0.0, 2.0 );
    glEnd();
    glEnable( GL_LIGHTING );

    // Draw a simple triangle facing up near the origin.
    glBegin( GL_TRIANGLES );
        glNormal3d( 0.0, 1.0, 0.0 ); // Normal facing up.

        // The winding is correct so the "front" is facing up,
        // in the same direction as the normal.
        glVertex3d( 0.0, 0.0, 0.0 );
        glVertex3d( 0.5, 0.0, 1.0 );
        glVertex3d( 1.0, 0.0, 0.2 );
    glEnd();
glPopMatrix();
glFinish();

}

//------------------------------------------------
int main( int argc, char * argv )
{
int width = 400;
int height = 400;
initSDL( width, height );
initGL( width, height );

while ( true )
{
    SDL_Delay( 500 ); // This is just here to slow things down
                      // enough to see the effect I'm asking about.
    processEvents();
    theta += 5.0;
    if ( theta > 360.0 )
    {
        theta -= 360.0;
    }
    draw();
    SDL_GL_SwapBuffers();
}

SDL_Quit();
return 0;

}

//------------------------------------------------

And here’s the makefile:

makefile for tiny_sdl_gl

APP_NAME = tiny_sdl_gl

LDFLAGS = sdl-config --libs -L/usr/X11R6/lib -lGL -lGLU

CFLAGS = -c sdl-config --cflags -I/usr/X11R6/include/GL

#----------------------------------------------
(APP_NAME): main.o g++ -o (APP_NAME) $(LDFLAGS) main.o

main.o: main.cpp
g++ $(CFLAGS) main.cpp

clean:
rm -f $(APP_NAME)
rm -f *.o

[This message has been edited by jmg (edited 11-30-2002).]

If I add a call to glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE ) just before enabling the lighting, and leave the light set to positional, the GL_POINT doesn’t show up at all…

Can someone please confirm whether or not they get the same strange behaviour so I can tell if this is an implementation bug on my end?

glVertex4fv( light_pos ); ?
Try changing that to
glVertex3fv( light_pos );

dunno why you’re using 4 component vertices…

The fourth parameter to glVertex doesn’t matter in this case. The default value for the fourth parameter is 1, which is the fourth value he’s passing in with glVertex4fv.

Whoa, knackered,… it worked. Thanks.

If anyone could offer an explanation, I’d love to hear it, because it makes no sense to me at all. I agreed with Coriolis that the default parameter is 1 anyway and it shouldn’t matter.

The only reason I’d written it that way was:
A. I had light_pos hanging around looking to be reused, and
B. I just assumed that since light_pos was a 4-element array, I should pass it to glVertex4fv(). It didn’t even occur to me that using glVertex3fv() would compile just fine.

Agreed, it should work because your w element is 1.0
So, it must be a driver bug - what drivers are you using?

> what drivers are you using?

I don’t think I know how to answer that. I’m running Mandrake Linux 8.2. I’m using DRI/Mesa with my Matrox G400 – had to hand-edit XF86Config-4. I installed Mesa myself (./configure, make, make install); it’s 4.0.4. Maybe this is useful:

[john@localhost src]$ lspci
—[snip]—
01:00.0 VGA compatible controller: Matrox Graphics, Inc. MGA G400 AGP (rev 04)

[john@localhost src]$ glxinfo
name of display: :0.0
display: :0 screen: 0
direct rendering: Yes
server glx vendor string: SGI
server glx version string: 1.2
server glx extensions:
GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_EXT_import_context
client glx vendor string: SGI
client glx version string: 1.2
client glx extensions:
GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_EXT_import_context
GLX extensions:
GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_EXT_import_context
OpenGL vendor string: VA Linux Systems Inc.
OpenGL renderer string: Mesa DRI G400 20010622 AGP 1x x86/MMX/3DNow!
OpenGL version string: 1.2 Mesa 3.4.2
OpenGL extensions:
—[snip]—

Hmm… dunno why it says Mesa 3.4.2 there… Uh oh. I think I recall reading somewhere that when you use DRI, you’re supposed to use only the Mesa libs that come with the DRI release.

I may have installed Mesa improperly. I need to study this some more.