Буфер глубины игнорируется в зависимости от положения X / Y с использованием ортографической проекции - PullRequest
0 голосов
/ 11 декабря 2018

Используя libgdx, я хочу отбросить скрытые спрайты, используя буфер глубины.Для этого я использую предоставленные Decal и DecalBatch с OrthographicCamera и устанавливаю позицию z вручную.

В зависимости от положения моего спрайта по осям x и y, буфер глубины работает или не работает должным образом.

красный квадрат z = 98 зеленый квадрат z = 10

Square comparaison

Квадрат прозрачен на 50%, поэтому я могу видеть, что тест на глубину проводился какожидается.

Вот тестовый код:

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g3d.decals.CameraGroupStrategy;
import com.badlogic.gdx.graphics.g3d.decals.Decal;
import com.badlogic.gdx.graphics.g3d.decals.DecalBatch;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import fr.t4c.ui.GdxTest;

public class DecalTest extends GdxTest {
    DecalBatch batch;
    Array<Decal> decals = new Array<Decal>();
    OrthographicCamera camera;
    OrthoCamController controller;
    FPSLogger logger = new FPSLogger();

    Decal redDecal;
    Decal greenDecal;

    public void create() {

        camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        //camera.near = 1;
        camera.position.set(600, 600, 100);
        camera.near = 1;
        camera.far = 100;

        controller = new OrthoCamController(camera);

        Gdx.input.setInputProcessor(controller);
        batch = new DecalBatch(new CameraGroupStrategy(camera));

        TextureRegion[] textures = {
                new TextureRegion(new Texture(Gdx.files.internal("src/test/resources/redsquare.png"))),
                new TextureRegion(new Texture(Gdx.files.internal("src/test/resources/greensquare.png")
                ))};

        redDecal = Decal.newDecal(textures[0], true);
        redDecal.setPosition(600, 600, 98f);
        decals.add(redDecal);

        greenDecal = Decal.newDecal(textures[1], true);
        greenDecal.setPosition(630, 632f, 10f);
        decals.add(greenDecal);

        Decal decal = Decal.newDecal(textures[0], true);
        decal.setPosition(400, 500, 98f);
        decals.add(decal);

        decal = Decal.newDecal(textures[1], true);
        decal.setPosition(430f, 532f, 10f);
        decals.add(decal);
    }

    public void render() {
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
        Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
        Gdx.gl.glDepthFunc(GL20.GL_LEQUAL);

        camera.update();
        for (int i = 0; i < decals.size; i++) {
            Decal decal = decals.get(i);
            batch.add(decal);
        }
        batch.flush();
    }

    @Override
    public void dispose() {
        batch.dispose();
    }

    public static void main(String[] args) {
        LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
        cfg.useGL30 = false;
        cfg.width = 640;
        cfg.height = 480;
        cfg.resizable = false;
        cfg.foregroundFPS = 0; // Setting to 0 disables foreground fps
        // throttling
        cfg.backgroundFPS = 0; // Setting to 0 disables background fps
        new LwjglApplication(new DecalTest(), cfg);
    }
}

Это проблема точности буфера глубины, ориентация камеры, которая испортила исчисление или что-то еще?

Изменить: Я ожидаю, что спрайты будут закрыты, если они находятся позади другого.Так что в моем примере красный квадрат должен перекрывать зеленую часть, перед которой он находится.Левые нижние квадраты имеют правильное поведение, а верхние правые - нет.Дело в том, что красные квадраты имеют одинаковое значение Z, а зеленые квадраты тоже имеют одинаковое значение Z (конечно, отличное от красных квадратов Z).Таким образом, единственное, что делало квадратные пары различными, это их положение x и y, которое не должно влиять на тест глубины.

Итак, я хочу, чтобы было последовательное поведение теста глубины, которое закрывало скрытую текстуру, как мы видим из этого.нижние левые квадраты независимо от их положения х и у.Согласно комментарию, я добавил информацию о том, что я ожидаю.

1 Ответ

0 голосов
/ 24 января 2019

Decal и DecalBatch полагаются на GroupStrategy для сортировки по глубине, а не на камеру.Кроме того, эти стратегии сортируют глубину ЛИБО по расстоянию от камеры ИЛИ только по оси Z, что потребуется для перспективной камеры, то есть наклейка, которая находится ближе и должна быть закрыта, как измерено Z, может быть дополнительно измерена расстоянием от камеры.

т.е. (x, y, z) Камера 0,0,1.

Наклейка A 1,1,0 (Z расстояние 1, векторное расстояние 1,73)

Наклейка B 0,0, -0,1 (Z-расстояние 1,1, векторное расстояние 1,1)

Стратегия глубины, которую вы выбрали для вышеупомянутых наклеек, может сначала рассмотреть A или B.

Наиболее распространенный рекомендуемыйGroupStrategy - CameraGroupStrategy, но она не сортирует по Z, а использует расстояние до камеры.Если вместо этого вы инициализируете DecalBatch с помощью SimpleOrthoGroupStrategy, то глубина будет отсортирована исключительно по Z, здесь приведена сортировка по глубине, вы можете посмотреть на другие групповые стратегии и увидеть их чисто абсолютное расстояние.

    class Comparator implements java.util.Comparator<Decal> {
        @Override
        public int compare (Decal a, Decal b) {
            if (a.getZ() == b.getZ()) return 0;
            return a.getZ() - b.getZ() < 0 ? -1 : 1;
        }
    }
...