Использование библиотеки 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.
Итак начнем. Приведу иерархию объектов, использованных в данной библиотеке:
Введение[править | править код]
Пример 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;
Пример 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); // добавим дельфина на сцену
Пример 3[править | править код]
Изменения: У объекта Dolphin ищутся нормали к TFace, при этом получается эффект объемного пространства:
Dolphin.CalcNormals; // высчитываем нормали векторов объекта
Dolphin.Center;
Пример 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
Пример 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; // обновим сцену
Пример 6[править | править код]
Соберем все в один пример, добавим возможность печати и покажем FPS при повороте.
Ну вот, самая основа должна стать Вам понятна. Если у Вас не запускаются примеры, проверьте наличие библиотек 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;
Пример 2[править | править код]
Формат DXF является очень неудобным для записи т.к. имеет большие размеры. Для этого автор создает другой формат записи. Добавлена функция чтения-записи.
Пример 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;
Пример 4[править | править код]
Установка прозрачности у текстур (альфа каналов)
thing.Texture.EnvironmentMode := GL_decal; // Установка transparent texturing
thing.Texture.EnvBlendColor[3] := ScrollBar1.Position; // Значение 0 - 255
При запуске программы сначала создается сцена с освещением, но объект создается только после установки, по выполнению процедуры FormCreate_partII.
Пример 5[править | править код]
Программная текстура :) Процесс прост - при нажатии на кнопки с цифрами мы создаем TBitmap и через его Canvas пишем эти цифры. Далее сохраняем этот ТBitmap в файл 'texture.bmp'. Удаляем с экрана компа старую текстуру и загружаем новую из ранее созданного 'texture.bmp'.
Исходные тексты всех примеров находятся в каталогах 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);
Пример 2[править | править код]
Наиболее полно контролируем параметры освещения и даже перемещаем источник в пространстве.
Все, исходные тексты всех примеров этой главы вы найдете в каталогах 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. Для нормального эффекта тумана очень важно подобрать правильный цвет фона и самого тумана. Они должны примерно совпадать /см картинку /.
Файлы для загрузки[править | править код]
- Исходники примеров (102 Кб)
Author: Мироводин Дмитрий
Source: http://www.interface.ru/home.asp?artId=8520