"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Maximizando o desempenho: um mergulho profundo na otimização do PixiJS

Maximizando o desempenho: um mergulho profundo na otimização do PixiJS

Publicado em 2024-11-08
Navegar:806

Leve seus aplicativos PixiJS para o próximo nível com estratégias e técnicas avançadas

Prefácio

Esta postagem aborda as diferentes maneiras de otimizar melhor a renderização de vários elementos dentro do pixiJS em termos de CPU/Memória. Por exemplo, considerando a diferença entre renderizar novamente cada quadro sem qualquer cache - que funciona bem em termos de uso da CPU - ou armazenar em cache um gráfico renderizado na memória. Isso aumentará o uso de memória proporcionalmente ao número de gráficos na cena.

Existem várias estratégias para lidar com essas otimizações. Digno de nota é o Design Orientado a Dados, que apresenta um conjunto radicalmente alternativo de abordagens da forma mais tradicionalmente comum de programação Orientada a Objetos.

Outras formas importantes incluem: selecionar e utilizar formatos muito mais estruturados - NativeArrays em C# e TypedArrays em TypeScript, por exemplo. Isso permitirá um gerenciamento muito maior de buffers de memória, o que pode limitar falhas de cache, mas que também requer experiência significativa em engenharia e/ou personalização.

Nesta postagem, focarei em um método de trabalho de otimização para um ambiente WebGL com PixiJS: a abordagem orientada a objetos, incluindo as melhores práticas. Isso fornecerá a você um meio bem organizado para aumentar a velocidade e a eficiência em seus aplicativos PixiJS.

Em meu próximo artigo, falarei sobre outra forte abordagem de otimização: a abordagem Entidade-Componente-Sistema. A abordagem ECS é surpreendentemente orientada a dados e oferece uma nova visão quando se trata de otimizar PixiJS em ambientes de alto desempenho. Continue no Medium para este artigo, onde, em profundidade, abordo os detalhes da abordagem ECS.

Lembre-se sempre de que sempre há algo que pode ser feito melhor na tentativa de otimizar e melhorar ainda mais o desempenho do seu aplicativo Pixi. Por melhor, não significa mais otimizado ou mais rápido. A melhor solução é uma questão de equilíbrio entre a quantidade de tempo que você investe em uma otimização e o retorno desse investimento para garantir que você possa cumprir os prazos do projeto, mas com otimização suficiente para satisfazer qualquer usuário em potencial sem expandir demais seus recursos.

Abordagem Orientada a Objetos

Nesta seção, vou guiá-lo pelas melhores maneiras de otimizar aplicativos PixiJS.

Esta seção é baseada em dicas oficiais, vale a pena conferir!

O resto da nossa discussão girará em torno de Pixi Graphics, Sprites, Meshes e quando usar um Particle Container em vez do Pixi Container padrão. Este capítulo deve lhe dar uma visão clara de como tudo pode ser usado de forma otimizada em um contexto orientado a objetos para que seus projetos PixiJS sejam funcionais e renderizados com a maior eficiência.

Compreendendo o funcionamento interno dos gráficos Pixi

Para usar os gráficos Pixi de maneira eficaz, precisamos entender como eles funcionam internamente. Então vamos começar mostrando um exemplo bem básico de criação de um objeto gráfico no Pixi:


const gráficos = new PIXI.Graphics(); gráficos.beginFill(0xff0000); gráficos.drawRect(0, 0, 200, 100); gráficos.endFill();
const graphics = new PIXI.Graphics();
graphics.beginFill(0xff0000);
graphics.drawRect(0, 0, 200, 100);
graphics.endFill();
O que é importante nesta implementação simples, entretanto, é o que acontece “nos bastidores”. Ao criar esse tipo de gráfico, Pixi cria algo chamado objeto GraphicsGeometry. Esse objeto assume a forma e o tamanho com base nas dimensões e propriedades especificadas para a forma que você está desenhando. O objeto Geometry final é então armazenado dentro de um GeometryList dentro do objeto Graphics.

Observe que cada vez que você desenha algo com a ajuda do PIXI.Graphics, GeometryList é atualizado. Às vezes, você só quer limpar esta lista, mas ao mesmo tempo manter seu objeto Graphics vivo - é aí que o método .clear() entra em ação. Saber como esse processo funciona irá ajudá-lo muito ao usar o Pixi, pois afeta diretamente como o Pixi irá manipular e renderizar os gráficos em seu aplicativo.

Técnicas de otimização para gráficos Pixi

Vamos explorar estratégias de otimização por meio de um caso de uso de criação de 100 objetos gráficos no PixiJS.


função criarGráficos(x, y) { gráfico const = novo PIXI.Graphics(); gráfico.beginFill(0xDE3249); gráfico.drawCircle(x, y, 10); gráfico.endFill(); gráfico de retorno; } para (seja i = 0; i const graphics = new PIXI.Graphics(); graphics.beginFill(0xff0000); graphics.drawRect(0, 0, 200, 100); graphics.endFill(); Neste cenário, se todos os 100 objetos gráficos compartilharem a mesma largura e altura, podemos otimizar reutilizando a geometria.

Maximising Performance: A Deep Dive into PixiJS Optimization

Passando GraphicsGeometry como referência

Crie uma única geometria para um círculo e reutilize-a:


// Cria uma única geometria para um círculo const círculoGeometria = novo PIXI.Graphics(); círculoGeometry.beginFill(0xDE3249); círculoGeometry.drawCircle(0, 0, 10); //Desenha um círculo na origem círculoGeometry.endFill(); //Função para criar um gráfico utilizando a geometria circular função criarCírculo(x, y) { const círculo = novo PIXI.Graphics(circleGeometry.geometry); círculo.x = x; círculo.y = y; círculo de retorno; } // Cria 100 círculos usando a mesma geometria para (seja i = 0; i const graphics = new PIXI.Graphics(); graphics.beginFill(0xff0000); graphics.drawRect(0, 0, 200, 100); graphics.endFill(); Este método reduz significativamente o uso de memória referenciando a mesma geometria em vez de duplicá-la para cada objeto.

Maximising Performance: A Deep Dive into PixiJS Optimization

Desenhe tudo em um objeto gráfico

Para gráficos estáticos ou estruturas complexas, desenhar todos os elementos em um único objeto Gráfico é outra técnica de otimização:


const gráficos = new PIXI.Graphics(); // Desenha 100 círculos usando a mesma instância PIXI.Graphics para (seja i = 0; i const graphics = new PIXI.Graphics(); graphics.beginFill(0xff0000); graphics.drawRect(0, 0, 200, 100); graphics.endFill(); Nesta abordagem, em vez de criar novos objetos Graphics, adicionamos novas geometrias ao GeometryList de uma única instância Graphics. Este método é particularmente eficiente para estruturas gráficas mais complexas.

Maximising Performance: A Deep Dive into PixiJS Optimization


Aproveitando o poder do CacheAsBitmap no PixiJS

Um dos recursos mais poderosos do PixiJS é o CacheAsBitmap. Essencialmente, permite que o mecanismo trate os gráficos como sprites. Isso pode aumentar substancialmente o desempenho em certos casos.

  • Use CacheAsBitmap somente se o objeto não for atualizado com muita frequência.

  • Grandes lotes de gráficos podem ser armazenados em cache como bitmap no contêiner. Em vez de ter 100 gráficos renderizados novamente, o pixi tirará um instantâneo e o pré-renderizará como um bitmap.

  • Sempre considere o uso de memória, os bitmaps em cache estão usando muita memória.

Quando usar CacheAsBitmap

Deve-se usar cacheAsBitmap criteriosamente. Será mais eficaz quando aplicado a objetos que raramente precisam ser atualizados. Por exemplo, se alguém tiver milhares de volumes de gráficos estáticos ou com apenas uma alteração rara, armazená-los em cache como um bitmap reduz radicalmente a sobrecarga de renderização.

Em vez de renderizar novamente 100 gráficos individuais, o PixiJS pode tirar um 'instantâneo' deles e renderizá-los como um único bitmap. É assim que você pode implementar:


const graphicsContainer = new PIXI.Container(); // Adicione seus gráficos ao contêiner // ... // Armazena em cache todo o contêiner como um bitmap gráficosContainer.cacheAsBitmap = true;
const graphics = new PIXI.Graphics();
graphics.beginFill(0xff0000);
graphics.drawRect(0, 0, 200, 100);
graphics.endFill();
Consideração sobre uso de memória

No entanto, é importante estar atento ao uso da memória. Os bitmaps armazenados em cache podem consumir uma quantidade significativa de memória. Portanto, embora cacheAsBitmap possa reduzir drasticamente a carga de renderização, ele compensa usando mais memória. Essa compensação deve ser cuidadosamente considerada com base nas necessidades e restrições específicas da sua aplicação.

Em resumo, cacheAsBitmap é uma ferramenta eficaz para otimizar o desempenho em PixiJS, especialmente para gráficos estáticos ou raramente atualizados. Ele simplifica a renderização tratando gráficos complexos como bitmaps únicos, mas é essencial equilibrar isso com as implicações do consumo de memória.

Por que Sprites costumam ser mais eficientes que gráficos no PixiJS

Quando se trata de eficiência de memória no PixiJS, os sprites geralmente têm vantagem sobre os gráficos. Isto é particularmente evidente quando se lida com vários objetos que compartilham a mesma forma ou textura. Vamos revisitar o exemplo de criação de gráficos de 100 círculos, mas desta vez usando sprites.

Criando Sprites a partir de uma única textura

Primeiro, criamos uma textura a partir da geometria de um único gráfico circular:


const círculoGraphic = new PIXI.Graphics(); círculoGraphic.beginFill(0xDE3249); círculoGraphic.drawCircle(0, 0, 10); círculoGraphic.endFill(); //Gera uma textura a partir do gráfico const círculoTexture = app.renderer.generateTexture(circleGraphic); A seguir, usamos esta textura para criar sprites: //Função para criar um sprite usando a textura circular função criarCírculoSprite(x, y) { const sprite = novo PIXI.Sprite(circleTexture); sprite.x = x; sprite.y = y; ator de retorno; } // Cria e adiciona 100 sprites circulares ao cenário para (seja i = 0; i const graphics = new PIXI.Graphics(); graphics.beginFill(0xff0000); graphics.drawRect(0, 0, 200, 100); graphics.endFill(); Nesta abordagem, em vez de renderizar novamente os gráficos e gerenciar uma lista crescente de geometrias para cada objeto, criamos uma textura e a reutilizamos em vários sprites. Isso reduz significativamente a carga de renderização e o uso de memória.

Limitações e soluções criativas

Uma limitação deste método é que você está limitado pelas texturas que criou. No entanto, é aqui que a criatividade se torna fundamental. Você pode gerar texturas de vários formatos usando PIXI.Graphics e aplicá-las aos Sprites. Uma abordagem especialmente eficiente é criar uma baseTexture, como um bitmap de 1x1 pixel, e reutilizá-la para todos os sprites retangulares. Ao redimensionar o sprite para dimensões diferentes, você pode aproveitar a mesma baseTexture em vários sprites sem redundância.

Por exemplo:

// Isso cria uma textura branca 16x16 const baseTexture = PIXI.Texture.WHITE; // Use esta baseTexture para todas as formas retangulares const sprite= novo PIXI.Sprite(baseTexture); sprite.tint = 0xDE3249; //Define a cor do sprite sprite.posição.set(x, y); sprite.largura = largura; sprite.height = altura;
const graphics = new PIXI.Graphics();
graphics.beginFill(0xff0000);
graphics.drawRect(0, 0, 200, 100);
graphics.endFill();

Maximising Performance: A Deep Dive into PixiJS Optimization

Com esse método, .tint() permite colorir o sprite sem acionar uma nova renderização completa, já que a tonalidade é aplicada como um efeito de sombreamento adicional diretamente na GPU.

Usando 100k Sprites no Particle Container

Para ilustrar o poder dessa técnica, imagine executar 100.000 sprites individuais com tonalidades aleatórias, cada um se transformando em cada quadro, ao mesmo tempo em que mantém suaves 60 FPS.

Maximising Performance: A Deep Dive into PixiJS Optimization

Maximising Performance: A Deep Dive into PixiJS Optimization

Para ler mais sobre como otimizar o PixiJS, recomendo fortemente um artigo esclarecedor de um dos criadores originais do PixiJS, que se aprofunda na técnica renderTexture. 

Você pode encontrá-lo aqui

Uau! Se você chegou até aqui, quero agradecer sinceramente por permanecer comigo neste mergulho profundo na otimização do PixiJS. Espero que você tenha achado os insights e técnicas compartilhados aqui valiosos para seus projetos. Fique ligado no meu próximo artigo, onde explorarei a abordagem Entity-Component-System (ECS) e o poder dos NativeArrays com ainda mais detalhes. Esses métodos levarão seus aplicativos PixiJS a novos patamares de desempenho e eficiência. Obrigado pela leitura e até a próxima!

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/recursivevoid/maximising-performance-a-deep-dive-into-pixijs-optimization-4i0g?1 Se houver alguma violação, entre em contato com [email protected] para excluir isto
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3