OpenGL: Lighting

Für den Aufbau eines individuellen Beleuchtungssetup eines Szenario in OpenGL gilt es einige Fallstricke zu beachten:

1. Positionierung per Frame

Lichtquellen, die sicht NICHT mit der Kamera mitbewegen sollen, müssen in jedem Durchlauf der Renderloop positioniert werden. Wird eine Lichtquelle initiiert und ihre Position (bzw. Richtung für gerichtete Lichtquellen) via glLightfv(GL_LIGHTx, GL_POSITION, pos) definiert, multipliziert OpenGL den gegebenen Positionsvektor pos mit der aktuellen ModelViewMatrix und speichert das Ergebnis als Position der Lichtquelle. Eine Änderung der ModelViewMatrix in der Renderloop, z.Bsp durch Kamerabewegung, führt jedoch später nicht zum Update der initial berechneten Lichtposition. Die Lichtquelle bewegt sich daher mit wenn der Nutzer die Kamera in der Szene bewegt. Dieses Konzept funktioniert zwar für Headlights ist jedoch für eine fixe Positionierung von Lichtquellen in der Szene ungeeignet.

2. Richtung statt Position

Setzt man bei der Definition der Lichtposition im Positionsvektor w = 0.0, kreiert man eine gerichtete Lichtquelle. Die x,y,z Komponenten geben für gerichtete Lichtquellen jedoch NICHT die Richtung der Lichstrahlen an, sondern die Position im Unendlichen. Die resultierende Richtung der Lichtstrahlen ist der inverse Vektor. Eine Position xyzw = { 1.0, 1.0, 0.0, 0.0 } definiert folgende Lichtrichtung: xyz = {-1.0, -1.0, 0.0 }.

3. Große Polygone ganz dunkel

Ist PerVertex Lighting (Gouraud Shading) aktiviert so können Punktlichtquellen große Polygone sehr dunkel erscheinen lassen wenn sie nicht nahe der Eckpunkte positioniert sind. An den Eckpunkten ist der Einfallswinkel des Lichtes, aufgrund der Entfernung zur Lichtquelle, sehr flach, was in einer geringen Helligkeit der Eckpunkte resultiert. Da diese Helligkeitswerte im Inneren des Polygons interpoliert werden, bleibt dieses ebenfalls dunkel. In dieser Situation kann eine gerichtete Lichtquelle eine Alternative sein.
Der gleiche Effekt ist für spekulare Highlights zu beobachten, die interpoliert im Inneren des Polygons verschmiert erscheinen oder gar verschluckt werden.

4. Globale Einstellungen

Steuert man die Beleuchtung in OpenGL über die Aktivierung einzelner Lichtquellen via glEnable(GL_LIGHTx) kommt man nicht unbedingt mit der Funktion für globale Beleuchtungsparameter glLightModel in Berührung. Will man eine exakte Beleuchtung einer Szene kreieren ist es essentiell zu wissen, dass man mit dieser Funktion eine globale ambiente Intensität setzen kann. OpenGL tut dies leider auch OHNE das Wissen des Nutzers und setzt den default Wert dafür auf RGBA(0.2, 0.2, 0.2, 1.0). Das bedeutet auch ohne Lichtquelle in der Szene werden alle Objekte mit dieser ambienten Intensität aufgehellt. Möchte man ein Objekt ganz dunkel RGBA(0.0, 0.0, 0.0, 1.0) zeichnen lassen, muss man die globale Intensität auf 0 setzen:

GLfloat light_ambient_global[] = { 0.0, 0.0, 0.0, 1.0 };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_ambient_global);

Mehr Wissen: OpenGL FAQ Lights and Shadows

Author: Michael Keutel | 25.08.2013