Использование пользовательских и общих атрибутов вершинных шейдеров в OpenGL и OpenGL ES

Так как общие атрибуты вершин устарели в OpenGL, я попытался переписать свой вершинный шейдер, используя только пользовательские атрибуты. И я не работал на меня. Вот вершинный шейдер:

attribute vec3 aPosition;
attribute vec3 aNormal;

varying   vec4 vColor;

vec4 calculateLight(vec4 normal) {
    // ...
}

void main(void) {
    gl_Position = uProjectionMatrix * uWorldViewMatrix * vec4(aPosition, 1);
    vec4 rotatedNormal = normalize(uWorldViewMatrix * vec4(aNormal, 0));
    vColor = calculateLight(rotatedNormal);
}

Это прекрасно работает в OpenGL ES 2.0. Однако, когда я пытаюсь использовать его с OpenGL, я вижу черный экран. Если я изменю aNormal для общего gl_Normal все работает хорошо, а также (обратите внимание, что aPosition отлично работает в обоих контекстах, и я не должен использовать gl_Vertex).

Что я делаю неправильно?

Я использую RenderMonkey для тестирования шейдеров, и я настроил в нем отображение потоков с соответствующими именами атрибутов (aPosition и aNormal). Может быть, это как-то связано с индексами атрибутов, потому что у меня все они установлены в 0? Кроме того, вот что говорится в документации RenderMonkey об установке имен пользовательских атрибутов в "Сопоставлении потоков":

В поле "Имя атрибута" отображается имя по умолчанию, которое можно использовать в редакторе шейдеров для ссылки на этот поток. В эффекте OpenGL ES измененное имя должно использоваться для ссылки на поток; однако в эффекте DirectX или OpenGL новое имя не влияет на редактор шейдеров.

Интересно, эта проблема специфична для RenderMonkey или самого OpenGL? И почему aPosition все еще работает тогда?

1 ответ

Решение

Индексы атрибутов должны быть уникальными. Можно сказать OpenGL использовать определенные индексы через glBindAttribLocation перед тем как связать программу. В любом случае нормальным способом является запрос индекса с glGetAttribLocation, Похоже, что RenderMonkey позволяет вам выбирать, в каком случае вы пытались разделить их?

Я видел фиксированную функцию рендеринга при переходе к атрибутам вершины, где glVertexPointer может привести к привязке к первому атрибуту, если он не связан (я не знаю, можно ли его воспроизвести).

Я также вижу некоторые странные вещи, экспериментируя с атрибутами и именами фиксированных функций. Без звонка glBindAttribLocationЯ собираю следующий шейдер:

attribute vec4 a;
attribute vec4 b;
void main()
{
    gl_Position = gl_Vertex + vec4(gl_Normal, 0) + a + b;
}

и я получаю следующие места (через glGetActiveAttrib):

a: 1
b: 3
gl_Vertex: -1
gl_Normal: -1

Экспериментируя, кажется, использование gl_Vertex занимает индекс 0 а также gl_Normal берет индекс 2 (даже если его не сообщили). Интересно, если вы добавите атрибут заполнения между aPosition а также aNormal (не забудьте использовать его в выходных данных, иначе он будет скомпилирован) заставляет его работать.

В этом случае возможно, что данные о местоположении просто привязаны к местоположению с нулевым последним. Тем не менее, черный экран с aNormal указывает на то, что ничто не связано (в этом случае оно всегда будет {0, 0, 0}). Это немного менее согласуется - если нормаль была привязана к тем же данным, что и позиция, вы ожидаете некоторый цвет, если не правильный цвет, так как нормаль будет иметь данные позиции.

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

Я чувствую, что RenderMonkey использует только glVertexPointer/glNormalPointer вместо атрибутов, которые я бы, однако, связал бы и с нормой, и с положением, либо с данными нормалей, либо с данными о положении, поскольку вы говорите, что оба индекса равны нулю.

в эффекте DirectX или OpenGL новое имя не влияет на редактор шейдеров

Может быть, это означает, что "именованные потоки" просто не доступны в не-ES версии OpenGL?

Это не связано, но в более поздних версиях OpenGL-GLSL #version нужен номер и атрибуты используют ключевое слово in,

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