Почему единообразные переменные не работают в GLSL? - PullRequest
1 голос
/ 18 апреля 2020

В настоящее время я пытаюсь создать Blur Shader для целей постобработки с использованием LWJGL, но наткнулся на проблему.

Униформы, которые я хочу изменить, - это разрешение, радиус и направление размытия (горизонтальное или вертикальное, так что я могу использовать один шейдер для обоих направлений). Я отображаю вывод в FrameBuffer, который затем отображается на экране. Но почему-то текстура просто черная. Когда я использую постоянные значения вместо униформ, это работает точно так, как и ожидалось, поэтому проблема должна заключаться в равномерных переменных.

Это код моего фрагментного шейдера:

#version 330 core

out vec4 fragColor;

in vec2 coords;
in vec4 color;
in float samplerIndex;

uniform sampler2D samplers[32]; //Just an Array with ints from 0 to 31
uniform float radius;
uniform vec2 resolution; //Screen Resolution, or width & height of Framebuffer
uniform vec2 direction; //Either 1 or 0 for x and y

void main() {
    int index = int(samplerIndex);

    vec4 sum = vec4(0.0);

    float blurX = radius / resolution.x * direction.x;
    float blurY = radius / resolution.y * direction.y;

    sum += texture2D(samplers[index], vec2(coords.x - 4.0 * blurX, coords.y - 4.0 * blurY)) * 0.0162162162;
    sum += texture2D(samplers[index], vec2(coords.x - 3.0 * blurX, coords.y - 3.0 * blurY)) * 0.0540540541;
    sum += texture2D(samplers[index], vec2(coords.x - 2.0 * blurX, coords.y - 2.0 * blurY)) * 0.1216216216;
    sum += texture2D(samplers[index], vec2(coords.x - 1.0 * blurX, coords.y - 1.0 * blurY)) * 0.1945945946;
    sum += texture2D(samplers[index], vec2(coords.x, coords.y)) * 0.2270270270;
    sum += texture2D(samplers[index], vec2(coords.x + 1.0 * blurX, coords.y + 1.0 * blurY)) * 0.1945945946;
    sum += texture2D(samplers[index], vec2(coords.x + 2.0 * blurX, coords.y + 2.0 * blurY)) * 0.1216216216;
    sum += texture2D(samplers[index], vec2(coords.x + 3.0 * blurX, coords.y + 3.0 * blurY)) * 0.0540540541;
    sum += texture2D(samplers[index], vec2(coords.x + 4.0 * blurX, coords.y + 4.0 * blurY)) * 0.0162162162;

    fragColor = color * vec4(sum.rgb, 1.0);
}

Это как я отрисовываю FrameBuffer:

    public void render(boolean fixed) {
        model.setTextureID(Shader.getTextureID(texture));

        model.buffer(vertices);
        indices.put(0).put(1).put(2).put(2).put(3).put(0);

        vertices.flip();
        indices.flip();

        shader.bind();
        texture.bind();

        shader.setUniform1iv("samplers", Shader.SAMPLERS);
        shader.setUniform1f("radius", 10.0f);
        shader.setUniform2f("resolution", width, height);
        shader.setUniform2f("direction", horizontal, vertical);
        if(fixed) {
            shader.setUniformMatrix4f("camProjection", Camera.fixedProjection);
            shader.setUniformMatrix4f("camTranslation", Camera.fixedTranslation);
        } else {
            shader.setUniformMatrix4f("camProjection", Camera.projection);
            shader.setUniformMatrix4f("camTranslation", Camera.translation);
        }

        vao.bind();

        vbo.bind();
        vbo.uploadSubData(0, vertices);
        ibo.bind();
        ibo.uploadSubData(0, indices);

        GL11.glDrawElements(GL11.GL_TRIANGLES, Model.INDICES, GL11.GL_UNSIGNED_INT, 0);

        vao.unbind();

        texture.unbind();
        shader.unbind();

        vertices.clear();
        indices.clear();
    }

Форма сэмплера работает отлично, хотя, похоже, проблема затрагивает только три других формы. У меня нет большого опыта работы с OpenGL и GLSL, что мне не хватает?

1 Ответ

3 голосов
/ 18 апреля 2020

Ваш код шейдера не может работать вообще, потому что

samplers[index]

samplers - это массив sampler2D, а index устанавливается из вершинного шейдера input samplerIndex:

int index = int(samplerIndex);

См. GLSL версии 3.30, которую вы используете (из OpenGL Shading Language 3.30 Спецификация - 4.1.7 Samplers ):

Сэмплеры, агрегированные в массивы внутри шейдера (с использованием квадратных скобок []), могут индексироваться только с помощью целочисленных константных выражений

См. GLSL версии 4.60 (самая последняя) (из * 1023) * OpenGL Shading Language 4.60 Спецификация - 4.1.7. Непрозрачные типы ):
(Это правило применяется ко всем версиям, начиная с GLSL 4.00)

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

Таким образом, ни в используемой вами версии GLSL, ни в самой последней версии массив сэмплеров не может быть проиндексирован с помощью ввода (атрибута) вершинного шейдера.

Начиная с GLSL 4.00, можно было бы индексировать массив сэмплеров по униформе, поскольку индексация по унифицированной переменной - это динамически равномерное выражение .


Я рекомендую использовать s sampler2DArray (см. Sampler ) вместо массива sampler2D.
Когда вы используете sampler2DArray, тогда вам вообще не нужна индексация, потому что «индекс» кодируется в 3-м компоненте координаты текстуры при поиске текстуры (см. texture).

...