هل يجب أن أسمي glenable و gldisable في كل مرة أرسم فيها شيئًا؟

StackOverflow https://stackoverflow.com/questions/802079

  •  03-07-2019
  •  | 
  •  

سؤال

كم مرة يجب أن أسمي وظائف OpenGL مثل glEnable() أو glEnableClientState() والمقابلة glDisable نظرائه؟ هل من المفترض أن يتم استدعاؤهم مرة واحدة في بداية التطبيق ، أم يجب أن أبقيهم معاقين وتمكين فقط تلك الميزات التي أحتاجها على الفور لرسم شيء ما؟ هل هناك فرق في الأداء؟

هل كانت مفيدة؟

المحلول

"هذا يعتمد على".

إذا كنت يستخدم التطبيق بالكامل مزيجًا واحدًا فقط من الحالات تمكين/تعطيل ، فعندئذٍ بكل الوسائل ، فقط قم بإعداده في البداية والانتقال.

تحتاج معظم تطبيقات العالم الحقيقي إلى الخلط ، ثم تضطر إلى الاتصال glEnable() لتمكين بعض حالات (حالات) معينة ، قم بإجراء مكالمات السحب ، ثم glDisable() لهم مرة أخرى عندما تنتهي من "مسح المسرح".

تنبع من هذا التصوير الحكومي ، وتتبع الدولة ، والعديد من مخططات التحسين من هذا ، حيث أن تبديل الحالة غالي في بعض الأحيان.

نصائح أخرى

إذا وجدت أنك تقوم بالتحقق من قيمة متغيرات الحالة في كثير من الأحيان ، وبعد ذلك استدعاء glenable / gldisable ، فقد تتمكن من تنظيف الأشياء قليلاً باستخدام مكدس السمة (glpushatrib / glpopattrib).

يتيح لك مكدس السمة عزل المناطق في الكود الخاص بك ، ولا تؤثر التغييرات على السمة في أقسام واحدة على حالة السمة في أقسام أخرى.

void drawObject1(){
  glPushAttrib(GL_ENABLE_BIT);

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);    

  /* Isolated Region 1 */

  glPopAttrib();
}        

void drawObject2(){
  glPushAttrib(GL_ENABLE_BIT);

  glEnable(GL_FOG);
  glEnable(GL_GL_POINT_SMOOTH);    

   /* Isolated Region 2 */

  glPopAttrib();
}    

void drawScene(){
  drawObject1();
  drawObject2();
}

رغم GL_LIGHTING و GL_DEPTH_TEST يتم تعيينها في DrawObject1 ولايتهم غير محفوظة على DrawObject2. في غياب glpushattrib لن يكون هذا هو الحال. أيضًا - لاحظ أنه لا توجد حاجة للاتصال بـ gldisable في نهاية مكالمات الوظائف ، يقوم Glpopattrib بالمهمة.

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

يمكن أن تساعد مكدس الإسناد في الحفاظ على طبقات التجريد وإنشاء مناطق من العزلة.

glpushtrib manpage

بادئ ذي بدء ، ما هو إصدار OpenGL الذي تستخدمه؟ وأي جيل من أجهزة الرسومات التي لديها مجموعتك المستهدفة؟ إن معرفة هذا من شأنه أن يجعل من السهل إعطاء إجابة أكثر صحة. إجابتي تفترض OpenGL 2.1.

OpenGL هي آلة الولاية ، مما يعني أنه كلما تم تغيير حالة ما ، يتم إجراء هذه الحالة "الحالية" حتى تتغير مرة أخرى بشكل صريح من قبل المبرمج مع مكالمة API OpenGL جديدة. توجد استثناءات لهذه القاعدة ، مثل مكالمات صفيف حالة العميل مما يجعل لون الرأس الحالي غير محدد. لكن هذه هي الاستثناءات التي تحدد القاعدة.

"مرة واحدة في بداية التطبيق"ليس من المنطقي ، لأن هناك أوقات تحتاج إلى تدمير سياق OpenGL الخاص بك أثناء تشغيل التطبيق. أفترض أنك تعني بعد كل إنشاء نافذة. هذا يعمل مع الحالة التي لا تحتاج إلى تغييرها لاحقًا. : إذا استخدمت جميع مكالمات السحب الخاصة بك نفس بيانات صفيف الرأس ، فلن تحتاج إلى تعطيلها باستخدام gldisableClientState بعد ذلك.

هناك الكثير من حالة تمكين/تعطيل المرتبطة بخط أنابيب الوظيفة الثابتة القديم. إن الفداء السهل لهذا هو: استخدام التظليل! إذا كنت تستهدف جيلًا من البطاقات في عمر خمس سنوات على الأكثر ، فمن المحتمل أن يحاكي خط أنابيب الوظيفة الثابتة مع التظليل على أي حال. باستخدام التظليل ، تكون في تحكم كامل أو أقل في ما يحدث أثناء مراحل التحويل والنقطية ، ويمكنك صنع "حالاتك" الخاصة بك مع الزي الرسمي ، والتي تكون رخيصة للغاية للتغيير/التحديث.

إن مع العلم أن OpenGL هي آلة الحالة كما قلت أعلاه ، يجب أن توضح أنه ينبغي للمرء أن يسعى إلى الحفاظ على تغييرات الحالة إلى الحد الأدنى ، طالما كان ذلك ممكنًا. ومع ذلك ، على الأرجح هناك أشياء أخرى تؤثر على الأداء أكثر بكثير من تمكين/تعطيل مكالمات الحالة. إذا كنت تريد أن تعرف عنهم ، اقرأ.


حساب الدولة ليس المرتبطة بمكالمات حالة الوظيفة الثابتة القديمة والتي لا يمكن أن تختلف حالة تمكين/تعطيل بسيطة في التكلفة. بشكل خاص ربط التظليلات ، والأسماء الملزمة ، عادة ما تكون ("أسماء" القوام والبرامج والكائنات العازلة) باهظة الثمن إلى حد ما. هذا هو السبب في أن الكثير من الألعاب والتطبيقات المستخدمة لفرز ترتيب السحب لشبكاتها وفقًا للملمس. وبهذه الطريقة ، لم يكن عليهم ربط نفس الملمس مرتين. في الوقت الحاضر ومع ذلك ، ينطبق الشيء نفسه على برامج التظليل. لا تريد ربط نفس برنامج التظليل مرتين إذا لم يكن عليك ذلك. أيضًا ، ليست جميع الميزات الموجودة في إصدار OpenGL معين من الأجهزة التي يتم تسريعها على جميع البطاقات ، حتى لو كان بائعين تلك البطاقات يزعمون أنهم متوافقون معهم. أن تكون الامتثال يعني أنهم يتبعون المواصفات ، وليس أنهم يديرون جميع الفوائد بالضرورة بكفاءة. يجب أن تتذكر بعض الوظائف مثل glhistogram و glminmax من GL__ ARB __imaging في هذا الصدد.


الخلاصة: ما لم يكن هناك سبب واضح لعدم استخدام التظليل! إنه يوفر لك الكثير من مكالمات الحالة غير الضرورية حيث يمكنك استخدام الزي الرسمي بدلاً من ذلك. ظلال OpenGL كانت موجودة منذ حوالي ست سنوات التي تعرفها. أيضا ، النفقات العامة لتمكين/تعطيل تغييرات الحالة يستطيع كن مشكلة ، ولكن عادةً ما يكون هناك الكثير مما يمكن كسبه من تحسين تغييرات الحالة الأكثر تكلفة الأخرى ، مثل GlusePerogram و Glcompileshader و GllinkProgram و Glbindbuffer و GlbindTexture.

PS: OpenGL 3.0 إزالة حالة العميل تمكين/تعطيل المكالمات. يتم تمكينها ضمنيًا لأن صفائف السحب هي الطريقة الوحيدة للرسم في هذا الإصدار. تمت إزالة الوضع الفوري. تمت إزالة مكالمات gl..pointer أيضًا ، لأن المرء يحتاج حقًا إلى glvertexattribpointer.

قلت قاعدة عامة تم تعليميها أنه من الأرخص دائمًا أن تكون مجرد تمكين/تعطيل الإرادة بدلاً من التحقق من الحالة الحالية والتغيير فقط إذا لزم الأمر.

ومع ذلك ، فإن إجابة مارك هي شيء يجب أن ينجح بالتأكيد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top