【问题标题】:Need help to optimize texture drawing on LibGDX, SpriteBatch需要帮助优化 LibGDX、SpriteBatch 上的纹理绘制
【发布时间】:2019-10-17 10:13:02
【问题描述】:

我正在使用 LibGDX 将我的游戏 Hold & Drag 从 Swift (SpriteKit) 转换为 Android,我创建了我的“SpriteKit”api,它是 Xcode 上官方的一个小克隆。

我正在寻找优化纹理渲染的方法,尤其是因为我的 FPS 下降 (45-60 /60 fps) 当我不绘制纹理时,我得到了 60(最大值)。

希望您能尽可能高效地帮助我!

@Override
public void draw() {
    if (texture == null)
        return;

    Gdx.gl.glEnable(GL20.GL_BLEND);
    Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

    spriteBatch.setTransformMatrix(getTransformMatrix());
    spriteBatch.begin();
    Color color = spriteBatch.getColor();
    color.a = getAlpha();
    spriteBatch.setColor(color);
    spriteBatch.draw(texture, -size.width / 2, -size.height / 2, size.width, size.height);
    spriteBatch.end();

    Gdx.gl.glDisable(GL20.GL_BLEND);
}
public List<SKNode> getParents() {
    List<SKNode> parents = new ArrayList<>();
    if (parent != null) {
        parents.add(parent);
        parents.addAll(parent.getParents());
    }
    return parents;
}

public Matrix4 getTransformMatrix() {
    List<SKNode> nodes = getParents();
    Collections.reverse(nodes);
    nodes.add(this);

    Matrix4 transformMatrix = new Matrix4();
    transformMatrix.idt();
    for (SKNode node : nodes) {
        transformMatrix.translate(node.position.x + node.origin.x, node.position.y + node.origin.y, 0);
        transformMatrix.rotate(0, 0, 1, node.zRotation);
        transformMatrix.scale(node.xScale, node.yScale, 0);
        transformMatrix.translate(-node.origin.x, -node.origin.y, 0);
    }

    return transformMatrix;
}

【问题讨论】:

    标签: libgdx spritebatch


    【解决方案1】:

    执行导致精灵批处理“刷新”的事情很慢,这意味着它必须发出许多 OpenGL 命令并传输顶点数据等。当您调用 spriteBatch.end() 时会发生刷新,但如果你:

    • 使用与上次绘制的不同纹理实例绘制的东西
    • 更改投影或变换矩阵
    • 启用/禁用混合

    所以你想要组织,这样你就不会在你绘制的每个对象上触发刷新。通常所做的是开始批处理,然后使用包含您想要的所有参数的spriteBatch.draw() 方法之一在其特定位置绘制每个精灵。像这样:

    batch.setProjectionMatrix(camera.combined);
    batch.begin();
    for (GameObject obj : myGameObjects)
        obj.draw();
    batch.end();
    
    //And in your game object / sprite class
    public void draw() {
        if (texture == null)
            return;
        spriteBatch.setColor(1f, 1f, 1f, getAlpha());
        spriteBatch.draw(texture, -size.width / 2, -size.height / 2, size.width, size.height);
    }
    

    请注意,以上假设您在每个对象中引用相同的精灵批处理实例。

    现在,为了让它表现得更像 SpriteKit(我假设因为我没有使用它),你的每个对象都需要一个变换。但是你不想打电话给setTransformMatrix,否则你会触发冲洗。相反,您可以使用 Affine2 类而不是 Matrix4。它同样适用于保存 2D 对象的变换数据。然后你可以使用spriteBatch.draw(textureRegion, width, height, affine2Transform) 来绘制它而不触发刷新。

    为避免使用不同的纹理实例触发刷新,您应该使用 TextureAtlas 和纹理区域。您可以在他们的 wiki 上的 LibGDX 文档中阅读。

    顺便说一句,在使用 SpriteBatch 时,您不需要调用 OpenGL 来启用和禁用混合。这由 SpriteBatch 内部处理。请致电spriteBatch.enableBlending()

    【讨论】:

    • Affine2 的绘图与 Matrix4 不同,我的精灵在右边,有点高。有人能帮我吗 ? pastebin.com/J2nzCs9j
    • 已经有一段时间了,我不记得对转换执行更改的顺序规则了。但我认为您首先将仿射移动宽度和高度的一半,然后应用其他更改。这意味着您不能使用 Matrix4 并以这种方式应用它。您应该直接在仿射上进行与 Matrix4 相同的操作。
    • 感谢您抽出宝贵时间帮助我! pastebin.com/Byteuf0Hyoutu.be/rLELMrAZ6js
    • 另一件事。你不应该每次使用它时都创建一个新的 Affine2,因为这会在你对很多对象执行此操作时触发 GC,而 GC 会使其卡顿。
    • 它比以前好,但我不明白 Affine2 是如何工作的。它连接到非逻辑 mmh 的节点。 youtu.be/3ErGAcvyC8s
    猜你喜欢
    • 2014-09-05
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    • 2014-10-28
    • 2011-11-24
    • 2020-02-27
    • 1970-01-01
    相关资源
    最近更新 更多