(LWJGL3) OpenGL 2D Texture Array остается пустым после загрузки данных изображения с помощью glTexSubImage3D - PullRequest
0 голосов
/ 16 сентября 2018

Так что в настоящее время я пытаюсь заменить мой старый текстурный атлас на массив текстур 2D, чтобы сделать жизнь проще с анизотропной фильтрацией и жадным зацеплением позже.

Я загружаю png-файлы с помощью stb и знаю, что буферы заполнены правильно, потому что, если я экспортирую каждый слой атласа, который скоро появится, прямо перед его загрузкой, это правильный файл png.

Моя установка работает так:

Я загружаю каждую текстуру в моем jar-файле с помощью stb и создаю с ним объект, в котором хранятся ширина, высота, слой и pixelData.

Когда загружается каждая текстура, я ищу самую большую текстуру и масштабирую каждую меньшую текстуру до того же размера, что и самый большой, потому что я знаю, что двухмерные текстурные массивы работают, только если каждый из слоев имеет одинаковый размер.

Затем я инициализирую массив текстур 2d следующим образом:

public void init(int layerCount, boolean supportsAlpha, int textureSize) {
    this.textureId = glGenTextures();
    this.maxLayer = layerCount;

    int internalFormat = supportsAlpha ? GL_RGBA8 : GL_RGB8;
    this.format = supportsAlpha ? GL_RGBA : GL_RGB;

    glBindTexture(GL_TEXTURE_2D_ARRAY, this.textureId);
    glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalFormat, textureSize, textureSize, layerCount, 0, this.format, GL_UNSIGNED_BYTE, 0);
}

После этого я просматриваю карту объектов textureLayer и загружаю каждый из них следующим образом:

public void upload(ITextureLayer textureLayer) {
    if (textureLayer.getLayer() >= this.maxLayer) {
        LOGGER.error("Tried uploading a texture with a too big layer.");
        return;
    } else if (this.textureId == 0) {
        LOGGER.error("Tried uploading texture layer to uninitialized texture array.");
        return;
    }

    glBindTexture(GL_TEXTURE_2D_ARRAY, this.textureId);

    // Tell openGL how to unpack the RGBA bytes
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);


    // Tell openGL to not blur the texture when it is stretched
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    // Upload the texture data
    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, textureLayer.getLayer(), textureLayer.getWidth(), textureLayer.getHeight(), 0, this.format, GL_UNSIGNED_BYTE, textureLayer.getPixels());

    int errorCode = glGetError();
    if (errorCode != 0) LOGGER.error("Error while uploading texture layer {} to graphics card. {}", textureLayer.getLayer(), GLHelper.errorToString(errorCode));
}

Код ошибки для каждого из моих слоев равен 0, поэтому я предполагаю, что все прошло хорошо. Но когда я отлаживаю игру с помощью RenderDoc, я вижу, что на каждом слое каждый бит равен 0, и поэтому это просто прозрачная текстура с правильной шириной и высотой.

Я не могу понять, что я делаю неправильно, так как openGL говорит мне, что все прошло хорошо. Для меня важно, что я использую только openGL 3.3 и ниже, так как я хочу, чтобы игра также игралась на старых компьютерах, поэтому предварительное выделение памяти с помощью glTexStorage3D не вариант.

1 Ответ

0 голосов
/ 16 сентября 2018

8-й параметр glTexSubImage3D должен быть равен 1 (depth).
Обратите внимание, размер слоя составляет textureLayer.getWidth(), textureLayer.getHeight(), 1:

glTexSubImage3D(
    GL_TEXTURE_2D_ARRAY, 0, 0, 0, textureLayer.getLayer(),
    textureLayer.getWidth(), textureLayer.getHeight(), 1,    // depth is 1
    this.format, GL_UNSIGNED_BYTE, textureLayer.getPixels());

Передача width, height или depth от 0 до glTexSubImage3D не является ошибкой, но это не повлияет на хранилище данных объектов текстуры.

...