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.

注意:cacheAsTexture 是 PixiJS v8 中与之前的 cacheAsBitmap 功能相同的功能。如果你从 v7 或更早版本迁移,只需在代码中将 cacheAsBitmap 替换为 cacheAsTexture

¥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.

使用示例 此处

¥Play around with the example here.

高级用法

¥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 是纹理的分辨率。默认情况下,这与你的渲染器或应用相同。

    ¥resolution is the resolution of the texture. By default this is the same as you renderer or application.

  • antialias 是用于纹理的抗锯齿模式。与分辨率非常相似,这默认为渲染器或应用抗锯齿模式。

    ¥antialias is the antialias mode to use for the texture. Much like the resolution this defaults to the renderer or application antialias mode.


cacheAsTexture 的优势

¥Benefits of cacheAsTexture

  • 性能提升:将复杂容器渲染为单个纹理可避免在每帧期间单独处理每个子元素。

    ¥Performance Boost: Rendering a complex container as a single texture avoids the need to process each child element individually during each frame.

  • 针对静态内容进行了优化:非常适合具有静态或很少更新子项的容器。

    ¥Optimized for Static Content: Ideal for containers with static or rarely updated children.


高级细节

¥Advanced Details

  • 内存权衡:每个缓存的纹理都需要 GPU 内存。使用 cacheAsTexture 会牺牲渲染速度以换取增加的内存使用量。

    ¥Memory Tradeoff: Each cached texture requires GPU memory. Using cacheAsTexture trades rendering speed for increased memory usage.

  • GPU 限制:如果你的容器太大(例如,超过 4096x4096 像素),纹理可能无法缓存,具体取决于 GPU 限制。

    ¥GPU Limitations: If your container is too large (e.g., over 4096x4096 pixels), the texture may fail to cache, depending on GPU limitations.


内部工作原理

¥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 面板。

    ¥Use for Static Content: Apply cacheAsTexture to containers with elements that don't change frequently, such as a UI panel with static decorations.

  • 性能优势:使用 cacheAsTexture 将复杂容器渲染为单个纹理,从而减少每帧单独处理每个子元素的开销。这对于包含昂贵效果(例如过滤器)的容器特别有用。

    ¥Leverage for Performance: Use cacheAsTexture to render complex containers as a single texture, reducing the overhead of processing each child element individually every frame. This is especially useful for containers that contain expensive effects eg filters.

  • 抗锯齿切换:将抗锯齿设置为 false 可以稍微提高性能,但纹理在其子项边缘周围可能看起来更像素化。

    ¥Switch of Antialiasing: setting antialiasing to false can give a small performance boost, but the texture may look a bit more pixelated around its children's edges.

  • 分辨率:请根据你的情况调整分辨率,如果缩小了某些东西,则可以使用较低的分辨率。如果放大了某些东西,则可能需要使用更高的分辨率。但请注意,分辨率越高,纹理和内存占用就越大。

    ¥Resolution: Do adjust the resolution based on your situation, if something is scaled down, you can use a lower resolution.If something is scaled up, you may want to use a higher resolution. But be aware that the higher the resolution the larger the texture and memory footprint.

DON'T:

  • 应用于非常大的容器:避免在过大的容器上使用 cacheAsTexture(例如,超过 4096x4096 像素),因为它们可能会因 GPU 限制而无法缓存。而是将它们拆分成更小的容器。

    ¥Apply to Very Large Containers: Avoid using cacheAsTexture on containers that are too large (e.g., over 4096x4096 pixels), as they may fail to cache due to GPU limitations. Instead, split them into smaller containers.

  • 过度使用动态内容:在容器上频繁打开/关闭 cacheAsTexture,因为这会导致不断重新缓存,从而抵消其好处。最好在一次缓存时将其作为纹理,然后使用 updateCacheTexture 来更新它。

    ¥Overuse for Dynamic Content: Flick cacheAsTexture on / off frequently on containers, as this results in constant re-caching, negating its benefits. Its better to Cache as texture when you once, and then use updateCacheTexture to update it.

  • 应用于稀疏内容:不要将 cacheAsTexture 用于元素很少或内容稀疏的容器,因为性能改进将微不足道。

    ¥Apply to Sparse Content: Do not use cacheAsTexture for containers with very few elements or sparse content, as the performance improvement will be negligible.

  • 忽略内存影响:注意 GPU 内存使用情况。每个缓存的纹理都会消耗内存,因此过度使用 cacheAsTexture 会导致资源限制。

    ¥Ignore Memory Impact: Be cautious of GPU memory usage. Each cached texture consumes memory, so overusing cacheAsTexture can lead to resource constraints.


陷阱

¥Gotchas

  • 渲染取决于场景可见性:缓存仅在渲染包含场景时更新。在设置 cacheAsTexture 之后但在渲染场景之前修改布局将反映在缓存中。

    ¥Rendering Depends on Scene Visibility: The cache updates only when the containing scene is rendered. Modifying the layout after setting cacheAsTexture but before rendering your scene will be reflected in the cache.

  • 容器渲染时没有变换:缓存的项目以其实际大小渲染,忽略缩放等变换。例如,缩小 50% 的项目,其纹理将以 100% 大小缓存,然后按场景缩小。

    ¥Containers are rendered with no transform: Cached items are rendered at their actual size, ignoring transforms like scaling. For instance, an item scaled down by 50%, its texture will be cached at 100% size and then scaled down by the scene.

  • 缓存和过滤器:过滤器可能无法按照预期与 cacheAsTexture 一起运行。要缓存滤镜效果,请将项目封装在父容器中,并将 cacheAsTexture 应用于父容器。

    ¥Caching and Filters: Filters may not behave as expected with cacheAsTexture. To cache the filter effect, wrap the item in a parent container and apply cacheAsTexture to the parent.

  • 重复使用纹理:如果你想基于容器创建新的纹理,最好使用 const texture = renderer.generateTexture(container) 并在你的对象之间共享它!

    ¥Reusing the texture: If you want to create a new texture based on the container, its better to use const texture = renderer.generateTexture(container) and share that amongst you objects!

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

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