Использование библиотеки OpenGL

Материал из DRKB

Использование библиотеки OpenGL

Эта достаточно большая статья посвящена обзору библиотеки расширения OpenGL написанная Ricardo Sarmiento. Все примеры приведенные ниже написаны с использованием этой библиотеки - точнее я нашел примеры и написал статью. Cтатья скорее обзор возможностей технологии OpenGL, чем руководство к программированию. Хотя некоторые функции и процедуры Вы можете использовать и для своих приложений - например чтение файлов DXF.

Хочу разъяснить ситуацию со всевозможными версиями библиотек и заголовочных файлов OpenGL.

Начиная с Delphi 3 в каталоге Source можно найти файл OpenGL.pas - это и есть оригинальная версия заголовков библиотеки OpenGL. Она получена трансляцией файлов Gl.h и Glu.h, соответственно с языка C.

Существует еще одно практически стандартное расширение - Glut. В оригинале Glut.h и ее трансляция на Delphi Glut.pas. Это расширение создано для более быстрого построения различных объектов OpenGL и набор полезных процедур.

Все остальные версии библиотек и заголовков OpenGL являются расширениями стандартной версии и пишутся сторонними производителями. Как и та, о которой пойдет речь ниже.

Призываю использовать стандартную библиотеку OpenGL. Во первых вы получите наибольшую быстроту исполнения кода, и совместимость. Но в статье я использую обзор библиотеки расширения OpenGL, почему? Дело в том, что новичку порой сложно разобраться в дебрях программирования, а расширение стандартной библиотеки позволяет быстро написать код и получить зрелищный результат. Именно результат может подтолкнуть вас на дальнейшее изучение библиотеки OpenGL.

Итак начнем. Приведу иерархию объектов, использованных в данной библиотеке:

8520 1.gif


Введение[править | править код]

Пример 1[править | править код]

В этом примере рассмотрены следующие вопросы:

Создание сцены TSceneGL

var
  Scene: TSceneGL;
begin
  Scene := TSceneGL.create; // Создаем новую сцену

Создание объекта TEntity - куб, задание его с помощью TFace, установка цвета и добавление на сцену.

var
  Cube: TEntity;
  Face: TFace;
begin
  Cube := TEntity.Create; // Создаем пустой объект TEntity
  Cube.SetColor(90, 200, 150); // Инициируем цвета R,G,B
  Face := Cube.addFace;
  // Создаем 1-й face в исходном кубе всего 6 граней (в кубе)
  Face.AddVertex(1.0, 1.0, 1.0,0.0, 0.0, 1.0); // добавляем 1-й vertex
  Face.AddVertex(-1.0, 1.0, 1.0,0.0, 0.0, 1.0); // добавляем 2-й vertex
  Face.AddVertex(-1.0, -1.0, 1.0,0.0, 0.0, 1.0);// добавляем 3-й vertex
  Face.AddVertex(1.0, -1.0, 1.0,0.0, 0.0, 1.0);// добавляем 4-й vertex

  Scene.Entities.add(cube);// добавим куб на сцену
end;


Задание источника света Tlight и добавление на сцену.

  Light := TLight.Create(1); // создадим источник света и добавим его на сцену
  Scene.Lights.Add(Light);


Инициализация сцены

  // передадим Handle Panel1 нашей сцене, на ней будет происходить рендеринг
  Scene.InitRC(Panel1.Handle);
  Scene.UpdateArea(Panel1.Width, Panel1.Height);


Простейший поворот объекта

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // изменяем rx, ry,rz
  {...}
  TEntity(Scene.Entities.Items[0]).Rotate(rx, ry, rz); // повернем куб
  Scene.Redraw; // обновим сцену
end;

8520 2.gif


Пример 2[править | править код]

Отличия от предыдущего примера: Оъект TEntity - дельфин задается не через TFace, а грузится из DXF файла - что очень упрощает жизнь.

  Dolphin := TEntity.Create;
  Dolphin.SetColor(100, 100, 160);
  Dolphin.LoadDXF('Dolphin.dxf', True);
  with Dolphin do
  begin
    Move(0, 0, -15); // переместим немного назад
    Rotate(-30, -30, -30); // и повернем
  end;
  Scene.Entities.Add(Dolphin); // добавим дельфина на сцену

8520 3.gif


Пример 3[править | править код]

Изменения: У объекта Dolphin ищутся нормали к TFace, при этом получается эффект объемного пространства:

Dolphin.CalcNormals; // высчитываем нормали векторов объекта
Dolphin.Center;

8520 4.gif


Пример 4[править | править код]

Добавили класс T3DMouse - теперь можно манипулировать объектами.

procedure TForm1.FormCreate(Sender: TObject);
begin
  Mouse := T3DMouse.Create(Dolphin); // Создаем T3DMouse для нашего объекта
  Mouse.Scale(1, 1, 0.1, 1, 1, 1); // задаем скорость перемещения и поворота
end;


Перемещение объекта можно осуществить:

procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  Mouse.Move(X, Y, Shift); // обновляем объект - дельфин в новых координатах
  Scene.Redraw; // перерисуем сцену
end;


Можно установить блокировку на перемещение:

Mouse.Block(4, TSpeedButton(Sender).Down); // блокировка поворота rx

128935.gif


Пример 5[править | править код]

Добавим управление отображением:

case dolphin.wireframe of
  0:
  begin
    SpeedButton5.Caption := 'Линии';
    Dolphin.WireFrame := 1;
  end;
  1:
  begin
    SpeedButton5.Caption := 'Заливка';
    Dolphin.WireFrame := 2;
  end;
  2:
  begin
    SpeedButton5.Caption := 'Точки';
    Dolphin.WireFrame := 0;
  end; 
end;
Scene.Redraw; // обновим сцену

8520 6.gif


Пример 6[править | править код]

Соберем все в один пример, добавим возможность печати и покажем FPS при повороте.

8520 7.gif


Ну вот, самая основа должна стать Вам понятна. Если у Вас не запускаются примеры, проверьте наличие библиотек Opengl32.dll и Glu32.dll. Исходники примеров находятся в каталогах Demo1-XXX.


Текстуры[править | править код]

Эта глава посвящена текстурированию объектов в OpenGL. В каждом примере я даю пояснения только к новому. По этому лучше посмотреть сначала пример 1 потом 2, а не начинать с примера 5. В этой главе описаны примеры использующие фильтрации текстур, и при использовании GL_linear нужен 3D ускоритель, иначе будет работать ОЧЕНЬ медленно.


Пример 1[править | править код]

Закрашиваем полигоны

var
  Point: TVertex;
begin
  // Получаем выбранный полигон при нажатии на панель Panel1 
  Mouse.FindVertex(x, Panel1.Height-y, Scene, Point);
  for i := 1 to numFound do // Для всех полигонов найденных по Mouse.FindVertex
  begin
    poly := VertexHits[i] shr 16;
    vert := VertexHits[i] mod 65536;
    if  (poly < Dolphin.Faces.Count)
    and (vert < TFace(Dolphin.Faces.Items[poly]).Vertices.Count) then
    begin
      // получаем составляющие цвета из ColorActual (TColor) 
      ir := (ColorActual) mod 256; // R
      ig := (ColorActual shr 8) mod 256; // G
      ib := (ColorActual shr 16) mod 256; // B
      TVertex(TFace(Dolphin.Faces.Items[poly].Vertices.Items[vert]).Point.SetColor(ir, ig, ib);
    end;
  end;
end;

8520 8.gif


Пример 2[править | править код]

Формат DXF является очень неудобным для записи т.к. имеет большие размеры. Для этого автор создает другой формат записи. Добавлена функция чтения-записи.

8520 9.gif


Пример 3[править | править код]

Наложение текстур на объект


thing.CreateTexture; // добавим текстуры на объект
thing.Texture.LoadTexture('texture.bmp');
thing.Texture.Automatic := False;

// а далее идет рутинный процесс задания вершин для текстур у каждой поверхности объекта
with thing do
begin
  vertex := TVertex(TFace(thing.Faces.Items[1]).Vertices.Items[0]); // x,y,z =0,0,0
  vertex.tx := 1;
  vertex.tz := 0;
end;

Да в качестве эксперимента вы можете убрать все начиная с with thing do ... end (задания точек для текстур ) и переписать thing.Texture.Automatic := True.

Использование типов фильтрации текстур

thing.Texture.MagFilter := GL_linear;

или

thing.Texture.MagFilter := GL_nearest;

8520 10.gif


Пример 4[править | править код]

Установка прозрачности у текстур (альфа каналов)

thing.Texture.EnvironmentMode := GL_decal; // Установка transparent texturing 
thing.Texture.EnvBlendColor[3] := ScrollBar1.Position; // Значение 0 - 255

При запуске программы сначала создается сцена с освещением, но объект создается только после установки, по выполнению процедуры FormCreate_partII.

8520 11.gif


Пример 5[править | править код]

Программная текстура :) Процесс прост - при нажатии на кнопки с цифрами мы создаем TBitmap и через его Canvas пишем эти цифры. Далее сохраняем этот ТBitmap в файл 'texture.bmp'. Удаляем с экрана компа старую текстуру и загружаем новую из ранее созданного 'texture.bmp'.

8520 12.gif


Исходные тексты всех примеров находятся в каталогах Demo2-XXX


Освещение[править | править код]

Пример 1[править | править код]

В этом примеры показано как задать параметры источника. Ранее источник света задавался по умолчанию. Создадим источник типа прожектор

Light := TLight.Create(1);
Light.LightType := CLspot;
Light.CutOffAngle := 5;
Light.SpotExponent := 100;

Параметры:

  • CutOffAngle - угол расхождения луча.
  • SpotExponent - параметр затухания источника.

Грубо говоря это коэффициент показывающий как далеко пройдет свет. Если SpotExponent=0, то пучок света уходит в бесконечность. Идем далее:

Light.SetOrientation(0, -1, 0);
Light.Source.SetPosition(0, 5, -20);

Задаем ориентацию прожектора и его положение в системе координат.

При изменении позиций полос прокрутки просто меняем компоненты цвета в источнике. Например для Ambient:

SBlightRed.Position := Round(Light.FAmbient[0] * 100);
SBlightGreen.Position := Round(Light.FAmbient[1] * 100);
SBlightBlue.Position := Round(Light.FAmbient[2] * 100);

8520 13.gif


Пример 2[править | править код]

Наиболее полно контролируем параметры освещения и даже перемещаем источник в пространстве.

8520 14.gif


Все, исходные тексты всех примеров этой главы вы найдете в каталогах Demo3-XXX


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

Пример 1[править | править код]

Установить поддержку тумана в сцене очень просто :

var
  Scene: TSceneGL;
begin
  Scene.FogEnabled := True;

Все остальное в примере это установка параметров тумана:

Тип тумана может быть:

fogType := Gl_Linear;
fogType := GL_exp;
fogType := GL_exp2;


Минимальная и максимальная дистанция:

fogMaxDist
fogMinDist


Интенсивность:

fogDensity


Цвет для каждой компоненты RGB :

Scene.FogColor[0]; // R
Scene.FogColor[1]; // G
Scene.FogColor[2]; // B

После каждого изменения параметров не забывайте вызывать Redraw. Для нормального эффекта тумана очень важно подобрать правильный цвет фона и самого тумана. Они должны примерно совпадать /см картинку /.

8520 15.gif

Файлы для загрузки[править | править код]


Author: Мироводин Дмитрий
Source: http://www.interface.ru/home.asp?artId=8520