GLSL OpenGL 3.x как определить соответствие между общими индексами атрибутов вершин и семантикой? - PullRequest
1 голос
/ 05 марта 2012

Я переключаюсь с HLSL на GLSL

При определении атрибутов вершины буфера вершин необходимо вызвать

glVertexAttribPointer(  GLuint      index, 
    GLint   size, 
    GLenum      type, 
    GLboolean   normalized, 
    GLsizei     stride, 
    const GLvoid *      pointer);

и передать индекс. Но как мне указать, какой индекс соответствует какой семантике в шейдере?

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

1 Ответ

7 голосов
/ 05 марта 2012

В GLSL нет такой вещи, как "семантика". Есть только индексы атрибутов и входы вершинных шейдеров.

Существует два вида ввода вершинных шейдеров. Вид, который был удален в 3.1 (те, которые начинаются с "gl_") и определяемый пользователем вид. Удаленный вид не может быть установлен с помощью glVertexAttribPointer; У каждой из этих переменных была своя специальная функция. gl_Normal имел glNormalPointer, gl_Color имел glColorPointer и т. Д. Но эти функции больше не присутствуют в ядре OpenGL.

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

  1. С помощью синтаксиса расширения GLSL 3.30 или ARB_explicit_attrib_location layout(location = #), где # - индекс атрибута. Поэтому, если у меня есть вход с именем position, я бы присвоил ему индекс 3 следующим образом:

    layout(location = 3) in vec4 position;
    

    Это мой предпочтительный метод обработки этого. Explicit_attrib_location доступен практически на любом оборудовании, которое все еще поддерживается (это не Intel).

  2. Явная связь через glBindAttribLocation. Вы вызываете эту функцию перед связыванием программы. Для этого мы сделаем следующее:

    GLuint program = glCreateProgram();
    glAttachShader(program, some_shader);
    glBindVertexAttrib(program, 3, "position");
    glLinkProgram(program);
    

    Вы можете установить несколько атрибутов. Действительно, вы можете установить несколько имен атрибутов для одного и того же индекса. Идея заключается в том, чтобы иметь возможность просто установить несколько сопоставлений автоматически и позволить OpenGL выяснить, какое из них работает с реальным кодом шейдера. Таким образом, вы можете иметь «положение» и «ось» в соответствии с индексом 3, и до тех пор, пока вы не добавите шейдер в эту систему, которая имеет оба этих входа, все будет в порядке.

  3. Пусть OpenGL назначит его. Если вы не назначите индекс атрибута для атрибута другим способом, компоновщик GLSL назначит его для вас. Вы можете получить пост-связывание атрибута с помощью glGetAttribLocation.

    Я действительно не советую этого, потому что OpenGL назначит индексы произвольно . Таким образом, каждый шейдер, который использует атрибут с именем position, может иметь позицию в другом индексе. Я не думаю, что это хорошая идея. Так что, если вы не можете явно установить его в шейдере, то, по крайней мере, явно установите его в своем коде OpenGL перед компоновкой. Таким образом, вы можете договориться о том, что означает индекс атрибута 0, что означает индекс 1 и т. Д.

...