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

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

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

利用先进的策略和技术将您的 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]刪除
最新教學 更多>
  • 釋放效能:Java Web 框架中的虛擬執行緒
    釋放效能:Java Web 框架中的虛擬執行緒
    Level up your Java web applications with Virtual Threads — where speed meets simplicity, and performance breaks all records on the field! As Java cont...
    程式設計 發佈於2024-11-08
  • 避免 React 中不必要的重新渲染
    避免 React 中不必要的重新渲染
    建立高效能 React 應用程式的關鍵之一是避免不必要的重新渲染。 React 的渲染引擎非常高效,但防止在不需要的地方重新渲染仍然至關重要。在這篇文章中,我們將介紹常見錯誤以及如何避免這些錯誤。 1. 使用 React.memo 記憶組件 當元件的 props 沒有改變時,Mem...
    程式設計 發佈於2024-11-08
  • 如何解決資料庫連線中的「呼叫成員函數prepare() on null」錯誤?
    如何解決資料庫連線中的「呼叫成員函數prepare() on null」錯誤?
    空成員函數錯誤:資料庫連線中的問題空成員函數錯誤:資料庫連線中的問題遇到「Call to a member function prepare() on null」錯誤時,問題通常源自於類別實例中未初始化的變數。在您的情況下,問題在於缺少 $pdo 變數的初始化。 <?php // Instan...
    程式設計 發佈於2024-11-08
  • Python 中 exit() 和 sys.exit() 有什麼不同?
    Python 中 exit() 和 sys.exit() 有什麼不同?
    Python 中的Exit 和sys.exit:差異和用法Python 提供了兩個具有相似用途但具有不同功能的函數: exit( ) 和sys.exit()。了解這兩個函數之間的差異對於在各種情況下正確使用它們至關重要。 exit()exit() 主要用於互動式 Python殼。它提供了一種終止 s...
    程式設計 發佈於2024-11-08
  • 在 Slack、Python 自動化中為最後一刻的會議預訂房間
    在 Slack、Python 自動化中為最後一刻的會議預訂房間
    在繁忙的組織中,管理會議室的可用性可能是一項挑戰,尤其是在最後一刻的臨時預訂方面。為了解決這個問題,我開發了一個基於 Python 的自動化工具,該工具將 Slack 與 Google Calendar 無縫集成,使員工能夠快速檢查房間可用性並預訂房間以立即召開會議。 Python程式碼較短且易於...
    程式設計 發佈於2024-11-08
  • 如何使用 pygame.draw.rect 在 Pygame 中繪製矩形?
    如何使用 pygame.draw.rect 在 Pygame 中繪製矩形?
    用Pygame繪製矩形在Python的Pygame庫中,創建矩形是開發遊戲的基本任務。 對於像 3.2 這樣的 Pygame 版本,繪製矩形涉及使用 pygame.draw.rect 函數。實現此目的的方法如下:導入 Pygame 和基本常數:import pygame, sys from pyga...
    程式設計 發佈於2024-11-08
  • 如何將 CSS 樣式專門套用至 Internet Explorer 7、8 和 9?
    如何將 CSS 樣式專門套用至 Internet Explorer 7、8 和 9?
    僅將CSS 應用到Internet Explorer僅將CSS 應用到Internet Explorer將CSS 的應用限製到特定版本的Internet Explorer,如7、8 和9、利用Microsoft 特定的媒體查詢提供了一個有效的解決方案。 @media screen and (-ms-...
    程式設計 發佈於2024-11-08
  • 為什麼我的 jqGrid 編輯表單中的狀態選擇框選項值不正確?
    為什麼我的 jqGrid 編輯表單中的狀態選擇框選項值不正確?
    jqgrid 在編輯框中選擇下拉選項值不正確儘管在編輯表單中正確選擇了“國家/地區”和“州”值,但“州」選擇框中顯示的選項值編輯表格時不正確。即使在選擇美國國家/地區後切換回英國國家/地區,此問題仍然存在。 如何解決「州」選擇框中不正確的選項值要解決此問題,需要正確載入編輯表單時,根據所選國家/地區...
    程式設計 發佈於2024-11-08
  • 如何在Java中使用堆疊將算術表達式解析為樹結構?
    如何在Java中使用堆疊將算術表達式解析為樹結構?
    在Java 中將算術表達式解析為樹結構從算術表達式創建自定義樹可能是一項具有挑戰性的任務,特別是在確保樹結構時準確反映表達式的操作和優先順序。 要實現這一點,一種有效的方法是使用堆疊。以下是該過程的逐步描述:初始化:從空堆疊開始。 處理令牌:迭代表達式中的每個標記:如果標記是左括號,則將其壓入堆疊。...
    程式設計 發佈於2024-11-08
  • 考慮到特定於平台的結尾,如何有效地從 Java 中的檔案中刪除換行符?
    考慮到特定於平台的結尾,如何有效地從 Java 中的檔案中刪除換行符?
    從Java 中的文件中刪除換行符在Java 中,從文件中刪除換行符可以透過替換所有出現的換行符來實現。但是,考慮特定於平台的行結尾以確保 Windows 和 Linux 之間的兼容性至關重要。 要有效替換換行符,應使用以下步驟:以字串形式讀取檔案: 使用readFileAsString 等函數將文字...
    程式設計 發佈於2024-11-08
  • 如何從內容中刪除 HTML 特殊字元?
    如何從內容中刪除 HTML 特殊字元?
    刪除 HTML 特殊字元在嘗試產生 RSS 原始檔時,您使用了 strip_tags 函數來從應用程式中刪除 HTML 標記。但是,您遇到了一個缺點:strip_tags 無法刪除 HTML 特殊程式碼字符,例如「 」、「&」和「©」。 要解決此問題,請考慮使用替代函數,例如作為 html_enti...
    程式設計 發佈於2024-11-08
  • 如何在Python中透過拆分和刪除字元來解析和清理清單元素?
    如何在Python中透過拆分和刪除字元來解析和清理清單元素?
    如何拆分列表元素並刪除不需要的字符要拆分列表元素並刪除不需要的字符,您可以使用split() 和列表理解技術的組合。以下是如何獲得所需結果:在Python中,split()方法根據指定的分隔符號將字串劃分為列表。預設情況下,它會按空格字元進行分割,但您也可以傳遞可選的分隔符號。 要刪除 \t 字元及...
    程式設計 發佈於2024-11-08
  • Wagtail 以程式設計方式建立頁面翻譯
    Wagtail 以程式設計方式建立頁面翻譯
    我找不到任何程式介面來建立頁面翻譯。所有邏輯似乎都在 wagtail.contrib.simple_translation.views. 的 SubmitTranslationView 中實現 因此,以程式設計方式存取這些內容的唯一方法是模擬存取視圖的請求。我將其包裝在一個名為translate_p...
    程式設計 發佈於2024-11-08
  • Java 切換初學者指南
    Java 切換初學者指南
    Java Switching 在 Java 中引入了 Switch 語句的概念,為複雜的 if-else 鏈提供了替代方案。 Switch 語句可讓您將一個變數與多個可能的值進行比較,從而使您的程式碼更有效率且可讀。 本指南涵蓋了語法、不同資料類型的用法以及在 Java 中實現 switch 語...
    程式設計 發佈於2024-11-08
  • 如何修正 getMonth() 函數以在 JavaScript 中傳回正確的月份?
    如何修正 getMonth() 函數以在 JavaScript 中傳回正確的月份?
    JavaScript 中的getMonth() 函數傳回上個月在JavaScript 中,getMonth() 方法傳回指定日期的月份,從從0(一月)開始。但是,當與格式為“Sun Jul 7 00:00:00 EDT 2013”​​的日期一起使用時,它可以提供上個月而不是預期的月份。 這是因為 g...
    程式設計 發佈於2024-11-08

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

Copyright© 2022 湘ICP备2022001581号-3