android - 在 libgdx 中构建一个一侧带有纹理的盒子 - 性能

标签 android opengl-es libgdx

在类似 3D 拼字游戏的游戏中,我遇到了只能获得 8 FPS 的性能问题。将其缩小到字母拼贴。它们有 100 个,减少它们的数量可以迅速提高性能。我排除了纹理绑定(bind),因为即使所有图 block 都具有与屏幕截图相同的纹理,速度也不会提高。

screenshot

这是我创建每个盒子的方式:

public static void createModel() {
  matWhite = new Material(ColorAttribute.createDiffuse(Color.WHITE));
  ModelBuilder modelBuilder = new ModelBuilder();
  modelBuilder.begin();
  MeshPartBuilder tileBuilder;
  tileBuilder = modelBuilder.part("top", GL10.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.TextureCoordinates, matWhite);
  tileBuilder.rect(-0.45f, 0.1f, 0.45f,   0.45f, 0.1f, 0.45f,    0.45f, 0.1f, -0.45f,  -0.45f, 0.1f, -0.45f,  0f, 1f, 0f);
  tileBuilder = modelBuilder.part("bottom", GL10.GL_TRIANGLES, Usage.Position | Usage.Normal, matWhite);
  tileBuilder.rect(-0.45f, 0f, -0.45f,    0.45f, 0f, -0.45f,     0.45f, 0f, 0.45f,     -0.45f, 0f,  0.45f,    0f, -1f, 0f);
  tileBuilder = modelBuilder.part("front", GL10.GL_TRIANGLES, Usage.Position | Usage.Normal, matWhite);
  tileBuilder.rect(-0.45f, 0.1f, 0.45f,  -0.45f, 0f, 0.45f,      0.45f, 0f, 0.45f,      0.45f, 0.1f,  0.45f,    0f, 0f, 1f);
  tileBuilder = modelBuilder.part("left", GL10.GL_TRIANGLES, Usage.Position | Usage.Normal, matWhite);
  tileBuilder.rect(-0.45f, 0.1f, 0.45f,  -0.45f, 0.1f, -0.45f,  -0.45f, 0f, -0.45f,    -0.45f, 0f,  0.45f,    -1f, 0f, 0f);
  tileBuilder = modelBuilder.part("right", GL10.GL_TRIANGLES, Usage.Position | Usage.Normal, matWhite);
  tileBuilder.rect( 0.45f, 0.1f, 0.45f,   0.45f, 0f, 0.45f,      0.45f, 0f, -0.45f,     0.45f, 0.1f,  -0.45f,    0f, 0f, 1f);
  tileBuilder = modelBuilder.part("back", GL10.GL_TRIANGLES, Usage.Position | Usage.Normal, matWhite);
  tileBuilder.rect(-0.45f, 0.1f, -0.45f,  0.45f, 0.1f, -0.45f,   0.45f, 0f, -0.45f,    -0.45f, 0f,  -0.45f,    0f, 0f, 1f);
  modelTile = modelBuilder.end();
}

public void createModelInstance(com.badlogic.gdx.assets.AssetManager assetManager) {
  Texture texTile = assetManager.get("textures/" + textureFile + ".jpg", Texture.class);
  Material mat = new Material(TextureAttribute.createDiffuse(texTile));
  modelInstance = new ModelInstance(modelTile); 
  modelInstance.nodes.get(0).parts.get(0).material.set(mat);
}

在实验过程中,我发现如果我用创建一个简单的盒子(显示所有面的纹理,所以它不是很有用)来替换网格部分构建代码,速度会上升到 25 FPS(即使使用了所有 100 个纹理)对于这个游戏)。他们的 createBox 方法也调用了 rect() 6 次,但到目前为止我看不出有什么不同。

modelTile = modelBuilder.createBox(0.9f, 0.1f, 0.9f, matWhite, Usage.Position | Usage.Normal | Usage.TextureCoordinates);

我在第一个代码中做错了什么?创建仅在一侧具有纹理的盒子的正确方法是什么?

最佳答案

每次调用 modelBuilder.part 都意味着调用绘制。由于它们非常昂贵,您真的希望将绘制调用的数量保持在最低限度。此外,由于您具有不同的顶点属性,因此必须在第一部分和其他部分之间切换网格和着色器。您还需要将网格和着色器开关的数量保持在最低限度。

因此,要开始优化,您可能需要组合具有相同属性的部分:

tileBuilder = modelBuilder.part("top", GL10.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.TextureCoordinates, matWhite);
tileBuilder.rect(-0.45f, 0.1f, 0.45f,   0.45f, 0.1f, 0.45f,    0.45f, 0.1f, -0.45f,  -0.45f, 0.1f, -0.45f,  0f, 1f, 0f);
tileBuilder = modelBuilder.part("others", GL10.GL_TRIANGLES, Usage.Position | Usage.Normal, matWhite);
tileBuilder.rect(-0.45f, 0f, -0.45f,    0.45f, 0f, -0.45f,     0.45f, 0f, 0.45f,     -0.45f, 0f,  0.45f,    0f, -1f, 0f);
tileBuilder.rect(-0.45f, 0.1f, 0.45f,  -0.45f, 0f, 0.45f,      0.45f, 0f, 0.45f,      0.45f, 0.1f,  0.45f,    0f, 0f, 1f);
tileBuilder.rect(-0.45f, 0.1f, 0.45f,  -0.45f, 0.1f, -0.45f,  -0.45f, 0f, -0.45f,    -0.45f, 0f,  0.45f,    -1f, 0f, 0f);
tileBuilder.rect( 0.45f, 0.1f, 0.45f,   0.45f, 0f, 0.45f,      0.45f, 0f, -0.45f,     0.45f, 0.1f,  -0.45f,    0f, 0f, 1f);
tileBuilder.rect(-0.45f, 0.1f, -0.45f,  0.45f, 0.1f, -0.45f,   0.45f, 0f, -0.45f,    -0.45f, 0f,  -0.45f,    0f, 0f, 1f);

为了进一步优化(消除所有网格开关),您可以使用相同的顶点属性。当然,这会将纹理属性添加到没有纹理的侧面。但只要 Material 没有纹理,它们就会被忽略。

tileBuilder = modelBuilder.part("top", GL10.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.TextureCoordinates, matTop);
tileBuilder.rect(-0.45f, 0.1f, 0.45f,   0.45f, 0.1f, 0.45f,    0.45f, 0.1f, -0.45f,  -0.45f, 0.1f, -0.45f,  0f, 1f, 0f);
tileBuilder = modelBuilder.part("others", GL10.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.TextureCoordinates, matOthers);
tileBuilder.rect(-0.45f, 0f, -0.45f,    0.45f, 0f, -0.45f,     0.45f, 0f, 0.45f,     -0.45f, 0f,  0.45f,    0f, -1f, 0f);
...

要进一步优化(消除所有着色器开关并减少绘制调用的数量),您可以将单个像素添加到纹理中,该像素将被侧面使用并相应地设置 UV 范围:

tileBuilder = modelBuilder.part("top", GL10.GL_TRIANGLES, Usage.Position | Usage.Normal | Usage.TextureCoordinates, matWhite);
tileBuilder.setUVRange(0,0,1,1);
tileBuilder.rect(-0.45f, 0.1f, 0.45f,   0.45f, 0.1f, 0.45f,    0.45f, 0.1f, -0.45f,  -0.45f, 0.1f, -0.45f,  0f, 1f, 0f);
tileBuilder.setUVRange(0,0,0,0); // Assumes the top left pixel is the correct color for the other sides
tileBuilder.rect(-0.45f, 0f, -0.45f,    0.45f, 0f, -0.45f,     0.45f, 0f, 0.45f,     -0.45f, 0f,  0.45f,    0f, -1f, 0f);
...

现在,如果您仍然遇到性能问题,您可以考虑将多个图 block 组合成一个模型(部分:绘制调用)。但对于上述更改,这可能不是立即需要的。

更多信息:http://blog.xoppa.com/behind-the-3d-scenes-part1/

关于android - 在 libgdx 中构建一个一侧带有纹理的盒子 - 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21161456/

相关文章:

java - Android 和 PC 上的 OpenGL ES

java - OpenGL ES,向圆添加纹理

java - Libgdx Box2D 灯,在 Android 设备上看起来不同,光的轮廓很奇怪

Java 帧动画损害性能

android - React Native : error: resource android:style/TextAppearance. Material.Widget.Button.Borderless.Colored 未找到

Android 动画在启动时导致 "Activity idle timeout for History Record"

android - RecyclerView 添加新项目时滚动返回到列表顶部

c++ - 使用客户端顶点数组在没有 VBO 的情况下在 opengl 3.1+ 中呈现

java - libGDX : freezing my game when I call server host

java - 实时读取 Runtime.getRuntime().exec()