Начиная с этго номера, мы начинаем знакомиться с OpenGL. Как и все другие занятия, это сразу же начнётся с реального примера. Посмотри на рисунок 1. Вот такая у нас получится программа.
Рис 1. Пример работы программы
Для того, чтобы использовать функции OpenGL тебе понадобится подключить два файла: GL и GLU. Для этого напиши имена этих файлов в разделе Uses в начале файла. Оба этих файла ты можешь забрать вместе с исходниками в конце статьи. Начинаем программировать. Для начала нам понадобиться две переменные. Их ты должен объявить в разделе private
В первой строчке мы получаем контекст рисования на форме, и сохраняем его в созданной нами переменной DC. Во второй строке мы вызываем процедуру, которая будет устанавливать формат пиксела. Эту процедуру мы напишем чуть позже. Третья строка на основе контекста формы создаёт OpenGL контекст рисования. И последняя строка делает OpenGL контекст активным. Теперь перейдём к процедуре PixelFormat .
В разделе private , после объявленных нами переменных объяви процедуру.
procedure PixelFormat;
Теперь нажми Ctrl+Alt+C после этого Delphi создаст пустую процедуру и переместит тебя в неё. В ней нужно написать следующее:
procedure TForm1.PixelFormat;
var
nPixelFormat:Integer;
pfd:TPixelFormatDescriptor;
begin
FillChar(pfd,Sizeof(pfd),0); // заполняем структуру pfd нулями.
pfd.nSize:=sizeof(pfd); // Заполняем размер структуры.
pfd.nVersion:=1; //Версия
pfd.dwFlags:=PFD_DOUBLEBUFFER+PFD_SUPPORT_OPENGL+
PFD_DRAW_TO_WINDOW; //Флаги контекста
pfd.iPixelType:=PFD_TYPE_RGBA; //Тип цвета
pfd.cColorBits:=24; //Соличество цветов
pfd.cAlphaBits:=64;
pfd.cAccumBits:=64;
pfd.cDepthBits:=32;
pfd.cStencilBits:=64;
pfd.iLayerType:=PFD_MAIN_PLANE;
nPixelFormat:=ChoosePixelFormat(DC,@pfd);
if nPixelFormat<>0 then
SetPixelFormat(DC,nPixelFormat,@pfd);
end;
Самое интересное для нас это флаги:
PFD_DOUBLEBUFFER - при рисовании будет использована двойная буферизация.
PFD_SUPPORT_OPENGL - Этот флаг говорит, что окно будет поддерживать OpenGL
PFD_DRAW_TO_WINDOW - Этот флаг говорит, что рисование будет происходить в окне.
С остальным ты разберёшься сам по комментариям. А теперь небольшое замечание: параметры pfd.cColorBits, pfd.cAlphaBits и так далее можно назначать хоть 128. В этом случае OpenGL создаст максимально близкий по возможностям к этим значениям контекст.
ChoosePixelFormat -запрашиваем формат пиксела. В качестве первого параметра мы передаём контекст устройства в котором собираемся рисовать. Второй параметр - структура, которую мы уже заполнили. В этой структуре хранятся данные о запрашиваемом нами формате пиксела. Если возвращаемое значение не равно нулю, то всё в порядке.
Переходим к последнему этапу подготовки к рисованию. Создай обработчик события OnPaint , в нём нужно написать следующее:
glMatrixMode(GL_PROJECTION); // Устанавливаем матрицу
glLoadIdentity( ); // Загружаем единичную матрицу
if width <= height then
glOrtho (-2, 2, -2*height/width, 2*height/width, -10.0, 10.0)
else
glOrtho (-2*width/height, 2*width/height, -2, 2, -10.0, 10.0);
glViewport(0, 0, width, height); //Область видимости на форме
Со всем, что здесь происходит ты разберёшься по комментариям, я только объясню действие функции glOrtho. Эта процедура устанавливает область отсечения. Все точки выходящие за эту область будут отсечены.
Теперь мы готовы к рисованию с помощью OpenGL. В обработчике OnPaint мы напишем следующее:
var
ps:TPaintStruct;
begin
BeginPaint(Handle,ps); //Начало рисования
glClearColor(1,0.5,0.5,1);//Выставляем цвет фона
glClear(GL_COLOR_BUFFER_BIT);// Очищаем нарисованное ранее
glPointSize(10);//Выставляем размер точки
glColor3f (0.0, 1.0, 0.0);//Выбираем цвет для рисования
glBegin(GL_POINTS); // рисуем две точки
glVertex3f(1.25,1.25,0);
glVertex3f(-1.25,-1.25,0);
glEnd;
glEnable(GL_POINT_SMOOTH); //Включаем режим сглаживания
glBegin(GL_POINTS);// рисуем ещё две точки
glColor3f (1.0, 0.0, 0.0);
glVertex3f(1.25,-1.25,0);
glVertex3f(-1.25,1.25,0);
glEnd;
glColor3f (0.0, 0.0, 1.0);
glBegin(GL_LINES); //Рисуем две линии
glVertex3f(1.0,-1.0,0);
glVertex3f(-1.0,1.0,0);
glVertex3f(1,1,0);
glVertex3f(-1,-1,0);
glEnd;
glFlush();//Конец рисования OpenGL
swapBuffers(dc);//Вывести буфер на экран
EndPaint(Handle,ps);//Конец рисования
Я постарался написать комментарии, чтобы ты мог разобраться с тем, что здесь происходит. Рисование всех объектов начинается с glBegin. В скобках мы передаём значение, указывающее на тип объекта который будет рисоваться. Например:
glBegin(GL_POINTS); // рисуем две точки
glVertex3f(1.25,1.25,0); // Положение точки 1
glVertex3f(-1.25,-1.25,0);// Положение точки 2
glEnd;
Эта конструкция рисует одну точку. glVertex3f(x,y,z) - точка в позиции X,Y,Z.
glEnable - включает и выключает специальные режимы рисования. Мы использовали эту функцию, чтобы включить сглаживание, после чего наши точки стали круглыми.
Конструкция glBegin(GL_LINES) - нарисовала две линии (из первой точки во вторую и из третей в четвёртую). В конструкции GL_LINES должно быть чётное число точек. Если будет три точки, то третья точка отбрасывается.
Замечания к цвету. Цвет задаётся с помощью функции glColor3f (интенсивность красного, интенсивность зелёного, интенсивность синего). Интенсивность цвета изменяется от нуля до 1. Это не совсем привычно для нас, ведь мы привыкли, что цвет изменяется от 0 до 255, но к этому ты быстро привыкнешь.
После рисования нужно уничтожить всё, что мы намудрили. Для этого в обработчике события OnDistroy напиши:
Первая программа на OpenGL готова. В следующем номере я продолжу тебя знакомить с программированием на OpenGL с использованием Delphi. И пусть все те, кто считает Delphi не пригодным для этого, гниют в аду.