Skip to main content

纹理


我们正在慢慢地从高水平下降到低水平。 我们已经讨论了场景图,以及其中的显示对象。 我们即将讨论精灵和其他简单的显示对象。 但在此之前,我们需要先讨论一下纹理。

英:We're slowly working our way down from the high level to the low. We've talked about the scene graph, and in general about display objects that live in it. We're about to get to sprites and other simple display objects. But before we do, we need to talk about textures.

在 PixiJS 中,纹理是显示对象使用的核心资源之一。 从广义上讲,纹理表示用于填充屏幕上某个区域的像素源。 最简单的例子是精灵 - 一个完全填充有单个纹理的矩形。 但事情可能会变得更加复杂。

英:In PixiJS, textures are one of the core resources used by display objects. A texture, broadly speaking, represents a source of pixels to be used to fill in an area on the screen. The simplest example is a sprite - a rectangle that is completely filled with a single texture. But things can get much more complex.

纹理的生命周期

让我们通过跟踪图片数据到达屏幕的路径来检查纹理的实际工作原理。

英:Let's examine how textures really work, by following the path your image data travels on its way to the screen.

这是我们要遵循的流程: 源图片 > 加载器 > 基础纹理 > 纹理

英:Here's the flow we're going to follow: Source Image > Loader > BaseTexture > Texture

服务形象

首先,你拥有要显示的图片。 第一步是使其在你的服务器上可用。 这看起来似乎是显而易见的,但如果你从其他游戏开发系统转向 PixiJS,那么值得记住的是,所有内容都必须通过网络加载。 如果你在本地进行开发,请注意你必须使用网络服务器进行测试,否则由于浏览器对待本地文件安全的方式,你的图片将无法加载。

英:To start with, you have the image you want to display. The first step is to make it available on your server. This may seem obvious, but if you're coming to PixiJS from other game development systems, it's worth remembering that everything has to be loaded over the network. If you're developing locally, please be aware that you must use a webserver to test, or your images won't load due to how browsers treat local file security.

加载图片

要使用图片,第一步是将图片文件从网络服务器提取到用户的网络浏览器中。 为此,我们可以使用 PIXI.Texture.from(),它适用于快速演示,但在生产中你将使用 Loader 类。 Loader 使用 <IMG> 元素进行封装和管理,告诉浏览器获取图片,然后在完成时通知你。 此过程是异步的 - 你请求加载,然后时间过去,然后触发事件让你知道加载已完成。 我们将在后面的指南中更深入地介绍加载程序。

英:To work with the image, the first step is to pull the image file from your webserver into the user's web browser. To do this, we can use PIXI.Texture.from(), which works for quick demos, but in production you'll use the Loader class. A Loader wraps and manages using an <IMG> element to tell the browser to fetch the image, and then notifies you when that has been completed. This process is asynchronous - you request the load, then time passes, then an event fires to let you know the load is completed. We'll go into the loader in a lot more depth in a later guide.

BaseTextures 拥有数据

一旦加载器完成其工作,加载的 <IMG> 元素就包含我们需要的像素数据。 但要使用它来渲染某些内容,PixiJS 必须获取原始图片文件并将其上传到 GPU。 这给我们带来了纹理系统的真正主力 - BaseTexture 类。 每个 BaseTexture 管理一个像素源 - 通常是图片,但也可以是 Canvas 或 Video 元素。 BaseTextures 允许 PixiJS 将图片转换为像素并在渲染中使用这些像素。 此外,它还包含控制纹理数据渲染方式的设置,例如环绕模式(对于 0.0-1.0 范围之外的 UV 坐标)和缩放模式(缩放纹理时使用)。

英:Once the Loader has done its work, the loaded <IMG> element contains the pixel data we need. But to use it to render something, PixiJS has to take that raw image file and upload it to the GPU. This brings us to the real workhorse of the texture system - the BaseTexture class. Each BaseTexture manages a single pixel source - usually an image, but can also be a Canvas or Video element. BaseTextures allow PixiJS to convert the image to pixels and use those pixels in rendering. In addition, it also contains settings that control how the texture data is rendered, such as the wrap mode (for UV coordinates outside the 0.0-1.0 range) and scale mode (used when scaling a texture).

BaseTexture 会自动缓存,因此对同一 URL 重复调用 PIXI.Texture.from() 每次都会返回相同的 BaseTexture。 销毁 BaseTexture 会释放与其关联的图片数据。

英:BaseTextures are automatically cached, so that calling PIXI.Texture.from() repeatedly for the same URL returns the same BaseTexture each time. Destroying a BaseTexture frees the image data associated with it.

纹理是 BaseTextures 上的视图

最后,我们来到 PIXI.Texture 类本身! 此时,你可能想知道纹理对象的作用。 毕竟,BaseTexture 管理像素和渲染设置。 答案是,它的作用并不大。 纹理是底层 BaseTexture 上的轻量级视图。 它们的主要属性是从中拉取的 BaseTexture 内的源矩形。

英:So finally, we get to the PIXI.Texture class itself! At this point, you may be wondering what the Texture object does. After all, the BaseTexture manages the pixels and render settings. And the answer is, it doesn't do very much. Textures are light-weight views on an underlying BaseTexture. Their main attribute is the source rectangle within the BaseTexture from which to pull.

如果 PixiJS 绘制的所有内容都是精灵,那将是相当多余的。 但考虑 SpriteSheets。 SpriteSheet 是一个包含多个精灵图片的单个图片。 在 精灵表 对象中,单个 BaseTexture 由一组纹理引用,每个纹理对应原始精灵表中的每个源图片。 通过共享单个 BaseTexture,浏览器仅下载一个文件,并且我们的批处理渲染器可以快速绘制精灵,因为它们都共享相同的底层像素数据。 SpriteSheet 的纹理仅拉出每个精灵所需的像素矩形。

英:If all PixiJS drew were sprites, that would be pretty redundant. But consider SpriteSheets. A SpriteSheet is a single image that contains multiple sprite images arranged within. In a Spritesheet object, a single BaseTexture is referenced by a set of Textures, one for each source image in the original sprite sheet. By sharing a single BaseTexture, the browser only downloads one file, and our batching renderer can blaze through drawing sprites since they all share the same underlying pixel data. The SpriteSheet's Textures pull out just the rectangle of pixels needed by each sprite.

这就是为什么我们同时拥有纹理和基础纹理 - 允许精灵表、动画、按钮状态等作为单个图片加载,同时仅显示主图片中所需的部分。

英:That is why we have both Textures and BaseTextures - to allow sprite sheets, animations, button states, etc to be loaded as a single image, while only displaying the part of the master image that is needed.

加载纹理

我们将在后面的指南中讨论资源加载,但新用户在构建 PixiJS 项目时面临的最常见问题之一是如何最好地加载纹理。 正如我们在演示片段中所做的那样,使用 PIXI.Texture.from() 是可行的,但会导致在加载每个纹理时弹出窗口,而对象已在场景图中渲染。

英:We will discuss resource loading in a later guide, but one of the most common issues new users face when building a PixiJS project is how best to load their textures. Using PIXI.Texture.from() as we do in our demo snippets will work, but will result in pop-in as each texture is loaded while your objects are already being rendered in the scene graph.

相反,这里有一个好的解决方案的快速备忘单:

英:Instead, here's a quick cheat sheet of one good solution:

  1. 显示加载图片
  2. 创建一个加载器
  3. 运行所有基于纹理的对象,将它们的纹理添加到加载器
  4. 启动加载程序,并可选择根据进度回调更新加载图片
  5. 加载完成后,运行所有对象并使用 PIXI.Texture.from() 将加载的纹理从纹理缓存中提取出来
  6. 准备你的纹理(可选 - 见下文)
  7. 隐藏加载图片,开始渲染场景图

使用此工作流程可确保你的纹理已预先加载,以防止弹出,并且相对容易编码。

英:Using this workflow ensures that your textures are pre-loaded, to prevent pop-in, and is relatively easy to code.

关于准备纹理: 即使在加载纹理之后,图片仍然需要被推送到 GPU 并进行解码。 对大量源图片执行此操作可能会很慢,并且在项目首次加载时会导致延迟峰值。 为了解决这个问题,你可以使用 准备 插件,它允许你在显示项目之前的最后一步中预加载纹理。

英:Regarding preparing textures: Even after you've loaded your textures, the images still need to be pushed to the GPU and decoded. Doing this for a large number of source images can be slow and cause lag spikes when your project first loads. To solve this, you can use the Prepare plugin, which allows you to pre-load textures in a final step before displaying your project.

卸载纹理

使用完纹理后,你可能希望释放它使用的内存(WebGL 管理的缓冲区和基于浏览器的缓冲区)。 为此,你应该在拥有数据的 BaseTexture 上调用 destroy()。 请记住,纹理不管理像素数据!

英:Once you're done with a Texture, you may wish to free up the memory (both WebGL-managed buffers and browser-based) that it uses. To do so, you should call destroy() on the BaseTexture that owns the data. Remember that Textures don't manage pixel data!

对于短暂的图片(例如大型且仅使用一次的过场动画)来说,这是一个特别好的主意。 如果你想删除所有纹理并将石板擦干净,可以使用 PIXI.utils.destroyTextureCache() 功能。

英:This is a particularly good idea for short-lived imagery like cut-scenes that are large and will only be used once. If you want to remove all textures and wipe the slate clean, you can use the PIXI.utils.destroyTextureCache() function.

超越图片

正如我们上面提到的,你不仅可以使用图片来制作纹理:

英:As we alluded to above, you can make a Texture out of more than just images:

视频: 将 HTML5 <VIDEO> 元素传递给 PIXI.BaseTexture.from() 以允许你在项目中显示视频。 由于它是纹理,因此你可以对其进行着色、添加滤镜,甚至将其应用到自定义几何体。

英:Video: Pass an HTML5 <VIDEO> element to PIXI.BaseTexture.from() to allow you to display video in your project. Since it's a texture, you can tint it, add filters, or even apply it to custom geometry.

画布: 同样,你可以将 HTML5 <CANVAS> 元素封装在 BaseTexture 中,以便你使用 canvas 的绘制方法动态创建纹理。

英:Canvas: Similarly, you can wrap an HTML5 <CANVAS> element in a BaseTexture to let you use canvas's drawing methods to dynamically create a texture.

SVG: 传入 <SVG> 元素或加载 .svg URL,PixiJS 将尝试对其进行光栅化。 对于网络高度受限的项目,这可以以最短的网络加载时间实现漂亮的图形。

英:SVG: Pass in an <SVG> element or load a .svg URL, and PixiJS will attempt to rasterize it. For highly network-constrained projects, this can allow for beautiful graphics with minimal network load times.

渲染纹理: 一个更高级(但非常强大!)的功能是从 RenderTexture 构建纹理。 这可以允许使用 几何学 对象构建复杂的几何体,然后将该几何体烘焙为简单的纹理。

英:RenderTexture: A more advanced (but very powerful!) feature is to build a Texture from a RenderTexture. This can allow for building complex geometry using a Geometry object, then baking that geometry down to a simple texture.

这些纹理源中的每一个都有我们无法在本指南中涵盖的注意事项和细微差别,但它们应该让你感受到 PixiJS 纹理系统的强大功能。

英:Each of these texture sources has caveats and nuances that we can't cover in this guide, but they should give you a feeling for the power of PixiJS's texture system.

看看 渲染纹理示例代码

英:Check out the render texture example code.