Опубликован: 13.07.2010 | Доступ: свободный | Студентов: 889 / 20 | Оценка: 4.40 / 4.20 | Длительность: 77:34:00
Самостоятельная работа 22:

Свет и материалы в OpenGL

Модель самолета с зеркальным отражением (JetShiny)

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

  • Добавьте к проекту новый файл с именем JetShiny.h


  • С копируйте в новый файл код из файла JetLight.h и змените окончания всех функций и их прототипов с JetLight на JetShiny
  • Удалите весь код, помеченный как вспомогательный, вместе с прототипами вспомогательных функций
  • Добавьте в конец функции SetLightJetShiny() код установки отражательных свойств поверхности самолета
void SetLightJetShiny()
{
  GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };// Фоновый слабобелый
  GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };// Рассеяный среднебелый
  GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};// Расположение источника
  glShadeModel(GL_SMOOTH);
  
  GLfloat diffuseMaterial[] = {0.5, 0.5, 0.5, 1.0};
  glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseMaterial);// Начальное значение диффузного материала
  
  glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
  glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  
  // Режим согласования цветов назначаем для фонового и рассеянного
  glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  // Включаем поддержку согласования цветов
  glEnable(GL_COLOR_MATERIAL);
  
  // Задание свойства зеркального отражения
  GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
  glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
  glMateriali(GL_FRONT, GL_SHININESS, 50);
}
Листинг 23.26. Добавление свойства зеркального отражения в функцию SetLightJetShiny()
  • Добавьте в файл LightAndMaterial.cpp код, подключающий новое упражнение
// LightAndMaterial.cpp : Defines the entry point for the console application.
//
  
//**********************************************************
// Подключение стандартного файла с библиотекой OpenGL
#include "stdafx.h"
  
//**********************************************************
// Прототипы функций
void ExecuteMenu(int);    // Контекстное меню первого уровня
void TimerFunc(int);    // Обработчик события таймера
void SpecialKeys(int, int, int);  // Обработка нажатия клавиш
void RenderScene(void);    // Функция рендеринга
void ChangeSize(int, int);  // Функция установки отсекающего объема
  
// Глобальная переменная выбранного варианта основного меню
int choice = 1;
  
// Глобальные переменные для создания вращения
// в градусах
GLfloat xRot = 0.0f;
GLfloat yRot = 0.0f;
GLfloat zRot = 0.0f;
GLint w, h; // Ширина и высота экрана
  
//**********************************************************
// Подключение файлов с упражнениями
#include "ColorCube.h"    // Упражнение 1: "1) Куб цвета"
#include "Jet.h"      // Упражнение 2: "2) Самолет без освещения"
#include "LightSphere.h"  // Упражнение 3: "3) Рисование освещенной сферы"
#include "MultiMaterial.h"  // Упражнение 4: "4) Рисование с разными материалами"
#include "ColorSphere.h"  // Упражнение 5: "5) Способ согласования цветов"
#include "JetNight.h"    // Упражнение 6: "6) Самолет с нулевым освещением"
#include "JetLight.h"    // Упражнение 7: "7) Самолет с равномерным освещением"
#include "JetShiny.h"    // Упражнение 8: "8) Самолет с зеркальным отражением"
  
//**********************************************************
// Функция обратного вызова обработки выбора пользователя
void ExecuteMenu(int choice)
{
  // Сбрасываем углы вращения прежнего варианта
  xRot = yRot = zRot = 0;
  
  // Выключаем освещение
  glDisable(GL_LIGHTING);
  
  // Выключаем режим согласования цветов
  glDisable(GL_COLOR_MATERIAL);
  
  // Запоминаем выбор в глобальную переменную
  ::choice = choice; 
  
  switch(::choice)
  {
    case 1:
      ChangeSizeColorCube(w, h);
      break;
    case 2:
      ChangeSizeJet(w, h);
      break;
    case 3:
      ChangeSizeLightSphere(w, h);
      break;
    case 4:
      ChangeSizeMultiMaterial(w, h);
      break;
    case 5:
      ChangeSizeColorSphere(w, h);
      break;
    case 6:
      ChangeSizeJetNight(w, h);
      break;
    case 7:
      ChangeSizeJetLight(w, h);
      break;
    case 8:
      ChangeSizeJetShiny(w, h);
      break;
  }
    
  // Вызвать принудительно визуализацию
  glutPostRedisplay();
}
  
//**********************************************************
// Функция обратного вызова для рисования сцены
void RenderScene(void)
{
  // Сохранить прежние настройки OpenGL в стеке атрибутов
  glPushAttrib(GL_LIGHTING_BIT);
  
  switch(::choice)
  {
    case 1:
      RenderSceneColorCube();
      break;
    case 2:
      RenderSceneJet();
      break;
    case 3:
      RenderSceneLightSphere();
      break;
    case 4:
      RenderSceneMultiMaterial();
      break;
    case 5:
      RenderSceneColorSphere();
      break;
    case 6:
      RenderSceneJetNight();
      break;
    case 7:
      RenderSceneJetLight();
      break;
    case 8:
      RenderSceneJetShiny();
      break;
  }
  
  // Восстановить прежние настройки OpenGL из стека атрибутов
  glPopAttrib();
}
  
//**********************************************************
// Вызывается библиотекой GLUT при изменении размеров окна
void ChangeSize(int width, int height)
{  
  w = width;
  h = height;
  
  switch(::choice)
  {
    case 1:
      ChangeSizeColorCube(width, height);
      break;
    case 2:
      ChangeSizeJet(width, height);
      break;
    case 3:
      ChangeSizeLightSphere(width, height);
      break;
    case 4:
      ChangeSizeMultiMaterial(width, height);
      break;
    case 5:
      ChangeSizeColorSphere(width, height);
      break;
    case 6:
      ChangeSizeJetNight(width, height);
      break;
    case 7:
      ChangeSizeJetLight(width, height);
      break;
    case 8:
      ChangeSizeJetShiny(width, height);
      break;
  }
}
  
//**********************************************************
// Обработчик события таймера
void TimerFunc(int value)
{
  glutPostRedisplay(); // Перерисовка сцены
  glutTimerFunc(30, TimerFunc, 1); // Заряжаем новый таймер
}
  
//**********************************************************
// Управление с клавиатуры стрелками
// для задания новых значений матрицы поворота
void SpecialKeys(int key, int x, int y)
{
  if(key == GLUT_KEY_UP)  // Стрелка вверх
    xRot -= 5.0f;
  
  if(key == GLUT_KEY_DOWN)// Стрелка вниз
    xRot += 5.0f;
  
  if(key == GLUT_KEY_LEFT)// Стрелка влево
    yRot -= 5.0f;
  
  if(key == GLUT_KEY_RIGHT)// Стрелка вправо
    yRot += 5.0f;
  
  xRot = (GLfloat)((const int)xRot % 360);
  yRot = (GLfloat)((const int)yRot % 360);
  
  // Для упражнения 5 смены материала
  if(key == GLUT_KEY_F1) // Меняем красный
  {
    diffuseMaterial[0] += 0.1;
    *diffuseMaterial = *diffuseMaterial > 1.0 ? 0.0 : *diffuseMaterial;
    glColor4fv(diffuseMaterial);
  }
  if(key == GLUT_KEY_F2) // Меняем зеленый
  {
    diffuseMaterial[1] += 0.1;
    *(diffuseMaterial + 1) = diffuseMaterial[1] > 1.0 ? 0.0 : diffuseMaterial[1];
    glColor4fv(diffuseMaterial);
  }
  if(key == GLUT_KEY_F3) // Меняем синий
  {
    diffuseMaterial[2] += 0.1;
    *(diffuseMaterial + 2) = diffuseMaterial[2] > 1.0 ? 0.0 : diffuseMaterial[2];
    glColor4fv(diffuseMaterial);
  }
  
  // Вызвать принудительно визуализацию с помощью RenderScene()
  glutPostRedisplay();
}
  
//**********************************************************
void main(int argc, char* argv[])
{
  glutInit(&argc, argv);
  // Двойная буферизация, цветовая модель RGB, буфер глубины
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(300, 300);    // Начальные размеры окна
  glutCreateWindow("Свет и материалы");  // Заголовок окна
  glutDisplayFunc(RenderScene);  // Обновление сцены при разрушении окна
  glutReshapeFunc(ChangeSize);  // При изменении размера окна
  glutTimerFunc(100, TimerFunc, 1);  // Создали таймер
  glutSpecialFunc(SpecialKeys);    // Для управления с клавиатуры
    
  // Создание меню и добавление опций выбора
  glutCreateMenu(ExecuteMenu);
  glutAddMenuEntry("1) Куб цвета", 1);
  glutAddMenuEntry("2) Самолет без освещения", 2);
  glutAddMenuEntry("3) Рисование освещенной сферы", 3);
  glutAddMenuEntry("4) Рисование с разными материалами", 4);
  glutAddMenuEntry("5) Способ согласования цветов (F1, F2, F3)", 5);
  glutAddMenuEntry("6) Самолет с нулевым освещением", 6);
  glutAddMenuEntry("7) Самолет с равномерным освещением", 7);
  glutAddMenuEntry("8) Самолет с зеркальным отражением", 8);
  
  glutAttachMenu(GLUT_RIGHT_BUTTON);// Присоединяем 
  // Конец создания меню
  
  glutMainLoop();  // Цикл сообщений графического окна
}
Листинг 23.27. Код подключения модели самолета с зеркальным отражением в файле LightAndMaterial.cpp
  • Запустите приложение и выполните упражнение 8, результат должен быть примерно таким