Конфликт при использовании двух или более шейдеров с разным количеством атрибутов

Я пытаюсь реализовать выбор (используя цвета и readPixels) в моей программе WebGL. Когда я запускаю свою программу, я создаю отдельную shaderProgram. Один для затенения по фонгу, а другой просто придает фигурам цвет, который будет использоваться для определения, по какой фигуре щелкнули.

Фонг шейдер имеет 2 атрибута. Положение вершины и вершина нормальная. У выбора просто есть позиция.

Теперь я обнаружил, что по какой-то странной причине, когда оба этих шейдера существуют в одной и той же программе, и я использую один из них, мой вызов drawArray, похоже, не выполняется. Последнее, что должно произойти, это мой вызов gl.vertexAttribPointer. Я возился и обнаружил, что когда я проверяю активные массивы атрибутов с помощью: gl.getVertexAttrib(index,gl.VERTEX_ATTRIB_ARRAY_ENABLED);

оба 0,1 возвращают true (это когда шейдер выбора активен с помощью gl.useProgram(picking))

Теперь, если я отключу 1 с помощью gl.disableVertexAttribArray(1); Все снова работает. Другое исправление - сначала рисовать с помощью шейдера Phong, а затем использовать шейдер выбора, и это каким-то волшебным образом делает все нормально. Я предполагаю, что в этом случае при подключении моего буфера нормалей вершин при использовании шейдера phong он каким-то образом остается, когда я затем переключаюсь на шейдер выбора и вызов drawArray работает.

Я хотел бы знать, если я использую gl.enableAttribArray неправильно и должен отключить их при переключении шейдеров или что-то в этом роде.

Я также пытался создавать шейдерные программы в другом порядке, но безуспешно.

3 ответа

Решение

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

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

Трудно сказать, не видя ваш код, но... WebGL требует, чтобы все атрибуты, к которым будет осуществляться доступ, имели достаточно данных, чтобы удовлетворить вызов отрисовки. Итак, если вы устанавливаете 2 атрибута, каждый из которых имеет 3 вершины данных, и рисуете 3 вершины, то переключаете шейдеры и настраиваете атрибут 1 с 6 вершинами, а второй атрибут оставляйте только с 3 вершинами, а затем пытайтесь рисовать с 6 вершинами, если В настоящее время рисование с доступом к обоим атрибутам WebGL завершится неудачно.

Если вы запускаете Chrome 19, он должен сообщить вам в консоли JavaScript, была ли это проблема.

OpenGL - это конечный автомат. Выбирая шейдер выбора, вы переводите OpenGL в состояние, в котором больше нет дополнительных атрибутов шейдера phong.

Многие люди впадают в неправильное и вредное привычку полагать, что с OpenGL была какая-то "однократная инициализация". Это не вариант. Вы должны установить все состояние, необходимое для какой-либо операции рисования, непосредственно перед этой операцией рисования, а в идеале также вернуть настройки после завершения. Это означает: после связывания шейдера вы также должны включить и связать необходимые входные данные шейдера, то есть атрибуты вершины.

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