OpenSceneGraph: encapsulation d'une machine d'état OpenGL

image

Présentation


En règle générale, lorsque vous travaillez avec des paramètres de rendu, OpenGL agit comme une machine à états. Un état de rendu est une collection d'attributs d'état, tels que les sources lumineuses, les matériaux, les textures et les modes d'affichage, activés et désactivés par les fonctions glEnable () et glDisable (). Lorsqu'un certain état est défini, il reste en vigueur jusqu'à ce qu'une autre fonction le modifie. Le pipeline OpenGL prend en charge une pile d'états pour enregistrer et restaurer des états à tout moment. La machine à états donne au développeur un contrôle complet sur les états de rendu actuels et enregistrés sur la pile.

Cependant, cette approche n'est pas pratique lorsque vous travaillez avec OSG. Pour cette raison, la machine à états OpenGL est encapsulée par la classe osg :: StateSet, qui s'occupe de travailler avec la pile d'états et de les paramétrer dans le processus de traversée du graphe de scène.

Une instance de la classe osg :: StateSet contient un sous-ensemble des différents états de rendu et peut les appliquer aux nœuds de scène osg :: Node et aux objets géométriques osg :: Drawable à l'aide de la méthode setStateSet ()

osg::StateSet *stateset = new osg::StateSet; node->setStateSet(stateset); 

Un moyen plus sûr serait d'utiliser la méthode getOrCreateStateSet (), qui garantit le retour de l'état correct et son attachement au nœud ou à l'objet dessinable

 osg::StateSet *stateset = node->getOrCreateStateSet(); 

Les classes osg :: Node et osg :: Drawable contrôlent la variable membre osg :: StateSet via le pointeur intelligent osg :: ref_ptr <>. Cela signifie qu'un ensemble d'états peut être divisé entre plusieurs objets de la scène et ne sera détruit que lorsque tous ces objets seront détruits.

1. Attributs et modes


OSG définit la classe osg :: StateAttribute pour stocker les attributs de rendu. Il s'agit d'une classe de base virtuelle héritée de divers attributs de rendu tels que la lumière, le matériau et le brouillard.

Les modes de rendu fonctionnent comme des commutateurs qui peuvent être activés et désactivés. De plus, ils sont associés à des énumérateurs, qui sont utilisés pour indiquer le type de mode OpenGL. Parfois, le mode de rendu est associé à un attribut, par exemple, le mode GL_LIGHTING inclut des variables pour les sources lumineuses qui sont envoyées au pipeline OpenGL lorsqu'il est activé, et désactive l'éclairage autrement.

La classe osg :: StateSet divise les attributs et les modes en deux groupes: texture et non-texture. Il a plusieurs méthodes publiques pour ajouter des attributs et des modes non texturés à un ensemble d'états:

  1. setAttribute () - Ajoute un objet de type osg :: StateAttribute à l'ensemble d'états. Les attributs du même type ne peuvent pas coexister dans le même ensemble d'états. Le point de consigne précédent sera remplacé par le nouveau.
  2. setMode () - attache un énumérateur de mode à un ensemble d'états et définit sa valeur sur osg :: StateAttribute :: ON ou osg :: StateAttribute :: OFF, ce qui signifie activer ou désactiver le mode.
  3. setAttributeAndModes () - attache l'attribut de rendu et son mode associé et définit la valeur du commutateur (par défaut ON). Il convient de garder à l'esprit que tous les attributs n'ont pas un mode correspondant, mais vous pouvez utiliser cette méthode dans tous les cas.

Pour définir l'attribut et son mode associé, vous pouvez utiliser ce code

 stateset->setAttributeAndModes(attr, osg::StateAttribute::ON); 

Pour définir les attributs de texture, un paramètre supplémentaire doit être transmis pour indiquer la texture à laquelle il doit être appliqué. Osg :: StateSet fournit plusieurs autres méthodes publiques pour cela, telles que setTextureAttribute (), setTextureMode () et setTextureAttributeAndModes ()

 stateset->setTextureAttributeAndModes(0, textattr, osg::StateAttribute::ON); 

applique l'attribut textattr à la texture avec l'identifiant 0.

2. Définition du mode d'affichage des polygones pour les nœuds de scène


Nous illustrons la théorie ci-dessus avec un exemple pratique - changer le mode de pixellisation des polygones OpenGL en utilisant la classe osg :: PolygonMode, qui hérite d'osg :: StateAttribute. Cette classe encapsule la fonction glPolygonMode () et fournit une interface pour définir le mode d'affichage des polygones pour un nœud de scène particulier.

Exemple en mode polygone
main.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(); } 


Ici, nous téléchargeons le modèle de notre bien-aimé cessna et en lui appliquant des transformations, nous obtenons deux instances du modèle. À l'un d'eux, à gauche, nous appliquons un attribut qui définit le mode d'affichage filaire des polygones

 osg::ref_ptr<osg::PolygonMode> pm = new osg::PolygonMode; pm->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE); transform1->getOrCreateStateSet()->setAttribute(pm.get()); 



Si nous nous tournons vers la spécification OpenGL, nous pouvons facilement imaginer quelles options d'affichage de polygone seront disponibles lorsque nous utiliserons setMode () dans ce cas particulier. Le premier paramètre peut prendre les valeurs osg :: PolygonMode :: FRONT, BACK et FRONT_AND_BACK, correspondant aux énumérateurs OpenGL GL_FRONT, GL_BACK, GL_FRONT_AND_BACK. Le deuxième paramètre peut prendre les valeurs osg :: PolygonMode :: POINT, LINE et FILL, qui correspondent à GL_POINT, GL_LINE et GL_FILL. Aucune autre astuce, comme c'est souvent le cas lors du développement sur un OpenGL pur, n'est pas nécessaire ici - OSG prend en charge la plupart du travail. Le mode d'affichage polygonal n'a pas de mode associé et ne nécessite pas d'appeler la paire glEnable () / glDisable (). La méthode setAttributeAndModes () fonctionnera également très bien dans ce cas, mais la valeur de son troisième paramètre sera inutile.

3. Héritage des états de rendu. Application d'attributs et de modes


L'ensemble des états de nœud affecte le nœud actuel et tous ses enfants. Par exemple, l'attribut osg :: PolygonMode défini pour transform1 dans l'exemple précédent sera appliqué à tous les enfants de ce nœud. Cependant, le nœud enfant peut remplacer les attributs parents, c'est-à-dire que l'état de rendu sera hérité du nœud parent si le nœud enfant ne change pas le comportement.

Parfois, vous devez redéfinir le comportement d'un nœud en termes d'utilisation d'attribut. Par exemple, dans la plupart des éditeurs 3D, l'utilisateur peut charger plusieurs modèles et changer le mode d'affichage pour tous les modèles chargés en même temps, quelle que soit la façon dont ils ont été affichés précédemment. En d'autres termes, tous les modèles de l'éditeur doivent hériter d'un seul attribut, quelle que soit la façon dont ils étaient précédemment définis pour chacun des modèles. Dans OSG, cela peut être implémenté en utilisant le drapeau osg :: StateAttribute :: OVERRIDE, par exemple

 stateset->StateAttribute(attr, osg::StateAttribute::OVERRIDE); 

Lors de la définition des modes et des modes avec des attributs, l'opérateur OR au niveau du bit est utilisé

 stateset->StateAttributeAndModes(attr, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 

En outre, l'attribut peut également être protégé contre la substitution - pour cela, il doit être marqué avec l'indicateur osg :: StateAttribute :: PROTECTED.

Il existe un troisième indicateur, osg :: StateAttribute :: INHERIT, qui est utilisé pour indiquer que cet attribut doit être hérité de l'ensemble d'états du nœud parent.

Voici un court exemple utilisant les drapeaux OVERRIDE et PROTECTED. Le nœud racine sera défini sur OVERRIDE pour forcer tous les nœuds enfants à hériter de ses attributs et modes. Dans ce cas, les nœuds enfants essaieront de changer leur état avec ou sans l'aide de l'indicateur PROTECTED, ce qui conduira à des résultats différents.

Hériter du texte d'exemple
main.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(); } 




Pour comprendre ce qui se passe, vous devez regarder à quoi ressemble un deltaplane normalement éclairé en téléchargeant son OSGviewer OSG à plein temps

 $ osgviewer glider.osg 

Dans l'exemple, nous essayons de changer le mode d'éclairage pour les nœuds transform1 et transform2 en éteignant complètement l'éclairage.

 transform1->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); transform2->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED); 

Dans ce cas, nous activons le mode d'éclairage pour le nœud racine et utilisons l'indicateur OVERRIDE pour tous ses nœuds enfants, afin qu'ils héritent de l'état du nœud racine. Cependant, trnsform2 utilise l'indicateur PROTECTED pour empêcher les paramètres du nœud racine d'affecter.

 transform2->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED); 

En conséquence, malgré le fait que nous désactivions l'éclairage au niveau du nœud transform1, le deltaplane gauche est toujours allumé, car les paramètres de la racine de la scène ont bloqué notre tentative de désactiver l'éclairage pour lui. Le deltaplane droit s'affiche sans éclairage (il semble plus lumineux uniquement parce qu'il est inondé d'une couleur simple sans rendu de lumière), car transform2 est protégé contre l'héritage des attributs du nœud racine.

4. Liste des attributs OpenGL pris en charge dans OpenSceneGraph


OSG prend en charge presque tous les attributs et modes de rendu pris en charge par OpenGL via des classes dérivées d'osg :: StateAttribute. Le tableau présente tous les paramètres de la machine d'état OpenGL disponibles à partir du moteur.
ID de type d'attributNom de classeMode associéFonction OpenGL équivalente
ALPHEFUNCosg :: AlphaFuncGL_ALPHA_TESTglAlphaFunc ()
BLENDFUNCosg :: BlendFuncGL_BLENDglBlendFunc () et glBlendFuncSeparate ()
CLIPPLANEosg :: ClipPlaneGL_CLIP_PLANEi (i de 1 à 5)glClipPlane ()
Colormaskosg :: ColorMask-glColorMask ()
CULLFACEosg :: CullFaceGL_CULLFACEglCullFace ()
Profondeurosg :: ProfondeurGL_DEPTH_TESTglDepthFunc (), glDepthRange () et glDepthMask ()
BROUILLARDosg :: BrouillardGL_FOGglFog ()
FRONTFACEosg :: FrontFace-glFrontFace ()
Lumièreosg :: LightGL_LIGHTi (i de 1 à 7)glLight ()
LIGHTMODELosg :: LightModel-glLightModel ()
LINESTRIPPLEosg :: LineStrippleGL_LINE_STRIPPLEglLineStripple ()
LARGEURosg :: LineWidth-glLineWidht ()
LOGICOPosg :: LogicOpGL_COLOR_LOGIC_OPglLogicOp ()
MATERIELosg :: Matériel-glMaterial () et glColorMaterial ()
POINTosg :: PointGL_POINT_SMOOTHglPointParameter ()
POINTSPRITEosg :: PointSpriteGL_POINT_SPRITE_ARBFonctions pour travailler avec les sprites OpenGL
POLYGONMODEosg :: PolygonMode-glPolygonMode ()
POLYGONOFFSETosg :: PolygonOffsetGL_POLYGON_OFFSET_POINTglPolygonOffset ()
POLYGONSTRIPPLEosg :: PolygonStrippleGL_POLYGON_STRIPPLEglPolygonStripple ()
CISEAUXosg :: CiseauxGL_SCISSOR_TESTglScissor ()
SHADEMODELosg :: ShadeModel-glShadeModel ()
POCHOIRosg :: PochoirGL_STENCIL_TESTglStencilFunc (), glStencilOp () et glStencilMask ()
Texenvosg :: TexEnv-glTexEnv ()
Texgenosg :: TexGenGL_TEXTURE_GEN_SglTexGen ()

La colonne ID de type d'attribut indique l'identifiant OSG spécifique qui identifie cet attribut dans les énumérateurs de la classe osg :: StateAttribute. Il peut être utilisé dans la méthode getAttribute pour obtenir la valeur d'un attribut spécifique.

 osg::PolygonMode *pm = dynamic_cast<osg::PolygonMode *>(stateset->getAttribute(osg::StateAttribute::POLYGONMODE)); 

Un pointeur valide indique que l'attribut a été défini précédemment. Sinon, la méthode sera NULL. Vous pouvez également obtenir la valeur du mode actuel en utilisant l'appel

 osg::StateAttribute::GLModeValue value = stateset->getMode(GL_LIGHTING); 

Ici, l'énumérateur GL_LIGHTING est utilisé pour activer / désactiver l'éclairage dans toute la scène.

5. Application de brouillard au modèle dans la scène


Citons l'effet de brouillard comme un moyen idéal de montrer comment travailler avec divers attributs et modes de rendu. OpenGL utilise une équation linéaire et deux équations exponentielles décrivant le modèle de brouillard, prises en charge par la classe osg :: Fog.

Exemple de brouillard de texte
main.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(); } 


Créez d'abord l'attribut fog. Nous utilisons un modèle linéaire, ajustons la plage d'affichage du brouillard par la distance au modèle

 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)); 

Nous chargeons l'exemple de paysage lz.osg et lui appliquons cet attribut

 osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../data/lz.osg"); model->getOrCreateStateSet()->setAttributeAndModes(fog.get()); 

Dans la fenêtre de visualisation, nous voyons un paysage flou et nous pouvons voir comment la densité du brouillard change en fonction de la distance au modèle







6. Travailler avec des sources lumineuses et l'éclairage


Comme avec OpenGL, OSG prend en charge jusqu'à huit sources de lumière pour rencontrer directement des objets de scène. Comme OpenGL, OSG ne calcule pas automatiquement les ombres. Les rayons lumineux proviennent de sources en lignes droites, sont réfléchis par les objets et dispersés par eux, après quoi ils sont perçus par les yeux du spectateur. Pour un traitement d'éclairage de haute qualité, il est nécessaire de définir les propriétés des matériaux, la géométrie normale des objets, etc.

La classe osg :: Light fournit des méthodes pour contrôler les sources de lumière, notamment: setLightNum () et getLightNum () - pour travailler avec le nombre de sources; setAmbient () et getAmbient () pour contrôler le composant environnant; setDiffuse () et getDiffuse () - pour travailler avec un composant dispersé, etc.

OSG décrit également la classe osg :: LightSource pour ajouter des sources de lumière à la scène. Il fournit la méthode setLight () et est le nœud feuille du graphe de scène avec un seul attribut. Tous les autres nœuds du graphique de scène sont affectés par la source de lumière si le mode correspondant pour GL_LIGHTi est défini. Par exemple:

 //   1 osg::ref_ptr<osg::Light> light = new osg::Light; light->setLightNum( 1 ); ... //       osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource; lightSource->setLight( light.get() ); ... //             root->addChild( lightSource.get() ); root->getOrCreateStateSet()->setMode( GL_LIGHT1, osg::StateAttribute::ON ); 

Une autre solution plus pratique est la méthode setStateSetModes (), avec laquelle la source de lumière avec le nombre souhaité est automatiquement attachée au nœud racine

 root->addChild( lightSource.get() ); lightSource->setStateSetModes( root->getOrCreateStateSet(), osg::StateAttribute::ON ); 

Vous pouvez ajouter des nœuds enfants à la source de lumière, mais cela ne signifie pas du tout, vous illuminerez le sous-graphique qui lui est associé d'une manière spéciale. Il sera traité comme une géométrie, représentée par la forme physique de la source lumineuse.

Le nœud osg :: LightSource peut être attaché au nœud de transformation et, par exemple, une source de lumière ponctuelle peut être déplacée dans l'espace. Ceci peut être désactivé en définissant le système de coordonnées absolu pour la source lumineuse.

 lightSource->setReferenceFrame( osg::LightSource::ABSOLUTE_RF ); 

7. Création de sources de lumière dans la scène


Par défaut, OSG définit automatiquement la source de lumière sur le numéro 0, qui émet une lumière directionnelle uniforme vers la scène. Cependant, à tout moment, vous pouvez ajouter plusieurs sources de lumière supplémentaires et même les contrôler à l'aide des nœuds de transformation de coordonnées. Seules les sources de position (sources ponctuelles) peuvent être déplacées. La lumière directionnelle n'a qu'une direction (un flux de rayons parallèles venant de l'infini) et n'est pas liée à une position spécifique sur la scène. OpenGL et OSG utilisent le quatrième composant du paramètre de position pour spécifier le type de source lumineuse. S'il vaut 0, alors la lumière est considérée comme dirigée; avec une valeur de 1 - positionnel.

Prenons un petit exemple de travail avec l'éclairage.

Cap de spoiler
main.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" //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ 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(); } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ 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::Group> root = new osg::Group; root->addChild(model.get()); 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)); root->getOrCreateStateSet()->setMode(GL_LIGHT0, osg::StateAttribute::ON); root->getOrCreateStateSet()->setMode(GL_LIGHT1, osg::StateAttribute::ON); root->addChild(light0); root->addChild(light1); osgViewer::Viewer viewer; viewer.setSceneData(root.get()); return viewer.run(); } 


Pour créer une source de lumière, nous avons une fonction distincte

 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(); } 

Dans cette fonction, nous déterminons d'abord les paramètres d'éclairage donnés par la source, créant ainsi l'attribut GL_LIGHTi

 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)); 

Après cela, une source lumineuse est créée à laquelle cet attribut est affecté.

 osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource; lightSource->setLight(light); 

Nous créons et configurons le nœud de transformation, en lui passant notre source de lumière comme nœud enfant

 osg::ref_ptr<osg::MatrixTransform> sourceTrans = new osg::MatrixTransform; sourceTrans->setMatrix(osg::Matrix::translate(trans)); sourceTrans->addChild(lightSource.get()); 

Retourne un pointeur sur le nœud de transformation

 return sourceTrans.release(); 

Dans le corps du programme principal, nous chargeons un modèle tridimensionnel (encore une fois, notre cessna préféré)

 osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../data/cessna.osg"); osg::ref_ptr<osg::Group> root = new osg::Group; root->addChild(model.get()); 

Nous créons deux sources lumineuses avec les nombres 0 et 1. La première brillera en jaune, la seconde - bleu-vert

 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)); 

Nous informons la machine d'état OpenGL qu'il est nécessaire d'activer les sources lumineuses 0 et 1 et d'ajouter les sources que nous avons créées à la scène

 root->getOrCreateStateSet()->setMode(GL_LIGHT0, osg::StateAttribute::ON); root->getOrCreateStateSet()->setMode(GL_LIGHT1, osg::StateAttribute::ON); root->addChild(light0); root->addChild(light1); 

Après avoir initialisé et démarré la visionneuse, nous obtenons une image



Conclusion


Très ému par l'attention des personnes intéressées à ce cycle. Cette action n'a pas beaucoup commencé, mais je pense que la communauté a besoin d'articles. Merci pour toutes sortes de retours positifs.

Aujourd'hui, j'ai essayé de considérer, encore une fois, les choses plutôt basiques du moteur OSG. Je ne sais pas ce qui est sorti cool. Mais jusqu'à présent, j'expose des choses précisément primitives, dans la veine où je les ai moi-même comprises. J'ai vérifié personnellement tous les exemples, mon référentiel est disponible ici . Merci, chers collègues, je vais essayer de continuer cette histoire ...

Source: https://habr.com/ru/post/fr430348/


All Articles