
مقدمة
كقاعدة ، عند العمل مع معلمات التقديم ، يعمل OpenGL كآلة حالة. حالة العرض هي مجموعة من سمات الحالة ، مثل مصادر الضوء ، والمواد ، والأنماط ، وأوضاع العرض ، والتي يتم تشغيلها وإيقافها بواسطة الدالتين glEnable () و glDisable (). عند تعيين حالة معينة ، تظل سارية حتى تقوم بعض الوظائف الأخرى بتغييرها. يدعم خط أنابيب OpenGL مكدس حالة لحفظ واستعادة الحالات في أي وقت. تمنحك آلة الحالة للمطور تحكمًا كاملاً في حالات العرض الحالية والمحفوظة على المكدس.
ومع ذلك ، فإن هذا الأسلوب غير مريح عند العمل مع OSG. لهذا السبب ، يتم تغليف جهاز حالة OpenGL بواسطة فئة osg :: StateSet ، والتي تهتم بالعمل مع حزمة الحالة وإعدادها أثناء اجتياز الرسم البياني للمشهد.
يحتوي مثيل فئة osg :: StateSet على مجموعة فرعية من حالات العرض المختلفة ويمكن تطبيقها على عقد مشهد osg :: Node وكائنات هندسية قابلة للرسم باستخدام طريقة setStateSet ()
osg::StateSet *stateset = new osg::StateSet; node->setStateSet(stateset);
قد تكون الطريقة الأكثر أمانًا هي استخدام طريقة getOrCreateStateSet () ، والتي تضمن عودة الحالة الصحيحة ومرفقها بالعقدة أو الكائن القابل للرسم
osg::StateSet *stateset = node->getOrCreateStateSet();
تتحكم الفئات osg :: Node و osg :: Drawable في متغير العضو osg :: StateSet من خلال المؤشر الذكي osg :: ref_ptr <>. هذا يعني أنه يمكن تقسيم مجموعة من الحالات بين عدة كائنات في المشهد وسيتم تدميرها فقط عندما يتم تدمير كل هذه الكائنات.
1. السمات والأوضاع
يحدد OSG فئة osg :: StateAttribute لتخزين سمات التقديم. هذه فئة أساسية افتراضية موروثة بعدة سمات عرض مثل الضوء ، والمواد ، والضباب.
تعمل أوضاع التقديم مثل المفاتيح التي يمكن تشغيلها وإيقاف تشغيلها. بالإضافة إلى ذلك ، فهي مرتبطة بالعدّاد ، والتي تُستخدم للإشارة إلى نوع وضع OpenGL. في بعض الأحيان يرتبط وضع العرض بسمة ، على سبيل المثال ، يتضمن وضع GL_LIGHTING متغيرات لمصادر الضوء التي يتم إرسالها إلى خط أنابيب OpenGL عند تشغيله ، وإيقاف الإضاءة بخلاف ذلك.
تقسم فئة osg :: StateSet السمات والأوضاع إلى مجموعتين: الملمس وغير الملمس. لديها العديد من الطرق العامة لإضافة السمات والأنماط غير الملمس إلى مجموعة من الحالات:
- setAttribute () - يضيف كائنًا من النوع osg :: StateAttribute إلى مجموعة الحالات. لا يمكن أن تتواجد السمات من نفس النوع في نفس مجموعة الحالات. سيتم استبدال نقطة التحديد السابقة بالنقطة الجديدة.
- setMode () - يقوم بإرفاق عداد الوضع بمجموعة من الحالات وتعيين قيمته على osg :: StateAttribute :: ON أو osg :: StateAttribute :: OFF ، مما يعني تمكين أو تعطيل الوضع.
- setAttributeAndModes () - إرفاق سمة العرض والوضع المرتبط بها وتعيين قيمة المفتاح (الإعدادات الافتراضية على ON). يجب أن يوضع في الاعتبار أنه ليس لكل سمة وضع مناظر ، ولكن يمكنك استخدام هذه الطريقة في أي حال.
لتعيين السمة والوضع المرتبط بها ، يمكنك استخدام هذا الرمز
stateset->setAttributeAndModes(attr, osg::StateAttribute::ON);
لتعيين خصائص النسيج ، يجب تمرير معلمة إضافية للإشارة إلى النسيج الذي يجب تطبيقه عليه. يوفر Osg :: StateSet العديد من الطرق العامة الأخرى لهذا ، مثل setTextureAttribute () و setTextureMode () و setTextureAttributeAndModes ()
stateset->setTextureAttributeAndModes(0, textattr, osg::StateAttribute::ON);
تطبيق سمة textattr على مادة ذات معرّف 0.
2. ضبط وضع عرض المضلع لعقد المشهد
نوضح النظرية أعلاه بمثال عملي - تغيير وضع التنقيط للمضلعات OpenGL باستخدام فئة osg :: PolygonMode ، التي ترث من osg :: StateAttribute. تقوم هذه الفئة بتغليف دالة glPolygonMode () وتوفر واجهة لضبط وضع عرض المضلع لعقدة مشهد معينة.
مثال Polygonmodemain.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(); }
هنا نقوم بتحميل نموذج السيسنا المحبوب وتطبيق التحولات عليه ، نحصل على حالتين من النموذج. على أحدهم ، على اليسار ، نطبق سمة تحدد وضع عرض الإطار السلكي للمضلعات
osg::ref_ptr<osg::PolygonMode> pm = new osg::PolygonMode; pm->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE); transform1->getOrCreateStateSet()->setAttribute(pm.get());

إذا انتقلنا إلى مواصفات OpenGL ، فيمكننا بسهولة تخيل خيارات عرض المضلع التي ستتوفر لنا عند استخدام setMode () في هذه الحالة بالذات. يمكن أن تأخذ المعلمة الأولى القيم osg :: PolygonMode :: FRONT و BACK و FRONT_AND_BACK ، المقابلة لعددي OpenGL GL_FRONT و GL_BACK و GL_FRONT_AND_BACK. يمكن أن تأخذ المعلمة الثانية القيم osg :: PolygonMode :: POINT و LINE و FILL ، والتي تتوافق مع GL_POINT و GL_LINE و GL_FILL. لا توجد هنا حيل أخرى ، كما هو الحال غالبًا عند تطوير برنامج OpenGL النقي ، حيث تتولى OSG معظم العمل. لا يحتوي وضع عرض المضلع على وضع مرتبط ولا يتطلب استدعاء زوج glEnable () / glDisable (). ستعمل طريقة setAttributeAndModes () بشكل جيد في هذه الحالة أيضًا ، ولكن ستكون قيمة المعلمة الثالثة عديمة الفائدة.
3. وراثة حالات التقديم. تطبيق السمات والأوضاع
تؤثر مجموعة حالات العقدة على العقدة الحالية وجميع أتباعها. على سبيل المثال ، سيتم تطبيق السمة osg :: PolygonMode لمجموعة التحويل 1 من المثال السابق على جميع التوابع لهذه العقدة. ومع ذلك ، يمكن للعقدة الفرعية تجاوز السمات الرئيسية ، أي أن حالة التقديم سيتم توريثها من العقدة الأصلية إذا لم تغير العقدة الفرعية السلوك.
في بعض الأحيان تحتاج إلى إعادة تعريف سلوك العقدة من حيث استخدام السمة. على سبيل المثال ، في معظم برامج التحرير ثلاثية الأبعاد ، يمكن للمستخدم تحميل العديد من النماذج وتغيير وضع العرض لجميع النماذج المحملة في نفس الوقت ، بغض النظر عن كيفية عرضها مسبقًا. بمعنى آخر ، يجب أن ترث جميع النماذج في المحرر سمة واحدة ، بغض النظر عن كيفية تعيينها مسبقًا لكل نموذج. في OSG ، يمكن تنفيذ ذلك باستخدام علامة osg :: StateAttribute :: OVERRIDE ، على سبيل المثال
stateset->StateAttribute(attr, osg::StateAttribute::OVERRIDE);
عند ضبط الأوضاع والأوضاع مع السمات ، يتم استخدام عامل تشغيل أحادي المعامل OR
stateset->StateAttributeAndModes(attr, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
بالإضافة إلى ذلك ، يمكن أيضًا حماية السمة من التجاوز - لهذا ، يجب تمييزها بعلامة osg :: StateAttribute :: PROTECTED.
هناك إشارة ثالثة ، osg :: StateAttribute :: INHERIT ، تُستخدم للإشارة إلى أن هذه السمة يجب أن تكون موروثة من مجموعة حالات العقدة الأصلية.
هنا مثال قصير باستخدام علامتي "تجاوز" و "حماية". سيتم تعيين العقدة الجذرية على تجاوز لإجبار جميع العقد الفرعية على وراثة سماتها وأوضاعها. في هذه الحالة ، ستحاول العقد الفرعية تغيير حالتها مع أو بدون مساعدة العلامة المحمية ، مما سيؤدي إلى نتائج مختلفة.
اكتساب نص مثال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(); }

لفهم ما يحدث ، تحتاج إلى النظر في شكل طائرة شراعية معلقة بشكل طبيعي عن طريق تنزيل OSGviewer بدوام كامل
$ osgviewer glider.osg
في المثال ، نحاول تغيير وضع الإضاءة للعقد التحويلية 1 و convert2 عن طريق إيقاف تشغيل الإضاءة تمامًا.
transform1->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); transform2->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
في هذه الحالة ، نقوم بتشغيل وضع الإضاءة للعقدة الجذرية ، واستخدام علامة OVERRIDE لجميع العقد التابعة لها ، بحيث ترث حالة العقدة الجذرية. ومع ذلك ، يستخدم trnsform2 علامة PROTECTED لمنع إعدادات عقدة الجذر من التأثير.
transform2->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
ونتيجة لذلك ، على الرغم من حقيقة أننا نقوم بإيقاف تشغيل الإضاءة في العقدة transform1 ، فإن طائرة شراعية تعليق اليسار لا تزال مضاءة ، لأن إعدادات جذر المشهد سدت محاولتنا لإيقاف الإضاءة من أجلها. يتم عرض المنزلق المعلق الأيمن بدون إضاءة (يبدو أكثر إشراقًا فقط لأنه مغمور بلون بسيط بدون عرض الإضاءة) ، حيث أن المحول 2 محمي من وراثة خصائص العقدة الجذرية.
4. قائمة سمات OpenGL المدعومة في OpenSceneGraph
يدعم OSG تقريبًا جميع السمات وأوضاع العرض التي يدعمها OpenGL من خلال الفئات المشتقة من osg :: StateAttribute. يوضح الجدول جميع معلمات آلة حالة OpenGL المتوفرة من المحرك.
معرف نوع السمة | اسم الفصل | الوضع المرتبط | دالة OpenGL المكافئة |
---|
ALPHEFUNC | osg :: AlphaFunc | GL_ALPHA_TEST | glAlphaFunc () |
بليند فونك | osg :: BlendFunc | GL_BLEND | glBlendFunc () و glBlendFuncSeparate () |
CLIPPLANE | osg :: ClipPlane | GL_CLIP_PLANEi (أنا من 1 إلى 5) | glClipPlane () |
Colormask | osg :: ColorMask | - | glColorMask () |
فجوة | osg :: CullFace | GL_CULLFACE | glCullFace () |
العمق | osg :: العمق | GL_DEPTH_TEST | glDepthFunc () و glDepthRange () و glDepthMask () |
ضباب | osg :: ضباب | GL_FOG | glFog () |
الواجهة | osg :: FrontFace | - | glFrontFace () |
خفيف | osg :: خفيف | GL_LIGHTi (أنا من 1 إلى 7) | glLight () |
نموذج LIGHTMODEL | osg :: LightModel | - | glLightModel () |
خطوط النقل | osg :: LineStripple | GL_LINE_STRIPPLE | glLineStripple () |
LINEWIDTH | osg :: LineWidth | - | glLineWidht () |
LOGICOP | osg :: LogicOp | GL_COLOR_LOGIC_OP | glLogicOp () |
المواد | osg :: مادة | - | glMaterial () و glColorMaterial () |
نقطة | osg :: Point | GL_POINT_SMOOTH | معلمة glPoint () |
نقطة مهمة | osg :: PointSprite | GL_POINT_SPRITE_ARB | وظائف للعمل مع نقوش OpenGL |
مضلع | osg :: PolygonMode | - | glPolygonMode () |
POLYGONOFFSET | osg :: PolygonOffset | GL_POLYGON_OFFSET_POINT | glPolygonOffset () |
مضلع | osg :: PolygonStripple | GL_POLYGON_STRIPPLE | glPolygonStripple () |
مقص | osg :: مقص | GL_SCISSOR_TEST | glScissor () |
شاديموديل | osg :: ShadeModel | - | glShadeModel () |
الستينسيل | osg :: Stencil | GL_STENCIL_TEST | glStencilFunc () و glStencilOp () و glStencilMask () |
Texenv | osg :: TexEnv | - | glTexEnv () |
تكسجين | osg :: TexGen | GL_TEXTURE_GEN_S | glTexGen () |
يشير عمود معرف نوع السمة إلى معرف OSG المحدد الذي يعرّف هذه السمة في عدّاد فئة osg :: StateAttribute. يمكن استخدامه في طريقة getAttribute للحصول على قيمة سمة معينة.
osg::PolygonMode *pm = dynamic_cast<osg::PolygonMode *>(stateset->getAttribute(osg::StateAttribute::POLYGONMODE));
يشير المؤشر الصالح إلى أنه تم تعيين السمة مسبقًا. وإلا ، ستكمن الطريقة فارغة. يمكنك أيضًا الحصول على قيمة الوضع الحالي باستخدام المكالمة
osg::StateAttribute::GLModeValue value = stateset->getMode(GL_LIGHTING);
هنا يستخدم العداد GL_LIGHTING لتمكين / تعطيل الإضاءة في جميع أنحاء المشهد.
5. تطبيق الضباب على النموذج في المشهد
دعنا نذكر تأثير الضباب كطريقة مثالية لإظهار كيفية العمل مع مختلف السمات وأوضاع العرض. يستخدم OpenGL معادلة خطية ومعادلة أسية تصف نموذج الضباب ، مدعومًا من فئة osg :: Fog.
مثال ضباب النص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(); }
أولاً ، قم بإنشاء سمة الضباب. نحن نستخدم نموذجًا خطيًا ، ونعدل نطاق عرض الضباب من خلال المسافة إلى النموذج
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));
نقوم بتحميل نموذج أفقي lz.osg ونطبق هذه السمة عليه
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../data/lz.osg"); model->getOrCreateStateSet()->setAttributeAndModes(fog.get());
في نافذة العارض ، نرى منظرًا غير واضح ، ويمكننا أن نرى كيف تتغير كثافة الضباب اعتمادًا على المسافة إلى النموذج



6. العمل مع مصادر الإضاءة والإضاءة
كما هو الحال مع OpenGL ، يدعم OSG ما يصل إلى ثمانية مصادر ضوئية لتلبية كائنات المشهد مباشرة. مثل OpenGL ، لا يحسب OSG الظلال تلقائيًا. تأتي أشعة الضوء من مصادر في خطوط مستقيمة ، تنعكس من الأشياء وتنتشر بها ، وبعد ذلك يتم رؤيتها من قبل عيون المشاهد. من أجل معالجة الإضاءة عالية الجودة ، من الضروري تعيين خصائص المواد ، والهندسة العادية للأشياء ، وما إلى ذلك.
توفر فئة osg :: Light طرقًا للتحكم في مصادر الضوء ، بما في ذلك: setLightNum () و getLightNum () - للعمل مع عدد المصادر ؛ setAmbient () و getAmbient () للتحكم في المكون المحيط ؛ setDiffuse () و getDiffuse () - للعمل مع مكون مبعثر ، إلخ.
يصف OSG أيضًا فئة osg :: LightSource لإضافة مصادر الضوء إلى المشهد. يوفر طريقة setLight () وهي عقدة طرفية للرسم البياني للمشهد بسمة واحدة. تتأثر جميع العقد الأخرى في الرسم البياني للمشهد بمصدر الضوء إذا تم تعيين الوضع المقابل لـ GL_LIGHTi. على سبيل المثال:
حل آخر أكثر ملاءمة هو طريقة setStateSetModes () ، حيث يتم إرفاق مصدر الضوء مع الرقم المطلوب تلقائيًا بالعقدة الجذر
root->addChild( lightSource.get() ); lightSource->setStateSetModes( root->getOrCreateStateSet(), osg::StateAttribute::ON );
يمكنك إضافة العقد الفرعية إلى مصدر الضوء ، لكن هذا لا يعني على الإطلاق ، سوف تضيء الرسم الفرعي المرتبط به بطريقة أو بأخرى. ستتم معالجتها على هيئة هندسة ، ممثلة بالشكل المادي لمصدر الضوء.
يمكن توصيل العقدة osg :: LightSource بعقدة التحويل ، وعلى سبيل المثال ، يمكن نقل مصدر ضوء نقطي في الفضاء. يمكن تعطيل هذا عن طريق تعيين نظام الإحداثيات المطلق لمصدر الضوء.
lightSource->setReferenceFrame( osg::LightSource::ABSOLUTE_RF );
7. إنشاء مصادر الضوء في المشهد
افتراضيًا ، يقوم OSG تلقائيًا بتعيين مصدر الضوء على الرقم 0 ، الذي ينبعث ضوء اتجاهي موحد إلى المشهد. ومع ذلك ، يمكنك في أي وقت إضافة العديد من مصادر الضوء الإضافية ، وحتى التحكم فيها باستخدام عقد تحويل الإحداثيات. يمكن نقل المصادر الموضعية فقط (المصادر النقطية). للضوء الاتجاهي اتجاه فقط (تيار من الأشعة المتوازية القادمة من اللانهاية) ولا يرتبط بموضع معين على المسرح. يستخدم OpenGL و OSG المكون الرابع من معلمة الموضع لتحديد نوع مصدر الضوء. إذا كان 0 ، فإن الضوء يعتبر موجهاً ؛ بقيمة 1 - موضعي.
فكر في مثال صغير للعمل مع الإضاءة.
عنوان المفسد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(); }
في هذه الوظيفة ، نحدد أولاً معلمات الإضاءة التي قدمها المصدر ، وبالتالي ننشئ سمة GL_LIGHTi
osg::ref_ptr<osg::Light> light = new osg::Light;
بعد ذلك ، يتم إنشاء مصدر ضوء يتم تعيين هذه السمة إليه.
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();
في جسم البرنامج الرئيسي ، نقوم بتحميل نموذج ثلاثي الأبعاد (مرة أخرى ، سيسنا المفضلة لدينا)
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../data/cessna.osg"); osg::ref_ptr<osg::Group> root = new osg::Group; root->addChild(model.get());
نقوم بإنشاء اثنين من مصادر الضوء برقمين 0 و 1. الأول سيضيء باللون الأصفر ، والثاني - الأزرق والأخضر
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));
نبلغ جهاز حالة OpenGL أنه من الضروري تشغيل مصادر الضوء 0 و 1 وإضافة المصادر التي أنشأناها إلى المشهد
root->getOrCreateStateSet()->setMode(GL_LIGHT0, osg::StateAttribute::ON); root->getOrCreateStateSet()->setMode(GL_LIGHT1, osg::StateAttribute::ON); root->addChild(light0); root->addChild(light1);
بعد تهيئة العارض وبدء تشغيله ، نحصل على صورة

الخلاصة
تأثرت كثيرًا باهتمام الأشخاص المهتمين بهذه الدورة. لم يبدأ هذا الإجراء كثيرًا ، لكني أشعر أن المجتمع بحاجة إلى مقالات. شكرا لجميع أنواع ردود الفعل الإيجابية.
حاولت اليوم التفكير مرة أخرى في الأشياء الأساسية لمحرك OSG. لست متأكدا ما خرج باردا. لكن حتى الآن ، أشرح أشياء بدائية بدقة ، في السياق الذي فهمته بنفسي. لقد راجعت جميع الأمثلة شخصيًا ، مستودعي متاح
هنا . أشكركم ، زملائي الأعزاء ، سأحاول الحفاظ على
استمرار هذه القصة ...