利用先进的策略和技术将您的 PixiJS 应用程序提升到新的水平
这篇文章介绍了在 CPU / 内存方面可以最好地优化 pixiJS 中多个元素的渲染的不同方法。例如,考虑在没有任何缓存的情况下重新渲染每一帧(在 CPU 使用率方面表现良好)或将渲染的图形缓存在内存中之间的差异。这将根据场景中的图形数量按比例增加内存使用量。
有许多策略可以处理此类优化。特别值得注意的是面向数据的设计,它提出了一组与更传统的常见面向对象编程方式完全不同的方法。
其他主要方法包括:例如,剔除和利用更加结构化的格式 - C# 中的 NativeArrays 和 TypeScript 中的 TypedArrays。这些将允许更好地管理内存缓冲区,这可能会限制缓存未命中,但这也需要大量的工程经验和/或定制。
在这篇文章中,我将重点介绍一种使用 PixiJS 优化 WebGL 环境的工作方法:面向对象的方法,包括最佳实践。这将为您提供一种组织良好的方法来提高 PixiJS 应用程序的速度和效率。
在我的下一篇文章中,我将讨论另一种强大的优化方法:实体组件系统方法。 ECS 方法非常以数据为导向,并且在高性能环境中优化 PixiJS 时提供了全新的外观。继续在 Medium 上阅读本文,我将深入探讨 ECS 方法的本质。
永远记住,为了优化和进一步增强 Pixi 应用程序的性能,总有一些事情可以做得更好。更好并不意味着最优化或最快。最佳解决方案是在优化投入的时间和投资回报之间进行权衡的问题,以确保您能够满足项目期限,但有足够的优化来满足任何潜在用户的需求,而不会过度扩展您的资源。
在本节中,我将指导您了解优化 PixiJS 应用程序的最佳方法。
此部分基于官方提示,值得查看!
我们的其余讨论将围绕 Pixi 图形、精灵、网格以及何时使用粒子容器而不是默认的 Pixi 容器。本章应该让您清楚地了解如何在面向对象的上下文中最佳地使用所有内容,以便您的 PixiJS 项目正常运行并以最高的效率进行渲染。
为了有效地使用 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 如何处理和渲染应用程序中的图形。
让我们通过在 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 对象共享相同的宽度和高度,我们可以通过重用几何体进行优化。
传递 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此方法通过引用相同的几何图形而不是为每个对象重复它,显着减少了内存使用量。
在一个图形对象中绘制所有内容
对于静态图形或复杂结构,在单个 Graphics 对象中绘制所有元素是另一种优化技术:
const graphics = new PIXI.Graphics(); // Draw 100 circles using the same PIXI.Graphics instance for (let i = 0; i在这种方法中,我们不是创建新的 Graphics 对象,而是将新的几何图形添加到单个 Graphics 实例的 GeometryList 中。此方法对于更复杂的图形结构特别有效。
在 PixiJS 中利用 CacheAsBitmap 的强大功能
PixiJS 中最强大的功能之一是 CacheAsBitmap。本质上,它让引擎像精灵一样处理图形。在某些情况下,这可以显着提高性能。
仅当对象不经常更新时才使用 CacheAsBitmap。
大批量的图形可以作为位图缓存在容器中。 pixi 将拍摄快照并将其预渲染为位图,而不是重新渲染 100 个图形。
始终考虑内存使用情况,缓存位图正在使用大量内存。
应该明智地使用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 的内存效率时,精灵通常比图形更具优势。当处理共享相同形状或纹理的多个对象时,这一点尤其明显。让我们回顾一下创建 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;使用此方法,.tint() 允许您在不触发完全重新渲染的情况下为精灵着色,因为色调将作为附加着色器效果直接应用在 GPU 上。
在粒子容器中使用 100k 精灵
为了说明此技术的威力,想象一下运行 100,000 个具有随机色调的单独精灵,每个精灵在每一帧上进行变换,同时保持平滑的 60 FPS。
为了进一步阅读有关优化 PixiJS 的内容,我强烈推荐 PixiJS 的原始创建者之一撰写的一篇富有洞察力的文章,该文章深入研究了 renderTexture 技术。
你可以在这里找到它
哇! 如果您已经做到了这一步,我真诚地感谢您在深入研究 PixiJS 优化过程中与我一起坚持。我希望您发现这里分享的见解和技术对您的项目有价值。请继续关注我的下一篇文章,我将更详细地探讨实体组件系统 (ECS) 方法和 NativeArrays 的强大功能。这些方法将使您的 PixiJS 应用程序的性能和效率达到新的高度。感谢您的阅读,我们下一篇再见!
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3