- •Г.М. Набережнов, н.Н. Максимов Установка отображаемого пространства
- •Казань 2007
- •1. Функции, устанавливающие отображаемый объем и положение наблюдателя в 3d
- •2. Обработка событий
- •3. 3D примитивы из библиотеки glut
- •4. Установка источника света
- •5. Удаление невидимых поверхностей
- •Задания для самостоятельного выполнения
4. Установка источника света
Реалистический эффект при визуализации 3D примитивов будет наблюдаться только если в программе включено их освещение. В OpenGL может быть установлено большое количество параметров и их значений, характеризующих источники света, их положение, свойства и цвет материала. Ниже приведен минимум установок, требуемых для освещения объекта.
OpenGL позволяет задать до восьми источников с именами GL_LIGHT0, GL_LIGHT1 и т.д. Каждый источник обладает различными свойствами и должен быть задействован (включен). У каждого его свойства имеется значение по умолчанию. Например, для создания источника, расположенного в точке (3, 6, 5) в мировых координатах, следует включить в текст программы следующий код:
GLfloat myLightPosition[] = {3.0, 6.0, 5.0, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, myLightPosition);
glEnable(GL_LIGHTING); // включаем (свет)
glEnable(GL_LIGHT0); // включаем этот конкретный источник
Массив myLightPosition[ ] (имя можно использовать любое) определяет положение источника света и передается в функцию glLightfv( ) вместе с именем источника GL_LIGHT0, для того чтобы связать его с конкретным источником, обозначенным именем GL_LIGHT0. В этом примере параметры, характеризующие свойства и цвет источника, а так же свойства и цвет материала объекта устанавливаются по умолчанию.
Внимание.
-
Позиция источника, заданного функцией glLightfv(GL_LIGHT0, GL_POSITION, myLightPosition), является объектом, который, как и любая точка, посылаемая в конвейер, подвергается преобразованию матрицей VM. Это надо учитывать в программе!
-
После включения освещения функцией glEnable(GL_LIGHTING), все установки цвета glColor*( ), не действуют. Если на фоне освещенного объекта 3D вам необходимо нарисовать какие-то линии в цвете, то необходимо выключить освещение glDisable(GL_LIGHTING).
5. Удаление невидимых поверхностей
Удаление невидимых – сложная задача. Зачастую, с целью получения эффективной программы, программисту приходится комбинировать возможности, предоставляемые OpenGL (использование буфера глубины), с собственными алгоритмическими приемами. Ниже приведены те действия, которые необходимо включить в программу, для решения задачи удаления невидимых с использованием только буфера глубины.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) – вместе с очисткой буфера цвета предусмотреть очистку буфера глубины.
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH) – устанавливая режим дисплея в функции main( ), предусмотреть использование буфера глубины.
glEnable(GL_DEPTH_TEST) – включение режима удаления невидимых.
glDisable(GL_DEPTH_TEST) – выключение режима удаления невидимых.
Ниже приведен текст программы, иллюстрирующий изложенный материал.
#include <gl\glut.h>
#include <math.h>
GLfloat angle=0;
void init(void)
{ glClearColor(1.0, 1.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity( );
gluPerspective(60, 1, 1, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity( );
}
void myDisplay( )
{ glPushMatrix( ); //Сохраняем VM = 1
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
gluLookAt(3, 2, 1, 0, 0, 0, 0, 1, 0); // VM=Fwe
GLfloat myLightPosition[] = {3.0, 3.0, 3.0, 1.0}; // Источник света в CKw
glLightfv(GL_LIGHT0, GL_POSITION, myLightPosition); /*Позиция источника света будет преобразована в CKe*/
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glPushMatrix(); //Сохраняем VM=Fwe
glRotatef(angle, 0, 1, 0); // VM=Fwe*R
glRotatef(angle, 0, 1, 0); // VM=Fwe*R*R
glRotatef(angle, 0, 0, 1); // VM=Fwe*R*R*R
glutSolidCube(0.95);
//glutWireCube(0.95);
glPopMatrix( ); // Восстанавливаем VM=Fwe
glDisable(GL_LIGHTING); //Выключаем освещение
glBegin(GL_LINES);
glColor3f(1,0,0 ); glVertex3f(0, 0, 0); glVertex3f(1, 0, 0);
glColor3f(0,1,0 ); glVertex3f(0, 0, 0); glVertex3f(0, 1, 0);
glColor3f(0,0,1 ); glVertex3f(0, 0, 0); glVertex3f(0, 0, 1);
glEnd();
glBegin(GL_LINES);
glColor3f(1,1,1); glVertex3f(3, 3, 3); glVertex3f(0.0, 0.0, 0.0);
glEnd();
glPopMatrix( );
glutSwapBuffers( );
}
void myReshape(int width, int height)
{ if(width/height<1) glViewport(0, 0, width, width);
else glViewport(0, 0, height, height);
}
void myIdle( )
{ angle+=0.5;
if(angle > 360.0) angle=0;
glutPostRedisplay( );
}
int main(int argc, char* argv[])
{ glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(800, 800);
glutInitWindowPosition(0, 0);
glutCreateWindow("my window");
glutDisplayFunc(myDisplay);
glutReshapeFunc(myReshape);
glutIdleFunc(myIdle);
init( );
glutMainLoop( );
}