OpenGL в Delphi

       

Параметры вида


В предыдущей главе мы убедились, что объем сцены ограничен кубом с координатами точек вершин по диагоналям (-1, -1, -1) и (1, 1, 1). Начнем дальнейшее изучение с того, что увеличим объем этого пространства. Проект из подкаталога ExOl нам поможет. На сцене присутствует все тот же треугольник, одну из вершин которого можно перемещать по оси Z нажатием клавиши <пробел>, значение координаты вершины выводится в заголовке окна. Теперь мы видим треугольник целиком в пределах большего, чем раньше, объема.
Код перерисовки окна выглядит так:

wglMakeCurrent(Canvas.Handle, hrc);
glViewport(0, 0, ClientWidth, ClientHeight);
9lPushMatrix;
glFrustum (-1, 1, -1, 1, 3, 10); // задаем перспективу
glTranslatef(0.0, 0.0, -5.0); // перенос объекта по оси 1
9lClearColor (0.5, 0.5, 0.75, 1.0);
glClear (GL_COLOR_BUFFER_BIT) ;
glColor3f (1.0, 0.0, 0.5);
glBegin (GLJTRIANGLES);
glVertex3f (-1, -1, 0);
glVertex3f (-1, 1, 0) ;
glVertexSf (1, 0, h);
glEnd;
glPopMatrix;
SwapBuffers (Canvas.Handle);
wglMakeCurrent (0, 0) ;

Основная последовательность действий заключена между командами glPushMatrix и glPopMatrix. Если этого не делать, то при каждой перерисовке окна, например, при изменении его размеров, сцена будет уменьшаться в размерах.
Здесь встречается новая для нас команда - glFrustum, задающая параметры вида, в частности, определяющие область воспроизведения в пространстве. Все, что выходит за пределы этой области, будет отсекаться при воспроизведении. Первые два аргумента задают координаты плоскостей отсечения слева и справа, третий и четвертый параметры определяют координаты плоскостей отсечения снизу и сверху. Последние аргументы задают расстояния до ближней и дальней плоскостей отсечения, значения этих двух параметров должны быть положительными - это не координаты плоскостей, а расстояния от глаза наблюдателя до плоскостей отсечения.

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

Теперь все, что рисуется с нулевым значением координаты Z, не будет видно наблюдателю, поскольку ближнюю плоскость отсечения мы расположили на расстоянии трех единиц от глаза наблюдателя, располагающегося в точке (0, 0, 0). Поэтому перед воспроизведением треугольника смещаем систему координат на пять единиц вниз.
Треугольник удалился от наблюдателя, и его вершины располагаются уже не на границе окна, а сместились вглубь экрана.

Замечание
В главе 6 мы узнаем, как соотнести пространственные и оконные координаты, если видовые параметры заданы с помощью команды glFrustum

Переходим к следующему примеру - проекту из подкаталога Ех02 отличие от первого примера состоит в том, что команды glPushMatrix И glPopMatrix удалены, а перед вызовом команды glFrustum стоит вызов команды glboadidentity. Будем понимать это как действие "вернуться в исходное состояние". При каждой перерисовке экрана перед заданием видовых параметров это следует проделывать, иначе объем сцены будет последовательно отсекаться из предыдущего.

Замечание
Устанавливать видовые параметры не обязательно при каждой перерисовке экрана, достаточно делать это лишь при изменении размеров окна.

Это несложное соображение предваряет следующий пример - проект из подкаталога Ех03. Для повышения надежности работы приложения пользуемся явно получаемой ссылкой на контекст устройства, а не значением свойства canvas.Handle Сразу же после получения контекста воспроизведения делаем его текущим в обработчике события create формы, а непосредственно перед удалением освобождаем контекст в обработчике Destroy.
Теперь такие параметры OpenGL, как цвет фона и цвет примитивов, можно задавать единственный раз - при создании формы, а не выполнять это действие каждый раз при перерисовке экрана. В отличие от всех предыдущих проектов, в данном появляется отдельный обработчик события, связанного с изменением размеров окна. Напомню, раньше при этом событии выполнялся тот же код, что и при перерисовке окна.
Во всех оставшихся примерах, как правило, будет присутствовать отдельный обработчик события, связанного с изменением размеров окна. В этом обработчике задается область вывода и устанавливаются параметры вида, после чего окно необходимо перерисовать:

procedure TfrmGL.FormResize(Sender: TObject);
begin
glViewport (0, 0, ClientWidth, ClientHeight);
glLoadldentity;
glFrustum (-1, 1, -1, 1, 3, 10); // видовые параметры
glTranslatef (0.0, 0.0, -5.0); // начальный сдвиг системы координат
InvalidateRect(Handle, nil. False);
end;

Код, связанный с перерисовкой окна, теперь сокращается и становится более читабельным:

Procedure TfrmGL.FormPaint(Sender: TObject);
WClear (GL_COLOR_BUFFER_BIT);
9lBegin (GLJTRIANGLES) ;
glVertex3f (-1, -1, 0) ;
glVertex3f (-1, 1, 0);
glVertex3f (1, 0, h);
glEnd;
SwapBuffers(DC);
end;

Хоть мы уже и рисуем пространственные картинки, однако почувствовать трехмерность пока не могли. Попробуем нарисовать что-нибудь действительно объемное, например, куб (проект из подкаталога Ex04). Результат работы программы - на Рисунок 3. 1.



Содержание раздела