Pixi.js: كيف يمكن تحقيق معدل إطارات مرتفع في الثانية أثناء عرض الكثير من النص وتحديث موضعه؟

تم إنشاؤها على ٢٥ سبتمبر ٢٠٢٠  ·  10تعليقات  ·  مصدر: pixijs/pixi.js

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

هدف

1500 تسمية نصية
60 تحديث موضع في الثانية
60 إطارًا في الثانية

ملعب بيكسي

لقد قمت بالفعل بإنشاء مثال بسيط باستخدام BitMapText مما أدى إلى ~ 28 إطارًا في الثانية على MacBook Pro.
https://www.pixiplayground.com/#/edit/rLbAN_xrw7yUU_cg_c8Xv

هل لديك أي فكرة لتحسين هذا؟ شكرا جزيلا مقدما!

🤔 Question

التعليق الأكثر فائدة

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

ومع ذلك ، يقوم التطبيق الآن بتحديث جميع أوضاع الملصقات 1500 في كل إطار باستخدام 60 إطارًا في الثانية. علاوة على ذلك ، يتم تحديث محتوى النص في كل ثانية. هذا يؤدي إلى تجميد قصير كل ثانية. لذا ستكون الخطوة التالية هي جعل هذه التحديثات النصية غير متزامنة ، على سبيل المثال في عامل الويب. أنا أقرأ حاليًا عن ImageBitmap و OffscreenCanvas. قد يكون هذا ممتعًا للآخرين ، لذلك سأشارك تقدمي.

ال 10 كومينتر

هل أنت متأكد أنك بحاجة إلى 1500 على الشاشة في جميع الأوقات؟ سيساعد استبعاد الملصقات خارج الشاشة كثيرًا في الأداء. لا تقوم Pixi بأي عملية استبعاد خارج الصندوق ، ولكن هناك بعض المكونات الإضافية للمجتمع (على سبيل المثال ، @pixi-essentials/cull بواسطةSukantPal) التي قد تساعدك هنا.

هل كل 1500 ملصق فريد؟ إذا كان هناك العديد من التكرارات ، يمكنك تحويلها إلى Sprite باستخدام RenderTexture ومشاركة المراجع بتكلفة أكبر من الذاكرة.

ChristophWalter قد يستفيد المثال الذي أظهرته من الإعدام كما ذكر bigtimebuddy . 1500 ملصق يحتوي كل منها على 112 حرفًا هي _ الكثير_ لتقديمها. هناك أسباب لعدم إمكانية استخدام المثال الخاص بك لاقتراح تحسين ذي صلة ، على سبيل المثال النص متداخل في الغالب. لا أعتقد أن مشروعك سيعرض نصًا مختلطًا كثيفًا للغاية بحيث لا يمكن للمستخدم قراءته.

قد يساعد ضبط MESH.BATCHABLE_SIZE على قيمة أعلى مثل 200. لم أختبر هذا بشكل كامل لأنه لا يزال يعمل من خلال 45 إطارًا في الثانية بعد تباطؤ وحدة المعالجة المركزية 6x على iMac.

أنا لم أحدد المثال كثيرا. ومع ذلك ، إذا كنت تعمل في مشروع تجاري واتضح أن هذا يمثل عنق الزجاجة من جانب وحدة معالجة الرسومات ، فقد تفكر في الخروج من الترتيب الذي يعرض كل حرف (الكل كـ ، ثم كل B ، وكل C ، وما إلى ذلك) معًا لتحسين موقع النسيج ، وتطوير محرك تجانب و / أو إجراء تحسين مختلف على المستقيم الذي يعرض جزء الشاشة الذي تم تغييره (أي استنادًا إلى 60 تحديثًا من أصل 1500 ملصق). هذه مجرد أفكار ويجب أخذها على هذا النحو.

شكرا لك على مساعدتك!

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

ستكون التسميات فريدة. لكنهم قد لا يتغيرون كثيرًا. المثال لا يغير محتوى النص على الإطلاق. لذلك قد يكون هناك بعض الاحتمالات للتحسين. لقد لاحظت أن FPS يظل كما هو حتى لو لم أقوم بتحديث المواضع ( الملعب ). هل هناك طريقة لعرض النصوص فقط عندما تتغير؟

لم يغير إعداد MESH.BATCHABLE_SIZE أي شيء من جانبي. سألقي نظرة على أفكارك الأخرى أو أوصي بشراء iMacs أنا لست كثيرًا في العرض ، لذلك تساعدني هذه الأفكار حقًا!

آه ، إذا كنت تعمل حقًا على تحسين هذا المثال المحدد ، فستكون الطريقة العليا هي القيام بما قاله bigtimebuddy ، مع تغيير واحد - استخدم Mesh وقم بتحديث هذه الشبكة مباشرةً (بدلاً من استخدام 1500 sprites).

يوفر هذا ميزتين رئيسيتين:

  • سيؤدي هذا إلى التخلص من الحمل الزائد لمرحلة التخزين المؤقت لجهاز عرض الدُفعات.
  • سيتم قطع عدد الرؤوس بمقدار 112x (4 / نص بدلاً من 4 / حرف). هذا ينزل القمم إلى 6 كيلو.
  • كائن DisplayObject واحد فقط في المشهد.

إذن ، ستبدو العملية في الأساس كما يلي:

  1. تقديم BitmapText إلى RenderTexture
  2. قم بإنشاء شبكة ذات 1500 * 4 رؤوس.
  3. تحريك الرؤوس مباشرة. يجب أن تكون حريصًا نظرًا لوجود أربعة رؤوس لكل حالة (أي مستطيلات). لذلك عليك حساب موضع الرأس الأول. ثم الثلاثة الأخرى ستكون (س + عرض ، ارتفاع) ، (س + عرض ، ص + ارتفاع) ، (س ، ص + ارتفاع).

يجب أن تكون هذه عملية مباشرة. من فضلك اخبرنا كيف ستسير الامور

مرحبًا ، لقد حاولت تنفيذ اقتراحك. يبدو أن تحويل BitmapText إلى مادة قد نجح. لكنني حاليًا عالق في محاولة عرض النسيج في شبكة. حاولت استخدام PIXI.Mesh و PIXI.SimpleMesh. هل أحتاج إلى إنشاء تظليل خاص بي أم يمكنني استخدام PIXI.MeshMaterial؟

const bitmapFontText = new PIXI.BitmapText(
    'Lorem ipsum dolor\nsit amet consetetur\nsadipscing elitr sed', 
    { font: '55px Desyrel', align: 'left' }
);

const texture =  PIXI.RenderTexture.create({ width: 800, height: 600 });
app.renderer.render(bitmapFontText, texture);

const vertices = [
    -0.5, -0.5,
    0.5, -0.5,
    0.5, 0.5,
    -0.5, 0.5
];
const uvs = [
    0, 0,
    1, 0,
    1, 1,
    0, 1,
];
const indices = [0, 1, 2, 0, 2, 3];
const geometry = new PIXI.MeshGeometry(vertices, uvs, indices);
const shader = new PIXI.MeshMaterial(texture);

const mesh = new PIXI.Mesh(geometry, shader);
app.stage.addChild(mesh);

https://www.pixiplayground.com/#/edit/7RHqFti0tdSzw -6iOtylk

-
_Edit_: تم إصلاحه. يجب أن تمثل الرؤوس إحداثيات البكسل. _الخطوة التالية_: استخدم أكثر من مادة في الشبكة.

const vertices = [
    0, 0,
    500, 0,
    500, 500,
    0, 500
];

-
_Edit 2_: لن يعمل هذا إلا عند استخدام مادة واحدة لجميع الملصقات ، أليس كذلك؟ ربما أخطأت في التعبير عن نفسي. ستكون التسميات فريدة ، لكن المحتويات لن تتغير في كل إطار.

لقد لاحظت أن FPS يظل كما هو حتى لو لم أقوم بتحديث المواضع ( الملعب ). هل هناك طريقة لعرض النصوص فقط عندما تتغير؟

هل سيساعد PIXI.Mesh في ذلك؟ هل تعرف أي مصدر يمكنني أن أقرأ فيه عن عملية عرض PixiJS؟

ChristophWalter يمكنك إنشاء عارض بنفسك (بدلاً من استخدام تطبيق) ، قم بإعداد حلقة شريطية تستدعي Renderer.render _only_ عندما يتغير مشهدك.

يمكنك أيضًا تمرير autoStart: false إلى خيارات التطبيق ثم الاتصال بـ app.render() عندما يتغير شيء ما. نفس الفرق.

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

ومع ذلك ، يقوم التطبيق الآن بتحديث جميع أوضاع الملصقات 1500 في كل إطار باستخدام 60 إطارًا في الثانية. علاوة على ذلك ، يتم تحديث محتوى النص في كل ثانية. هذا يؤدي إلى تجميد قصير كل ثانية. لذا ستكون الخطوة التالية هي جعل هذه التحديثات النصية غير متزامنة ، على سبيل المثال في عامل الويب. أنا أقرأ حاليًا عن ImageBitmap و OffscreenCanvas. قد يكون هذا ممتعًا للآخرين ، لذلك سأشارك تقدمي.

تحديث قصير حيث توقفت عن التحقيق منذ بضعة أسابيع
لقد قدمت النص في عامل الويب الذي عمل في الواقع بشكل مباشر تمامًا:

// render-text-worker.js
onmessage = function(event) {
    const textLines = event.data.text.split(/\n/);
    const index = event.data.index;
    const offscreen = new OffscreenCanvas(150,45);
    const ctx = offscreen.getContext("2d");
    ctx.font = "15px monospace";
    textLines.forEach((text, index) => {
        ctx.fillText(text, 0, 15 + index * 15)
    })
    const imageBitmap = offscreen.transferToImageBitmap();
    postMessage({imageBitmap, index});
};
// index.js
const worker = new Worker("render-text-worker.js");
const callbacks ={}
function getLabelTexture(index, text, callback) {
  callbacks[index] = callback
  worker.postMessage({ index, text });
}
worker.onmessage = function({ data }) {
  const callback = callbacks[data.index]
  callback(PIXI.Texture.from(data.imageBitmap));
}

لسوء الحظ ، لا يوجد تحسن في حالة الاستخدام الخاصة بي. لا تزال الإطارات تتساقط أثناء عرض النصوص. ربما بسبب العمل المطلوب لنقل الصور النقطية من العامل.

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

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات