Использование пользовательских и общих атрибутов вершинных шейдеров в 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
,