
Einführung
Bei der Arbeit mit Rendering-Parametern fungiert OpenGL in der Regel als Zustandsmaschine. Ein Rendering-Status ist eine Sammlung von Statusattributen wie Lichtquellen, Materialien, Texturen und Anzeigemodi, die von den Funktionen glEnable () und glDisable () ein- und ausgeschaltet werden. Wenn ein bestimmter Status festgelegt ist, bleibt er wirksam, bis eine andere Funktion ihn ändert. Die OpenGL-Pipeline unterstützt einen Statusstapel zum Speichern und Wiederherstellen von Status zu einem bestimmten Zeitpunkt. Die Zustandsmaschine gibt dem Entwickler die vollständige Kontrolle über die aktuellen und gespeicherten Renderzustände auf dem Stapel.
Dieser Ansatz ist jedoch bei der Arbeit mit OSG unpraktisch. Aus diesem Grund wird die OpenGL-Zustandsmaschine von der Klasse osg :: StateSet gekapselt, die sich darum kümmert, mit dem Zustandsstapel zu arbeiten und sie beim Durchlaufen des Szenendiagramms einzurichten.
Eine Instanz der osg :: StateSet-Klasse enthält eine Teilmenge der verschiedenen Rendering-Zustände und kann sie mit der setStateSet () -Methode auf die osg :: Node-Szenenknoten und osg :: Drawable-geometrischen Objekte anwenden
osg::StateSet *stateset = new osg::StateSet; node->setStateSet(stateset);
Ein sicherer Weg wäre die Verwendung der Methode getOrCreateStateSet (), die die Rückgabe des korrekten Status und dessen Verknüpfung mit dem Knoten oder dem zeichnbaren Objekt garantiert
osg::StateSet *stateset = node->getOrCreateStateSet();
Die Klassen osg :: Node und osg :: Drawable steuern die Mitgliedsvariable osg :: StateSet über den Smart Pointer osg :: ref_ptr <>. Dies bedeutet, dass eine Reihe von Zuständen auf mehrere Objekte in der Szene aufgeteilt werden kann und nur dann zerstört wird, wenn alle diese Objekte zerstört werden.
1. Attribute und Modi
OSG definiert die osg :: StateAttribute-Klasse zum Speichern von Rendering-Attributen. Dies ist eine virtuelle Basisklasse, die von verschiedenen Rendering-Attributen wie Licht, Material und Nebel geerbt wird.
Die Rendering-Modi funktionieren wie Schalter, die ein- und ausgeschaltet werden können. Darüber hinaus sind sie Enumeratoren zugeordnet, mit denen der Typ des OpenGL-Modus angegeben wird. Manchmal ist der Rendering-Modus einem Attribut zugeordnet. Beispielsweise enthält der GL_LIGHTING-Modus Variablen für Lichtquellen, die beim Einschalten an die OpenGL-Pipeline gesendet werden, und schaltet die Beleuchtung ansonsten aus.
Die osg :: StateSet-Klasse unterteilt Attribute und Modi in zwei Gruppen: Textur und Nicht-Textur. Es gibt verschiedene öffentliche Methoden zum Hinzufügen von Nicht-Textur-Attributen und -Modi zu einer Reihe von Zuständen:
- setAttribute () - Fügt der Menge der Zustände ein Objekt vom Typ osg :: StateAttribute hinzu. Attribute desselben Typs können nicht in derselben Gruppe von Zuständen koexistieren. Der vorherige Sollwert wird mit dem neuen überschrieben.
- setMode () - Hängt einen Modus-Enumerator an eine Reihe von Zuständen an und setzt seinen Wert auf osg :: StateAttribute :: ON oder auf osg :: StateAttribute :: OFF, was bedeutet, dass der Modus aktiviert oder deaktiviert wird.
- setAttributeAndModes () - Hängt das Rendering-Attribut und den zugehörigen Modus an und legt den Wert des Switch fest (standardmäßig ON). Es sollte beachtet werden, dass nicht jedes Attribut einen entsprechenden Modus hat, aber Sie können diese Methode in jedem Fall verwenden.
Mit diesem Code können Sie das Attribut und den zugehörigen Modus festlegen
stateset->setAttributeAndModes(attr, osg::StateAttribute::ON);
Um Texturattribute festzulegen, muss ein zusätzlicher Parameter übergeben werden, der die Textur angibt, auf die er angewendet werden soll. Osg :: StateSet bietet hierfür mehrere andere öffentliche Methoden an, z. B. setTextureAttribute (), setTextureMode () und setTextureAttributeAndModes ().
stateset->setTextureAttributeAndModes(0, textattr, osg::StateAttribute::ON);
Wendet das textattr-Attribut auf die Textur mit dem Bezeichner 0 an.
2. Einstellen des Polygon-Anzeigemodus für Szenenknoten
Wir veranschaulichen die obige Theorie anhand eines praktischen Beispiels: Ändern des Rasterisierungsmodus von OpenGL-Polygonen mithilfe der Klasse osg :: PolygonMode, die von osg :: StateAttribute erbt. Diese Klasse kapselt die Funktion glPolygonMode () und bietet eine Schnittstelle zum Festlegen des Polygonanzeigemodus für einen bestimmten Szenenknoten.
Beispiel für einen Polygonmodusmain.h #ifndef MAIN_H #define MAIN_H #include <osg/PolygonMode> #include <osg/MatrixTransform> #include <osgDB/ReadFile> #include <osgViewer/Viewer> #endif
main.cpp #include "main.h" int main(int argc, char *argv[]) { (void) argc; (void) argv; osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../data/cessna.osg"); osg::ref_ptr<osg::MatrixTransform> transform1 = new osg::MatrixTransform; transform1->setMatrix(osg::Matrix::translate(-25.0f, 0.0f, 0.0f)); transform1->addChild(model.get()); osg::ref_ptr<osg::MatrixTransform> transform2 = new osg::MatrixTransform; transform2->setMatrix(osg::Matrix::translate(25.0f, 0.0f, 0.0f)); transform2->addChild(model.get()); osg::ref_ptr<osg::PolygonMode> pm = new osg::PolygonMode; pm->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE); transform1->getOrCreateStateSet()->setAttribute(pm.get()); osg::ref_ptr<osg::Group> root = new osg::Group; root->addChild(transform1.get()); root->addChild(transform2.get()); osgViewer::Viewer viewer; viewer.setSceneData(root.get()); return viewer.run(); }
Hier laden wir das Modell unserer geliebten Cessna hoch und wenden Transformationen darauf an. Wir erhalten zwei Instanzen des Modells. Links von ihnen wenden wir ein Attribut an, das den Modus der Drahtgitteranzeige von Polygonen festlegt
osg::ref_ptr<osg::PolygonMode> pm = new osg::PolygonMode; pm->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE); transform1->getOrCreateStateSet()->setAttribute(pm.get());

Wenn wir uns der OpenGL-Spezifikation zuwenden, können wir uns leicht vorstellen, welche Polygonanzeigeoptionen uns in diesem speziellen Fall bei Verwendung von setMode () zur Verfügung stehen. Der erste Parameter kann die Werte osg :: PolygonMode :: FRONT, BACK und FRONT_AND_BACK annehmen, die den OpenGL-Enumeratoren GL_FRONT, GL_BACK, GL_FRONT_AND_BACK entsprechen. Der zweite Parameter kann die Werte osg :: PolygonMode :: POINT, LINE und FILL annehmen, die GL_POINT, GL_LINE und GL_FILL entsprechen. Keine anderen Tricks, wie sie häufig bei der Entwicklung auf einem reinen OpenGL der Fall sind, werden hier nicht benötigt - OSG kümmert sich um den größten Teil der Arbeit. Der Polygon-Anzeigemodus hat keinen zugeordneten Modus und erfordert keinen Aufruf des Paares glEnable () / glDisable (). Die setAttributeAndModes () -Methode funktioniert auch in diesem Fall einwandfrei, aber der Wert des dritten Parameters ist unbrauchbar.
3. Vererbung von Renderzuständen. Anwenden von Attributen und Modi
Die Menge der Knotenzustände wirkt sich auf den aktuellen Knoten und alle seine untergeordneten Knoten aus. Beispielsweise wird das Attribut osg :: PolygonMode, das im vorherigen Beispiel für transform1 festgelegt wurde, auf alle untergeordneten Elemente dieses Knotens angewendet. Der untergeordnete Knoten kann jedoch die übergeordneten Attribute überschreiben. Das heißt, der Renderstatus wird vom übergeordneten Knoten geerbt, wenn der untergeordnete Knoten das Verhalten nicht ändert.
Manchmal müssen Sie das Verhalten eines Knotens in Bezug auf die Attributverwendung neu definieren. In den meisten 3D-Editoren kann der Benutzer beispielsweise mehrere Modelle laden und den Anzeigemodus für alle geladenen Modelle gleichzeitig ändern, unabhängig davon, wie sie zuvor angezeigt wurden. Mit anderen Worten, alle Modelle im Editor müssen ein einzelnes Attribut erben, unabhängig davon, wie sie zuvor für jedes der Modelle festgelegt wurden. In OSG kann dies beispielsweise mit dem Flag osg :: StateAttribute :: OVERRIDE implementiert werden
stateset->StateAttribute(attr, osg::StateAttribute::OVERRIDE);
Beim Festlegen von Modi und Modi mit Attributen wird der bitweise ODER-Operator verwendet
stateset->StateAttributeAndModes(attr, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
Darüber hinaus kann das Attribut auch vor dem Überschreiben geschützt werden. Dazu muss es mit dem Flag osg :: StateAttribute :: PROTECTED gekennzeichnet werden.
Es gibt ein drittes Flag, osg :: StateAttribute :: INHERIT, das angibt, dass dieses Attribut von der Gruppe der Zustände des übergeordneten Knotens geerbt werden soll.
Hier ist ein kurzes Beispiel mit den Flags OVERRIDE und PROTECTED. Der Stammknoten wird auf OVERRIDE gesetzt, um alle untergeordneten Knoten zu zwingen, ihre Attribute und Modi zu erben. In diesem Fall versuchen die untergeordneten Knoten, ihren Status mit oder ohne Hilfe des Flag PROTECTED zu ändern, was zu unterschiedlichen Ergebnissen führt.
Beispieltext erbenmain.h #ifndef MAIN_H #define MAIN_H #include <osg/PolygonMode> #include <osg/MatrixTransform> #include <osgDB/ReadFile> #include <osgViewer/Viewer> #endif
main.cpp #include "main.h" int main(int argc, char *argv[]) { (void) argc; (void) argv; osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../data/glider.osg"); osg::ref_ptr<osg::MatrixTransform> transform1 = new osg::MatrixTransform; transform1->setMatrix(osg::Matrix::translate(-0.5f, 0.0f, 0.0f)); transform1->addChild(model.get()); osg::ref_ptr<osg::MatrixTransform> transform2 = new osg::MatrixTransform; transform2->setMatrix(osg::Matrix::translate(0.5f, 0.0f, 0.0f)); transform2->addChild(model.get()); osg::ref_ptr<osg::Group> root = new osg::Group; root->addChild(transform1.get()); root->addChild(transform2.get()); transform1->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); transform2->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED); root->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); osgViewer::Viewer viewer; viewer.setSceneData(root.get()); return viewer.run(); }

Um zu verstehen, was los ist, müssen Sie sich ansehen, wie ein normal beleuchteter Drachen aussieht, indem Sie seinen Vollzeit-OSG-Osgviewer herunterladen
$ osgviewer glider.osg
In diesem Beispiel versuchen wir, den Beleuchtungsmodus für die Knoten transform1 und transform2 zu ändern, indem wir die Beleuchtung vollständig ausschalten.
transform1->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); transform2->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
In diesem Fall aktivieren wir den Beleuchtungsmodus für den Stammknoten und verwenden das OVERRIDE-Flag für alle untergeordneten Knoten, damit diese den Status des Stammknotens erben. Trnsform2 verwendet jedoch das Flag PROTECTED, um zu verhindern, dass sich die Einstellungen des Stammknotens auswirken.
transform2->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
Trotz der Tatsache, dass wir die Beleuchtung am Knoten transform1 ausschalten, leuchtet der linke Hängegleiter weiterhin, da die Einstellungen des Szenenstamms unseren Versuch blockierten, die Beleuchtung dafür auszuschalten. Der rechte Hängegleiter wird ohne Beleuchtung angezeigt (er sieht nur heller aus, weil er mit einer einfachen Farbe überflutet ist, ohne dass die Beleuchtung wiedergegeben wird), da transform2 vor dem Erben der Attribute des Wurzelknotens geschützt ist.
4. Liste der in OpenSceneGraph unterstützten OpenGL-Attribute
OSG unterstützt fast alle Attribute und Rendering-Modi, die von OpenGL durch von osg :: StateAttribute abgeleitete Klassen unterstützt werden. Die Tabelle zeigt alle Parameter der OpenGL-Zustandsmaschine, die von der Engine verfügbar sind.
Attributtyp-ID | Klassenname | Zugehöriger Modus | Äquivalente OpenGL-Funktion |
---|
ALPHEFUNC | osg :: AlphaFunc | GL_ALPHA_TEST | glAlphaFunc () |
BLENDFUNC | osg :: BlendFunc | GL_BLEND | glBlendFunc () und glBlendFuncSeparate () |
CLIPPLANE | osg :: ClipPlane | GL_CLIP_PLANEi (i von 1 bis 5) | glClipPlane () |
Farbmaske | osg :: ColorMask | - - | glColorMask () |
CULLFACE | osg :: CullFace | GL_CULLFACE | glCullFace () |
Tiefe | osg :: Tiefe | GL_DEPTH_TEST | glDepthFunc (), glDepthRange () und glDepthMask () |
NEBEL | osg :: Nebel | GL_FOG | glFog () |
VORNE | osg :: FrontFace | - - | glFrontFace () |
Licht | osg :: Licht | GL_LIGHTi (i von 1 bis 7) | glLight () |
LICHTMODELL | osg :: LightModel | - - | glLightModel () |
LINESTRIPPEL | osg :: LineStripple | GL_LINE_STRIPPLE | glLineStripple () |
LINIENBREITE | osg :: LineWidth | - - | glLineWidht () |
LOGICOP | osg :: LogicOp | GL_COLOR_LOGIC_OP | glLogicOp () |
MATERIAL | osg :: Material | - - | glMaterial () und glColorMaterial () |
PUNKT | osg :: Point | GL_POINT_SMOOTH | glPointParameter () |
POINTSPRITE | osg :: PointSprite | GL_POINT_SPRITE_ARB | Funktionen zum Arbeiten mit OpenGL-Sprites |
POLYGONMODE | osg :: PolygonMode | - - | glPolygonMode () |
POLYGONOFFSET | osg :: PolygonOffset | GL_POLYGON_OFFSET_POINT | glPolygonOffset () |
POLYGONSTRIPPEL | osg :: PolygonStripple | GL_POLYGON_STRIPPLE | glPolygonStripple () |
SCHERE | osg :: Scissor | GL_SCISSOR_TEST | glScissor () |
SHADEMODEL | osg :: ShadeModel | - - | glShadeModel () |
Schablone | osg :: Schablone | GL_STENCIL_TEST | glStencilFunc (), glStencilOp () und glStencilMask () |
Texenv | osg :: TexEnv | - - | glTexEnv () |
Texgen | osg :: TexGen | GL_TEXTURE_GEN_S | glTexGen () |
Die Spalte Attributtyp-ID gibt den spezifischen OSG-Bezeichner an, der dieses Attribut in den Enumeratoren der Klasse osg :: StateAttribute identifiziert. Es kann in der Methode getAttribute verwendet werden, um den Wert eines bestimmten Attributs abzurufen.
osg::PolygonMode *pm = dynamic_cast<osg::PolygonMode *>(stateset->getAttribute(osg::StateAttribute::POLYGONMODE));
Ein gültiger Zeiger zeigt an, dass das Attribut zuvor festgelegt wurde. Andernfalls liegt die Methode bei NULL. Sie können den Wert des aktuellen Modus auch über den Aufruf abrufen
osg::StateAttribute::GLModeValue value = stateset->getMode(GL_LIGHTING);
Hier wird der GL_LIGHTING-Enumerator verwendet, um die Beleuchtung in der gesamten Szene zu aktivieren / deaktivieren.
5. Wenden Sie Nebel auf das Modell in der Szene an
Lassen Sie uns den Nebeleffekt als ideale Methode anführen, um zu zeigen, wie mit verschiedenen Attributen und Rendering-Modi gearbeitet wird. OpenGL verwendet eine lineare und zwei exponentielle Gleichungen, die das Nebelmodell beschreiben und von der Klasse osg :: Fog unterstützt werden.
Beispieltext Nebelmain.h #ifndef MAIN_H #define MAIN_H #include <osg/Fog> #include <osgDB/ReadFile> #include <osgViewer/Viewer> #endif
main.cpp #include "main.h" int main(int argc, char *argv[]) { (void) argc; (void) argv; osg::ref_ptr<osg::Fog> fog = new osg::Fog; fog->setMode(osg::Fog::LINEAR); fog->setStart(500.0f); fog->setEnd(2500.0f); fog->setColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../data/lz.osg"); model->getOrCreateStateSet()->setAttributeAndModes(fog.get()); osgViewer::Viewer viewer; viewer.setSceneData(model.get()); return viewer.run(); }
Erstellen Sie zunächst das Nebelattribut. Wir verwenden ein lineares Modell und passen den Bereich der Nebelanzeige an den Abstand zum Modell an
osg::ref_ptr<osg::Fog> fog = new osg::Fog; fog->setMode(osg::Fog::LINEAR); fog->setStart(500.0f); fog->setEnd(2500.0f); fog->setColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
Wir laden das Landschaftsbeispiel lz.osg und wenden dieses Attribut darauf an
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../data/lz.osg"); model->getOrCreateStateSet()->setAttributeAndModes(fog.get());
Im Viewer-Fenster sehen wir eine unscharfe Landschaft und können sehen, wie sich die Nebeldichte in Abhängigkeit von der Entfernung zum Modell ändert



6. Arbeiten Sie mit Lichtquellen und Licht
Wie bei OpenGL unterstützt OSG bis zu acht Lichtquellen, um Szenenobjekte direkt zu treffen. Wie OpenGL berechnet OSG Schatten nicht automatisch. Lichtstrahlen kommen von Quellen in geraden Linien, werden von Objekten reflektiert und von diesen gestreut, wonach sie von den Augen des Betrachters wahrgenommen werden. Für eine qualitativ hochwertige Verarbeitung der Beleuchtung müssen Materialeigenschaften, normale Geometrie von Objekten usw. eingestellt werden.
Die Klasse osg :: Light bietet Methoden zum Steuern von Lichtquellen, einschließlich: setLightNum () und getLightNum () - zum Arbeiten mit der Anzahl der Quellen; setAmbient () und getAmbient () zur Steuerung der umgebenden Komponente; setDiffuse () und getDiffuse () - zum Arbeiten mit einer verstreuten Komponente usw.
OSG beschreibt auch die osg :: LightSource-Klasse zum Hinzufügen von Lichtquellen zur Szene. Es stellt die setLight () -Methode bereit und ist der Blattknoten des Szenendiagramms mit einem einzelnen Attribut. Alle anderen Knoten des Szenendiagramms sind von der Lichtquelle betroffen, wenn der entsprechende Modus für GL_LIGHTi eingestellt ist. Zum Beispiel:
Eine weitere, bequemere Lösung ist die Methode setStateSetModes (), mit der die Lichtquelle mit der gewünschten Nummer automatisch an den Wurzelknoten angehängt wird
root->addChild( lightSource.get() ); lightSource->setStateSetModes( root->getOrCreateStateSet(), osg::StateAttribute::ON );
Sie können der Lichtquelle untergeordnete Knoten hinzufügen, dies bedeutet jedoch keineswegs, dass Sie den damit verbundenen Untergraphen auf besondere Weise beleuchten. Es wird als Geometrie verarbeitet, die durch die physikalische Form der Lichtquelle dargestellt wird.
Der Knoten osg :: LightSource kann an den Transformationsknoten angehängt werden, und beispielsweise kann eine Punktlichtquelle im Raum verschoben werden. Dies kann deaktiviert werden, indem das absolute Koordinatensystem für die Lichtquelle eingestellt wird.
lightSource->setReferenceFrame( osg::LightSource::ABSOLUTE_RF );
7. Erstellen von Lichtquellen in der Szene
Standardmäßig setzt OSG die Lichtquelle automatisch auf die Nummer 0, wodurch ein gleichmäßiges Richtungslicht an die Szene abgegeben wird. Sie können jedoch jederzeit mehrere zusätzliche Lichtquellen hinzufügen und diese sogar mithilfe der Koordinatentransformationsknoten steuern. Es können nur Positionsquellen (Punktquellen) verschoben werden. Richtungslicht hat nur eine Richtung (ein Strom paralleler Strahlen aus dem Unendlichen) und ist nicht an eine bestimmte Position auf der Bühne gebunden. OpenGL und OSG verwenden die vierte Komponente des Positionsparameters, um den Typ der Lichtquelle anzugeben. Wenn es 0 ist, wird das Licht als gerichtet betrachtet; mit einem Wert von 1 - positionell.
Betrachten Sie ein kleines Beispiel für die Arbeit mit Beleuchtung.
Spoiler Überschriftmain.h #ifndef MAIN_H #define MAIN_H #include <osg/MatrixTransform> #include <osg/LightSource> #include <osgDB/ReadFile> #include <osgViewer/Viewer> #endif
main.cpp #include "main.h"
Um eine Lichtquelle zu erstellen, haben wir eine separate Funktion
osg::Node *createLightSource(int num, const osg::Vec3 &trans, const osg::Vec4 &color) { osg::ref_ptr<osg::Light> light = new osg::Light; light->setLightNum(num); light->setDiffuse(color); light->setPosition(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource; lightSource->setLight(light); osg::ref_ptr<osg::MatrixTransform> sourceTrans = new osg::MatrixTransform; sourceTrans->setMatrix(osg::Matrix::translate(trans)); sourceTrans->addChild(lightSource.get()); return sourceTrans.release(); }
In dieser Funktion bestimmen wir zuerst die von der Quelle angegebenen Beleuchtungsparameter und erstellen dabei das Attribut GL_LIGHTi
osg::ref_ptr<osg::Light> light = new osg::Light;
Danach wird eine Lichtquelle erstellt, der dieses Attribut zugeordnet ist.
osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource; lightSource->setLight(light);
Wir erstellen und konfigurieren den Transformationsknoten und übergeben ihm unsere Lichtquelle als untergeordneten Knoten
osg::ref_ptr<osg::MatrixTransform> sourceTrans = new osg::MatrixTransform; sourceTrans->setMatrix(osg::Matrix::translate(trans)); sourceTrans->addChild(lightSource.get());
Geben Sie einen Zeiger auf den Transformationsknoten zurück
return sourceTrans.release();
Im Hauptteil des Hauptprogramms laden wir ein dreidimensionales Modell (wieder unsere Lieblings-Cessna).
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../data/cessna.osg"); osg::ref_ptr<osg::Group> root = new osg::Group; root->addChild(model.get());
Wir erstellen zwei Lichtquellen mit den Nummern 0 und 1. Die erste leuchtet gelb, die zweite blau-grün
osg::Node *light0 = createLightSource(0, osg::Vec3(-20.0f, 0.0f, 0.0f), osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); osg::Node *light1 = createLightSource(1, osg::Vec3(0.0f, -20.0f, 0.0f), osg::Vec4(0.0f, 1.0f, 1.0f, 1.0f));
Wir informieren die OpenGL-Zustandsmaschine darüber, dass 0 und 1 Lichtquellen eingeschaltet und die von uns erstellten Quellen zur Szene hinzugefügt werden müssen
root->getOrCreateStateSet()->setMode(GL_LIGHT0, osg::StateAttribute::ON); root->getOrCreateStateSet()->setMode(GL_LIGHT1, osg::StateAttribute::ON); root->addChild(light0); root->addChild(light1);
Nach dem Initialisieren und Starten des Viewers erhalten wir ein Bild

Fazit
Sehr bewegt von der Aufmerksamkeit interessierter Menschen auf diesen Zyklus. Diese Aktion hat nicht sehr viel begonnen, aber ich bin der Meinung, dass die Community Artikel braucht. Vielen Dank für alle möglichen positiven Rückmeldungen.
Heute habe ich versucht, noch einmal die ziemlich grundlegenden Dinge der OSG-Engine zu betrachten. Ich bin mir nicht sicher, was cool herausgekommen ist. Aber bisher stelle ich genau primitive Dinge dar, in dem Sinne, wie ich sie selbst verstanden habe. Ich habe alle Beispiele persönlich überprüft, mein Repository ist
hier verfügbar. Vielen Dank, liebe Kollegen, ich werde versuchen, diese Geschichte
fortzusetzen ...