Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

RedBook

.pdf
Скачиваний:
18
Добавлен:
11.06.2015
Размер:
7.43 Mб
Скачать

spin=(spin+1)%360;

glutPostRedisplay();

}

void mouse(int button,int state,int x, int y)

{

switch(button)

{

case GLUT_LEFT_BUTTON: if(state==GLUT_DOWN)

glutIdleFunc(light_moving); else

glutIdleFunc(NULL);

break;

}

}

int main(int argc, char **argv)

{

glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH); glutInitWindowSize(500,500); glutInitWindowPosition(100,100);

glutCreateWindow("Moving a Light with Modeling Transformations"); init();

glutDisplayFunc(display);

glutReshapeFunc(reshape);

glutMouseFunc(mouse);

glutMainLoop(); return 0;

}

5.4.5.3 Перемещение источника света вместе с точкой наблюдения

Чтобы создать источник света, который передвигается вместе с точкой наблюдения, вам следует задать его позицию до видового преобразования. Тогда видовое

преобразование будет одинаковым образом воздействовать и на источник света и на точку наблюдения. Помните, что положение источника света сохраняется в видовых координатах это один из небольшого числа случаев, в которых видовые координаты весьма важны. В примере 5-7 позиция источника света задается в функции init() и сохраняется в видовых координатах (0, 0, 0). Другими словами, свет излучается из линзы камеры.

Пример 5-7. Источник света, перемещающийся вместе с точкой наблюдения

GLfloat light_position[]={0.0, 0.0, 0.0, 1.0};

glViewport(0,0,(GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity();

gluPerspective(40.0, (GLfloat)w/(GLfloat)h,1.0,100.0); glMatrixMode(GL_MODELVIEW);

glLoadIdentity(); glLightfv(GL_LIGHT0,GL_POSITION,light_position);

Теперь, если точка наблюдения переместится, источник света переместится вместе с ней, сохраняя дистанцию (0, 0, 0) относительно глаза. В продолжении примера 5-7, следующим далее, глобальные переменные (ex, ey, ez) управляют положением точки наблюдения, а (upx, upy, upz) определяют вектор верхнего направления. Функция display(), вызываемая из цикла обработки сообщений для перерисовки сцены, может выглядеть следующим образом:

GLdlouble ex, ey, ez, upx, upy, upz;

void display()

{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix();

gluLookAt(ex, ey, ez, 0.0, 0.0, 0.0, upx, upy, upz); glutSolidTorus(0.275, 0.85, 8, 15);

glPopMatrix();

glFlush();

}

Когда перерисовывается освещенный торус, и источник света, и точка наблюдения перемещаются в одно и то же место. С изменением величин, передаваемых в gluLookAt() (и перемещением наблюдателя), объект никогда не будет темным, поскольку он всегда освещается с позиции наблюдателя. Даже если вы не измените координаты позиции источника света явно, он все равно будет перемещаться, поскольку изменяется видовая координатная система.

Этот метод может быть весьма полезен при эмуляции фонаря на каске шахтера. Другим примером может быть свеча или лампа, которую несут в руке. Позиция источника света, задаваемая вызовом glLightfv(GL_LIGHTi, GL_POSITION, position), по смыслу будет соответствовать указанию расстояний источника от наблюдателя по x, y и z. Затем при изменении положения наблюдателя, источник света будет оставаться на том же относительном расстоянии.

5.5 Выбор модели освещения

ВOpenGL понятие модели освещения разделяется на 4 компонента:

Интенсивность глобального фонового света.

Считается ли положение точки наблюдения локальным к сцене или бесконечно удаленным.

Должен ли расчет освещенности производиться по-разному для лицевых и обратных граней объектов.

Должен ли зеркальный цвет отделяться от фонового и диффузного и накладываться на объект после операций текстурирования.

Этот раздел объясняет, как задавать модель освещения. Здесь также обсуждается, как включать освещение то есть, как сказать OpenGL, что она должна производить расчет освещенности.

glLightModel*() это команда, используемая для задания всех параметров модели освещения. glLightModel*() принимает два аргумента: имя параметра модели освещения в виде константы и значение для этого параметра.

void glLightModel{if} (GLenum pname, TYPE param); void glLightModel{if}v (GLenum pname, TYPE *param);

Устанавливает свойства модели освещения. Устанавливаемая характеристика модели освещения определяется аргументом pname (таблица 5-2). param задает величину, в которую устанавливается pname; если используется векторная версия команды, то это указатель на группу величин, если применяется невекторная версия в param содержится сама величина. Невекторная версия команды может использоваться только для установки параметров, определяемых одной величиной (и не может применяться для GL_LIGHT_MODEL_AMBIENT).

Таблица 5-2. Значения по умолчанию для параметра pname модели освещения

Имена параметров

Значения по

Смысл

умолчанию

 

 

 

 

 

GL_LIGHT_MODEL_AMBIENT

(0.2,0.2,0.2,1.0)

RGBA интенсивность всей сцены

GL_LIGHT_MODEL_LOCAL_VIEWER

0.0 или GL_FALSE

способ вычисления углов зеркального

отражения

 

 

GL_LIGHT_MODEL_TWO_SIDE

0.0 или GL_FALSE

выбор между односторонним и двухсторонним

освещением

 

 

GL_LIGHT_MODEL_COLOR_CONTROL GL_SINGLE_COLOR

вычисляется ли зеркальный цвет отдельно от

фонового и диффузного

 

5.5.1 Глобальный фоновый свет

Как обсуждалось ранее, каждый источник света может добавлять к сцене фоновый свет. Кроме того, может присутствовать другой фоновый свет, не принадлежащий никакому конкретному источнику. Чтобы задать RGBA интенсивность такого глобального фонового света, используйте параметр GL_LIGHT_MODEL_AMBIENT следующим образом:

GLfloat lmodel_ambient[]={0.2,0.2,0.2,1.0}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);

В этом примере значения для lmodel_ambient совпадают со значениями по умолчанию для GL_LIGHT_MODEL_AMBIENT. Поскольку эти числа задают небольшое количество белого фонового света, вы можете видеть объекты сцены даже в том случае, если отсутствуют какие-либо дополнительные источники света. На рисунке 5-4 изображены три чайника, нарисованные на сцене с разным количеством глобального фонового света (его интенсивность увеличивается слева направо).

Рисунок 5-4. Чайники, освещенные разным количеством глобального фонового света

5.5.2 Локальная или бесконечно удаленная точка наблюдения

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

расчеты могут быть различными на основании предположения о ее мнимом местонахождении.

Если предполагается, что точка наблюдения бесконечно удалена, то направления из нее ко всем вершинам считаются одинаковыми. Локальная точка наблюдения позволяет получать более реалистичный результат, но, поскольку должны быть рассчитаны направления между ней и каждой вершиной, среднее быстродействие приложения может значительно снизиться. По умолчанию используется бесконечно удаленная точка наблюдения. Вы можете сменить ее на локальную следующим вызовом:

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

Этот вызов помещает точку наблюдения в (0, 0, 0) в видовых координатах. Для

переключения обратно к бесконечно удаленной точке наблюдения в предыдущей строке кода замените GL_TRUEна GL_FALSE.

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

Расчет освещенности производится для всех полигонов, являются ли они лицевыми или обратными. Поскольку вы обычно настраиваете источники света, размышляя о лицевых полигонах, обратные могут быть неверно освещены. В примере 5-1, где в качестве объекта используется сфера, всегда видны только лицевые грани, поскольку именно они находятся снаружи сферы. Таким образом, в данном случае неважно, как выглядят обратные. Однако, если часть сферы будет отсечена и ее внутренняя поверхность станет видимой, вам возможно захочется, чтобы эта поверхность была освещена в соответствии с заданными вами условиями освещения; возможно вам также потребуется задать для обратной поверхности иные свойства материала, чем для лицевой. Когда вы включаете двухстороннее освещение вызовом:

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

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

дополнительные операции по обеспечению двухстороннего освещения делают его более медленным, чем принятое по умолчанию одностороннее освещение.

Чтобы выключить двухстороннее освещение, измените GL_TRUE в предыдущей строке кода на GL_FALSE. Вы также можете управлять тем, какие грани OpenGL считает лицевыми с помощью команды glFrontFace().

5.5.4 Отделение зеркального цвета

При обычном расчете освещенности, фоновый, диффузный, зеркальный вклады

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

glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);

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

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

Чтобы восстановить метод расчета освещенности по умолчанию, вызовите:

glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);

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

Если вы не производите наложение текстуры на объект, отделение зеркального цвета от остальных не имеет никакого смысла.

5.5.5 Включение расчета освещенности

При использовании OpenGL вам необходимо включать (или выключать) механизм расчета освещенности. Если данный механизм не включен, текущий цвет просто ассоциируется с текущей вершиной, и не производится никаких вычислений, касающихся нормалей, источников света, модели освещения и свойств материала. Расчет освещенности включается командой:

glEnable(GL_LIGHTING);

и выключается командой:

glDisable(GL_LIGHTING);

Кроме того, вам требуется включать каждый источник света, после того, как вы определили его параметры. В примере 5-1 используется только один источник света

GL_LIGHT0:

glEnable(GL_LIGHT0);

5.6 Указание свойств материала

Вы видели, как создать источник света с определенными характеристиками и как задать нужную модель освещения. В этом разделе описано, как задать свойства материала для объектов на сцене: фоновый, диффузный и зеркальный цвета, степень сияния (насколько блестящим выглядит объект) и цвет исходящего от объекта света. Большинство свойств материала концептуально похожи на те, которые использовались при создании источников света. Механизм из указания также аналогичен установке параметров источника света за исключением того, что здесь используется команда glMaterial*().

void glMaterial{if}(GLenum face, GLenum pname, TYPE param); void glMaterial{if}v(GLenum face, GLenum pname, TYPE *param);

Задает свойство материала для использования при расчете освещенности. Аргумент face может принимать значения GL_FRONT, GL_BACKили GL_FRONT_AND_BACK,

указывая для каких граней объекта задается свойство материала. Устанавливаемое свойство материала определяется значением аргумента pname, а его значение содержится в param (в виде указателя на вектор величин в случае векторной версии команды или в виде самой величины при использовании невекторного варианта). Невекторная версия команды работает только для параметра GL_SHININESS. Возможные значения для аргумента pname перечислены в таблице 5-3. Заметьте, что константа GL_AMBIENT_AND_DIFFUSE позволяет вам одновременно установить фоновый и диффузный цвета материала в одно и то же RGBAзначение.

Таблица 5-3. Значения по умолчанию для параметра материала pname

Имена параметров

Значения по

Смысл

умолчанию

 

 

GL_AMBIENT

(0.2,0.2,0.2,1.0)

фоновый цвет материала

GL_DIFFUSE

(0.8,0.8,0.8,1.0)

диффузный цвет материала

GL_AMBIENT_AND_DIFFUSE

 

фоновый и диффузный цвет материала

GL_SPECULAR

(0.0,0.0,0.0,1.0)

зеркальный цвет материала

GL_SHININESS

0.0

показатель зеркального отражения

GL_EMISSION

(0.0,0.0,0.0,1.0)

исходящий цвет материала

GL_COLOR_INDEXES

(0,1,1)

индексы фонового, диффузного и зеркального

цветов

 

 

 

 

 

Как обсуждалось ранее, вы можете задать расчет освещенности для лицевых и обратных полигонов объекта. Если в вашем приложении обратные грани могут быть видимыми, вы можете по-разному задать параметры материала для лицевых и обратных граней объекта, используя аргумент face команды glMaterial*(). На рисунке 5-5 изображен объект, нарисованный с применением разных свойств материала для его лицевых и обратных граней.

Рисунок 5-5. Разный материал для лицевых и обратных граней

В примере 5-8 приведен код, используемый для рисования чайника на рисунке 5-5.

Пример 5-8. Отсеченный чайник с разными материалами для лицевых и обратных граней: файл two_side_lighting.cpp

#include <glut.h>

//Инициализация void init(void)

{

glClearColor(0.0,0.0,0.0,0.0); glShadeModel(GL_SMOOTH);

//Настраиваем источник света

GLfloat light_position[]={1.0,1.0,1.0,0.0}; GLfloat white_light[]={1.0,1.0,1.0,1.0}; glLightfv(GL_LIGHT0,GL_POSITION,light_position); glLightfv(GL_LIGHT0,GL_DIFFUSE,white_light); glLightfv(GL_LIGHT0,GL_SPECULAR,white_light);

//...и модель двухстороннего освещения

GLfloat lmodel_ambient[]={1.0,1.0,1.0,1.0}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT,lmodel_ambient); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

//Включаем нужные механизмы glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST);

//Задаем параметры материала для лицевых граней

GLfloat mat_specular_front[]={0.0,0.3,0.9,1.0}; GLfloat mat_ambient_front[]={0.0,0.1,0.3,1.0}; glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular_front); glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient_front);

//... и для обратных

GLfloat mat_specular_back[]={1.0,0.0,0.0,1.0}; GLfloat mat_ambient_back[]={0.5,0.1,0.1,1.0}; glMaterialfv(GL_BACK,GL_SPECULAR,mat_specular_back); glMaterialfv(GL_BACK,GL_AMBIENT,mat_ambient_back);

//GL_SHININESS в данном случае одинаково для всех граней

GLfloat mat_shininess[]={50.0}; glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,mat_shininess);

//Задаем дополнительную плоскость отсечения

GLdouble equation[]={0.4,0.5,-0.5,0.6}; glClipPlane(GL_CLIP_PLANE1, equation); glEnable(GL_CLIP_PLANE1);

//Задаем какие грани считать лицевыми glFrontFace(GL_CW);

}

//Отображение

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glutSolidTeapot(0.9);

glFlush();

}

//Изменение размеров окна void reshape(int w, int h)

{

glViewport(0,0,(GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity();

if (w<=h)

glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,- 10.0,10.0);

else

glOrtho(-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h,-1.5,1.5,- 10.0,10.0);

glMatrixMode(GL_MODELVIEW); glLoadIdentity();

}

//Точка входа

int main(int argc, char **argv)

{

glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH); glutInitWindowSize(310,310); glutInitWindowPosition(100,100); glutCreateWindow("Two-sided lighting");

init();

glutDisplayFunc(display);

glutReshapeFunc(reshape);

glutMainLoop(); return 0;

}

Чтобы получить представление о том, каких эффектов можно достигнуть с помощью различных свойств материала, взгляните на рисунок 5-6. На этом рисунке изображено несколько экземпляров одного и того же объекта, нарисованных с применением разных свойств материала. Каждый раз был использован один и тот же источник света и одинаковая модель освещения. В разделах следующих далее, обсуждаются отдельные свойства материалов.

Рисунок 5-6. Чайники из разных материалов

Заметьте, что большинство параметров материала, устанавливаемых с помощью команды glMaterial*() являются RGBA величинами. Независимо от величины альфа, задаваемой в других параметрах, величиной альфа для конкретной вершины принимается та, которая была задана для диффузного цвета, то есть для параметра GL_DIFFUSE. Также заметьте, что в индексном цветовом режиме RGBA значения для свойств материала не используются.

5.6.1 Диффузное и фоновое отражение

Параметры GL_DIFFUSEи GL_AMBIENT, устанавливаемые командой glMaterial*() влияют на цвета диффузного и фонового света, отражаемого объектом. Диффузное отражение играет наиболее важную роль в определении того, что вы воспринимаете как цвет объекта. На ваше восприятие оказывает влияние цвет падающего диффузного света и угол между этим светом и вектором нормали к поверхности. (Диффузное отражение наиболее заметно, если диффузный свет падает перпендикулярно к

поверхности.) Положение точки наблюдения вообще не влияет на диффузное отражение.

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

В реальном мире, диффузное и фоновое отражение от одного и того же объекта, как правило, имеет одинаковый цвет. По этой причине OpenGL предоставляет упрощенный путь для задания обоих параметров материала в команде glMaterial*():

GLfloat mat_amb_diff[]={0.1,0.5,0.8,1.0}; glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);

В этом примере RGBA цвет (0.1, 0.5, 0.8, 1.0) – глубокий синий цвет задается в

качестве текущих цветов фонового и диффузного отражения для лицевых и обратных граней полигонов.

5.6.2 Зеркальное отражение

Зеркальное отражение от объекта создает блик. В отличие от фонового и диффузного отражения, количество зеркального отражения, видимого наблюдателем, зависит от положения точки наблюдения. Чтобы это понять, представьте, что вы смотрите на металлический шарик под солнечным светом. При движении вашей головы, блик,

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

OpenGL позволяет вам задавать эффект, производимый материалом на отраженный свет (с помощью параметра GL_SPECULAR), и контролировать размер и яркость блика (с помощью параметра GL_SHININESS). GL_SHININESS может принимать значения в диапазоне [0.0, 128.0]: чем больше значение, тем меньше и ярче зеркальный блик (то есть при увеличении значения GL_SHININESS блик будет все более и более сфокусирован).

5.6.3 Исходящий (эмиссионный) цвет

Задавая RGBA цвет для параметра GL_EMISSION, вы можете изобразить объект так, как будто он излучает свет этого цвета. Поскольку большинство реальных объектов (помимо источников света) сами не излучают свет, вы, вероятно, будете использовать этот эффект для симуляции ламп и других источников света.

Имейте в виду, что хотя объекты с высокой интенсивностью исходящего света выглядят светящимися, на самом деле они не работают в качестве источников света, то есть не оказывают никакого воздействия на другие объекты сцены. Для того, чтобы имитировать лампу или фонарь, вам нужно создать дополнительный источник света и поместить его в ту же позицию, что и светящийся объект.

5.6.4 Изменение свойств материала

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

Более вероятно, что на сцене будет больше одного объекта. Например, посмотрите на выдержку кода в примере 5-9.

Пример 5-9. Разные свойства материала

GLfloat no_mat[]={0.0,0.0,0.0,1.0}; GLfloat mat_ambient[]={0.7,0.7,0.7,1.0};

GLfloat mat_ambient_color[]={0.8,0.8,0.2,1.0}; GLfloat mat_diffuse[]={0.1,0.5,0.8,1.0}; GLfloat mat_specular[]={1.0,1.0,1.0,1.0}; GLfloat no_shininess[]={0.0};

GLfloat low_shininess[]={5.0}; GLfloat high_shininess[]={100.0};

GLfloat mat_emission[]={0.3,0.2,0.2,0.0}; glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

//Нарисовать первую сферу слева glPushMatrix(); glTranslate(-3.75,0.0,0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); glutSolidSphere(1.0,16,16);

glPopMatrix();

//Нарисовать вторую сферу правее первой glPushMatrix(); glTranslate(-1.25,0.0,0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); glutSolidSphere(1.0,16,16);

glPopMatrix();

//Нарисовать третью сферу правее первых двух glPushMatrix();

glTranslate(1.25,0.0,0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); glutSolidSphere(1.0,16,16);

glPopMatrix();

//Нарисовать последнюю сферу справа glPushMatrix(); glTranslate(3.75,0.0,0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); glutSolidSphere(1.0,16,16);

glPopMatrix();

Как вы видите, glMaterial*() вызывается несколько раз для установки требуемого свойства материала для каждой сферы. Заметьте, что эту команду необходимо вызывать только для тех параметров, которые действительно изменяются. Вторая,

третья и четвертая сферы используют одинаковые фоновое и диффузное свойство материала, так что на самом деле нет смысла задавать их каждый раз. Поскольку существуют некоторые временные затраты на выполнение glMaterial*(), пример 5-9 может быть переписан более эффективным образом (на самом деле из него нужно просто удалить некоторые строки).

Соседние файлы в предмете Компьютерная Графика