Ошибка шейдера Diffuse Lighting OpenGL? - PullRequest
0 голосов
/ 13 марта 2010

Оранжевая книга, раздел 16.2, перечисляет реализацию рассеянного освещения как:

void main()
{
  vec3 N = normalize(gl_NormalMatrix * gl_Normal);
  vec4 V = gl_ModelViewMatrix * gl_vertex;
  vec3 L = normalize(lightPos - V.xyz);
  gl_FrontColor = gl_Color * vec4(max(0.0, dot(N, L));
}

Однако, когда я запускаю это, освещение меняется, когда я двигаю свою камеру. С другой стороны, когда я меняю

  vec3 N = normalize(gl_NormalMatrix * gl_Normal);

в vec3 N = нормализовать (gl_Normal);

Я получаю рассеянное освещение, которое работает как фиксированный трубопровод.

Что это за gl_NormalMatrix, что делает его удаление, ... и это ошибка в оранжевой книге ... или я неправильно настраиваю свой OpenGl-код?

[Для полноты, фрагментный шейдер просто копирует цвет]

1 Ответ

6 голосов
/ 27 ноября 2010

Хорошо, я надеюсь, что нет ничего плохого в том, чтобы ответить на ваш вопрос через полгода? :)

Итак, здесь нужно обсудить две вещи:


а) Как должен выглядеть шейдер

Вы ДОЛЖНЫ преобразовать свои нормали с помощью матрицы вида модели - это само собой разумеющееся. Подумайте, что произойдет, если вы этого не сделаете - ваша матрица вида модели может содержать некоторый поворот. Ваш куб будет вращаться, но нормали все равно будут указывать в старом направлении! Это явно неправильно.

Итак: когда вы преобразовываете свои вершины по матрице вида модели, вы должны также преобразовывать нормали. Ваши нормали vec3 не vec4, и вас не интересуют переводы (нормали содержат только направление), так что вы можете просто умножить свой нормаль на mat3(gl_ModelViewMatrix), то есть верхнюю левую подматрицу 3-3.

Затем: это ПОЧТИ правильно, но все же немного неправильно - причины хорошо описаны на Lighthouse 3D - прочитайте . Короче говоря, вместо mat3(gl_ModelViewMatrix), вы должны умножить на обратную транспонирование этого.

И OpenGL 2 очень полезен и рассчитывает это для вас как gl_NormalMatrix. Следовательно, правильный код:

vec3 N = normalize(gl_NormalMatrix * gl_Normal);

б) Но почему он отличается от фиксированного конвейера?

Первое, что приходит мне в голову, это то, что "что-то не так с вашим использованием фиксированного конвейера".

Я не особо заинтересован в FP (да здравствуют шейдеры!), Но, насколько я помню, когда вы указываете свои источники света с помощью glLightParameterfv(GL_LIGHT_POSITION, something), на это влияла матрица вида модели. Было легко (по крайней мере для меня :)) ошибиться, указав положение источника света (или направление света для направленных источников света) в неправильной системе координат.

Я не уверен, правильно ли я помню, как это работало тогда, так как в настоящее время я использую GL3 и шейдеры, но позвольте мне попробовать ... каково было ваше состояние матрицы вида модели? Я думаю, вполне возможно, что вы указали направленное направление света в пространстве объекта, а не в пространстве глаза, чтобы ваш свет вращался вместе с вашим объектом. IDK, если это актуально здесь, но не забудьте обратить на это внимание при использовании FF. Это ошибка, которую я часто делаю, когда все еще использовал GL 1.1.

В зависимости от состояния просмотра модели, вы можете указать свет в:

  • глаз (камера) пространство,
  • мировое пространство,
  • пространство объекта.

Убедитесь, какой это.

Хм .. Надеюсь, это сделает эту тему более понятной для вас. Выводы:

  1. всегда преобразуйте ваши нормали вместе с вершинами в ваших вершинных шейдерах, и
  2. Если он выглядит не так, как вы ожидаете, подумайте, как вы определяете свои световые позиции. (Может быть, вы тоже хотите умножить вектор положения света в шейдере? Замечания о системах координат положения света остаются в силе)
...