Ambil Aplikasi PixiJS anda ke Tahap Seterusnya dengan Strategi dan Teknik Lanjutan
Siaran ini membincangkan cara yang berbeza untuk mengoptimumkan pemaparan berbilang elemen dalam pixiJS dari segi kedua-dua CPU / Memori. Sebagai contoh, mempertimbangkan perbezaan antara memaparkan semula setiap bingkai tanpa sebarang caching-yang berfungsi dengan baik dari segi penggunaan CPU-atau caching grafik yang diberikan dalam ingatan. Ini akan meningkatkan penggunaan memori mengikut kadar bilangan grafik dalam adegan.
Terdapat beberapa strategi untuk menangani pengoptimuman sedemikian. Nota khusus ialah Reka Bentuk Berorientasikan Data, yang mempersembahkan set pendekatan alternatif yang radikal daripada cara pengaturcaraan Berorientasikan Objek yang lebih lazim.
Cara utama lain termasuk: pemusnahan dan penggunaan format yang jauh lebih berstruktur - NativeArrays dalam C# dan TypedArrays dalam TypeScript, contohnya. Ini akan membolehkan pengurusan penimbal memori yang lebih besar, yang mungkin mengehadkan kehilangan cache, tetapi yang juga memerlukan pengalaman kejuruteraan dan/atau penyesuaian yang ketara.
Dalam siaran ini, saya akan menumpukan pada satu kaedah kerja pengoptimuman untuk persekitaran WebGL dengan PixiJS: Pendekatan Berorientasikan Objek, termasuk amalan terbaik. Ini akan menyediakan anda cara yang teratur untuk meningkatkan kelajuan dan kecekapan dalam aplikasi PixiJS anda.
Dalam artikel saya yang seterusnya, saya akan bercakap tentang satu lagi pendekatan pengoptimuman yang kukuh: Pendekatan Entiti-Komponen-Sistem. Pendekatan ECS sangat berorientasikan data dan menawarkan penampilan yang segar apabila ia datang untuk mengoptimumkan PixiJS dalam persekitaran berprestasi tinggi. Teruskan di Medium untuk artikel ini di mana, secara mendalam, saya pergi ke butir-butir pendekatan ECS.
Sentiasa ingat bahawa sentiasa ada sesuatu yang boleh dilakukan dengan lebih baik dalam usaha untuk mengoptimumkan dan meningkatkan lagi prestasi aplikasi Pixi anda. Dengan lebih baik, ini tidak bermakna paling dioptimumkan atau terpantas. Penyelesaian terbaik ialah persoalan pertukaran antara jumlah masa anda melabur dalam pengoptimuman dan pulangan pelaburan itu untuk memastikan anda dapat memenuhi tarikh akhir projek tetapi dengan pengoptimuman yang mencukupi untuk diharapkan dapat memuaskan mana-mana bakal pengguna tanpa terlalu mengembangkan sumber anda.
Dalam bahagian ini, saya akan membimbing anda melalui cara terbaik untuk mengoptimumkan aplikasi PixiJS.
Bahagian ini adalah berdasarkan petua rasmi, patut disemak!
Selebihnya perbincangan kami akan berkisar pada Grafik Pixi, Sprite, Meshes dan masa untuk menggunakan Bekas Zarah dan bukannya Bekas Pixi lalai. Bab ini harus memberi anda gambaran yang jelas tentang cara semua boleh digunakan secara optimum dalam konteks Berorientasikan Objek supaya projek PixiJS anda berfungsi dan diberikan dengan kecekapan yang paling tinggi.
Untuk menggunakan grafik Pixi dengan berkesan, kita perlu memahami cara grafik tersebut berfungsi secara dalaman. Jadi mari kita mulakan dengan menunjukkan contoh yang sangat asas untuk mencipta objek grafik dalam Pixi:
const graphics = new PIXI.Graphics(); graphics.beginFill(0xff0000); graphics.drawRect(0, 0, 200, 100); graphics.endFill();
Apa yang penting dalam pelaksanaan mudah ini, bagaimanapun, adalah apa yang berlaku 'di bawah tudung'. Dalam mencipta grafik jenis ini, Pixi mencipta sesuatu yang dipanggil objek GraphicsGeometry. Objek itu mengambil bentuk dan saiz berdasarkan dimensi dan sifat yang anda tentukan untuk bentuk yang anda lukis. Objek Geometri akhir kemudiannya disimpan di dalam GeometryList dalam objek Grafik.
Perhatikan bahawa setiap kali anda melukis sesuatu dengan bantuan PIXI.Graphics, GeometryList akan dikemas kini. Kadangkala, anda hanya mahu mengosongkan senarai ini, tetapi pada masa yang sama memastikan objek Grafik anda hidup-di situlah kaedah .clear() dimainkan. Mengetahui cara proses ini berfungsi akan sangat membantu anda apabila menggunakan Pixi, kerana ia secara langsung mempengaruhi cara Pixi mengendalikan dan memaparkan grafik dalam apl anda.
Mari kita terokai strategi pengoptimuman melalui kes penggunaan mencipta 100 objek Grafik dalam PixiJS.
function createGraphics(x, y) { const graphic = new PIXI.Graphics(); graphic.beginFill(0xDE3249); graphic.drawCircle(x, y, 10); graphic.endFill(); return graphic; } for (let i = 0; i < 100; i++) { const x = Math.random() * app.screen.width; const y = Math.random() * app.screen.height; const graphics = createGraphics(x, y); app.stage.addChild(graphic); }
Dalam senario ini, jika semua 100 objek Grafik berkongsi lebar dan ketinggian yang sama, kita boleh mengoptimumkan dengan menggunakan semula geometri.
Buat satu geometri untuk bulatan dan gunakannya semula:
// Create a single geometry for a circle const circleGeometry = new PIXI.Graphics(); circleGeometry.beginFill(0xDE3249); circleGeometry.drawCircle(0, 0, 10); // Draw a circle at the origin circleGeometry.endFill(); // Function to create a graphic using the circle geometry function createCircle(x, y) { const circle = new PIXI.Graphics(circleGeometry.geometry); circle.x = x; circle.y = y; return circle; } // Create 100 circles using the same geometry for (let i = 0; i < 100; i++) { const x = Math.random() * app.screen.width; const y = Math.random() * app.screen.height; const circle = createCircle(x, y); app.stage.addChild(circle); }
Kaedah ini mengurangkan penggunaan memori dengan ketara dengan merujuk geometri yang sama dan bukannya menduplikasinya untuk setiap objek.
For static graphics or complex structures, drawing all elements in a single Graphics object is another optimization technique:
const graphics = new PIXI.Graphics(); // Draw 100 circles using the same PIXI.Graphics instance for (let i = 0; i < 100; i++) { const x = Math.random() * app.screen.width; const y = Math.random() * app.screen.height; graphics.beginFill(0xDE3249); graphics.drawCircle(x, y, 10); graphics.endFill(); } // Add the graphics to the stage app.stage.addChild(graphics);
In this approach, instead of creating new Graphics objects, we add new geometries to the GeometryList of a single Graphics instance. This method is particularly efficient for more complex graphic structures.
One of the most powerful features within PixiJS is CacheAsBitmap. Essentially, it lets the engine treat graphics like sprites. This can bring performance up substantially in certain cases.
Only use CacheAsBitmap if the object is not updated too often.
Big batch of Graphics can be cached as bitmap in container. Instead having 100 Graphics re-rendered, pixi will take a snapshot and pre-render it as a bitmap.
Always consider the memory usage, cached bitmaps are using a lot of memory.
One should use cacheAsBitmap judiciously. It will be most effective when applied to objects that need to update seldom. For instance, if one happens to have thousands of volume of Graphics that are static or have only a rare change, caching them as a bitmap radically reduces rendering overhead.
Instead of re-rendering 100 individual Graphics, PixiJS can take a 'snapshot' of these and render them as single bitmap. This is how you can implement:
const graphicsContainer = new PIXI.Container(); // Add your graphics to the container // ... // Cache the entire container as a bitmap graphicsContainer.cacheAsBitmap = true;
However, it's important to be mindful of memory usage. Cached bitmaps can consume a significant amount of memory. Therefore, while cacheAsBitmap can drastically reduce the rendering load, it trades off by using more memory. This trade-off should be carefully considered based on the specific needs and constraints of your application.
In summary, cacheAsBitmap is an effective tool for optimizing performance in PixiJS, particularly for static or seldom-updated graphics. It simplifies rendering by treating complex graphics as single bitmaps, but it's essential to balance this with the memory footprint implications.
When it comes to memory efficiency in PixiJS, sprites generally have the upper hand over graphics. This is particularly evident when dealing with multiple objects that share the same shape or texture. Let's revisit the example of creating 100 circle graphics, but this time using sprites.
First, we create a texture from the geometry of a single circle graphic:
const circleGraphic = new PIXI.Graphics(); circleGraphic.beginFill(0xDE3249); circleGraphic.drawCircle(0, 0, 10); circleGraphic.endFill(); // Generate a texture from the graphic const circleTexture = app.renderer.generateTexture(circleGraphic); Next, we use this texture to create sprites: // Function to create a sprite using the circle texture function createCircleSprite(x, y) { const sprite = new PIXI.Sprite(circleTexture); sprite.x = x; sprite.y = y; return sprite; } // Create and add 100 circle sprites to the stage for (let i = 0; i < 100; i++) { const x = Math.random() * app.screen.width; const y = Math.random() * app.screen.height; const circleSprite = createCircleSprite(x, y); app.stage.addChild(circleSprite); }
In this approach, instead of re-rendering graphics and managing a growing geometry list for each object, we create one texture and reuse it across multiple sprites. This significantly reduces the rendering load and memory usage.
One limitation of this method is that you're constrained by the textures you've created. However, this is where creativity becomes key. You can generate various shaped textures using PIXI.Graphics and apply them to Sprites. An especially efficient approach is to create a baseTexture, like a 1x1 pixel bitmap, and reuse it for all rectangular sprites. By resizing the sprite to different dimensions, you can leverage the same baseTexture across multiple sprites without redundancy.
For instance:
// This creates a 16x16 white texture const baseTexture = PIXI.Texture.WHITE; // Use this baseTexture for all rectangular shapes const sprite= new PIXI.Sprite(baseTexture); sprite.tint = 0xDE3249; // Set the sprite color sprite.position.set(x, y); sprite.width = width; sprite.height = height;
With this method, .tint() allows you to color the sprite without triggering a full re-render, as the tint is applied as an additional shader effect directly on the GPU.
To illustrate the power of this technique, imagine running 100,000 individual sprites with random tints, each transforming on every frame, all while maintaining a smooth 60 FPS.
For further reading on optimizing PixiJS, I highly recommend an insightful article by one of the original creators of PixiJS, which delves deeply into the renderTexture technique.
You can find it here
Wah! Jika anda telah berjaya sejauh ini, saya ingin mengucapkan terima kasih yang tulus kerana terus bersama saya melalui penyelaman mendalam ini ke dalam pengoptimuman PixiJS. Saya harap anda mendapati cerapan dan teknik yang dikongsi di sini berharga untuk projek anda. Nantikan artikel saya yang seterusnya, di mana saya akan meneroka pendekatan Entity-Component-System (ECS) dan kuasa NativeArrays dengan lebih terperinci. Kaedah ini akan membawa aplikasi PixiJS anda ke tahap yang baharu dalam prestasi dan kecekapan. Terima kasih kerana membaca, dan jumpa lagi pada yang seterusnya!
Atas ialah kandungan terperinci Memaksimumkan Prestasi: Menyelam Lebih Dalam ke dalam Pengoptimuman PixiJS. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!