Нужна помощь в оптимизации рисования текстур на LibGDX, SpriteBatch - PullRequest
0 голосов
/ 31 мая 2019

Я конвертирую свою игру Hold & Drag из Swift (SpriteKit) в Android, используя LibGDX, я создал свой «SpriteKit» api, небольшой клон официального релиза в Xcode.

Я ищу оптимизациюрендеринг текстур, особенно потому, что я получил FPS drop (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;
}

1 Ответ

2 голосов
/ 31 мая 2019

Медленно выполняется то, что заставляет пакет спрайтов «сбрасываться», что означает, что он должен выполнить ряд команд OpenGL и передать данные вершин и т. Д. Сброс происходит при вызове spriteBatch.end(), но также происходит, еслиyou:

  • Нарисуйте что-нибудь с экземпляром текстуры, отличным от последнего нарисованного объекта
  • Измените матрицы проекции или преобразования
  • Включите / отключите смешивание

Итак, вы хотите организовать, чтобы не вызывать сброс на каждый нарисованный объект.Обычно это делается для запуска пакета, а затем каждый спрайт рисуется в определенном месте одним из методов 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 и области текстуры.Вы можете прочитать об этом в документации LibGDX на их вики.

Кроме того, при использовании SpriteBatch вам не нужно делать вызовы OpenGL для включения и отключения смешивания.Это обрабатывается внутри SpriteBatch.Позвоните spriteBatch.enableBlending() вместо.

...