OpenGL, paralleles Licht "flackert"

Cecidi

Mitglied
Hi,
ich hab da ein interessantes Problem mit OpenGl:

Wenn ich paralleles (direktionales) Licht auf eine Fläche mit senkrechtem Normalenvektor scheinen lasse, "flackert" das Licht, wenn man die Kamera etwas dreht.

Das ist sehr schwer zu beschreiben, aber ich habe hier mal ne Renderfunktion zusammengestellt wo man das Problem sieht (wenn man es ausführt).

Code:
void renderCube() 
{ 
    float normal[3]; 
     
    glBegin(GL_QUADS); 
     
    normal[0]=0.0f; normal[1]=1.0f; normal[2]=0.0f; 
    glNormal3fv( normal ); 
    glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Top) 
    glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Top) 
    glVertex3f(-1.0f, 1.0f, -1.0f); // Bottom Left Of The Quad (Top) 
    glVertex3f( 1.0f, 1.0f, -1.0f); // Bottom Right Of The Quad (Top) 
 
    normal[0]=0.0f; normal[1]=-1.0f; normal[2]=0.0f; 
    glNormal3fv( normal ); 
    glVertex3f( 1.0f, -1.0f, -1.0f); // Top Right Of The Quad (Bottom) 
    glVertex3f(-1.0f, -1.0f, -1.0f); // Top Left Of The Quad (Bottom) 
    glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Quad (Bottom) 
    glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Quad (Bottom) 
     
    normal[0]=0.0f; normal[1]=0.0f; normal[2]=-1.0f; 
    glNormal3fv( normal ); 
    glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Quad (Front) 
    glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Quad (Front) 
    glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Front) 
    glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Front) 
     
    normal[0]=0.0f; normal[1]=0.0f; normal[2]=1.0f; 
    glNormal3fv( normal ); 
    glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Quad (Back) 
    glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Quad (Back) 
    glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Back) 
    glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Back) 
     
    normal[0]=-1.0f; normal[1]=0.0f; normal[2]=0.0f; 
    glNormal3fv( normal ); 
    glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Quad (Left) 
    glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Left) 
    glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Quad (Left) 
    glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Left) 
    
    normal[0]=1.0f; normal[1]=0.0f; normal[2]=0.0f; 
    glNormal3fv( normal ); 
    glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Right) 
    glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left Of The Quad (Right) 
    glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Right) 
    glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Quad (Right) 
    
    glEnd(); // Done Drawing The Quad 
}

//--------------------------------------------------------------------
void DrawGLScene()
{
  static float rquad = 0.0f;

  glEnable(GL_DEPTH_TEST);          
  glEnable(GL_LIGHTING);   
  glEnable(GL_LIGHT0); 

  //Lösche Bildschirm
  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);    // Clear The Screen And The Depth Buffer
  glLoadIdentity();                // Reset The View 
 
  //Setze Standartwerte für das Licht (Lichtreflexe(specular) = Rot)
  //Diffuses Licht aus
  //Ambientes Licht auf dunkel grau
  //Specular Licht auf rot (grau + rot = rosa) 
  const float specular[4] = {1.0f,0.0f,0.0f,1.0f}; 
  const float ambient[4] = {0.5f,0.5f,0.5f,1.0f}; 
  const float diffuse[4] = {0.0f,0.0f,0.0f,1.0f}; 
  const float emission[4] = {0.0f,0.0f,0.0f,1.0f}; 
     
  //Übernehme Lichtwerte 
  glMaterialfv( GL_FRONT, GL_SPECULAR, specular ); 
  glMaterialfv( GL_FRONT, GL_AMBIENT, ambient ); 
  glMaterialfv( GL_FRONT, GL_DIFFUSE, diffuse ); 
  glMaterialfv( GL_FRONT, GL_EMISSION, emission ); 
  glMaterialf( GL_FRONT, GL_SHININESS, 0.0f );

  //Verschibe nach hinten links
  glTranslated(-2.0f, 0.0f, -5.0f);

  //drehe um y-achse
  glRotatef(rquad,0.0f,1.0f,0.0f);        // Rotate The Cube On Y
  
  //Setze Lichtquelle
  const float direction[4] = {0.0f, 0.0f, 1.0f, 0.0f}; 
  glLightfv(GL_LIGHT0, GL_POSITION, direction);
  glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); 
  glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); 
  glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
 
  renderCube(); 
  
  rquad+=0.5f;                    // Decrease The Rotation Variable For The Cube
  usleep(50000);                 //Zeitverzögerung um 50Millisekunden


  // swap the buffers to display, since double buffering is used.
  glutSwapBuffers();
}
Der Codeschnipsel stammt aus einem Linux GLUT-Projekt (abgewandelte Version von NEHE-Lesson5).
Auf das Problem gestoßen bin ich aber mit Qt unter Windows.
Es sollte also egal sein wo man das ganze ausführt. (auch in einer anderen OpenGl Renderfunktion sollte es (nicht) gehen)

Auf jeden Fall sollte es nicht flackern.

mfg Cecidi
 
Ok, ich hab mir noch mal die mühe gemacht das Problem ordentlich darzustellen:

Das Problem besteht darin, parallel Licht zusammen mit "specular" light (Materialeigenschaft) zubenutzen, wenn der Winkel zwischen Licht und dem Normalenvektor der einer Fläche 90 Grad ist.

Das gerenderte Ergebnis ist abhänig vom Betrachtungswinkel der Kamera(), was aber eigentlich nicht sein darf!

Um das ganze leichter verständlich zu machen habe ich ein paar Screenshots gemacht:

Zu sehen ist ein Würfel, der von links mit parallelem Licht bestrahlt wird. Dementsprechend ist auch nur die zum Licht zeigende Fläche beleuchted. (so weit so gut)

Auf dem 2. Bild ist die Kamera() um 0,1 Grad um die Y-Achse gedreht worden. Die Lichtquelle und der Würfel sind immernoch an der gleichen Position. Folglich müsste auch das Bild fast identisch sein.

Ist es aber nicht.

Die nächsten Bilder drehen einfach noch ein bisschen weiter...

Beispiel mit einem Würfel:
Würfel (Bild 1 von 4)
Würfel (Bild 2 von 4)
Würfel (Bild 3 von 4)
Würfel (Bild 4 von 4)

Beispiel mit einer Kugel:
Kugel (Bild 1 von 3)
Kugel (Bild 2 von 3)
Kugel (Bild 3 von 3)

Ich habe das ganze sowohl mit QT unter WinXp als auch mit GLUT unter Linux (Ubuntu) ausprobiert. Das Ergebnis ist das gleiche

-----------------------------------------------------------------------
Kompletter Sourcecode (abgewandelte Version von Nehe-Lesson07):
Code:
// This code was created by Jeff Molofee '99 (ported to Linux/GLUT by Richard Campbell '99)
//
// If you've found this code useful, please let me know.
//
// Visit me at www.demonews.com/hosted/nehe 
// (email Richard Campbell at ulmont@bellsouth.net)
//
#include <GL/glut.h>    // Header File For The GLUT Library 
#include <GL/gl.h>    // Header File For The OpenGL32 Library
#include <GL/glu.h>    // Header File For The GLu32 Library
#include <unistd.h>     // Header file for sleeping.
#include <stdio.h>      // Header file for standard file i/o.
#include <stdlib.h>     // Header file for malloc/free.

void renderSphere()

{    
    GLUquadricObj *quadratic;
    quadratic=gluNewQuadric();            // Create A Pointer To The Quadric Object ( NEW )
    gluQuadricNormals(quadratic, GLU_SMOOTH);    // Create Smooth Normals ( NEW )
    gluQuadricTexture(quadratic, GL_TRUE);
    gluSphere(quadratic,1.0f,32,32);
    gluDeleteQuadric(quadratic);
}

void renderCube()

{    

    glBegin(GL_QUADS);                        // begin drawing a cube
    
    // Front Face (note that the texture's corners have to match the quad's corners)
    glNormal3f( 0.0f, 0.0f, 1.0f);                              // front face points out of the screen on z.
    glVertex3f(-1.0f, -1.0f,  1.0f);    // Bottom Left Of The Texture and Quad
    glVertex3f( 1.0f, -1.0f,  1.0f);    // Bottom Right Of The Texture and Quad
    glVertex3f( 1.0f,  1.0f,  1.0f);    // Top Right Of The Texture and Quad
    glVertex3f(-1.0f,  1.0f,  1.0f);    // Top Left Of The Texture and Quad
    
    // Back Face
    glNormal3f( 0.0f, 0.0f,-1.0f);                              // back face points into the screen on z.
    glVertex3f(-1.0f, -1.0f, -1.0f);    // Bottom Right Of The Texture and Quad
    glVertex3f(-1.0f,  1.0f, -1.0f);    // Top Right Of The Texture and Quad
    glVertex3f( 1.0f,  1.0f, -1.0f);    // Top Left Of The Texture and Quad
    glVertex3f( 1.0f, -1.0f, -1.0f);    // Bottom Left Of The Texture and Quad
    
    // Top Face
    glNormal3f( 0.0f, 1.0f, 0.0f);                              // top face points up on y.
    glVertex3f(-1.0f,  1.0f, -1.0f);    // Top Left Of The Texture and Quad
    glVertex3f(-1.0f,  1.0f,  1.0f);    // Bottom Left Of The Texture and Quad
    glVertex3f( 1.0f,  1.0f,  1.0f);    // Bottom Right Of The Texture and Quad
    glVertex3f( 1.0f,  1.0f, -1.0f);    // Top Right Of The Texture and Quad
    
    // Bottom Face       
    glNormal3f( 0.0f, -1.0f, 0.0f);                             // bottom face points down on y. 
    glVertex3f(-1.0f, -1.0f, -1.0f);    // Top Right Of The Texture and Quad
    glVertex3f( 1.0f, -1.0f, -1.0f);    // Top Left Of The Texture and Quad
    glVertex3f( 1.0f, -1.0f,  1.0f);    // Bottom Left Of The Texture and Quad
    glVertex3f(-1.0f, -1.0f,  1.0f);    // Bottom Right Of The Texture and Quad
    
    // Right face
    glNormal3f( 1.0f, 0.0f, 0.0f);                              // right face points right on x.
    glVertex3f( 1.0f, -1.0f, -1.0f);    // Bottom Right Of The Texture and Quad
    glVertex3f( 1.0f,  1.0f, -1.0f);    // Top Right Of The Texture and Quad
    glVertex3f( 1.0f,  1.0f,  1.0f);    // Top Left Of The Texture and Quad
    glVertex3f( 1.0f, -1.0f,  1.0f);    // Bottom Left Of The Texture and Quad
    
    // Left Face
    glNormal3f(-1.0f, 0.0f, 0.0f);                              // left face points left on x.
    glVertex3f(-1.0f, -1.0f, -1.0f);    // Bottom Left Of The Texture and Quad
    glVertex3f(-1.0f, -1.0f,  1.0f);    // Bottom Right Of The Texture and Quad
    glVertex3f(-1.0f,  1.0f,  1.0f);    // Top Right Of The Texture and Quad
    glVertex3f(-1.0f,  1.0f, -1.0f);    // Top Left Of The Texture and Quad
    
    glEnd();                                    // done with the polygon.

}

/* ascii codes for various special keys */
#define ESCAPE 27
#define PAGE_UP 73
#define PAGE_DOWN 81
#define UP_ARROW 72
#define DOWN_ARROW 80
#define LEFT_ARROW 75
#define RIGHT_ARROW 77

/* The number of our GLUT window */
int window; 

/* lighting on/off (1 = on, 0 = off) */
int light;

/* L pressed (1 = yes, 0 = no) */
int lp;

/* F pressed (1 = yes, 0 = no) */
int fp;


GLfloat xrot;   // x rotation 
GLfloat yrot;   // y rotation 
GLfloat xspeed; // x rotation speed
GLfloat yspeed; // y rotation speed

GLfloat z=-5.0f; // depth into the screen.

/* white ambient light at half intensity (rgba) */
GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f };

/* super bright, full intensity diffuse light. */
GLfloat LightDiffuse[] = { 0.0f, 0.0f, 0.0f, 1.0f };

/* position of light (x, y, z, (position of light)) */
GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };

GLuint    filter;            /* Which Filter To Use (nearest/linear/mipmapped) */
GLuint    texture[3];        /* Storage for 3 textures. */

/* Image type - contains height, width, and data */
struct Image {
    unsigned long sizeX;
    unsigned long sizeY;
    char *data;
};
typedef struct Image Image;

// quick and dirty bitmap loader...for 24 bit bitmaps with 1 plane only.  
// See http://www.dcs.ed.ac.uk/~mxr/gfx/2d/BMP.txt for more info.
// if mesa ever gets glaux, let me know.
int ImageLoad(char *filename, Image *image) {
    FILE *file;
    unsigned long size;                 // size of the image in bytes.
    unsigned long i;                    // standard counter.
    unsigned short int planes;          // number of planes in image (must be 1) 
    unsigned short int bpp;             // number of bits per pixel (must be 24)
    char temp;                          // used to convert bgr to rgb color.

    // make sure the file is there.
    if ((file = fopen(filename, "rb"))==NULL)
    {
    printf("File Not Found : %s\n",filename);
    return 0;
    }
    
    // seek through the bmp header, up to the width/height:
    fseek(file, 18, SEEK_CUR);

    // read the width
    if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
    printf("Error reading width from %s.\n", filename);
    return 0;
    }
    printf("Width of %s: %lu\n", filename, image->sizeX);
    
    // read the height 
    if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
    printf("Error reading height from %s.\n", filename);
    return 0;
    }
    printf("Height of %s: %lu\n", filename, image->sizeY);
    
    // calculate the size (assuming 24 bits or 3 bytes per pixel).
    size = image->sizeX * image->sizeY * 3;

    // read the planes
    if ((fread(&planes, 2, 1, file)) != 1) {
    printf("Error reading planes from %s.\n", filename);
    return 0;
    }
    if (planes != 1) {
    printf("Planes from %s is not 1: %u\n", filename, planes);
    return 0;
    }

    // read the bpp
    if ((i = fread(&bpp, 2, 1, file)) != 1) {
    printf("Error reading bpp from %s.\n", filename);
    return 0;
    }
    if (bpp != 24) {
    printf("Bpp from %s is not 24: %u\n", filename, bpp);
    return 0;
    }
    
    // seek past the rest of the bitmap header.
    fseek(file, 24, SEEK_CUR);

    // read the data. 
    image->data = (char *) malloc(size);
    if (image->data == NULL) {
    printf("Error allocating memory for color-corrected image data");
    return 0;    
    }

    if ((i = fread(image->data, size, 1, file)) != 1) {
    printf("Error reading image data from %s.\n", filename);
    return 0;
    }

    for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
    temp = image->data[i];
    image->data[i] = image->data[i+2];
    image->data[i+2] = temp;
    }

    // we're done.
    return 1;
}

// Load Bitmaps And Convert To Textures
GLvoid LoadGLTextures(GLvoid) {    
    // Load Texture
    Image *image1;
    
    // allocate space for texture
    image1 = (Image *) malloc(sizeof(Image));
    if (image1 == NULL) {
    printf("Error allocating space for image");
    exit(0);
    }

    if (!ImageLoad("Data/lesson7/crate.bmp", image1)) {
    exit(1);
    }        

    // Create Textures    
    glGenTextures(3, &texture[0]);

    // texture 1 (poor quality scaling)
    glBindTexture(GL_TEXTURE_2D, texture[0]);   // 2d texture (x and y size)

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // cheap scaling when image bigger than texture
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // cheap scaling when image smalled than texture

    // 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image, 
    // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
    glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);

    // texture 2 (linear scaling)
    glBindTexture(GL_TEXTURE_2D, texture[1]);   // 2d texture (x and y size)
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture
    glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);

    // texture 3 (mipmapped scaling)
    glBindTexture(GL_TEXTURE_2D, texture[2]);   // 2d texture (x and y size)
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); // scale linearly + mipmap when image smalled than texture
    glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);

    // 2d texture, 3 colors, width, height, RGB in that order, byte data, and the data.
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image1->sizeX, image1->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image1->data); 
};

/* A general OpenGL initialization function.  Sets all of the initial parameters. */
GLvoid InitGL(GLsizei Width, GLsizei Height)    // We call this right after our OpenGL window is created.
{
    LoadGLTextures();                           // load the textures.
    //glEnable(GL_TEXTURE_2D);                    // Enable texture mapping.

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);    // This Will Clear The Background Color To Black
    glClearDepth(1.0);                // Enables Clearing Of The Depth Buffer
    glDepthFunc(GL_LESS);            // The Type Of Depth Test To Do
    glEnable(GL_DEPTH_TEST);            // Enables Depth Testing
    glShadeModel(GL_SMOOTH);            // Enables Smooth Color Shading
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();                // Reset The Projection Matrix
    
    gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);    // Calculate The Aspect Ratio Of The Window
    
    glMatrixMode(GL_MODELVIEW);

    // set up light number 1.
    glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);  // add lighting. (ambient)
    glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);  // add lighting. (diffuse).
    glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // set light position.
    glEnable(GL_LIGHT1);                             // turn light 1 on.
    glEnable(GL_LIGHTING);
    light = 1;
}

/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
GLvoid ReSizeGLScene(GLsizei Width, GLsizei Height)
{
    if (Height==0)                // Prevent A Divide By Zero If The Window Is Too Small
    Height=1;

    glViewport(0, 0, Width, Height);        // Reset The Current Viewport And Perspective Transformation

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
    glMatrixMode(GL_MODELVIEW);
}

/* The main drawing function. */
GLvoid DrawGLScene(GLvoid)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);        // Clear The Screen And The Depth Buffer
    glLoadIdentity();                // Reset The View

    glTranslatef(0.0f,0.0f,z);                  // move z units out from the screen.
    
    glRotatef(xrot,1.0f,0.0f,0.0f);        // Rotate On The X Axis
    glRotatef(yrot,0.0f,1.0f,0.0f);        // Rotate On The Y Axis

    //Setze Lichtquelle
    const GLfloat LightDirection[] = { 0.0f, 0.0f, 1.0f, 0.0f };
    const GLfloat LightSpecular[] =  { 1.0f, 0.0f, 0.0f, 1.0f };

    glLightfv(GL_LIGHT1, GL_POSITION, LightDirection);

    glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);  
    
    

    const GLfloat specular[] = {1.0f,0.0f,0.0f,1.0f};
    glMaterialf(GL_FRONT, GL_SHININESS, 1.0f);
    glMaterialfv(  GL_FRONT, GL_SPECULAR, specular );

    //Sphere:
    renderSphere();

    //Cube
    //renderCube();
   
    xrot+=xspeed;                        // X Axis Rotation    
    yrot+=yspeed;                        // Y Axis Rotation

    // since this is double buffered, swap the buffers to display what just got drawn.
    glutSwapBuffers();
}


/* The function called whenever a normal key is pressed. */
void keyPressed(unsigned char key, int x, int y) 
{
    /* avoid thrashing this procedure */
    usleep(100);

    switch (key) {    
    case ESCAPE: // kill everything.
    /* shut down our window */
    glutDestroyWindow(window); 
    
    /* exit the program...normal termination. */
    exit(1);                       
    break; // redundant.

    case 76: 
    case 108: // switch the lighting.
    printf("L/l pressed; light is: %d\n", light);
    light = light ? 0 : 1;              // switch the current value of light, between 0 and 1.
    printf("Light is now: %d\n", light);
    if (!light) {
        glDisable(GL_LIGHTING);
    } else {
        glEnable(GL_LIGHTING);
    }
    break;

    case 70:
    case 102: // switch the filter.
    printf("F/f pressed; filter is: %d\n", filter);
    filter+=1;
    if (filter>2) {
        filter=0;    
    }    
    printf("Filter is now: %d\n", filter);
    break;

    default:
    break;
    }    
}

/* The function called whenever a normal key is pressed. */
void specialKeyPressed(int key, int x, int y) 
{
    /* avoid thrashing this procedure */
    usleep(100);

    switch (key) {    
    case GLUT_KEY_PAGE_UP: // move the cube into the distance.
    z-=0.02f;
    break;
    
    case GLUT_KEY_PAGE_DOWN: // move the cube closer.
    z+=0.02f;
    break;

    case GLUT_KEY_UP: // decrease x rotation speed;
    xspeed-=0.01f;
    break;

    case GLUT_KEY_DOWN: // increase x rotation speed;
    xspeed+=0.01f;
    break;

    case GLUT_KEY_LEFT: // decrease y rotation speed;
    yspeed-=0.01f;
    break;
    
    case GLUT_KEY_RIGHT: // increase y rotation speed;
    yspeed+=0.01f;
    break;

    default:
    break;

    }    
}

int main(int argc, char **argv) 
{  
    /* Initialize GLUT state - glut will take any command line arguments that pertain to it or 
       X Windows - look at its documentation at http://reality.sgi.com/mjk/spec3/spec3.html */  
    glutInit(&argc, argv);  

    /* Select type of Display mode:   
     Double buffer 
     RGBA color
     Alpha components supported 
     Depth buffer */  
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);  

    /* get a 640 x 480 window */
    glutInitWindowSize(640, 480);  

    /* the window starts at the upper left corner of the screen */
    glutInitWindowPosition(0, 0);  

    /* Open a window */  
    window = glutCreateWindow("Jeff Molofee's GL Code Tutorial ... NeHe '99");  

    /* Register the function to do all our OpenGL drawing. */
    glutDisplayFunc(&DrawGLScene);  

    /* Go fullscreen.  This is as soon as possible. */
    glutFullScreen();

    /* Even if there are no events, redraw our gl scene. */
    glutIdleFunc(&DrawGLScene);

    /* Register the function called when our window is resized. */
    glutReshapeFunc(&ReSizeGLScene);

    /* Register the function called when the keyboard is pressed. */
    glutKeyboardFunc(&keyPressed);

    /* Register the function called when special keys (arrows, page down, etc) are pressed. */
    glutSpecialFunc(&specialKeyPressed);

    /* Initialize our window. */
    InitGL(640, 480);
  
    /* Start Event Processing Engine */  
    glutMainLoop();  

    return 1;
}
Hier jetzt nur der "wichtige" teil des Codes (relativ kurz):
Code:
/* The main drawing function. */
GLvoid DrawGLScene(GLvoid)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);        // Clear The Screen And The Depth Buffer
    glLoadIdentity();                // Reset The View

    glTranslatef(0.0f,0.0f,z);                  // move z units out from the screen.
    
    glRotatef(xrot,1.0f,0.0f,0.0f);        // Rotate On The X Axis
    glRotatef(yrot,0.0f,1.0f,0.0f);        // Rotate On The Y Axis

    //Setze Lichtquelle
    const GLfloat LightDirection[] = { 0.0f, 0.0f, 1.0f, 0.0f };
    const GLfloat LightSpecular[] =  { 1.0f, 0.0f, 0.0f, 1.0f };

    glLightfv(GL_LIGHT1, GL_POSITION, LightDirection);

    glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);  
    
    

    const GLfloat specular[] = {1.0f,0.0f,0.0f,1.0f};
    glMaterialf(GL_FRONT, GL_SHININESS, 1.0f);
    glMaterialfv(  GL_FRONT, GL_SPECULAR, specular );

    //Sphere:
    renderSphere();

    //Cube
    //renderCube();
   
    xrot+=xspeed;                        // X Axis Rotation    
    yrot+=yspeed;                        // Y Axis Rotation

    // since this is double buffered, swap the buffers to display what just got drawn.
    glutSwapBuffers();
}
Ich habe übrigens eine Möglichkeit gefunden das Problem zu umschiffen. Wenn man einfach statt dem parallelen Licht eine sehr weit entfernte Punktlichtquelle verwendet, funktioniert alles super.
Das erklärt aber nicht das Problem und löst es meiner Meinung nach nur sehr unbefriedigend!

mfg Cecidi

Workaround:
Code:
const GLfloat LightDirection[] = { 0.0f, 0.0f, 9999.0f, 1.0f };
 
Zurück