sampler2DArray - настройка и использование

Я изучаю OpenGL, и мне пришлось использовать sampler2DArray. Я весь день мучаюсь - все безрезультатно. У меня есть два вопроса:

  1. Как создать список текстур?
  2. Как использовать sampler2DArray в шейдере?

Вот результат моих попыток создать список текстур:

// textures - ids loaded textures
private int createTextureArray(GL2 gl, int[] textures, int width, int height) {
        int layerCount = textures.length;
        int mipLevelCount = 1;
        IntBuffer texture = IntBuffer.allocate(1);
        gl.glGenTextures(1, texture);
        gl.glActiveTexture(GL.GL_TEXTURE0);
        gl.glBindTexture(GL2.GL_TEXTURE_2D_ARRAY, texture.get(0));
        gl.glTexStorage3D(GL2.GL_TEXTURE_2D_ARRAY, mipLevelCount, GL2.GL_RGBA8, width, height, layerCount);

        for (int i = 0; i<textures.length; i++) {
             gl.glTexSubImage3D(GL2.GL_TEXTURE_2D_ARRAY, i, // error here
                     0, 0, 0,
                     width, height, layerCount,
                     GL2.GL_RGBA, GL2.GL_UNSIGNED_BYTE,
                     textures[i]);

        }

        // Always set reasonable texture parameters
        gl.glTexParameteri(GL2.GL_TEXTURE_2D_ARRAY, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D_ARRAY, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D_ARRAY, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D_ARRAY, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);

        return texture.get(0);
    }

Пример шейдера:

#version 130
uniform sampler2DArray textures;
varying vec2 UV;
...
void main() {
   ...
   int layer = 0;
   gl_FragColor = texture2DArray(textures, vec3(UV, layer));
}

Буду благодарен за помощь.

2 ответа

Решение

Текстура массива не является "списком текстур". Текстура массива - это отдельная текстура OpenGL, в которой по отдельности имеется несколько квазинезависимых слоев. Хотя вы можете концептуально рассматривать каждый слой текстуры массива как отдельную концептуальную текстуру, в OpenGL (и GLSL) это отдельный объект.

Учитывая это, интерфейс в вашей функции неверен. Он должен возвращать один объект текстуры, и он должен принимать в качестве параметра, а не массив int (примечание: объекты OpenGL представляют собой целые числа без знака), но одно целое число: количество слоев массива, создаваемых в этой текстуре.

Как вы используете текстуру массива в GLSL просто. Ваш uniform для сэмплера используется тип сэмплера массива-текстуры (например sampler2DArray для 2D массивов текстур). Вы привязываете текстуру массива к той же единице изображения текстуры, которую вы указали в качестве привязки для униформы сэмплера (так же, как и для 2D-текстуры без массива).

Ваш GLSL пропускает одну вещь. Здесь нет texture2DArray функция. Правильная функция для использования просто texture, Тип текстуры в Post-GL 3.0 определяется исключительно параметром, а не именем функции.

В дополнение к тому, что @NicolBolas уже сказал: существует множество проблем с кодом шейдера, в основном из-за функциональности, которая устарела в версии 130:

  • Нет способа texture2DArray в любой стандартной версии glsl. Был один в расширении EXT_texture_array, но он никогда не был интегрирован, так как в glsl 130 все функции поиска текстуры (texture2D, texture3D, ...) были заменены перегруженными texture команда. Если вы нацелены на 130 без расширений, вы должны использовать
    texture(textures, vec3(UV, layer))
  • varying Ключевое слово устарело в GLSL 130 и должно быть заменено in/out

  • gl_FragColor устарел и пользовательский вывод (out) переменная должна быть использована.

Возможно, вы захотите взглянуть на Раздел 1.2.1 Спецификации GLSL 130, в котором описаны амортизации и способы их обработки. В целом, я бы посоветовал всем не использовать 130 вообще сегодня, если только для этого нет особой причины. Лучше перейти на OpenGL 3.3+ Core Profile и GLSL 330+.

Другие вопросы по тегам