」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 最大化效能:深入探討 PixiJS 最佳化

最大化效能:深入探討 PixiJS 最佳化

發佈於2024-11-08
瀏覽:972

利用先进的策略和技术将您的 PixiJS 应用程序提升到新的水平

前言

这篇文章介绍了在 CPU / 内存方面可以最好地优化 pixiJS 中多个元素的渲染的不同方法。例如,考虑在没有任何缓存的情况下重新渲染每一帧(在 CPU 使用率方面表现良好)或将渲染的图形缓存在内存中之间的差异。这将根据场景中的图形数量按比例增加内存使用量。

有许多策略可以处理此类优化。特别值得注意的是面向数据的设计,它提出了一组与更传统的常见面向对象编程方式完全不同的方法。

其他主要方法包括:例如,剔除和利用更加结构化的格式 - C# 中的 NativeArrays 和 TypeScript 中的 TypedArrays。这些将允许更好地管理内存缓冲区,这可能会限制缓存未命中,但这也需要大量的工程经验和/或定制。

在这篇文章中,我将重点介绍一种使用 PixiJS 优化 WebGL 环境的工作方法:面向对象的方法,包括最佳实践。这将为您提供一种组织良好的方法来提高 PixiJS 应用程序的速度和效率。

在我的下一篇文章中,我将讨论另一种强大的优化方法:实体组件系统方法。 ECS 方法非常以数据为导向,并且在高性能环境中优化 PixiJS 时提供了全新的外观。继续在 Medium 上阅读本文,我将深入探讨 ECS 方法的本质。

永远记住,为了优化和进一步增强 Pixi 应用程序的性能,总有一些事情可以做得更好。更好并不意味着最优化或最快。最佳解决方案是在优化投入的时间和投资回报之间进行权衡的问题,以确保您能够满足项目期限,但有足够的优化来满足任何潜在用户的需求,而不会过度扩展您的资源。

面向对象的方法

在本节中,我将指导您了解优化 PixiJS 应用程序的最佳方法。

此部分基于官方提示,值得查看!

我们的其余讨论将围绕 Pixi 图形、精灵、网格以及何时使用粒子容器而不是默认的 Pixi 容器。本章应该让您清楚地了解如何在面向对象的上下文中最佳地使用所有内容,以便您的 PixiJS 项目正常运行并以最高的效率进行渲染。

了解 Pixi 图形的内部工作原理

为了有效地使用 Pixi 图形,我们需要了解它们的内部功能。让我们首先展示一个在 Pixi 中创建图形对象的非常基本的示例:

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

然而,在这个简单的实现中重要的是“幕后”发生的事情。在创建这种图形时,Pixi 创建了一个称为 GraphicsGeometry 对象的东西。该对象的形状和大小取决于您为正在绘制的形状指定的尺寸和属性。然后,最终的 Geometry 对象存储在 Graphics 对象内的 GeometryList 内。

请注意,每次您在 PIXI.Graphics 的帮助下绘制某些内容时,GeometryList 都会更新。有时,您只想清除此列表,但同时保持 Graphics 对象处于活动状态 - 这就是 .clear() 方法发挥作用的地方。了解此过程的工作原理将对您使用 Pixi 时有很大帮助,因为它直接影响 Pixi 如何处理和渲染应用程序中的图形。

Pixi 图形优化技术

让我们通过在 PixiJS 中创建 100 个 Graphics 对象的用例来探索优化策略。

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 个 Graphics 对象共享相同的宽度和高度,我们可以通过重用几何体进行优化。

Maximising Performance: A Deep Dive into PixiJS Optimization

传递 GraphicsGeometry 作为参考

为圆创建单个几何图形并重复使用它:

// 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 



此方法通过引用相同的几何图形而不是为每个对象重复它,显着减少了内存使用量。

Maximising Performance: A Deep Dive into PixiJS Optimization

在一个图形对象中绘制所有内容

对于静态图形或复杂结构,在单个 Graphics 对象中绘制所有元素是另一种优化技术:

const graphics = new PIXI.Graphics();
// Draw 100 circles using the same PIXI.Graphics instance
for (let i = 0; i 



在这种方法中,我们不是创建新的 Graphics 对象,而是将新的几何图形添加到单个 Graphics 实例的 GeometryList 中。此方法对于更复杂的图形结构特别有效。

Maximising Performance: A Deep Dive into PixiJS Optimization


在 PixiJS 中利用 CacheAsBitmap 的强大功能

PixiJS 中最强大的功能之一是 CacheAsBitmap。本质上,它让引擎像精灵一样处理图形。在某些情况下,这可以显着提高性能。

  • 仅当对象不经常更新时才使用 CacheAsBitmap。

  • 大批量的图形可以作为位图缓存在容器中。 pixi 将拍摄快照并将其预渲染为位图,而不是重新渲染 100 个图形。

  • 始终考虑内存使用情况,缓存位图正在使用大量内存。

何时使用 CacheAsBitmap

应该明智地使用cacheAsBitmap。当应用于很少需要更新的对象时,它将是最有效的。例如,如果碰巧有数千个静态或只有很少变化的图形,则将它们缓存为位图可以从根本上减少渲染开销。

PixiJS 可以拍摄这些图形的“快照”并将它们渲染为单个位图,而不是重新渲染 100 个单独的图形。您可以这样实施:

const graphicsContainer = new PIXI.Container();
// Add your graphics to the container
// ...
// Cache the entire container as a bitmap
graphicsContainer.cacheAsBitmap = true;

内存使用注意事项

但是,注意内存使用情况很重要。缓存的位图可能会消耗大量内存。因此,虽然cacheAsBitmap可以大大减少渲染负载,但它会使用更多的内存来进行权衡。应根据应用程序的具体需求和限制仔细考虑这种权衡。

总之,cacheAsBitmap 是 PixiJS 中优化性能的有效工具,特别是对于静态或很少更新的图形。它通过将复杂图形视为单个位图来简化渲染,但必须平衡这一点与内存占用的影响。

为什么 PixiJS 中的精灵通常比图形更有效

当谈到 PixiJS 的内存效率时,精灵通常比图形更具优势。当处理共享相同形状或纹理的多个对象时,这一点尤其明显。让我们回顾一下创建 100 个圆形图形的示例,但这次使用精灵。

从单个纹理创建精灵

首先,我们根据单个圆形图形的几何形状创建纹理:

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 



在这种方法中,我们不是重新渲染图形并管理每个对象不断增长的几何列表,而是创建一个纹理并在多个精灵中重用它。这显着减少了渲染负载和内存使用。

局限性和创造性解决方案

此方法的一个限制是您受到所创建的纹理的限制。然而,这就是创造力变得关键的地方。您可以使用 PIXI.Graphics 生成各种形状的纹理并将它们应用到 Sprites。一种特别有效的方法是创建一个基本纹理(例如 1x1 像素位图),并将其重用于所有矩形精灵。通过将精灵大小调整为不同的尺寸,您可以在多个精灵中利用相同的基本纹理,而无需冗余。
例如:

// 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;

Maximising Performance: A Deep Dive into PixiJS Optimization

使用此方法,.tint() 允许您在不触发完全重新渲染的情况下为精灵着色,因为色调将作为附加着色器效果直接应用在 GPU 上。

在粒子容器中使用 100k 精灵

为了说明此技术的威力,想象一下运行 100,000 个具有随机色调的单独精灵,每个精灵在每一帧上进行变换,同时保持平滑的 60 FPS。

Maximising Performance: A Deep Dive into PixiJS Optimization

Maximising Performance: A Deep Dive into PixiJS Optimization

为了进一步阅读有关优化 PixiJS 的内容,我强烈推荐 PixiJS 的原始创建者之一撰写的一篇富有洞察力的文章,该文章深入研究了 renderTexture 技术。 

你可以在这里找到它

哇! 如果您已经做到了这一步,我真诚地感谢您在深入研究 PixiJS 优化过程中与我一起坚持。我希望您发现这里分享的见解和技术对您的项目有价值。请继续关注我的下一篇文章,我将更详细地探讨实体组件系统 (ECS) 方法和 NativeArrays 的强大功能。这些方法将使您的 PixiJS 应用程序的性能和效率达到新的高度。感谢您的阅读,我们下一篇再见!

版本聲明 本文轉載於:https://dev.to/recursivevoid/maximising-performance-a-deep-dive-into-pixijs-optimization-4i0g?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • CSS強類型語言解析
    CSS強類型語言解析
    您可以通过其强度或弱输入的方式对编程语言进行分类的方式之一。在这里,“键入”意味着是否在编译时已知变量。一个例子是一个场景,将整数(1)添加到包含整数(“ 1”)的字符串: result = 1 "1";包含整数的字符串可能是由带有许多运动部件的复杂逻辑套件无意间生成的。它也可以是故意从单个真理...
    程式設計 發佈於2025-07-13
  • 反射動態實現Go接口用於RPC方法探索
    反射動態實現Go接口用於RPC方法探索
    在GO 使用反射來實現定義RPC式方法的界面。例如,考慮一個接口,例如:鍵入myService接口{ 登錄(用戶名,密碼字符串)(sessionId int,錯誤錯誤) helloworld(sessionid int)(hi String,錯誤錯誤) } 替代方案而不是依靠反射...
    程式設計 發佈於2025-07-13
  • 同實例無需轉儲複製MySQL數據庫方法
    同實例無需轉儲複製MySQL數據庫方法
    在同一實例上複製一個MySQL數據庫而無需轉儲在同一mySQL實例上複製數據庫,而無需創建InterMediate sqql script。以下方法為傳統的轉儲和IMPORT過程提供了更簡單的替代方法。 直接管道數據 MySQL手動概述了一種允許將mysqldump直接輸出到MySQL cli...
    程式設計 發佈於2025-07-13
  • 使用jQuery如何有效修改":after"偽元素的CSS屬性?
    使用jQuery如何有效修改":after"偽元素的CSS屬性?
    在jquery中了解偽元素的限制:訪問“ selector 嘗試修改“:”選擇器的CSS屬性時,您可能會遇到困難。 This is because pseudo-elements are not part of the DOM (Document Object Model) and are th...
    程式設計 發佈於2025-07-13
  • 如何使用node-mysql在單個查詢中執行多個SQL語句?
    如何使用node-mysql在單個查詢中執行多個SQL語句?
    Multi-Statement Query Support in Node-MySQLIn Node.js, the question arises when executing multiple SQL statements in a single query using the node-mys...
    程式設計 發佈於2025-07-13
  • 圖片在Chrome中為何仍有邊框? `border: none;`無效解決方案
    圖片在Chrome中為何仍有邊框? `border: none;`無效解決方案
    在chrome 在使用Chrome and IE9中的圖像時遇到的一個頻繁的問題是圍繞圖像的持續薄薄邊框,儘管指定了圖像,儘管指定了;和“邊境:無;”在CSS中。要解決此問題,請考慮以下方法: Chrome具有忽略“ border:none; none;”的已知錯誤,風格。要解決此問題,請使用以下...
    程式設計 發佈於2025-07-13
  • 我可以將加密從McRypt遷移到OpenSSL,並使用OpenSSL遷移MCRYPT加密數據?
    我可以將加密從McRypt遷移到OpenSSL,並使用OpenSSL遷移MCRYPT加密數據?
    將我的加密庫從mcrypt升級到openssl 問題:是否可以將我的加密庫從McRypt升級到OpenSSL?如果是這樣,如何? 答案:是的,可以將您的Encryption庫從McRypt升級到OpenSSL。 可以使用openssl。 附加說明: [openssl_decrypt()函數要求...
    程式設計 發佈於2025-07-13
  • Java字符串非空且非null的有效檢查方法
    Java字符串非空且非null的有效檢查方法
    檢查字符串是否不是null而不是空的 if(str!= null && str.isementy())二手: if(str!= null && str.length()== 0) option 3:trim()。 isement(Isement() trim whitespace whites...
    程式設計 發佈於2025-07-13
  • 為什麼PHP的DateTime :: Modify('+1個月')會產生意外的結果?
    為什麼PHP的DateTime :: Modify('+1個月')會產生意外的結果?
    使用php dateTime修改月份:發現預期的行為在使用PHP的DateTime類時,添加或減去幾個月可能並不總是會產生預期的結果。正如文檔所警告的那樣,“當心”這些操作的“不像看起來那樣直觀。 ; $ date->修改('1個月'); //前進1個月 echo $ date->...
    程式設計 發佈於2025-07-13
  • 為什麼使用固定定位時,為什麼具有100%網格板柱的網格超越身體?
    為什麼使用固定定位時,為什麼具有100%網格板柱的網格超越身體?
    網格超過身體,用100%grid-template-columns 為什麼在grid-template-colms中具有100%的顯示器,當位置設置為設置的位置時,grid-template-colly修復了? 問題: 考慮以下CSS和html: class =“ snippet-code”> ...
    程式設計 發佈於2025-07-13
  • 如何在其容器中為DIV創建平滑的左右CSS動畫?
    如何在其容器中為DIV創建平滑的左右CSS動畫?
    通用CSS動畫,用於左右運動 ,我們將探索創建一個通用的CSS動畫,以向左和右移動DIV,從而到達其容器的邊緣。該動畫可以應用於具有絕對定位的任何div,無論其未知長度如何。 問題:使用左直接導致瞬時消失 更加流暢的解決方案:混合轉換和左 [並實現平穩的,線性的運動,我們介紹了線性的轉換。...
    程式設計 發佈於2025-07-13
  • 解決MySQL插入Emoji時出現的\\"字符串值錯誤\\"異常
    解決MySQL插入Emoji時出現的\\"字符串值錯誤\\"異常
    Resolving Incorrect String Value Exception When Inserting EmojiWhen attempting to insert a string containing emoji characters into a MySQL database us...
    程式設計 發佈於2025-07-13
  • 如何克服PHP的功能重新定義限制?
    如何克服PHP的功能重新定義限制?
    克服PHP的函數重新定義限制在PHP中,多次定義一個相同名稱的函數是一個no-no。嘗試這樣做,如提供的代碼段所示,將導致可怕的“不能重新列出”錯誤。 但是,PHP工具腰帶中有一個隱藏的寶石:runkit擴展。它使您能夠靈活地重新定義函數。 runkit_function_renction_...
    程式設計 發佈於2025-07-13
  • C++20 Consteval函數中模板參數能否依賴於函數參數?
    C++20 Consteval函數中模板參數能否依賴於函數參數?
    [ consteval函數和模板參數依賴於函數參數在C 17中,模板參數不能依賴一個函數參數,因為編譯器仍然需要對非contexexpr futcoriations contim at contexpr function進行評估。 compile time。 C 20引入恆定函數,必須在編譯時進...
    程式設計 發佈於2025-07-13
  • 如何使用不同數量列的聯合數據庫表?
    如何使用不同數量列的聯合數據庫表?
    合併列數不同的表 當嘗試合併列數不同的數據庫表時,可能會遇到挑戰。一種直接的方法是在列數較少的表中,為缺失的列追加空值。 例如,考慮兩個表,表 A 和表 B,其中表 A 的列數多於表 B。為了合併這些表,同時處理表 B 中缺失的列,請按照以下步驟操作: 確定表 B 中缺失的列,並將它們添加到表的...
    程式設計 發佈於2025-07-13

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3