纹理
我们正在缓慢地从高层级过渡到低层级。我们已经讨论了场景图,以及通常存在于其中的显示对象。我们即将接触精灵和其他简单显示对象。但在进行之前,我们需要讨论一下纹理。
在 PixiJS 中,纹理是显示对象使用的一项核心资源。广义上讲,纹理表示一个像素源,用来填充屏幕上的一个区域。最简单的示例是精灵 - 一个完全填充有单个纹理的矩形。但情况可能会变得更加复杂。
纹理的生命周期
让我们通过跟踪图像数据在传输到屏幕途中所经过的路径,来研究纹理的实际工作方式。
下面是我们即将遵循的流程:源图像 > 加载程序 > 基本纹理 > 纹理
提供图像
首先,你拥有要显示的图像。第一步是将其放在服务器上。这可能显而易见,但如果你从其他游戏开发系统转到 PixiJS,那么值得记住的是,所有内容都必须通过网络加载。如果你在本地开发,请注意你必须使用 Web 服务器进行测试,否则你的图像将无法加载,原因是浏览器对本地文件安全性的处理方式。
加载图像
开始使用图片时,第一步是将图片文件从网络服务器中拉到用户的网络浏览器的中。为此,我们可以使用 Assets.load('myTexture.png')
。Assets
对需要指示浏览器抓取图片、转换图片并告诉你何时完成这些操作进行封装和处理。该过程是异步的- 你请求加载,然后一段时间后,有一个承诺完成并让你知道加载已完成。我们会在后面的指南中更深入地探讨加载器。
const texture = await Assets.load('myTexture.png');
// pass a texture explicitly
const sprite = new Sprite(texture);
// as options
const sprite2 = new Sprite({texture});
// from the cache as the texture is loaded
const sprite3 = Sprite.from('myTexture.png')
TextureSources 拥有自己的数据
材质加载完成后,已加载的 <IMG>
元素将包含我们需要的像素数据。但若要使用它来渲染一些内容,PixiJS 必须获取该原始图片文件并将其上传到 GPU。这就引出了纹理系统中的真正主力 - TextureSource 类。每个 TextureSource 管理一个像素源 - 通常是一个图片,但也可能是一个画布或视频元素。TextureSource 允许 PixiJS 将图片转换成像素,并在渲染中使用这些像素。此外,它还包含控制如何渲染纹理数据的设置,例如,包装模式(用于低于 0.0-1.0 范围的 UV 坐标)和缩放模式(用于缩放一个纹理)。
TextureSource 会被自动缓存,因此,针对相同的 URL 重复调用 Texture.from()
将每次返回同一个 TextureSource。销毁一个 TextureSource 将释放与它关联的图片数据。
纹理是 BaseTextures 的视图
最后,我们终于看到了 Texture
类本身!此时,你可能想知道 Texture
对象做了些什么。毕竟,BaseTexture 管理着像素和渲染设置。答案是,它没有做什么。纹理是基础 BaseTexture 上轻量级的视图。它们的主要属性是从中提取的 TextureSource 中的源矩形。
如果 PixiJS 绘制的所有内容都是精灵,那么这将会非常冗余。但我们考虑一下 精灵表。精灵表是一个图片,其中包含多个精灵图片。在 Spritesheet 对象中,一组 Textures 引用一个 TextureSource,每个 Textures 对应原始精灵表中的每个源图片。通过共享一个 TextureSource,浏览器只会下载一个文件,而且我们的批处理渲染器可以通过绘制精灵来大放异彩,因为它们都共享相同的基础像素数据。精灵表的 Textures 仅提取每个精灵需要的像素矩形。
这就是我们既有纹理又有纹理源的原因 - 允许精灵页、动画、按钮状态等被加载为单个图像,同时仅显示所需的主图像部分。
加载纹理
我们将在后续指南中讨论资源加载,但新用户在构建 PixiJS 项目时面临的最常见问题之一是如何最好地加载他们的纹理。
这里有一个很好的解决方案快速秘籍
- 显示加载图像
- 使用 Assets 确保加载所有纹理
- 根据进度回调可选更新加载图像
- 在加载程序完成时,运行所有对象并使用
Texture.from()
从纹理高速缓存中提取加载的纹理 - 准备纹理(可选 - 参见下文)
- 隐藏加载图像,开始渲染场景图
使用此工作流可确保预加载纹理,以防止弹出,且相对容易编写代码。
关于准备纹理:即使您已经加载了纹理,仍然需要将图像推送到 GPU 并解码。对于大量源图像这样做可能会很慢,并在您的项目首次加载时导致延迟高峰。要解决此问题,可以使用 Prepare 插件,该插件允许您在显示项目之前的最后一步预加载纹理。
卸载纹理
完成纹理后,您可能希望释放它使用的内存(包括 WebGL 管理的缓冲区和基于浏览器的)。为此,您应该对拥有数据的 BaseTexture 调用 destroy()
。请记住,纹理不管理像素数据!
对于像过场动画这样的短时图像非常不错,因为它们庞大且仅使用一次。如果通过 Assets
加载纹理被销毁,那么资产类会自动为您从高速缓存中移除它。
图像之外
正如我们上面提到的,您还可以通过不仅仅是图像来制作纹理
视频:将 HTML5 <VIDEO>
元素传递给 TextureSource.from()
以允许您在项目中显示视频。由于它是纹理,您可以给它着色,添加滤镜,甚至将它应用于自定义几何体。
画布:同样,您可以在 BaseTexture 中包装 HTML5 <CANVAS>
元素,以允许您使用画布的绘图方法动态创建纹理。
SVG:传入 <SVG>
元素或加载 .svg URL,PixiJS 将尝试对其进行栅格化。对于网络受限的项目,这可以让您使用最少的网络加载时间获得精美的图形。
RenderTexture:一个更高级(但非常强大!)的功能是从一个 RenderTexture 构建一个纹理。这可以使用 Geometry 对象构建复杂几何图形,然后将该几何图形合成到一个简单的纹理中。
在本文档中,我们无法涵盖这些纹理源的每一个警告事项和细微差别,但它们应该能让你了解 PixiJS 纹理系统的强大功能。
查看 渲染纹理示例代码。