[OpenGL] Lichtrichtung immer nach -z? Warum?



  • Hallo.

    Ich mach gerade ein paar erste Gehversuche mit OpenGL, genauer gesagt mit den Java Bindings für OpenGL. Ich versuche mich an folgendem Szenario: Ich habe ein Objekt, das ich angucken möchte und ich möchte meine Position und Blickrichtung ändern können. Weiterhin möchte ich eine Lichtquelle hinter mir positionieren, die entweder nicht gerichtet ist oder in Blickrichtung gerichtet ist. Die Positionierung der Lichtquelle funktioniert auch, aber dummerweise ist sie wohl immer in negative z-Richtung gerichtet. Ich weiß nicht warum, denn eigentlich gehe ich davon aus, dass ich eine nichtgerichtete Lichtquelle erzeugt habe. Der relevante Code sieht ungefähr so aus:

    Die init-Methode:

    public void init(GLAutoDrawable glAutoDrawable)
       {
          GL gl = glAutoDrawable.getGL();
          System.out.println(glAutoDrawable.getChosenGLCapabilities());
          gl.glShadeModel(GL.GL_SMOOTH);
          gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
          gl.glClearDepth(10.0f);
          gl.glEnable(gl.GL_DEPTH_TEST);
          gl.glDepthFunc(gl.GL_LEQUAL);
          gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST);
          gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, new float[]{0.3f,0.3f,0.3f,1.0f}, 0);
          gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, new float[]{1.0f,1.0f,1.0f,1.0f}, 0);
          gl.glEnable(GL.GL_LIGHT0);
          gl.glEnable(GL.GL_LIGHTING);
       }
    

    ...und nachher die Methode zum zeichnen:

    public void display(GLAutoDrawable glAutoDrawable)
       {
          GL gl = glAutoDrawable.getGL();
    
          gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
          gl.glMatrixMode(GL.GL_PROJECTION);
          gl.glLoadIdentity();
          glu.gluPerspective(50.0, 1.0, 0.2, 20.0);
          gl.glMatrixMode(GL.GL_MODELVIEW);
          gl.glLoadIdentity();
    
          glu.gluLookAt(eyePos.getComponent(0),eyePos.getComponent(1),eyePos.getComponent(2),
                        eyePos.getComponent(0)+lookAtVector.getComponent(0),
                        eyePos.getComponent(1)+lookAtVector.getComponent(1),
                        eyePos.getComponent(2)+lookAtVector.getComponent(2),
                        upVector.getComponent(0), upVector.getComponent(1), upVector.getComponent(2));
    
          final Vector lightPos = new Vector(eyePos);
          lightPos.addMultipleOf(lookAtVector, -2.0);
    
          gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION,
             new float[]{(float)lightPos.getComponent(0),(float)lightPos.getComponent(1),
             (float)lightPos.getComponent(2),1.0f},
             0);
          gl.glBegin(GL.GL_TRIANGLES);
          {
             for(Triangle triangle : surface)
             {
                gl.glVertex3d(triangle.a.x,triangle.a.y,triangle.a.z);
                gl.glVertex3d(triangle.b.x,triangle.b.y,triangle.b.z);
                gl.glVertex3d(triangle.c.x,triangle.c.y,triangle.c.z);
             }
          }
    
          gl.glEnd();
       }
    

    Sieht jemand, warum das mit der Lichtgebung nicht so funktioniert, wie es funktionieren soll?

    PS: Vermutlich steht da auch ne Menge Unfug drin, weil ich OGL einfach noch nicht komplett verstehe und meinen Code momentan noch durch Imitation von irgendwelchem Beispielcode zu Stande bringe.



  • Ok, das Problem ist gelöst. Es hatte wohl etwas mit den Normalen der Dreiecke zu tun.

    Edit: Also um nochmal klarer zu sagen, was wohl los war: Ich hatte die Normalen nicht explizit gesetzt und dadurch wurden vermutlich irgendwelche Standardnormalen genutzt, die alle in positive z-Richtung zeigten. Wenn dann das Licht berechnet wird, sieht es so aus, als ob die nichtdirektionale Lichtquelle nur nach unten scheint. Die Lösung wandelt die Zeichenmethode so ab, dass der "Dreiecksteil" dieser Methode so aussieht:

    gl.glBegin(GL.GL_TRIANGLES);
          {
             for(Triangle triangle : surface)
             {
                final Point3D normal = triangle.normal;
                gl.glNormal3d(normal.x, normal.y, normal.z);
                gl.glVertex3d(triangle.a.x,triangle.a.y,triangle.a.z);
                gl.glVertex3d(triangle.b.x,triangle.b.y,triangle.b.z);
                gl.glVertex3d(triangle.c.x,triangle.c.y,triangle.c.z);
             }
          }
    

Anmelden zum Antworten