Типичная программа, использующая OpenGL, начинается с определения окна, в котором будет происходить отображение. Затем создается контекст (клиент) OpenGL и ассоциируется с этим окном. Далее программист может свободно использовать команды и операции OpenGL API.
Ниже приведен текст небольшой программы, написанной с использованием библиотеки GLUT – своеобразный аналог классического примера “Hello, World!”.
Все, что делает эта программа – рисует в центре окна красный квадрат. Тем не менее, даже на этом простом примере можно понять принципы программирования с помощью OpenGL.
#include
/* подключаем библиотеку GLUT */
#include
/* начальная ширина и высота окна */
GLint Width = 512, Height = 512;
/* размер куба */
const int CubeSize = 200;
/* эта функция управляет всем выводом на экран */
void Display(void)
{
int left, right, top, bottom;
left = (Width - CubeSize) / 2;
right = left + CubeSize;
bottom = (Height - CubeSize) / 2;
top = bottom + CubeSize;
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glColor3ub(255,0,0);
glBegin(GL_QUADS);
glVertex2f(left,bottom);
glVertex2f(left,top);
glVertex2f(right,top);
glVertex2f(right,bottom);
glEnd();
glFinish();
}
/* Функция вызывается при изменении размеров окна */
void Reshape(GLint w, GLint h)
{
Width = w;
Height = h;
/* устанавливаем размеры области отображения */
glViewport(0, 0, w, h);
/* ортографическая проекция */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/* Функция обрабатывает сообщения от клавиатуры */
void
Keyboard( unsigned char key, int x, int y )
{
#define ESCAPE '\033'
if( key == ESCAPE )
exit(0);
}
/* Главный цикл приложения */
main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(Width, Height);
glutCreateWindow("Red square example");
glutDisplayFunc(Display);
glutReshapeFunc(Reshape);
glutKeyboardFunc(Keyboard);
glutMainLoop();
}
Несмотря на малый размер, это полностью завершенная программа, которая должна компилироваться и работать на любой системе, поддерживающей OpenGL и GLUT.
Библиотека GLUT поддерживает взаимодействие с пользователем с помощью так называемых функций c обратным вызовом (callback function). Если пользователь подвинул мышь, нажал на кнопку клавиатуры или изменил размеры окна, происходит событие и вызывается соответствующая функция пользователя – обработчик событий (функция с обратным вызовом).
Рассмотрим более подробно функцию main данного примера. Она состоит из трех частей – инициализации окна, в котором будет рисовать OpenGL, настройки функций c обратным вызовом и главного цикла обработки событий.
Инициализация окна состоит из настройки соответствующих буферов кадра, начального положения и размеров окна, а также заголовка окна.
Функция glutInit(&argc, argv) производит начальную инициализацию самой библиотеки GLUT.
Команда glutInitDisplayMode(GLUT_RGB) инициализирует буфер кадра и настраивает полноцветный (непалитровый) режим RGB.
glutInitWindowSize(Width, Height) используется для задания начальных размеров окна.
Наконец, glutCreateWindow("Red square example") задает заголовок окна и визуализирует само окно на экране.
Затем команды
glutDisplayFunc(Display);
glutReshapeFunc(Reshape);
glutKeyboardFunc(Keyboard);
регистрируют функции Display(), Reshape() и Keyboard() как функции, которые будут вызваны, соответственно, при перерисовке окна, изменении размеров окна, нажатии клавиши на клавиатуре.
Контроль всех событий и вызов нужных функций происходит внутри бесконечного цикла в функции glutMainLoop()
Заметим, что библиотека GLUT не входит в состав OpenGL, а является лишь переносимой прослойкой между OpenGL и оконной подсистемой, предоставляя минимальный интерфейс. OpenGL-приложение для конкретной платформы может быть написано с использованием специфических API (Win32, X Window и т.д.), которые как правило предоставляют более широкие возможности.
Более подробно работа с библиотекой GLUT описана в Приложении А.
Все вызовы команд OpenGL происходят в обработчиках событий. Более подробно они будут рассмотрены в следующих главах. Сейчас обратим внимание на функцию Display, в которой сосредоточен код, непосредственно отвечающий за рисование на экране.
Следующая последовательность команд из функции Display
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glColor3ub(255,0,0);
glBegin(GL_QUADS);
glVertex2f(left,bottom);
glVertex2f(left,top);
glVertex2f(right,top);
glVertex2f(right,bottom);
glEnd();
очищает окно и выводит на экран квадрат, задавая координаты четырех угловых вершин и цвет.
В приложении B.1 приведен еще один пример несложной программы, при нажатии кнопку мыши рисующей на экране разноцветные случайные прямоугольники.
Контрольные вопросы: -
В чем, по вашему мнению, заключается необходимость создания стандартной графической библиотеки?
-
Кратко опишите архитектуру библиотек OpenGL и организацию конвейера.
-
Назовите категории команд (функций) библиотеки.
-
Зачем нужны различные варианты команд OpenGL, отличающиеся только типами параметров?
-
Почему организацию OpenGL часто сравнивают с конечным автоматом?
2.1.Процесс обновления изображения
Как правило, задачей программы, использующей OpenGL, является обработка трехмерной сцены и интерактивное отображение в буфере кадра. Сцена состоит из набора трехмерных объектов, источников света и виртуальной камеры, определяющей текущее положение наблюдателя.
Обычно приложение OpenGL в бесконечном цикле вызывает функцию обновления изображения в окне. В этой функции и сосредоточены вызовы основных команд OpenGL. Если используется библиотека GLUT, то это будет функция с обратным вызовом, зарегистрированная с помощью вызова glutDisplayFunc(). GLUT вызывает эту функцию, когда операционная система информирует приложение о том, что содержимое окна необходимо перерисовать (например, если окно было перекрыто другим). Создаваемое изображение может быть как статичным, так и анимированным, т.е. зависеть от каких-либо параметров, изменяющихся со временем. В этом случае лучше вызывать функцию обновления самостоятельно. Например, с помощью команды glutPostRedisplay(). За более подробной информацией можно обратиться к приложению A.
Приступим, наконец, к тому, чем занимается типичная функция обновления изображения. Как правило, она состоит из трех шагов:
-
очистка буферов OpenGL;
-
установка положения наблюдателя;
-
преобразование и рисование геометрических объектов.
Очистка буферов производится с помощью команды:
void glClearColor ( clampf r, clampf g, clampf b,
clampf a )
void glClear(bitfield buf)
Команда glClearColor устанавливает цвет, которым будет заполнен буфер кадра. Первые три параметра команды задают R,G и B компоненты цвета и должны принадлежать отрезку [0,1]. Четвертый параметр задает так называемую альфа компоненту (см. п. 6.1). Как правило, он равен 1. По умолчанию цвет – черный (0,0,0,1).
Команда glClear очищает буферы, а параметр buf определяет комбинацию констант, соответствующую буферам, которые нужно очистить (см. главу 6). Типичная программа вызывает команду
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
для очистки буферов цвета и глубины.
Установка положения наблюдателя и преобразования трехмерных объектов (поворот, сдвиг и т.д.) контролируются с помощью задания матриц преобразования. Преобразования объектов и настройка положения виртуальной камеры описаны в главе 3.
Сейчас сосредоточимся на том, как передать в OpenGL описания объектов, находящихся в сцене. Каждый объект является набором примитивов OpenGL.
Достарыңызбен бөлісу: |