В этом шаге мы посмотрим простенький пример работы с материалами.
Вообще-то понятие материала и источника света - это основа 3D графики (да и не только 3D, и не только графики ;) ).
Посмотрим каждый их них в отдельности:
Комбинаций свойств материала, источника света и окраски объекта может быть множество. В "Шаг 42 - Два источника света" мы задавали интенсивность источника света. Делали это так:
GLfloat light1_Intensity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
Попробуйте теперь уменьшить красную составляющую на 1/2. Что получилось увидите сами. Объяснение простое. На источник света как бы наложен фильтр, который пропускает только свет определенного спектра.
Такая ситуация как предыдущая в природе случается редко. Как правило мы сталкиваемся с тем, что источник света белый (или близкий к нему, т.е. дневной свет), а вот материалы имеют разные свойства и потому мы видим их как бы определенного цвета (если они не окрашены). Пример - кирпич, он не крашенный, но имеет оранжевый цвет (я даже задумался ... цвет кирпича-то оранжевый? Наверное да, но в любом случае, правильный ответ - цвет зависит от свойств материала этого кирпича)
Вот теперь посмотрим тот же пример, но уже менять будем не свойства источника света, а свойства материала объекта. Для начала 2 глобальных переменных:
GLuint m_lstCube; GLfloat m_matDiffuse[] = {0.0f, 0.0f, 0.0f};
Первая - это идентификатор списка, в котором будет содержаться куб. Второй - свойства материала рассеивать свет. Каждый элемент массива определяет рассеивает ли этот материал определенную длину волны света.
Теперь зададим это свойство:
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, m_matDiffuse);
Первая команда определяет так называемую модель освещения. Первый параметр может принимать два значения: GL_LIGHT_MODEL_TWO_SIDE и GL_LIGHT_MODEL_LOCAL_VIEWER. Первый определяет будет ли освещение расчитываться только для внешних граней или и для внешних и для внутренних, а второй - определяет как будет расчитываться угол отражения. Второй параметр задает значение для первого. Вторая команда собственно включает нам то самое свойство материала, которое мы ранее определили в массиве.
Вот и все. Свойства материала установлены, источник света включен. Все работает. Просто ради наглядности я добавил в обработчик от клавиатуры WM_KEYDOWN обработчики от кнопочек r,g,b.
Нажимая на них можно изименять свойство материала рассеивать ту или иную составляющую света.
case WM_KEYDOWN: if(wParam == VK_ESCAPE) SendMessage(hWnd, WM_CLOSE, 0, 0); if(wParam == 82) // r { if(red<=1.0f) red += 0.1f; else red = 0.0f; } if(wParam == 71) // g { if(green <= 1.0f) green += 0.1f; else green += 0.0f; } if(wParam == 66) // b { if(blue <= 1.0f) blue += 0.1f; else blue = 0.0f; } if(wParam == 76) // l (можно отключить и включить источник света) { if(light) { light=FALSE; glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); } else { light=TRUE; glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); } } if(wParam == 67) // c (можно включить или выключить окраску объекта) { if(color) { color=FALSE; glEnable(GL_COLOR_MATERIAL); } else { color=TRUE; glDisable(GL_COLOR_MATERIAL); } } m_matDiffuse[0] = red; m_matDiffuse[1] = green; m_matDiffuse[2] = blue; glMaterialfv(GL_FRONT, GL_DIFFUSE, m_matDiffuse); break;
И еще одна маленькая деталь. Я немного поменял аргументы в команде установки вида:
GLvoid Resize(GLsizei w, GLsizei h) { if(w>=h) glViewport ((w-h)/2, 0, (GLsizei) h, (GLsizei) h); if(w<h) glViewport (0, (h-w)/2, (GLsizei) w, (GLsizei) w); glMatrixMode (GL_PROJECTION); glLoadIdentity(); glFrustum (-1, 1, -1, 1, 4, 15); glMatrixMode (GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -12.0); glRotatef(30.0, 1.0, 0.0, 0.0); glRotatef(70.0, 0.0, 1.0, 0.0); }
Теперь куб - это действительно куб, а не что-то параллелепипедное.
Забыл один небольшой, но важный момент. В тексте я писал слово рассеивать, очень хотелось написать слово отражать, но дело в том, что слово diffuse действительно переводится как рассеивать. По логике работы приложение, нажимая, например, на букву "r" мы как бы говорим OpenGL-ю, что наш материал НЕ БУДЕТ рассеиваить красный свет. У материала есть так же свойство отражения света, т.е. как бы качество полировки поверхности, поэтому не стоит путать diffuse со specular, но об этом в следующем шаге.