Skip to main content

缓存为纹理

🌐 Cache As Texture

在 PixiJS 中使用 cacheAsTexture

🌐 Using cacheAsTexture in PixiJS

PixiJS 中的 cacheAsTexture 功能是优化应用渲染的强大工具。通过将容器及其子元素渲染到纹理,cacheAsTexture 可以显著提高静态或不频繁更新的容器的性能。让我们探讨如何有效使用它,以及它的优点和注意事项。

🌐 The cacheAsTexture function in PixiJS is a powerful tool for optimizing rendering in your applications. By rendering a container and its children to a texture, cacheAsTexture can significantly improve performance for static or infrequently updated containers. Let's explore how to use it effectively, along with its benefits and considerations.

Note

cacheAsTexture is PixiJS v8's equivalent of the previous cacheAsBitmap functionality. If you're migrating from v7 or earlier, simply replace cacheAsBitmap with cacheAsTexture in your code.


cacheAsTexture是什么?

🌐 What Is cacheAsTexture?

当你设置 container.cacheAsTexture() 时,容器会被渲染到一个纹理上。随后渲染会重用这个纹理,而不是渲染容器中的所有单独子元素。这种方法对于拥有许多静态元素的容器特别有用,因为它可以减少渲染工作量。

🌐 When you set container.cacheAsTexture(), the container is rendered to a texture. Subsequent renders reuse this texture instead of rendering all the individual children of the container. This approach is particularly useful for containers with many static elements, as it reduces the rendering workload.

要在对容器进行更改后更新纹理,请调用:

🌐 To update the texture after making changes to the container, call:

container.updateCacheTexture();

要关闭它,请调用:

🌐 and to turn it off, call:

container.cacheAsTexture(false);

基本用法

🌐 Basic Usage

这里有一个示例,演示如何使用 cacheAsTexture

🌐 Here's an example that demonstrates how to use cacheAsTexture:

import * as PIXI from 'pixi.js';

(async () => {
// Create a new application
const app = new Application();

// Initialize the application
await app.init({ background: '#1099bb', resizeTo: window });

// Append the application canvas to the document body
document.body.appendChild(app.canvas);

// load sprite sheet..
await Assets.load('https://pixi.nodejs.cn/assets/spritesheet/monsters.json');

// holder to store aliens
const aliens = [];
const alienFrames = ['eggHead.png', 'flowerTop.png', 'helmlok.png', 'skully.png'];

let count = 0;

// create an empty container
const alienContainer = new Container();

alienContainer.x = 400;
alienContainer.y = 300;

app.stage.addChild(alienContainer);

// add a bunch of aliens with textures from image paths
for (let i = 0; i < 100; i++) {
const frameName = alienFrames[i % 4];

// create an alien using the frame name..
const alien = Sprite.from(frameName);

alien.tint = Math.random() * 0xffffff;

alien.x = Math.random() * 800 - 400;
alien.y = Math.random() * 600 - 300;
alien.anchor.x = 0.5;
alien.anchor.y = 0.5;
aliens.push(alien);
alienContainer.addChild(alien);
}

// this will cache the container and its children as a single texture
// so instead of drawing 100 sprites, it will draw a single texture!
alienContainer.cacheAsTexture();
})();

在这个示例中,container及其子对象被渲染到一个纹理上,从而在绘制场景时降低渲染开销。

🌐 In this example, the container and its children are rendered to a single texture, reducing the rendering overhead when the scene is drawn.

高级用法

🌐 Advanced Usage

你可以传递与纹理源选项非常相似的配置对象,而不是使用 true 启用 cacheAsTexture。

🌐 Instead of enabling cacheAsTexture with true, you can pass a configuration object which is very similar to texture source options.

container.cacheAsTexture({
resolution: 2,
antialias: true,
});
  • resolution 是纹理的分辨率。默认情况下,它与你的渲染器或应用相同。
  • antialias 是用于纹理的抗锯齿模式。就像分辨率一样,它默认为渲染器或应用的抗锯齿模式。

cacheAsTexture 的好处

🌐 Benefits of cacheAsTexture

  • 性能提升:将复杂的容器渲染为单一纹理可以避免在每一帧中单独处理每个子元素的需要。
  • 针对静态内容优化:非常适合包含静态或很少更新子内容的容器。

高级细节

🌐 Advanced Details

  • 内存权衡:每个缓存的纹理都需要 GPU 内存。使用 cacheAsTexture 会以增加内存使用量为代价换取渲染速度。
  • GPU 限制:如果你的容器太大(例如,超过 4096x4096 像素),纹理可能无法缓存,这取决于 GPU 的限制。

内部工作原理

🌐 How It Works Internally

在底层,cacheAsTexture 将容器转换为渲染组并渲染到纹理。它使用与滤镜相同的纹理缓存机制:

🌐 Under the hood, cacheAsTexture converts the container into a render group and renders it to a texture. It uses the same texture cache mechanism as filters:

container.enableRenderGroup();
container.renderGroup.cacheAsTexture = true;

一旦纹理被缓存,通过 updateCacheTexture() 更新它是高效的,并且几乎没有开销。它的速度和正常渲染容器一样快。

🌐 Once the texture is cached, updating it via updateCacheTexture() is efficient and incurs minimal overhead. Its as fast as rendering the container normally.


最佳实践

🌐 Best Practices

🌐 DO:

  • 用于静态内容:将 cacheAsTexture 应用于包含不经常更改元素的容器,例如具有静态装饰的 UI 面板。
  • 性能杠杆:使用 cacheAsTexture 将复杂的容器渲染为单个纹理,减少每帧分别处理每个子元素的开销。这对于包含昂贵效果(例如滤镜)的容器尤其有用。
  • 抗锯齿开关:将抗锯齿设置为关闭可以获得小幅性能提升,但纹理在其子对象的边缘处可能会显得稍微有些像素化。
  • 分辨率:请根据你的情况调整分辨率,如果某些内容被缩小,可以使用较低的分辨率。如果某些内容被放大,你可能需要使用更高的分辨率。但请注意,分辨率越高,纹理和内存占用越大。

不要

🌐 DON'T:

  • 适用于超大容器:避免在过大的容器(例如超过 4096x4096 像素)上使用 cacheAsTexture,因为它们可能由于 GPU 限制而无法缓存。相反,应将它们拆分为较小的容器。
  • 动态内容的过度使用:频繁地在容器上开关 cacheAsTexture,会导致不断重新缓存,从而抵消其好处。更好的做法是先将其缓存为纹理,然后使用 updateCacheTexture 来更新它。
  • 应用于稀疏内容:不要在元素很少或内容稀疏的容器中使用 cacheAsTexture,因为性能提升将微不足道。
  • 忽略内存影响:注意 GPU 内存的使用。每个缓存的纹理都会消耗内存,因此过度使用 cacheAsTexture 可能会导致资源受限。

陷阱

🌐 Gotchas

  • 渲染取决于场景可见性:缓存仅在包含的场景被渲染时更新。在设置 cacheAsTexture 后但在渲染场景之前修改布局,将会反映在缓存中。
  • 容器以无变换方式渲染:缓存的项目按照其实际大小进行渲染,忽略诸如缩放之类的变换。例如,一个缩小50%的项目,其纹理将以100%的大小缓存,然后再由场景进行缩小。
  • 缓存与过滤器:过滤器在 cacheAsTexture 中可能不会按预期工作。要缓存过滤器效果,请将该项目封装在父容器中,并将 cacheAsTexture 应用于父容器。
  • 重用纹理:如果你想基于容器创建一个新纹理,最好使用 const texture = renderer.generateTexture(container) 并在你的对象之间共享它!

通过战略性地理解和应用 cacheAsTexture,你可以显著提升 PixiJS 项目的渲染性能。祝编码愉快!

🌐 By understanding and applying cacheAsTexture strategically, you can significantly enhance the rendering performance of your PixiJS projects. Happy coding!