теория, алгоритмы, примеры на С++ и OpenGL  

Мы vkontakte.ru


Rambler's Top100 Rambler's Top100
Каталог@Mail.ru - каталог ресурсов интернет

Друзья

Словарь синонимов русского языка

Нормали и двухстороннее освещение

Одной из характерных особенностей освещения в OpenGL является то, что оно может быть двухсторонним. В большинстве случаев, когда мы гарантированно видим лишь одну сторону поверхности (например, для замкнутых объектов) можно обойтись расчетом освещения только для лицевой стороны и, рекомендуется, по возможности, избегать двухстороннего режима, из-за накладных расходов на двойной расчет освещения.

Лицевая и тыльная стороны полигона

При описании полигона, вершины перечисляются одна за другой, чтобы не нарушить требование несамопересечения. Тем не менее существует две возможности для перечисления: по часовой стрелке (clockwise, CW) и против часовой (counterclockwise, CCW). По умолчанию, та сторона полигона, для которой порядок перечисления вершин совпадает с обходом против часовой стрелки, считается лицевой.

Можно задать порядок обхода для лицевых граней командой:

glFrontFace(GLenum mode);

Параметр mode команды glFrontFace

GL_CCW

Лицевая сторона задается обходом против часовой стрелки. Значение по умолчанию.

GL_CW
Лицевая сторона задается обходом по часовой стрелке.

Нормали

Для создания корректного освещения сцены нужно правильно установить нормали. Они задаются для вершин полигонов командой

glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);
glNormal3fv(const GLfloat *v);

которая вызывается внутри блока glBegin/glEnd перед описанием соответствующей вершины. Каких либо требований к нормалям не предъявляется, но по смыслу:

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

    glEnable(GL_NORMALIZE);

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

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

Более подробно о нормалях можно посмотреть в статье "Модели затенения". В том числе в ней описывается, почему в вершинах одного и того же полигона нормали могут быть различными.

Одностороннее/двухстороннее освещение

По умолчанию включено одностороннее освещение, т.е. освещенность просчитывается для лицевых сторон и переносится на тыльные без изменений. В этом случае требуется лишь правильно задать нормали. Свойства материала можно задавать только для лицевых сторон (GL_FRONT) или для обеих сторон (GL_FRONT_AND_BACK). Изменение свойств для тыльных граней (GL_BACK) при одностороннем освещении никак не скажется на результате.

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

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

glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GLfloat param);

Параметр param команды glLightModelf

GL_FALSE

Одностороннее освещение. Значение по умолчанию.

GL_TRUE
Двухстороннее освещение.