来自 LibGDX 中的 texturepacker 的纹理

2022-01-12 00:00:00 textures android java libgdx texturepacker

尝试了解(很棒的)LibGDX 框架中的纹理包装器,我需要帮助.

Trying get my head around the texture wrapper in (the awesome) LibGDX framework and I need help.

我想绑定一个纹理(根据 Mesh, Color & Texture) 是从使用 TexturePacker 打包的 TextureAtlas 中提取的.纹理绑定到一个矩形网格.

I would like to bind a texture (according to Mesh, Color & Texture) that is extracted from a TextureAtlas packed with the TexturePacker. The texture is binding to a rectangular mesh.

我希望基本上从打包文件中提取纹理(纹理的实例).

I want the texture (instance of Texture) to basically be extracted from a packed file.

是否可以使用 createsprite 或 findregion 方法并以某种方式跳过文件句柄步骤?

Is it doable to use a the createsprite or findregion methods and somehow skip the filehandle step?

另外:将上述方法与 AssetManager 结合使用时,有什么特别需要注意的吗?

Additionally: Anything special one should keep in mind when combining the above method with the AssetManager?

谢谢你帮我整理!

推荐答案

创建TextureRegion

首先,通过指向描述图集的文本文件创建一个 TextureAtlas 对象(创建图集的工具将创建两个文件:一个图像和一个描述其内容的文本文件):

Create the TextureRegion

First, you create a TextureAtlas object by pointing at the text file that describes your atlas (the tool that creates the atlas will create two files: an image and a text file describing its contents):

TextureAtlas myTextures = new TextureAtlas("images/packed.txt");

然后你可以在那个图集中查找一个TextureRegion(也就是图集中的特定子纹理).该区域应该具有所使用的原始文件的基本名称(如果您遵循一些特殊的命名约定来创建纹理元素数组,则会有更多详细信息和选项,但暂时不要这样做):

Then you can look up a TextureRegion in that atlas (that is, a specific sub-texture of the atlas). The region should have the basename of the original file that was used (there are more details and options if you follow some of the special naming conventions to create arrays of texture elements, but leave that off for now):

TextureRegion region = myTextures.findRegion(fname);

配置纹理网格

要在网格上绘制此纹理区域,您需要初始化 Mesh 以支持纹理坐标:

Mesh myMesh = new Mesh(...,
                       new VertexAttribute(Usage.TextureCoordinates, 2, "y"));

new VertexAttribute(Usage.TextureCoordinates, 2, ...) 告诉 libGDX 这个网格每个顶点有两个纹理坐标(传统上,这两个纹理坐标称为 uv).每个顶点可以有一堆不同的属性,但我假设唯一的其他属性是 x,y,z 空间坐标的 3 值 Usage.Position.

The new VertexAttribute(Usage.TextureCoordinates, 2, ...) tells libGDX that this mesh will have two texture coordinates per vertex (traditionally, the two texture coordinates are called u and v). You can have a bunch of different attributes per vertex, but I'm going to assume the only other attribute is a 3-valued Usage.Position for the x,y,z spatial coordinates.

现在,在定义网格的浮点数组(传递给 setVertices 的数组)中,您需要为每个设置 x、y 和 z 空间坐标加上 u 和 v 纹理坐标顶点:

Now, in the array of floats that defines your mesh (the array you pass to setVertices) you need to set x, y, and z spatial coordinates plus u, and v texture coordinates for each vertex:

final int floatsPerVertex = 5; // 3 spatial +  2 texture
float[] meshData = new float[numVerticies * floatsPerVertex];
for (int i = 0; i < numVerticies; i++) {
   meshData[(i * floatsPerVertex) + 0] = ... ; // x coordinate of i'th vertex
   meshData[(i * floatsPerVertex) + 1] = ... ; // y coordinate of i'th vertex
   meshData[(i * floatsPerVertex) + 2] = ... ; // z coordinate of i'th vertex
   meshData[(i * floatsPerVertex) + 3] = ... ; // u texture coordinate of i'th vertex
   meshData[(i * floatsPerVertex) + 4] = ... ; // v texture coordinate of i'th vertex
}
myMesh.setVertices(meshData);

您可以为特定的 u 和 v/gdx/graphics/g2d/T​​extureRegion.html" rel="noreferrer">TextureRegion 使用 getUgetVgetU2getV2 方法.请注意,纹理坐标的原点 (u1, v1) 在左上角,y 轴指向下"(OpenGL 中的屏幕和空间坐标通常原点在左下角,y 轴指向向上").它有点复杂,但非常灵活,您可以在纹理映射到网格时翻转、拉伸或扭曲纹理.

You can compute the right u and v for a specific TextureRegion using the getU, getV, getU2, and getV2 methods. Note that texture coordinates have the origin (u1, v1) in the top-left, and the y-axis points "down" (screen and spatial coordinates in OpenGL usually have the origin in the bottom-left and the y-axis points "up"). Its a little complicated, but very flexible in that you can flip or stretch or distort the texture as it maps onto your mesh.

由于纹理很大(例如 512x512)并且特定区域是其中的一小部分(例如 128x128 处的 20x20),因此您实际上最终会给出仅使用整个 512x512 的 20x20 子集的网格纹理坐标图片.

Since the texture is large (say 512x512) and the specific region is a small subset of that (say 20x20 at 128x128), you'll actually end up giving your mesh texture coordinates that utilize just the 20x20 subset of the entire 512x512 image.

最后,渲染时需要绑定图片,并在渲染前启用纹理:

Finally, when you render you need to bind the image, and enable texturing before rendering:

region.getTexture().bind();
Gdx.graphics.getGL10().glEnable(GL10.GL_TEXTURE_2D);
myMesh.render();
Gdx.graphics.getGL10().glDisable(GL10.GL_TEXTURE_2D);

请注意,这比应有的效率要低得多.纹理图集的部分好处是它应该包含许多可以一起渲染的区域,因此您只需绑定一个纹理,然后从该绑定纹理渲染许多不同的纹理网格.

Note that this is much less efficient than it should be. Part of the benefit of a texture atlas is that it should contain a lot of regions that can be rendered together, so you only need to bind one texture, and then render a lot of different textured meshes from that one bound texture.

SpriteBatch 支持 用 TextureRegionAssetManager 定义的精灵支持加载和查找 TextureAtlas 作为一等元素.

SpriteBatch supports sprites defined with a TextureRegion and the AssetManager supports loading and finding a TextureAtlas as a first-class element.

相关文章