سؤال

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

بشكل عام في واجهة المستخدم الرسومية ، لدينا نوعان من النص - ثابت وعيش. ثابت سهل بما فيه الكفاية - يمكننا تقديم TTF إلى نسيج ونسيانه. إنه النص "المباشر" الذي يزعجني أكثر-تخيل وحدة تحكم ، أو دردشة حية في لعبة متعددة اللاعبين.

فكرت في عدة خيارات:

  • لا توجد حالات خاصة - قم بإعداد وتحميل نسيج في كل مرة يتغير فيها النص ، مع الأخذ في الاعتبار فقط لإعادة تنفيذها عند ظهور نص جديد بالفعل ، ومحاولة تقسيم النص الأكبر إلى أجزاء صغيرة (مثل خط الدردشة). ومع ذلك ، فإن هذا سيتركنا معلقًا في حالات مثل خط النتيجة الذي يتغير طوال الوقت ، أو نص مقدمة يجعل "لكل حرف" (نمط الآلة الكاتبة التي شوهدت في بعض ألعاب الخيال العلمي)
  • حرف رباعي-يبدو هذا أيضًا حلًا شائعًا ، يمكنك إعداد نسيج مع جدول ASCII وتقدم حرفًا رباعيًا محكمًا. ومع ذلك ، لدي شكوك جدية حول كفاءة مثل هذا الحل. نصائح كيفية جعل ذلك أسرع سيكون موضع ترحيب.
  • الحلول الهجينة - ولكن ليس لدي أي فكرة عن كيفية تنفيذ ذلك نظيف

السؤال وبالتالي - كيفية تقديم النص في OpenGL بكفاءة؟

إذا كان هذا يساعد ، فأنا أقوم بترميز C ++ STL/BOOST وتهدف إلى GFORCE 6 وبطاقات الرسومات اللاحقة.

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

المحلول

EDIT2: تم إصدار شون باريت للتو خطوط صورة نقطية لمبرمجي C/C ++ 3D.

تحرير: جوهرة رمز أخرى تستحق نظرة خبأ الخط الذي يعزز شون باريت stb_truetype.h.


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

هذا ما أستخدمه وأعتقد أنه أسرع طريقة لتقديم النص في OpenGL. في البداية ، استخدمت مولد خط النقطات في AngelCode أداة ثم دمجت freetype مباشرة وصنعت نسيجًا كبيرًا يحتوي على جميع الحروف الرسومية عند إطلاق التطبيق. أما بالنسبة للنصائح لتحسين سرعة عرض الكواد ، فقد استخدمت للتو VBO كما لبقية الهندسة في طلبي.

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

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

نصائح أخرى

حاول قراءة هذا: http://dmedia.dprogramming.com/؟n=tutorials.textrenging1.

النهج الموصوف هو الطريقة النموذجية لتقديم النص مع واجهات برمجة تطبيقات الرسومات. حرف واحد لكل رباعي ، وجميع بيانات الصورة للنص في نسيج واحد. إذا تمكنت من وضع طابعك بالكامل في نسيج واحد (في الواقع ، اعتمادًا على حجم الملمس ، فقد تكون قادرًا على احتواء عدة).

المفتاح هو أن ربط الملمس هو العملية التي تحتاجها لتقليلها. إذا تمكنت من تقديم كل النص الخاص بك بنسيج واحد ، فلن يهم مقدار النص الذي تحتاج إلى وضعه على الشاشة. حتى إذا كان عليك تبديل القوام ، فيجب أن يظل الأداء جيدًا (خطوط مختلفة ، وسمات الخطوط المختلفة [Bold ، Thankline ، etc]) جيدًا. قد يكون أداء النص أكثر أهمية بالنسبة لـ HUD ، لكنه أقل أهمية في واجهة المستخدم الرسومية.

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

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

لكل حرف رباعي المعالجة ، يعتبر قائمة العرض (المحدثة فقط عندما يتغير النص) كافية لمعظم الحالات.

لقد استخدمته مع خطوط X11 باستخدام XLOADQUERYFONT و GLGENLISTS و GLXUSEXFONT و glcalllists لديك مجموعة من قوائم العرض التي تصف كل حرف.

تقبل وظيفة glcalllists وسيطة char * لنصك ويمكن تضمينها داخل قائمة العرض.

لذلك ينتهي بك الأمر بمكالمة واحدة لعرض نص الكتل.

يتشابه نسيج الخط الذي اقترحه G. Pakosz ، لكنك تقوم بحساب قوائم العرض الخاصة بك "بواسطة الحرف".

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

يمكن فقط استخدام هاتين الوظيفتين:

void renderstring2d(char string[], float r, float g, float b, float x, float y)
{
    glColor3f(r, g, b);

    glRasterPos2f(x, y);
    for(unsigned int i = 0; i < strlen(string); i++)
        glutBitmapCharacter(GLUT_BITMAP_9_BY_15, string[i]);
}

void renderstring3d(char string[], float r, float g, float b, float x, float y, float z)
{
    glDisable(GL_LIGHTING);
    glColor3f(r, g, b);

    glRasterPos3f(x, y, z);
    for(unsigned int i = 0; i < strlen(string); i++)
        glutBitmapCharacter(GLUT_BITMAP_9_BY_15, string[i]);
}

ثم عندما تقوم بتقديم نص ثنائي الأبعاد ، لا تنس إعادة تعيين كل من مصفوفات ModelView و Respection.

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();

// Render text and quads

glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();

لا تحتاج إلى تقديم رباعي باستخدام هذه الوظائف ، لأن هذه الوظائف تقدم مباشرة إلى FrameBuffer.

وإذا كان هذا لا يعمل من أجلك ، فتحقق من ذلك.http://www.opengl.org/resources/faq/technical/fonts.htm

يتحدث عن تقديم النص باستخدام GlbitMap و Gldrawpixels ومزج ألفا.

من الصعب القيام به ، خاصةً إذا كنت ترغب في استخدام تقنيات عرض خطوط البكسل الفرعية. ألق نظرة على Clanlib SDK. يستخدم عارض دفعة لتقديم شاشة كاملة من النص في مكالمة OpenGL واحدة. نظرًا لأنه يحتوي على ترخيص ZLIB ، يمكنك استخراج الكود الخاص به إذا كنت لا ترغب في استخدام SDK نفسها

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