2016-12-18 2 views
0

J'essaye de rendre une pièce simple (10x3x10) en utilisant OpenGL et GLUT, écrit en C.OpenGL: Comment rendre la lumière stationnaire lorsque vous déplacez la caméra?

Je voudrais créer un simple projecteur statique, pendant que je peux me déplacer dans la pièce.

(Le but ultime est de faire un coup de projecteur vient d'une lampe au plafond)

Le problème est la lumière change lorsque je déplace la caméra autour.

J'appelle la fonction suivante de main():

void init() { 
    glEnable(GL_TEXTURE_2D); 

    loadTexture(); // loading some textures using SOIL 
    loadModels(); // loading some OBJ models 

    glShadeModel(GL_SMOOTH); 
    glEnable(GL_NORMALIZE); 
    glEnable(GL_AUTO_NORMAL); 
    glEnable(GL_DEPTH_TEST); 
    glEnable(GL_COLOR_MATERIAL); 
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); 
    glClearDepth(1); 
    glEnable(GL_LIGHTING); 
    glEnable(GL_LIGHT0); 
    glDepthFunc(GL_LEQUAL); 
    glClearColor(0, 0, 0, 1); 
} 

La fonction i passe à glutDisplayFunc():

void display() { 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 

    initLight(); 

    gluLookAt(x, 1.5f, z, x + vX, 1.5f, z + vZ, 0.0f, 1.5f, 0.0f); 

    // ... 
    // drawing the ground, ceiling and the walls 
    // no matrix transformations here, just simple glVertex() calls 
    // ... 

    glPushMatrix(); 

    // drawing a table 
    glTranslatef(5, 0.842843, 5); 
    glBindTexture(GL_TEXTURE_2D, texture[1]); 
    draw_model(&modelTable); 

    // drawing some chairs 
    glTranslatef(0, -0.312053, chair1Position); 
    glBindTexture(GL_TEXTURE_2D, texture[2]); 
    draw_model(&modelChair1); 
    glTranslatef(0, 0, chair2Position); 
    draw_model(&modelChair2); 

    glPopMatrix(); 

    glutSwapBuffers(); 
} 

Et la fonction initLight():

void initLight() { 

    // i would like the light to originate from an upper corner 
    // directed to the opposing lower corner (across the room basically) 

    GLfloat lightPosition[] = { 10, 3, 0, 1 }; 
    GLfloat lightDirection[] = { 0, 0, 10, 0 }; 
    GLfloat ambientLight[] = { 0.3, 0.3, 0.3, 1 }; 
    GLfloat diffuseLight[] = { 1, 1, 1, 1 }; 

    glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); 
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); 
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); 
    glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180); 
    glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 64); 
    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection); 
} 

J'étais dit ce problème pourrait être s par le bon positionnement des appels glPushMatrix() et glPopMatrix(). Où que je les mette, la lumière ne cesse de changer quand je bouge l'appareil photo ou je n'ai pas de lumière du tout. Je ne peux pas le comprendre.

Quelle serait une bonne solution ici?

Merci d'avance.

EDIT: J'ai déplacé l'appel initLight() à après l'appel gluLookAt() comme @derhass suggéré ci-dessous. La lumière change encore lorsque je me déplace.

Il y a deux captures d'écran ci-dessous.

Sur le premier, la lumière n'est même pas visible. Quand je tourne légèrement vers la droite, il apparaît. enter image description here enter image description here

EDIT2:

Le code source complet (dépouillée):

#include <GL/glut.h> 
#include <SOIL/SOIL.h> 
#include <math.h> 

GLfloat lightPosition[] = { 10, 3, 0, 1 }; 
GLfloat lightDirection[] = { 0, 0, 10, 0 }; 
GLfloat diffuseLight[] = { 0, 1, 0, 1 }; 
GLfloat ambientLight[] = { 0.2, 0.2, 0.2, 1 }; 

float x = 1.0f, z = 5.0f; 
float vX = 1.0f, vZ = 0.0f; 
float angle = 1.5f; 

int windowWidth = 1024; 
int windowHeight = 768; 

char* textureFiles[13] = { "floortexture.png", "tabletexture.png", 
     "chairtexture.png", "orange.png", "helptexture.png", 
     "fridgetexture.png", "oven.png", "yellow.png", "dishwasher.png", 
     "metallic.png", "cabinet.png", "wood.png", "cabinet2.png" }; 
GLuint texture[13]; 

void loadTexture() { 
    for (int i = 0; i < 13; i++) { 
     texture[i] = SOIL_load_OGL_texture(textureFiles[i], SOIL_LOAD_RGBA, 
       SOIL_CREATE_NEW_ID, 0); 

     glBindTexture(GL_TEXTURE_2D, texture[i]); 

     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    } 
} 

void init() { 
    glEnable(GL_TEXTURE_2D); 

    loadTexture(); 

    glShadeModel(GL_SMOOTH); 
    glEnable(GL_NORMALIZE); 
    glEnable(GL_AUTO_NORMAL); 
    glEnable(GL_DEPTH_TEST); 
    glEnable(GL_COLOR_MATERIAL); 
    glClearDepth(1); 
    glEnable(GL_LIGHTING); 
    glEnable(GL_LIGHT0); 
    glDepthFunc(GL_LEQUAL); 
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); 
    glClearColor(0, 0, 0, 1); 
} 

void processSpecialKeys(int key, int xx, int yy) { 

    float moveFraction = 0.2f; 
    float angleFraction = 0.1f; 

    switch (key) { 
    case GLUT_KEY_LEFT: 
     angle -= angleFraction; 
     vX = sin(angle); 
     vZ = -cos(angle); 
     break; 
    case GLUT_KEY_RIGHT: 
     angle += angleFraction; 
     vX = sin(angle); 
     vZ = -cos(angle); 
     break; 
    case GLUT_KEY_UP: 
     x += vX * moveFraction; 
     z += vZ * moveFraction; 
     if (x < 1) { 
      x = 1; 
     } 
     if (z < 1) { 
      z = 1; 
     } 
     if (x > 9) { 
      x = 9; 
     } 
     if (z > 9) { 
      z = 9; 
     } 
     break; 
    case GLUT_KEY_DOWN: 
     x -= vX * moveFraction; 
     z -= vZ * moveFraction; 
     if (x < 1) { 
      x = 1; 
     } 
     if (z < 1) { 
      z = 1; 
     } 
     if (x > 9) { 
      x = 9; 
     } 
     if (z > 9) { 
      z = 9; 
     } 
     break; 
    } 
} 

void initLight() { 
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); 
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); 
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); 
    glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180); 
    glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 128); 
    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection); 
} 

void renderWalls() { 
    // floor 
    glBindTexture(GL_TEXTURE_2D, texture[0]); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
    glBegin(GL_QUADS); 

    glTexCoord2f(0, 0); 
    glVertex3f(0.0f, 0.0f, 0.0f); 

    glTexCoord2f(0, 8); 
    glVertex3f(0.0f, 0.0f, 10.0f); 

    glTexCoord2f(8, 8); 
    glVertex3f(10.0f, 0.0f, 10.0f); 

    glTexCoord2f(8, 0); 
    glVertex3f(10.0f, 0.0f, 0.0f); 

    glEnd(); 

    // walls 
    glBindTexture(GL_TEXTURE_2D, texture[3]); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 

    // first wall 
    glBegin(GL_QUADS); 

    glTexCoord2f(0, 0); 
    glVertex3f(0.0f, 0.0f, 0.0f); 

    glTexCoord2f(0, 1); 
    glVertex3f(0.0f, 3.0f, 0.0f); 

    glTexCoord2f(1, 1); 
    glVertex3f(10.0f, 3.0f, 0.0f); 

    glTexCoord2f(1, 0); 
    glVertex3f(10.0f, 0.0f, 0.0f); 

    glEnd(); 

    // second wall 
    glBegin(GL_QUADS); 

    glTexCoord2f(0, 0); 
    glVertex3f(10.0f, 0.0f, 0.0f); 

    glTexCoord2f(0, 1); 
    glVertex3f(10.0f, 3.0f, 0.0f); 

    glTexCoord2f(1, 1); 
    glVertex3f(10.0f, 3.0f, 10.0f); 

    glTexCoord2f(1, 0); 
    glVertex3f(10.0f, 0.0f, 10.0f); 

    glEnd(); 

    // third wall 
    glBegin(GL_QUADS); 

    glTexCoord2f(0, 0); 
    glVertex3f(10.0f, 0.0f, 10.0f); 

    glTexCoord2f(0, 1); 
    glVertex3f(10.0f, 3.0f, 10.0f); 

    glTexCoord2f(1, 1); 
    glVertex3f(0.0f, 3.0f, 10.0f); 

    glTexCoord2f(1, 0); 
    glVertex3f(0.0f, 0.0f, 10.0f); 

    glEnd(); 

    // fourth wall 
    glBegin(GL_QUADS); 

    glTexCoord2f(0, 0); 
    glVertex3f(0.0f, 0.0f, 0.0f); 

    glTexCoord2f(0, 1); 
    glVertex3f(0.0f, 3.0f, 0.0f); 

    glTexCoord2f(1, 1); 
    glVertex3f(0.0f, 3.0f, 10.0f); 

    glTexCoord2f(1, 0); 
    glVertex3f(0.0f, 0.0f, 10.0f); 

    glEnd(); 

    // ceiling 
    glBindTexture(GL_TEXTURE_2D, texture[7]); 
    glBegin(GL_QUADS); 

    glTexCoord2f(0, 0); 
    glVertex3f(0.0f, 3.0f, 0.0f); 

    glTexCoord2f(0, 1); 
    glVertex3f(10.0f, 3.0f, 0.0f); 

    glTexCoord2f(1, 1); 
    glVertex3f(10.0f, 3.0f, 10.0f); 

    glTexCoord2f(1, 0); 
    glVertex3f(0.0f, 3.0f, 10.0f); 

    glEnd(); 
} 

void display() { 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 

    gluLookAt(x, 1.5f, z, x + vX, 1.5f, z + vZ, 0.0f, 1.5f, 0.0f); 
    initLight(); 

    renderWalls(); 

    glutSwapBuffers(); 
} 

void changeWindowSize(int width, int height) { 
    if (height == 0) { 
     height = 1; 
    } 

    float ratio = 1.0 * width/height; 

    windowWidth = width; 
    windowHeight = height; 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 

    glViewport(0, 0, width, height); 

    gluPerspective(45.0f, ratio, 0.1f, 100.0f); 

    glMatrixMode(GL_MODELVIEW); 
} 

int main(int argc, char **argv) { 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); 
    glutInitWindowPosition(0, 0); 
    glutInitWindowSize(windowWidth, windowHeight); 
    glutCreateWindow("Kitchen"); 

    init(); 

    glutDisplayFunc(display); 
    glutReshapeFunc(changeWindowSize); 
    glutIdleFunc(display); 
    glutSpecialFunc(processSpecialKeys); 

    glutMainLoop(); 

    return 0; 
} 
+0

Qu'en est-il de l'appareil photo et de la lumière dans le même système de référence, pour obtenir l'effet désiré? –

+0

@LuisColorado Merci pour votre réponse. Comment pourrais-je réaliser cela? – justanoob

Répondre

3

Votre lumière est stationnaire - mais à la caméra.

Fonction fixe OpenGL effectue tous les calculs d'éclairage dans l'espace des yeux. Au moment où vous spécifiez le GL_POSITION d'une lumière, il est transformé selon la actuelle modelView matrice au moment de l'appel, pour obtenir la position de l'espace oculaire. Comme modelView est défini sur Identité, il définit toujours la lumière à l'emplacement de l'espace oculaire donné - peu importe où vous placerez la caméra plus tard.

Pour résoudre ce problème, il suffit de déplacer initLight() après le gluLookAt.

Cependant. Tu ne devrais pas faire ça du tout. Vous utilisez déprécié fonctionnalités OpenGL que vous ne devez pas utiliser depuis une décennie maintenant. Dans GL moderne, cette fonctionnalité est complètement supprimée. Donc, si vous apprenez OpenGL en 2016, faites-vous une faveur et oubliez ce vieux cruft, et apprenez juste les shaders directement.

+0

Merci pour votre réponse. Déplacer le 'initLight()' après l'appel 'gluLookAt()' ne fonctionne malheureusement pas. Voir ma question éditée pour des screenshots. Ceci est une cession et je dois utiliser ces fonctionnalités obsolètes. Si vous avez d'autres idées, pourquoi la lumière change-t-elle quand vous vous déplacez, s'il vous plaît faites le moi savoir. Je vous remercie. – justanoob

+0

Eh bien, il n'est pas clair ce que nous voyons réellement là. Comment est modélisée la "pièce"? Comment sont établies les normales? L'éclairage n'est pas indépendant de la position de visualisation - la composante spéculaire est toujours dépendante. Avec ombrage gouraud et tesselation assez faible sur les faces, le résultat pourrait même être correct. Ce que je ne sais pas, c'est d'où vient cette hésitation irrégulière. Quel genre de mise en œuvre GL est-ce? – derhass

+0

J'ai ajouté un lien pastebin au code source à la fin de la question. Réduit au strict minimum pour que le problème soit reproductible. S'il vous plaît jeter un oeil si vous avez le temps. Je vous remercie. J'utilise l'implémentation OpenGL par défaut sur ma machine Debian. – justanoob