Heim > Web-Frontend > js-Tutorial > Hauptteil

Maximierung der Leistung: Ein tiefer Einblick in die PixiJS-Optimierung

WBOY
Freigeben: 2024-09-04 18:33:00
Original
453 Leute haben es durchsucht

Bringen Sie Ihre PixiJS-Anwendungen mit fortschrittlichen Strategien und Techniken auf die nächste Stufe

Vorwort

In diesem Beitrag geht es um die verschiedenen Möglichkeiten, wie man das Rendering mehrerer Elemente in pixiJS sowohl in Bezug auf CPU als auch auf Speicher am besten optimieren kann. Betrachten wir beispielsweise den Unterschied zwischen dem erneuten Rendern jedes Frames ohne Zwischenspeicherung – was im Hinblick auf die CPU-Auslastung eine gute Leistung erbringt – oder dem Zwischenspeichern einer gerenderten Grafik im Speicher. Dadurch erhöht sich die Speichernutzung proportional zur Anzahl der Grafiken in der Szene.

Es gibt eine Reihe von Strategien, mit solchen Optimierungen umzugehen. Besonders hervorzuheben ist das datenorientierte Design, das eine radikal alternative Reihe von Ansätzen zur traditionell üblicheren objektorientierten Art der Programmierung darstellt.

Andere wichtige Möglichkeiten umfassen: Aussortieren und Verwenden weitaus strukturierterer Formate  –  NativeArrays in C# und TypedArrays in TypeScript zum Beispiel. Diese ermöglichen eine viel bessere Verwaltung der Speicherpuffer, was Cache-Fehler begrenzen kann, aber auch erhebliche technische Erfahrung und/oder Anpassung erfordert.

In diesem Beitrag werde ich mich auf eine Arbeitsmethode zur Optimierung einer WebGL-Umgebung mit PixiJS konzentrieren: den objektorientierten Ansatz, einschließlich Best Practices. Dies soll Ihnen eine gut organisierte Möglichkeit bieten, die Geschwindigkeit und Effizienz Ihrer PixiJS-Anwendungen zu steigern.

In meinem nächsten Artikel werde ich über einen weiteren starken Optimierungsansatz sprechen: den Entity-Component-System-Ansatz. Der ECS-Ansatz ist auffallend datenorientiert und bietet einen frischen Look, wenn es um die Optimierung von PixiJS in Hochleistungsumgebungen geht. Fahren Sie auf Medium für diesen Artikel fort, in dem ich ausführlich auf die Einzelheiten des ECS-Ansatzes eingehe.

Denken Sie immer daran, dass es immer etwas gibt, das besser gemacht werden kann, um die Leistung Ihrer Pixi-Anwendung zu optimieren und weiter zu verbessern. Mit „besser“ ist nicht gemeint, dass es am optimiertesten oder am schnellsten ist. Die beste Lösung ist eine Frage des Kompromisses zwischen der Zeit, die Sie in eine Optimierung investieren, und der Rendite dieser Investition, um sicherzustellen, dass Sie die Projektfristen einhalten können, aber mit ausreichend Optimierung, um hoffentlich alle potenziellen Benutzer zufrieden zu stellen, ohne Ihre Ressourcen übermäßig zu erweitern.

Objektorientierter Ansatz

In diesem Abschnitt werde ich Sie durch die besten Möglichkeiten zur Optimierung von PixiJS-Anwendungen führen.

Dieser Abschnitt basiert auf offiziellen Tipps, die einen Blick wert sind!

Der Rest unserer Diskussion wird sich um Pixi-Grafiken, Sprites, Meshes und die Verwendung eines Partikelcontainers anstelle des Standard-Pixi-Containers drehen. Dieses Kapitel soll Ihnen einen klaren Überblick darüber geben, wie alles optimal in einem objektorientierten Kontext verwendet werden kann, damit Ihre PixiJS-Projekte funktionsfähig sind und mit größter Effizienz gerendert werden.

Das Innenleben von Pixi-Grafiken verstehen

Um Pixi-Grafiken effektiv nutzen zu können, müssen wir verstehen, wie sie intern funktionieren. Beginnen wir also damit, ein sehr einfaches Beispiel für die Erstellung eines Grafikobjekts in Pixi zu zeigen:

const graphics = new PIXI.Graphics();
graphics.beginFill(0xff0000);
graphics.drawRect(0, 0, 200, 100);
graphics.endFill();
Nach dem Login kopieren

Wichtig bei dieser einfachen Umsetzung ist jedoch, was „unter der Haube“ passiert. Beim Erstellen dieser Art von Grafik erstellt Pixi ein sogenanntes GraphicsGeometry-Objekt. Dieses Objekt nimmt die Form und Größe an, die auf den Abmessungen und Eigenschaften basiert, die Sie für die Form angeben, die Sie zeichnen. Das endgültige Geometry-Objekt wird dann in einer GeometryList innerhalb des Graphics-Objekts gespeichert.

Beachten Sie, dass GeometryList jedes Mal aktualisiert wird, wenn Sie etwas mit Hilfe von PIXI.Graphics zeichnen. Manchmal möchten Sie einfach nur diese Liste löschen, aber gleichzeitig Ihr Grafikobjekt am Leben erhalten – hier kommt die Methode .clear() ins Spiel. Zu wissen, wie dieser Prozess funktioniert, wird Ihnen bei der Verwendung von Pixi sehr hilfreich sein, da es sich direkt darauf auswirkt, wie Pixi die Grafiken in Ihrer App verarbeitet und rendert.

Optimierungstechniken für Pixi-Grafiken

Lassen Sie uns Optimierungsstrategien anhand eines Anwendungsfalls der Erstellung von 100 Grafikobjekten in PixiJS untersuchen.

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);
}
Nach dem Login kopieren

Wenn in diesem Szenario alle 100 Grafikobjekte die gleiche Breite und Höhe haben, können wir durch Wiederverwendung der Geometrie optimieren.

Maximising Performance: A Deep Dive into PixiJS Optimization

Übergabe von GraphicsGeometry als Referenz

Erstellen Sie eine einzelne Geometrie für einen Kreis und verwenden Sie sie wieder:

// 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);
}
Nach dem Login kopieren

Diese Methode reduziert den Speicherverbrauch erheblich, indem sie auf dieselbe Geometrie verweist, anstatt sie für jedes Objekt zu duplizieren.

Maximising Performance: A Deep Dive into PixiJS Optimization

Draw All in One Graphics Object

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);
Nach dem Login kopieren

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.

Maximising Performance: A Deep Dive into PixiJS Optimization


Leveraging the Power of CacheAsBitmap in PixiJS

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.

When to Use CacheAsBitmap

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;
Nach dem Login kopieren

Memory Usage Consideration

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.

Why Sprites Are Often More Efficient than Graphics in PixiJS

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.

Creating Sprites from a Single Texture

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);
}
Nach dem Login kopieren

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.

Limitations and Creative Solutions

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;

Nach dem Login kopieren

Maximising Performance: A Deep Dive into PixiJS Optimization

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.

Using 100k Sprites in Particle Container

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.

Maximising Performance: A Deep Dive into PixiJS Optimization

Maximising Performance: A Deep Dive into PixiJS Optimization

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

Wow! Wenn Sie es bis hierher geschafft haben, möchte ich Ihnen aufrichtig dafür danken, dass Sie mich bei diesem tiefen Einblick in die PixiJS-Optimierung begleitet haben. Ich hoffe, dass Sie die hier geteilten Erkenntnisse und Techniken für Ihre Projekte wertvoll fanden. Seien Sie gespannt auf meinen nächsten Artikel, in dem ich den Entity-Component-System (ECS)-Ansatz und die Leistungsfähigkeit von NativeArrays noch detaillierter beleuchten werde. Diese Methoden bringen Ihre PixiJS-Anwendungen auf ein neues Niveau in Bezug auf Leistung und Effizienz. Vielen Dank fürs Lesen und bis zum nächsten Mal!

Das obige ist der detaillierte Inhalt vonMaximierung der Leistung: Ein tiefer Einblick in die PixiJS-Optimierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!