Versuchen Sie, das Licht auf OpenGL zu verstehen, wie Sie ein realistisches Sonnenlicht simulieren können?

13

Ich weiß nicht, ob ich etwas falsch mache oder etwas verpasse, aber ich möchte Sonnenlicht simulieren, wie an einem sonnigen Tag.

Wenn das Objekt dem gerichteten Licht zugewandt ist, ist es gut beleuchtet und es gibt dort keine Probleme. Wenn ich um das Objekt herum gehe und es wieder anschaue, ist es dunkel. Es ist nicht zu dunkel, weil ich es benutze, GL_AMBIENTaber es ist immer noch zu dunkel für einen sonnigen Tag. Wenn ich den Wert erhöhe, wird er niemals besser aussehen, da die dem Licht zugewandte Seite des Objekts zu hell ist.

Und es gibt ein weiteres ärgerliches Problem mit dem Umgebungslicht: Wenn ich auf die Rückseite des Objekts schaue, sehe ich keine Form, sondern nur eine einfache Farbe. Schwer zu erklären, hier ein paar Bilder:

Objekt Vorderseite: http://i.stack.imgur.com/YW53X.png
Objekt Rückseite: http://i.stack.imgur.com/Qufha.png

Wie Sie leicht sehen können, sieht die Vorderseite gut aus, Sie können die Form dieses roten Dings sehen. Auf der Rückseite ist es einfach, Sie können nicht die gleiche Form sehen.

Jetzt weiß ich, dass ich auf die Rückseite eines Objekts und in die Richtung des Lichts schaue und dass es dunkler sein sollte als die Vorderseite. Aber es sollte nicht so einfach aussehen. Das ist nicht das, was wir sehen, wenn wir gegen das Sonnenlicht auf ein Objekt schauen. Wir sehen, dass die Objekte eine Form bilden.

Wie kann ich den gleichen (oder einen ähnlichen) Effekt auf OpenGL haben?

Mein Licht ist momentan so definiert:

float posLight0[4] = {-1.0f, 1.0f, 1.0f, 0.0f};
float ambLight0[4] = {0.5f, 0.5f, 0.5f, 0.5f};

glLightfv(GL_LIGHT0, GL_POSITION, posLight0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambLight0);
Ricardo Amaral
quelle
Ich schlage vor, dass Sie, wenn möglich, die Verwendung von Shadern in Betracht ziehen. Die OpenGL-Pipeline mit festen Funktionen verwendet ein relativ einfaches Beleuchtungsmodell, wohingegen Shader Ihnen die volle Kontrolle über die Mathematik geben.
Incredulous Monk

Antworten:

11

Mit dem Umgebungslicht erscheinen Ihre Objekte zu hell, da das diffuse Licht dem Umgebungslicht hinzugefügt wird und das diffuse Licht standardmäßig 1,0 ist. Dies summiert sich zu 1,5 und alles über 1,0 wird geklemmt. Stellen Sie das diffuse Licht auf 0,5:

float difLight0[4] = {0.5f, 0.5f, 0.5f, 1.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, difLight0);

Das zweite Problem ist schwerer zu lösen. Sie können versuchen, der Oberfläche einige feine Details wie die Textur oder die Reliefkarte hinzuzufügen. In OpenGL ist das Umgebungslicht konstant, aber in der realen Welt ist dies niemals der Fall. Um die reale Welt zu simulieren, wird eine Art globale Beleuchtungslösung benötigt. Ambient Occlusion hilft hier sehr, ist aber schwieriger zu implementieren als nur das Setzen von OpenGL-Zuständen. Sie könnten die Umgebungsverdeckung in Ihrer 3D-Modellierungssoftware an den Scheitelpunkten Ihres Modells backen oder SSAO verwenden , aber ich gehe nicht auf die Details ein.

Sie können einfach eine andere Dimmerlichtquelle aus einer anderen Richtung (z. B. entgegengesetzte Richtung) hinzufügen. Dies ist nicht realistisch, gibt aber zumindest den Rückseiten Ihrer Objekte eine gewisse Form.

Ziehen Sie auch in Betracht, Ihrer Anwendung Glanzlichter hinzuzufügen. Es wird Objekte glänzend machen.

float specLight0[4] = {0.5f, 0.5f, 0.5f, 1.0f};
glLightfv(GL_LIGHT0, GL_SPECULAR, specLight0);
glMaterialfv(GL_FRONT, GL_SHININESS, 10.0f); // Shininess between 0 and 128

Sie können auch Licht- und Materialfarben separat festlegen, insbesondere wenn die Standardeinstellungen nicht für Sie geeignet sind.

msell
quelle
Es gibt also keine einfache und direkte Möglichkeit, in OpengGL das zu tun, was ich will ... Schade. Vielleicht werde ich versuchen, eine andere Lichtquelle hinzuzufügen, aber wie genau lege ich die Lichtintensität fest?
Ricardo Amaral
Die GL_SPECULARund GL_SHININESSscheinen jedoch keine Auswirkungen zu haben ... Ich habe zu gewechselt glMaterialfv, glMaterialiweil sie nicht kompiliert wurden. Und auch einen größeren Wert wie 128 ausprobiert. Es sieht für mich genauso aus ... Vielleicht liegt das Problem bei meinem geladenen Modell (obj / mtl), muss sich das mal ansehen.
Ricardo Amaral
1
@Nazgulled Nur überprüft, dass der Standardwert für light0 specular 1.0 ist, der Standardwert für material specular jedoch 0.0. Also ändere glLightfv (GL_LIGHT0, GL_SPECULAR, specLight0); zu glMaterialfv (GL_FRONT, GL_SPECULAR, specLight0); Es ist auch gut, glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE) zu setzen. oder das Spiegelbild wird möglicherweise falsch berechnet, wenn sich die Kamera dreht.
msell
1
@Nazgulled Setzen Sie für das Sekundärlicht die Umgebung und das Spiegelbild auf Null und einen kleinen Wert wie 0,2 für das diffuse Licht. Sie können auch die Umgebung aller Lichter auf Null setzen und stattdessen die globale Umgebung mit GL_LIGHT_MODEL_AMBIENT verwenden.
msell
2

Das Umgebungslicht von OpenGL ist einfarbig, aber das Umgebungslicht in der realen Welt ist normalerweise von oben heller und von unten dunkler. Sie können dies in OpenGL approximieren, indem Sie das Umgebungslicht auf sehr dunkelblau einstellen und ein dunkelblaues gerichtetes Licht hinzufügen, das nach unten zeigt. Dies und ein strahlend weißes, gerichtetes Licht, das von jedem Ort kommt, an dem sich die Sonne befindet, können sich dem Außenlicht ziemlich gut annähern.

Was Sie wirklich tun sollten, ist, einen Shader zu schreiben, der das Licht pro Pixel berechnet, aber es wird ein wenig dauern, bis Sie dort sind, wo Sie sind.

bmcnett
quelle
1

Die Antwort, die Sie hier haben, ist ziemlich gut. Nur eine Ergänzung. Wenn Sie es schöner haben möchten, versuchen Sie, atmosphärische Streuung zu implementieren

Notabene
quelle