Вторник, 21.11.2017, 05:18

Кибер-Сайт

Приветствую Вас Гость | RSS
Меню сайта
Наши реквизиты
Считаете полезными материалы нашего сайта?
Хотите и можете помочь проекту?
Z222164825293
Категории
Delphi [8]
Delphi, Object Pascal, уроки, статьи, исходники
OpenGL API [9]
Графика на OpenGL API, уроки, статьи, исходники
Blender [9]
Трехмерная графика, моделирование, разработка игр с помощью Blender
3D. Общие вопросы [1]
Наш опрос
Оцените мой сайт
Всего ответов: 91
Статистика
Ваш IP: 54.224.18.114
Онлайн всего: 1
Гостей: 1
Пользователей: 0

Форма входа
Главная » 2013 » Июль » 5 » Создаем программу для рендеринга. Инициализация OpenGL. Урок-2
08:35

Создаем программу для рендеринга. Инициализация OpenGL. Урок-2

Итак, вы решили написать программу, которая осуществляет рендерирг средствами OpenGL. Что для этого нужно? Сначала нужно получить контекст окна приложения, в которое будет осуществляться рендеринг, создать контекст рендеринга OpenGL, затем выбрать созданный контекст рендеринга.

Разберем всё более детально. Для подготовки OpenGL к работе нужно проделать следующие операции.

  1. Получить контекст окна, в которое будет осуществляться рендеринг
  2. Установить предполагаемый формат пикселя, для рисования в окне средствами OpenGL
  3. Выбрать наиболее подходящий формат пикселя из форматов, поддерживаемых операционной системой
  4. Установить выбранный формат пикселя
  5. Создать контекст рендерига OpenGL
  6. Сделать текущим контекст рендерига OpenGL

 

Перейдем от теории к практике. Перед вами пример модуля, который содержит все необходимые методы для создания программы, использующей функции OpenGL, с подробными комментариями.


unit GL_Utils;
 

interface 


uses 
 Windows, OpenGL;
 
type 
 // Структура сохраняет, контекст окна, 
 // контекст рендеринга OpenGL и дескриптор окна 
 TContextData = record 
 DC: HDC; // Контекст окна, в которое осуществляется рендеринг 
 RC: HGLRC; // Контекст рендеринга OpenGL 
 Handle: THandle; // Дескриптор окна, в которое осуществляется рендеринг 
 end;
 

 procedure CreateContext(const Handle: THandle; var ContextData: TContextData); 
 procedure DestroyContext(var ContextData: TContextData);
 

implementation 


// Процедура устанавливает предполагаемый формат пикселей 

procedure SetPFD(var PFD: TPixelFormatDescriptor); 
begin 
 FillChar(PFD, SizeOf(PFD), 0); // Обнуляем PFD 
 with PFD do 
 begin 
 nSize := SizeOf(PFD); // Устанавливаем размер структуры 
 nVersion := 1; // Устанавливаем версию 
 // Устанавливаем флаги буфера пикселей 
 dwFlags := PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER or PFD_SUPPORT_OPENGL; 
 iPixelType := PFD_TYPE_RGBA; // Устанавливаем тип пикселей 
 cColorBits := 24; // Устанавливаем количество битовых плоскостей в буфере цвета 
 cDepthBits := 32; // Устанавливаем размер буфера глубины 
 iLayerType := PFD_MAIN_PLANE; // Устанавливаем тип слоя 
 end; 
end;
 

// Процедура создаёт контекст рендеринга OpenGL и 
// устанавливает контекст окна 
procedure CreateContext(const Handle: THandle; var ContextData: TContextData); 
var 
 PFD: TPixelFormatDescriptor; // Описание формата пикселей 
 IPixelFormat: Integer; // Индекс формата пикселей
 

begin 
// Если хотябы один из контекстов или дескриптор окна не равен нулю, завершаем процесс 
with ContextData do 
 if (DC <> 0) or (RC <> 0) or (ContextData.Handle <> 0) then Exit;
 
 ContextData.Handle := Handle; // Сохраняем дескриптор окна 
 ContextData.DC := GetDC(Handle); // Получаем контекст окна 
 if ContextData.DC = 0 then Exit; // Если контекст не получен - завершаем процесс 
 SetPFD(PFD); // Устанавливаем предполагаемый формат пикселей 
 // Получаем наиболее подходящий формат пикселей 
 IPixelFormat := ChoosePixelFormat(ContextData.DC, @PFD); 
 // Если индекс формата пикселей не получен, завершаем процесс 
 if IPixelFormat = 0 then Exit; 
 // Устанавливаем полученный формат пикселей 
 SetPixelFormat(ContextData.DC, IPixelFormat, @PFD); 
 ContextData.RC := wglCreateContext(ContextData.DC); // Создаем контекст рендеринга OpenGL 
 if ContextData.RC = 0 then Exit; // Если контекст не создан, завершаем процесс 
 // Делаем текущим созданный контекст рендеринга 
 wglMakeCurrent(ContextData.DC, ContextData.RC); 
end; 

// Процедура удаляет контекст рендеринга OpenGL и 
// освобождает контекст окна 
procedure DestroyContext(var ContextData: TContextData); 
begin 
 with ContextData do 
 begin 
 // Если хотя бы один из контекстов либо дескриптор окна равен нулю, завершаем процесс 
 if (DC = 0) or (RC = 0) or (Handle = 0) then Exit; 
 // Сбрасываем текущий контекст рендеринга 
 wglMakeCurrent(0, 0); 
 // Удаляем контекст рендеринга 
 wglDeleteContext(RC); 
 // Освобождаем контекст окна 
 ReleaseDC(Handle, DC); 
 end; 
end; 

end.
 

Модуль содержит две основные процедуры: CreateContext и DestroyContext.

Разберем процедуру CreateContext, которая создает контекст рендеринга OpenGL и устанавливает контекст окна. Процедура сначала проверяет контексты и дескриптор окна (они должны быть установлены в ноль).

 
 with ContextData do if (DC <> 0) or (RC <> 0) or (ContextData.Handle <> 0) then Exit;
 

Переменная ContextData – это запись TContextData, созданная мной для удобства работы с контекстами.

TContextData = record
 DC: HDC; // Контекст окна, в которое осуществляется рендеринг
 RC: HGLRC; // Контекст рендеринга OpenGL
 Handle: THandle; // Дескриптор окна, в которое осуществляется рендеринг
end;

Далее сохраняем дескриптор окна.

 
ContextData.Handle := Handle;


Затем получаем контекст окна с помощью функции Win API.

 
ContextData.DC := GetDC(Handle);

Проверяем контекст.

 
if ContextData.DC = 0 then Exit;

Если контекст равен нулю – завершаем процедуру.

Далее устанавливаем предполагаемый формат пикселя TPixelFormatDescriptor. Рассмотрим эту структуру подробно. Структура TPixelFormatDescriptor – это запись tagPIXELFORMATDESCRIPTOR, которая описана в модуле Windows. Описания полей этой структуры приведены в таблице ниже.

nSize

Размер структуры (обычно устанавливается с помощью функции SizeOf модуля System (nSize := SizeOf(TPixelFormatDescriptor)))

nVersion

Версия (всегда устанавливаем в 1)

dwFlags

Флаги буфера пикселей

iPixelType

Тип данных пикселей

cColorBits

Количество битовых плоскостей в каждом буфере цвета

cRedBits

Количество битовых плоскостей красного в каждом цветовом буфере RGBA

cRedShift

Сдвиг битовых плоскостей красного в каждом цветовом буфере RGBA

cGreenBits

Количество битовых плоскостей зеленого в каждом цветовом буфере RGBA

cGreenShift

Сдвиг битовых плоскостей зеленого в каждом цветовом буфере RGBA

cBlueBits

Количество битовых плоскостей синего в каждом цветовом буфере RGBA

cBlueShift

Сдвиг битовых плоскостей синего в каждом цветовом буфере RGBA

cAlphaBits

Количество битовых плоскостей альфа канала в каждом цветовом буфере RGBA

cAlphaShift

Сдвиг битовых плоскостей альфа канала в каждом цветовом буфере RGBA

cAccumBits

Общее количество битовых плоскостей в буфере накопления

cAccumRedBits

Количество битовых плоскостей красного в буфере накопления

cAccumGreenBits

Количество битовых плоскостей зеленого в буфере накопления

cAccumBlueBits

Количество битовых плоскостей синего в буфере накопления

cAccumAlphaBits

Количество битовых плоскостей альфа канала в буфере накопления

cDepthBits

Размер буфера глубины

cStencilBits

Размер буфера трафарета

cAuxBuffers

Количество дополнительных буферов (дополнительные буферы не поддерживаются)

iLayerType

Тип слоя

bReserved

Не используется (всегда устанавливаем в 0)

dwLayerMask

Маска слоя (игнорируется)

dwVisibleMask

Видимая маска

dwDamageMask

Не используется (всегда устанавливаем в 0)

Чтобы установить формат пикселя вызываем процедуру SetPFD, которая и сохраняет все нужные параметры в структуру TPixelFormatDescriptor.

 
SetPFD(PFD);

 

 
procedure SetPFD(var PFD: TPixelFormatDescriptor); 
begin 
 FillChar(PFD, SizeOf(PFD), 0); // Обнуляем PFD 
 with PFD do 
 begin 
 nSize := SizeOf(PFD); // Устанавливаем размер структуры 
 nVersion := 1; // Устанавливаем версию 
 // Устанавливаем флаги буфера пикселей 
 dwFlags := PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER or PFD_SUPPORT_OPENGL; 
 iPixelType := PFD_TYPE_RGBA; // Устанавливаем тип пикселей 
 cColorBits := 24; // Устанавливаем количество битовых плоскостей в буфере цвета 
 cDepthBits := 32; // Устанавливаем размер буфера глубины 
 iLayerType := PFD_MAIN_PLANE; // Устанавливаем тип слоя 
 end; 
end;

 

Для того, чтобы не присваивать нули каждому параметру TPixelFormatDescriptor, заполняем нулями всю запись с помощью процедуры FillChar, модуля System.

 
FillChar(PFD, SizeOf(PFD), 0);

После очистки структуры PFD, можно приступить к установке нужных (запрашиваемых) значений пиксельного формата. Поле nSize, которое должно содержать размер записи TPixelFormatDescriptor заполняем с помощью функции SizeOf.

 
nSize := SizeOf(PFD);

Далее устанавливаем версию структуры.

 
nVersion := 1;

Затем устанавливаем параметр dwFlags. Это битовая комбинация следующих флагов.

PFD_DRAW_TO_WINDOW

Разрешает вывод в окно

PFD_DOUBLEBUFFER

Разрешает двойную буферизацию

PFD_SUPPORT_OPENGL

Разрешает рисование с помощью OpenGL

Устанавливаем другие параметры.

 
iPixelType := PFD_TYPE_RGBA; // Тип пикселей 
cColorBits := 24; // Количество битовых плоскостей в буфере цвета 
cDepthBits := 32; // Размер буфера глубины 
iLayerType := PFD_MAIN_PLANE; // Тип слоя

Все остальные параметры оставляем равными нулю.

Теперь, когда контекст окна получен и структура TPixelFormatDescriptor заполнена, можно приступить к установке поддерживаемого формата пикселей, который наиболее близок к запрашиваемому PFD. Делается это с помощью функции ChoosePixelFormat.

 
IPixelFormat := ChoosePixelFormat(ContextData.DC, @PFD);

Переменная IPixelFormat сохраняет индекс формата пикселя, который возвращает функция. Если индекс формата не получен – завершаем процесс.

 
if IPixelFormat = 0 then Exit;

Когда формат пикселя установлен, можно приступить к созданию контекста рендеринга OpenGL.

 
ContextData.RC := wglCreateContext(ContextData.DC);

Результат функции сохраняем в запись ContextData.

И в завершении делаем текущим созданный контекст рендеринга с помощью функции wglMakeCurrent:

 
wglMakeCurrent(ContextData.DC, ContextData.RC);

Теперь все готово для рисования инструментами OpenGL. Но об этом я расскажу на следующих занятиях. А сейчас продолжим рассматривать наш модуль.

Перед завершения программы нужно удалить контекст рендеринга OpenGL и освободить контекст окна. Для этого нужно вызвать процедуру DestroyContext. Прежде чем выполнить необходимые действия процедура проверяет контексты и дескриптор окна.

 
if (DC = 0) or (RC = 0) or (Handle = 0) then Exit;

Если хоть один из контекстов равен нулю – процесс завершается.

Далее сбрасываем текущий контекст рендеринга.

 
wglMakeCurrent(0, 0);

Затем удаляем его.

 
wglDeleteContext(RC);

И в завершении освобождаем контекст окна.

 
ReleaseDC(Handle, DC);

Теперь можно испытать наш модуль в действии.

 
unit Unit1; 

interface 

uses 
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, OpenGL, GL_Utils; 

type 
 TForm1 = class(TForm) 
 procedure FormCreate(Sender: TObject); 
 procedure FormDestroy(Sender: TObject); 
 private 
 { Private declarations } 
 public 
 { Public declarations } 
 end; 

var 
 Form1: TForm1; 

implementation 

{$R *.dfm} 

var 
 ContextData: TContextData; // Сохраняет контексты и дескриптор окна 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
 // Заполняем нулями структуру TContextData 
 ZeroMemory(@ContextData, SizeOf(ContextData)); 
 // Создаём контекст рендеринга OpenGL и 
 // устанавливаем контекст окна 
 CreateContext(Handle, ContextData); 
end; 

procedure TForm1.FormDestroy(Sender: TObject);
begin 
 // Удаляем контекст рэндэринга OpenGL и 
 // освобождаем контекст окна 
 DestroyContext(ContextData); 
end; 

end.

Откройте Делфи создайте новый проект, в главном модуле напишите код этого примера и сохраните проект в отдельную папку (он вам понадобится для следующих занятий). Затем создайте модуль и скопируйте в него содержимое примера модуля GL_Utils и сохраните его под именем GL_Utils.pas в папку с проектом или в папку с вашими модулями. Если папка, в которую вы сохранили модуль не подключена к среде разработки Делфи - подключите её (как подключить смотрим здесь). Рекомендую выполнить эти действия, так, как данный модуль понадобится вам в дальнейшем и у вас не будет проблем с линковкой модуля к проекту.

Вот, собственно и все на сегодня. В следующих уроках мы рассмотрим рендеринг средствами OpenGL.

Скачать исходники
Категория: OpenGL API | Просмотров: 2570 | Добавил: Admin | Теги: Уроки OpenGL, OpenGL API | Рейтинг: 0.0/0

Похожие материалы
Всего комментариев: 0
Имя *:
Email *:
Код *:
Поиск
Календарь
«  Июль 2013  »
ПнВтСрЧтПтСбВс
1234567
891011121314
15161718192021
22232425262728
293031
Друзья сайта
  • Скачать Blender
  • Архив записей
    Реклама
    Copyright Кибер-Сайт © 2017 | Используются технологии uCoz