переменные ввода / вывода среди шейдеров в конвейерной программе - PullRequest
1 голос
/ 20 января 2012

В настоящее время я использую 3 разных шейдера (Вершину, Геометрию и Фрагмент), каждый из которых принадлежит отдельной программе, и все они собраны в один программный конвейер.

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

для каждого шейдера:

glCreateShader(...)
glShadersource(...)
glCompileShader(...)
glGetShaderiv(*shd,GL_COMPILE_STATUS,&status)

для каждой программы:

program[index] = glCreateProgram()
glAttachShader(program[index],s[...])
glProgramParameteri(program[index],GL_PROGRAM_SEPARABLE,GL_TRUE)
glLinkProgram(program[index])
glGetProgramiv(program[index],GL_LINK_STATUS,&status)

тогда:

glGenProgramPipelines(1,&pipeline_object)

в розыгрыше:

glBindProgramPipeline(pipeline_object)
glUseProgramStages(pipeline_object,GL_VERTEX_SHADER_BIT,program[MY_VERTEX_PROGRAM])
and again for the geometry and fragment programs

вершинный шейдер:

#version 330

//modelview and projection mat(s) skipped
...

//interface to geometry shader
out vec3 my_vec;
out float my_float;

void main() {
    my_vec = vec3(1,2,3);
    my_float = 12.3;
    gl_Position = <whatever>
}

геометрия шейдера:

#version 330

//input/output layouts skipped
...

//interface from vertex shader
in vec3 my_vec[];
in float my_float[];
//interface to fragment shader
out vec3 my_vec_fs;
out float my_float_fs;

void main() {
    int i;
    for(i=0;i<3;i++) {
        my_vec_fs = my_vec[i];
        my_float_fs = my_float[i];
        EmitVertex();
    }
    EndPrimitive();
}

фрагментный шейдер:

#version 330

//interface from geometry
in vec3 my_vec_fs;
in float my_float_fs;

void main() {
    here my_vec_fs and my_float_fs come all zeroed
}

Я упускаю какой-то важный шаг в написании / чтении, различающийся между разными этапами в программном конвейере?

UPDATE:

Я попытался с помощью квалификатора расположения макета просто для того, чтобы убедиться, что все «разговаривают» по одному и тому же вектору, поскольку спецификации GLSL гласят:

расположение-идентификатор-спецификатора расположения = целочисленная константа Только один аргумент принят. Например, расположение (расположение = 3) в нормальном vec4; установит, что нормали ввода шейдера назначены на номер вектора 3. Для входов вершинного шейдера местоположение указывает номер общего атрибута вершины, из которого берутся входные значения. Для входных данных всех других типов шейдеров расположение указывает номер вектора, который можно использовать для сопоставления с выходными данными предыдущего этапа шейдера, даже если этот шейдер находится в другом программном объекте.

но с добавлением

layout(location = 3) out vec3 my_vec;

не компилируется

Итак, я попытался сделать то же самое с помощью glBindAttribLocation (), я получаю нет ошибок, но поведение остается неизменным

ОБНОВЛЕНИЕ 2

Если я добавлю "#extension GL_ARB_separate_shader_objects: enable"

тогда я могу использовать layout (location = n) in / out var; и тогда это работает.

найдено:

GLSL 330: Vertex shaders cannot have output layout qualifiers
GLSL 420: All shaders allow location output layout qualifiers on output variable declarations

Это интересно .. Если вы объявите #version 330, вы не сможете использовать спецификатор разметки, даже если вы включите расширение. ... но опять-таки состояние расширения:

Это расширение ARB расширяет использование языка GLSL для определения компоновки для обеспечения межэтапного взаимодействия.

Теперь я хотел бы знать, почему он не работает с помощью glBindAttribLocation () или просто с простыми совпадениями имен + включено расширение ARB!

1 Ответ

0 голосов
/ 08 апреля 2012

По крайней мере, в одной реализации (webgl on и более ранняя версия Chrome) я обнаружил ошибки с glBindAttribLocation() Я думаю, проблема заключалась в том, что вам приходилось связывать атрибуты вершин в числовом порядке. Так что оказалось бесполезным его использовать. Мне пришлось переключиться на getAttribLocation(), чтобы заставить его работать.

...