Open GL in Delphi

Материал из DRKB


Первая программа с использованием OpenGL

Часть 1. Первые полигоны[править | править код]

OpenGL ... Вам потребуется Borland DELPHI v.3-5 и OPENGl32.DLL

Начнём, пожалуй! Для начала скачайте пример ... и посмотрите на его работу... Если Вы видели ВРАЩАЮЩИЙСЯ КУБ, то я Вас поздравляю! Вы только-что запустили Вашу первую программу на OpenGL!!.

А теперь самое интересное начнём разбор полётов...

Нет, если Вы скачали пример, то бросать это не стоит. ЗДЕСЬ ВСЁ ПРОСТО. Откройте новый проект: File -> New -> Application; У Вас успехи (шутка). Теперь в директиву "uses" добавьте "OpenGL" вот так:

  uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
    Dialogs, ExtCtrls, OpenGL, // Подключаем OpenGL32.dll,
    dglut; // модуль для рисования правильных объектов одной строкой кода


Прекрасно!

Создайте обработку таких процедур в Object Inspector - > Events (я, надеюсь, что вы знакомы с Delphi):

    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormResize(Sender: TObject);


А теперь в разделе private сделайте следующее

  private 
    DC: HDC; //   переменные для получения контекста воспроизведения
    hrc: HGLRC; //
    Angle: GLfloat; // угол, на который будет поворачиваться куб
    procedure InitSvet;
    procedure SetPixFormat; // формат пикселя
    procedure Draww;
  protected
    procedure WMPaint(var Msg: TWMPaint); message WM_PAINT; // похожа на OnPaint, сообщение от OnPaint


просто вот так всё и пишите, компилятор не обидится!!

В качестве константы объявим:

const
  MaterialColor: array [0..3] of GLfloat = (0.3, 0.4, 1.0, 1.0);


Оформим процедурки:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Angle := 0;
  DC := GetDC(Handle); // получить окно
  SetPixFormat; // установим формат пикселя
  hrc := wglCreateContext(DC);
  wglMakeCurrent(DC, hrc); // сделаем "текущим контекст воспроизведения
  InitSvet; // включим свет
  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE , @MaterialColor);
  glMatrixMode(GL_MODELVIEW);
  Timer1.Enabled := True; // включим таймер
  GLShadeModel(GL_SMOOTH);
end;

// СВЕТ
procedure TForm1.InitSvet;
const
  fogColor: array [0..3] of GLfloat = (0.7, 0.7, 0.7, 2.0);
var
  fogMode: GLint;
begin
  glEnable(GL_DEPTH_TEST); // разрешить тест глубины
  glEnable(GL_LIGHTING);   // разрешить освещённость
  glEnable(GL_LIGHT0);     // включить нулевую лампу
end;

procedure TForm1.SetPixFormat;
var
  nPixelFormat: Integer;
  pfd: TPixelFormatDescriptor;
begin
  FillChar(pfd, SizeOf(pfd), 0);

  with pfd do
  begin
    nSize := sizeof(pfd);
    nVersion := 1;
    dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
    iPixelType := PFD_TYPE_RGBA;
    cColorBits := 24;
    cDepthBits := 32;
    iLayerType := PFD_MAIN_PLANE;
  end;
  nPixelFormat := ChoosePixelFormat(DC, @pfd);
  SetPixelFormat(DC, nPixelFormat, @pfd);
end;

procedure TForm1.WMPaint(var Msg: TWMPaint);
var
  ps: TPaintStruct;
begin
  BeginPaint(Handle, ps);

  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); // очистить цветовой буфер, и буфер глубины
  glClearColor(0.7, 0.7, 0.7, 0.0); // очищать экран серым цветом
  glLoadIdentity; // загрузить матрицу
  glTranslatef(0.0, 0.0, -9.0);
  glRotatef(Angle / (Random(1) + 1), 1.0, 0.0, 0.0);
  glRotatef(Angle, 0.0, 0.0, 1.0); //
  glpushmatrix; // сохраним текущую систему координат
  glutsolidcube(2); // нарисуем куб с ребром 2
  glpopmatrix; // восстановим систему координат
  SwapBuffers(DC); // перевернём передний и задний буферы

  EndPaint(Handle, ps);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Angle := Angle + 1.0; // увеличиваем угол
  if (Angle >= 360.0) then Angle := 0.0;  // если совершён полный оборот, то вернуть в 0
  InvalidateRect(Handle, nil, False); // перерисовать окно
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  glMatrixMode(GL_PROJECTION); // модель матрицы проекционная
  glLoadIdentity; // загрузить матрицу
  gluPerspective(60.0, Width / Height, 1.0, 10.0);
  glViewport(0, 0, Width, Height); // область вывода весь экран
  glMatrixMode(GL_MODELVIEW); // модель матрицы перспективная
  InvalidateRect(Handle, nil, False); // перерисовать всё окно
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Timer1.Enabled := False;
  wglMakeCurrent(0, 0);  // сделать контекст "текущим"
  wglDeleteContext(hrc); // удалить контекст воспроизведения
  ReleaseDC(Handle, DC); // удалить окно
end;


А теперь запускаем!!!!

Clip0124.png


Часть 2. Туман[править | править код]

Мы сегодня будем работать с туманом... Во всех предыдущих примерах использовался туман, но его действия вы наверное не замечали, но теперь вы это ощутите.

Объявим константу

const
  fogColor: array[0..3] of GLfloat = (0.7, 0.7, 0.7, 2.0); // цвет тумана


Циферки в конце устанавливают следующее: (0.7, 0.7, 0.7, 2.0) 1-ая - красный, 2-ая - синий, 3-ая - зелёный, ну а четвёртая - альфа-канал

Далее переменные:

var
  fogMode: GLint;


Перед тем как юзать, его надо включить:

  glEnable(GL_FOG);
  fogMode := GL_EXP;
  glFogi(GL_FOG_MODE, fogMode);
  glFogfv(GL_FOG_COLOR, @fogColor); // устанавливаем цвет см "const" вверху
  glFogf(GL_FOG_DENSITY,
         0.10 //плотность тумана
         );
  glHint(GL_FOG_HINT, GL_DONT_CARE);


Часть 3. Quadric - объекты[править | править код]

В разделе переменных укажим:

var
  quadObj: NewQuadricObj;

а далее пишем следующее (я просто прокомментирую код WMPaint):

  quadObj := gluNewQuadric; // новый объект
  glRotate(5.0, 0.0, 1.0, 0.0); // повернём
  glPushMatrix; // перейдём к новым координатам, сохранив старые
  glRotated(-90, 1.0, 0.0, 0.0); // ещё раз повернём
  gluSphere(quadObj, 1.3, 20, 20); // а теперь нарисуем сферу "1.3 - радиус",
    // а 20 и 20 - это количество разбиений
  glPopMatrix; // перейдём к старым координатам
  gluDeleteQuadric(quadObj); // эта функция сделает "чёрную" работу

  quadObj := gluNewQuadric;
  glRotate(9.0, 0.0, 7.0, 0.0);
  glPushMatrix;
  glRotated(-270, 1.0, 0.0, 0.0);
  gluCylinder(quadObj, 0.5, 0.5, 2.9, 30, 30); // 0.5- радиус, 0.5 - радиус, 2.9 - высота
  glPopMatrix;
  gluDeleteQuadric(quadObj);


Часть 4. Сглаживание[править | править код]

Сглаживание позволяет получить более красивую картинку. По умолчанию сглаживание включено. За включение/выключение этого самого сглаживания отвечает процедура glShadeModel. Параметры у неё следующие:

  • GL_SMOOTH - установлено по-умолчанию
  • GL_FLAT - отключение режима сглаживания

Кстати интерполяция цветов происходит ТОЛЬКО при включённом сглаживании! Как в этой демке

Существенные различия в работе процедуры с разными параметрами видны невооружонным глазом:

Clip0125.png Clip0126.png


Часть 5. GLAux[править | править код]

До этого мы писали программы с использованием OpenGL и GLUT. Но SGI* приготовила программистам ещё одну библиотеку. GLAUX - библиотека, где есть всё для работы с OpenGL (чтение файла растра, наложение текстуры, построение примитивов...). Правда одно маленькое замечание: в разделе Инструмент вы найдёте glaux.dll в архиве RAR (~160kb), но в распакованном виде она "весит" !1.32 Mb!, и вам придётся "таскать" этот файл вместе со своей программой. Так же в разделе Инструмент вы найдёте заголовки Этой библиотеки для DELPHI и для C++.

!!!ВНИМАНИЕ!!! Кто может "конвертнуть" заголовки из С++ в DELPHI, тот сделает благородное дело для себя и ОСТАЛЬНЫХ!

А теперь поговорим про программировании с этой библиотекой. Откройте новый проект: File -> New -> Application

Теперь в дириктиву "uses" добавьте "glaux" вот так (файл GLAUX.pas должен быть у вас):

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls,
  Forms, ExtCtrls, Dialogs, glaux // Подключаем Glaux.pas


Далее в процедуре TForm1.draww, после того как переведём камеру в нужную точку функцией

  glTranslatef(0.0, 0.0, -7.0);

можно рисовать всё, что угодно.

procedure TForm1.Draww;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glClearColor(0.7, 0.7, 0.7, 0.0);
  glLoadIdentity;
  glTranslatef(0.0, 0.0, -7.0);
  {}
  auxSolidSphere(2.0);
  {}
  SwapBuffers(DC);
end;


Вот список того, что можно построить:

auxWireSphere(1);
auxSolidSphere(1);
auxWireCube(1);
auxSolidCube(1);
auxWireBox(1, 2, 3);
auxSolidBox(1, 2, 3);
auxWireTorus(1, 2);
auxSolidTorus(1, 2);
auxWireCylinder(1, 2);
auxSolidCylinder(1, 2);
auxWireIcosahedron(1);
auxSolidIcosahedron(1);
auxWireOctahedron(1);
auxSolidOctahedron(1);
auxWireTetrahedron(1);
auxSolidTetrahedron(1);
auxWireDodecahedron(1);
auxSolidDodecahedron(1);
auxWireCone(1, 0.5);
auxSolidCone(1, 0.5);
auxWireTeapot(1);
auxSolidTeapot(1);


Вот и всё!


Source: http://www.ogldelphi.km.ru/about.html
ID: 03944
ID: 03945
ID: 03946
ID: 03947
ID: 03948