Реферат: Класс команд OpenGL. Очистка буфера цвета 14 Структура буферов
Библиотека трехмерной графики Open GL
Оглавление
Оглавление 2
Введение 2
Подготовка файловой системы проекта 3
Подготовка формы проекта 4
Форма сообщений об ошибках 5
Первые команды 7
Класс контекста воспроизведения 7
Класс команд OpenGL. Очистка буфера цвета 14
Структура буферов. Методы Get 17
Примитивы 23
Модуль 0. Точки 23
Модуль 1. Прямые линии 70
Модуль 2. Треугольники 74
Модуль 3. 4-угольники 84
Модуль 4. Многоугольники 89
Remaining 107
Модуль 5. Освещение (lighting) 108
Введение
OpenGL (Open Graphics Library – открытая графическая библиотека) содержит несколько сотен процедур и функций, которые обеспечивают формирование любого 3-мерного образа на экране компьютера. Библиотека OpenGL не требует специальной установки. Все ее процедуры реализованы в файлах opengl32.dll и glu32.dll, поставляемых вместе с OS Windows в каталоге System32.
Полную спецификацию команд, реализованных в модуле opengl32.dll, можно найти на сайте.
Так же на сайте можно найти презентацию этого курса.
В настоящем пособии изложение процедур и функций библиотеки OpenGL сопровождается интерактивными иллюстрациями и примерами конкретного кода на языке C# с применением этих функций. Программный код в целом образует решение (solution), состоящее из отдельных проектов, участвующих в иллюстрирующем приложении.
Читатель может
либо ограничиться общим знакомством с командами библиотеки OpenGL,
либо пойти дальше и поддерживать свое приложение, тестирующее работу отдельных команд OpenGL, используя для этого примеры, описанные в учебнике,
либо, наконец, следуя рекомендациям автора, использовать приведенный им код и участвовать в составлении авторского приложения, иллюстрирующего работу команд OpenGL.
Типичная программа, которая использует команды OpenGL, начинается с создания окна, получающего информацию из области памяти, которая именуется видеобуфером, или буфером кадров (frame buffer). Этому окну сопоставляется специальный контекст воспроизведения (rendering context), необходимый для визуализации работы команд библиотеки OpenGL. Контекст воспроизведения превращает окно в порт вывода команд OpenGL. После создания порта окно готово для визуализации команд OpenGL.
Одни команды OpenGL строят простые геометрические объекты (так называемые примитивы) - точки, сегменты линий, многоугольники. Другие команды определяют внешний вид этих объектов, их цвета, как они освещаются и как проецируются с 3-мерного пространства на 2-мерный экран.
В следующих трех разделах введения описаны технические действия, необходимые для создания приложения, иллюстрирующего работу команд OpenGL.
^ Подготовка файловой системы проекта
Откройте MS Visual Studio 2008 и создайте пока пустой контейнер (solution), в который будут помещаться приложения, иллюстрирующие работу команд графической библиотеки OpenGL. Для этого
В меню File командой New->Project… откройте окно New Project
На левой панели Project types: найдите и откройте узел Other Project Types
Выберите Visual Studio Solutions.
На панели Templates: выберите Blank Solution.
В окошке Name имя Solution1, задаваемое средой по умолчанию, замените slOpenGL.
В строке Location указана маршрутная строка, где будет располагаться папка с именем slOpenGL, содержащая все файлы, входящие в состав slOpenGL; обычно строка Location соответствует маршруту, выводящему на папку Visual Studio 2008\Projects, но удобнее, чтобы не мешать другим пользователям, работающим в этой же среде, организовать внутри каталога Projects новый каталог со своим именем, сохраняя свои проекты в этом подкаталоге.
Нажмите OK.
Добавьте в контейнер slOpenGL два проекта. Для этого
Откройте окно Solution Explorer.
Вызовите контекстное меню (правая кнопка) над строкой Solution ' slOpenGL' (0 projects).
Командой Add->New Project… откройте окно Add New Project.
На панели Templates: выберите шаблон Class Library.
В окошке Name наберите GL. Это будет имя библиотеки, в которую будут собираться классы графической библиотеки в процессе работы над проектом.
Нажмите OK.
Чтобы добавить еще один проект, повторите пункты 1-3.
На панели Templates: выберите шаблон Windows Forms Application.
Дайте имя gl3D. Эти файлы будут главной формой иллюстрирующего приложения.
Нажмите OK.
Откройте вновь окно Solution Explorer и в нем сделайте проект gl3D стартовым. Для этого откройте контекстное меню над именем этого проекта и выберите в нем команду Set As StartUp Project. Шрифт имени проекта gl3D должен стать полужирным. Теперь по команде Start среда будет активировать именно проект gl3D.
В том же окне Solution Explorer командой Rename из контекстного меню измените имена файлов следующим образом Class1.cs -> GL.cs, Form1-> f3D, Program.cs -> pr3D.cs, соглашаясь с предложениями среды.
Рекомендация
Для сохранения проекта на внешнем носителе (флэш-карте и т.п.) необходимо, вообще говоря, сохранять весь каталог решения slOpenGL. Для этого рекомендуется в начале архивировать всю папку slOpenGL в один файл (.rar, .zip и т.п.), который затем переписать на внешний носитель, либо отослать по почте. При работе в общей аудитории это необходимо делать уже потому, что никто не гарантирует сохранность информации в Ваше отсутствие.
^ Подготовка формы проекта
Замените значение Form1 в заголовке формы на 3D. Для этого
Войдите в окно визуального отображения формы f3D.cs [Design]. Там расположено изображение окна проекта с заголовком Form1 по умолчанию.
Щелкните по окну формы мышкой.
Откройте окно Properties.
Найдите в левой колонке свойство Text.
В правой колонке наберите 3D.
Поместите на форму компоненту-контейнер ToolStripContainer. Для этого
Откройте окно ToolBox, где находятся все компоненты, доступные для визуального проектирования.
Найдите и откройте раздел Menus&Toolbars.
Выберите компоненту ToolStripContainer и перетащите ее на форму.
Нажмите команду Dock Fill in Form. По этой команде контейнер займет всю клиентскую область окна формы и будет постоянно так расположен вне зависимости от размеров формы.
Компонента ToolStripContainer объединяет 5 панелей - одну в центре и 4 по краям. Все панели по умолчанию присутствуют и видны. Центральная панель этой компоненты называется Content-панелью. На нее поместите новую компоненту Panel. Для этого
Войдите вновь в окно ToolBox
Откройте раздел Containers.
Найдите компоненту Panel и перетащите ее на центральную панель формы.
Щелкните по кнопке, имеющей форму стрелки, в правом верхнем углу контура панели.
Дайте команду Dock in Parent Container. Новая панель полностью заполнит Content-панель контейнера ToolStripContainer1.
Откройте окно Properties, найдите свойство Name новой панели и замените значение panel1, стоящее там по умолчанию, значением panelGL.
На панель panelGL будет выводиться изображение, формируемое командами OpenGL. Для этого ей будет сопоставлен "порт вывода изображения", или "контекст визуализации" (rendering context), необходимый для работы команд OpenGL. Панели, расположенные по краям компоненты ToolStripContainer, будут использоваться в дальнейшем для размещения элементов управления (меню, строки статуса, кнопок, редакционных окошек и т.д.).
В частности, добавьте на нижнюю панель строку статуса, для чего
Откройте окно ToolBox, где находятся все компоненты, доступные для визуального проектирования.
Найдите и откройте раздел Menus&Toolbars.
Выберите компоненту StatusStrip и перетащите ее на нижнюю панель.
В свойство Items образовавшегося объекта StatusStrip1 добавьте объект типа StatusLabel, который назовите stLabel. В него будет помещаться текстовая информация.
В окне Properties у вновь образованной компоненты stLabel (для выделения компоненты в верхней части окна Properties есть выпадающий список) сотрите длинное значение свойства Text, установленное средой по умолчанию.
Измените стартовое положение окна на экране дисплея. Для этого
Перейдите в окно дизайнера f3D.cs [Design].
Откройте окно Properties .
Из выпадающего списка в верхней части окна Properties установите объект формы f3D, свойства которого намерены изменить.
В списке свойств объекта f3D найдите StartPosition.
В правой колонке установите CenterScreen.
Теперь окно будет всегда открываться в центре экрана.
Описание класса формы f3D среда размещает в двух файлах f3D.cs и f3D.Designer.cs. То, что описание класса разнесено на несколько файлов, указывается модификатором partial, стоящим в заголовке описания. Файл f3D.cs содержит ту часть описания, которая управляется непосредственно пользователем. Файл f3D.Designer.cs содержит описание тех членов класса, которыми управляет дизайнер среды в процессе визуального конструирования. Этот последний файл не рекомендуется редактировать.
Конструктор класса f3D находится в пользовательском файле f3D.cs. Его тело состоит по умолчанию только из вызова метода InitializeComponent(), описанного в файле дизайнера f3D.Designer.cs. После вызова метода InitializeComponent() пользователь может помещать в тело конструктора формы любые операторы, которые необходимы на стадии конструирования объекта формы. В данном случае поместите в тело конструктора после строки InitializeComponent(); операторы, которые делают форму квадратной и максимально заполняющей экран вне зависимости от его размеров и формы:
// Операторы, делающие форму квадратной со стороной side,
// равной минимальной стороне дисплея.
// Класс Screen представляет дисплей или несколько дисплеев.
// Статическое свойство PrimaryScreen класса Screen возвращает главный дисплей
// Свойство Bounds возвращает прямоугольник границ дисплея
int side =
Math.Min(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
// Свойство Size определяет размеры окна
Size = new Size(side, side);
Само тело конструктора f3D() поместите в раздел (region) с именем Ctr (принятое сокращение от слова Constructor) так, чтобы весь код принял следующий вид
#region Ctr
public f3D()
{
InitializeComponent();
// Операторы, делающие форму квадратной со стороной side,
// равной минимальной стороне дисплея.
// Класс Screen представляет дисплей или несколько дисплеев.
// Статическое свойство PrimaryScreen класса Screen возвращает главный дисплей
// Свойство Bounds возвращает прямоугольник границ дисплея
int side =
Math.Min(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
// Свойство Size определяет размеры окна
Size = new Size(side, side);
}
#endregion
Проверьте результат проектирования, активировав приложение командой Start Debugging из меню Debug (кнопка с зеленой стрелочкой на панели быстрого доступа).
^ Форма сообщений об ошибках
При отладке нового приложения практически неизбежны ошибки времени выполнения. Для вывода на экран сообщений о возможных ошибках, можно добавить к проекту форму, которая будет отображаться каждый раз, когда в цикле главной формы возникают ошибки.
Добавьте к проекту gl3D новую форму. Для этого
В окне Solution Explorer получите контекстное меню на строке gl3D.
Командой Add->Windows Form откройте окно Add New Item.
В строке Name поставьте имя файла новой формы ErrorMsgForm.cs и нажмите OK
Измените имя вновь созданной формы на ErrorMsgForm в окне Properties новой формы
В том же окне установите свойство формы StartPosition в CenterScreen
Из окна Tools перенесите на форму объект класса RichBoxText
Назовите этот объект errMsgTextBox
В окне Properties установите его свойство Modifiers в public
Там же установите его свойство Dock в Fill
Теперь проведите редакцию файла проекта pr3D.cs:
Добавьте строку using System.IO в самое начало файла
Вместо строки Application.Run поместите следующий код
try
{
Application.Run(new f3D());
}
catch (Exception e)
{
if
(
MessageBox.Show
(
e.Message + "\nДетали?",
Path.GetFileName(Application.ExecutablePath) + " Ошибка!!",
MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation,
MessageBoxDefaultButton.Button1
) == DialogResult.Yes
)
{
// Если запрошены детали,
// создается окно с редактором errMsgTextBox, в который выводится
// описание ошибки и детальный маршрут к функции, внутри которой ошибка возникла
gl3D.ErrorMsgForm emf = new gl3D.ErrorMsgForm();
// В errMsgTextBox помещается строка с подробным сообщением об ошибке
emf.errMsgTextBox.Text = e.ToString();
// Окно изображается в модальном режиме
// (пока окно не закроется, фокус не переводится на другие окна)
emf.ShowDialog();
// Окно уничтожается в памяти
emf.Dispose();
}
Application.Exit();
}
Для описания ошибок времени выполнения будет использоваться механизм объектов исключительной ситуации. Этот механизм предполагает, что при возникновении ошибки в операторах, находящихся в блоке try (в данном случае практически в любом месте выполняемой программы, т.к. в блоке try находится основной метод Application.Run с формой f3D), управление передается в блок catch, описанный здесь. Параметром блока catch служит объект "e" класса исключительной ситуации Exception, порожденный ошибочным кодом, или намеренно созданный программистом. У объектов класса Exception есть свойство Message, содержащее краткую информацию об ошибке. Метод ToString() объектов класса Exception возвращает полное описание маршрута к источнику ошибки. Проверка работы этого механизма будет проведена ниже на конкретном примере.
Скомпилируйте новую версию проекта.
^ Первые команды
Комплексная цель модуля
Познакомиться с тем, как создается контекст воспроизведения, необходимый для вывода результатов работы команд OpenGL в окно (на панель).
Познакомиться со структурой буферов – разделов памяти, хранящих информацию об отдельных элементах изображения – пикселях.
^ Класс контекста воспроизведения
В этом разделе
Описан класс, позволяющий сопоставить окну (в данном случае панели формы f3D) контекст воспроизведения команд OpenGL. Выполнение методов этого класса является необходимым условием получения изображения.
В конструкторе формы f3D создается экземпляр класса контекста воспроизведения, сопоставляемый панели. Этим завершается подготовка окна (панели) к воспроизведению команд OpenGL.
Для использования команд библиотеки OpenGL следует сопоставить панели panelGL формы f3D так называемый контекст воспроизведения. Контекст воспроизведения является портом, через который команды OpenGL будут выводить результат своей работы в окно (в данном случае на панель panelGL). С этой целью
В окне Solution Explorer в раздел References библиотеки GL командой Add References… через контекстное меню добавьте ссылку на библиотеку System.Windows.Forms из вкладки .NET
В начале созданного Вами библиотечного файла GL.cs добавьте операторы ссылок на две библиотеки, т.е. две строки
using System.Runtime.InteropServices;
using System.Windows.Forms;
Уберите скелет класса GL (имя класса с фигурными скобками), предложенный средой по умолчанию
Добавьте код нового класса glPort следующего содержания
///
/// Управляет созданием и освобождением контекста воспроизведения OpenGL
///
public class glPort : IDisposable
{
///
/// Буфер дублирован.
///
const uint PFD_DOUBLEBUFFER = 0x00000001;
///
/// Буфер может передавать содержание в окно или на поверхность устройства
///
const uint PFD_DRAW_TO_WINDOW = 0x00000004;
///
/// Буфер поддерживает команды OpenGL.
///
const uint PFD_SUPPORT_OPENGL = 0x00000020;
///
/// Описывает формат пикселей изображающей поверхности.
///
[StructLayout(LayoutKind.Sequential)]
class PIXELFORMATDESCRIPTOR
{
internal short nSize = 40;
internal short nVersion = 1;
internal uint dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |PFD_DOUBLEBUFFER;
internal byte iPixelType;
internal byte cColorBits = 32;
internal byte cRedBits;
internal byte cRedShift;
internal byte cGreenBits;
internal byte cGreenShift;
internal byte cBlueBits;
internal byte cBlueShift;
internal byte cAlphaBits = 8;
internal byte cAlphaShift;
internal byte cAccumBits = 8;
internal byte cAccumRedBits;
internal byte cAccumGreenBits;
internal byte cAccumBlueBits;
internal byte cAccumAlphaBits;
internal byte cDepthBits = 32;
internal byte cStencilBits = 8;
internal byte cAuxBuffers;
internal byte iLayerType;
internal byte bReserved;
internal int dwLayerMask;
internal uint dwVisibleMask;
internal uint dwDamageMask;
}
#region Поля и свойства
///
/// Хранит идентификатор библиотечного модуля OpenGL
///
static int openGLdllHandle;
///
/// Хранит дескриптор формата пикселей
///
PIXELFORMATDESCRIPTOR pixelFD = new PIXELFORMATDESCRIPTOR();
///
/// Устанавливает и возвращает текущий контекст устройства
///
public int deviceContext
{
private set;
get;
}
///
/// Хранит текущий контекст воспроизведения
///
int renderContext;
///
/// Хранит идентификатор (хэндл) окна
///
int controlHandle;
#endregion
#region Статические методы
#region Методы установки формата пикселей
///
/// Пытается найти формат пикселей, поддерживаемый данным контекстом устройства и
/// наиболее близким к данному формату.
///
///
/// Определяет контекст устройства, для которого должен быть выбран формат пикселей.
///
///
/// Ссылка на экземпляр структуры типа PIXELFORMATDESCRIPTOR,
/// который определяет требуемый формат пикселя
///
///
/// Индекс искомого формата пикселей. Если функция выполнена успешно,
/// то это значение больше нуля.
/// Если нет, то значение равно нулю.
///
[DllImport("GDI32")]
static extern int ChoosePixelFormat(int dvcContext,
[MarshalAs(UnmanagedType.LPStruct)]PIXELFORMATDESCRIPTOR pfd);
///
/// устанавливает формат пикселя указанного контекста устройства в формат,
/// определенный индексом pixelFormatIndex
///
///
/// Контекст устройства, для которого устанавливается данный формат пикселя
///
///
name="pixelFormatIndex">
/// Индекс формата пикселя
///
///
/// Ссылка на структуру
/// (в данном случае класс, который должен интерпретироваться как структура) типа
/// PIXELFORMATDESCRIPTOR, которая содержит спецификацию формата пикселя.
///
///
/// При успешном завершении возвращает TRUE, в противном случае FALSE.
///
[DllImport("GDI32")]
static extern bool SetPixelFormat(int dvcContext, int pixelFormatIndex,
[MarshalAs(UnmanagedType.LPStruct)]PIXELFORMATDESCRIPTOR pfd);
#endregion
#region Методы манипуляции с контекстами
///
/// Возвращает идентификатор контекста устройства дисплея для клиентской области окна.
/// Контекст может быть использован при вызове функций,
/// создающих изображение на клиентской области окна.
///
///
/// идентификатор (хэндл) окна, чей контекст должен быть возвращен
///
///
/// При успешном завершении возвращает идентификатор контекста устройства,
/// в противном случае 0
///
[DllImport("User32")]
static extern int GetDC(int handle);
///
/// Освобождает контекст устройства для использования другими приложениями.
///
///
/// идентификатор (хэндл) окна, чей контекст должен быть освобожден
///
///
/// идентификатор освобождаемого контекста устройства
///
///
/// При успешном завершении возвращает 1, в противном случае 0
///
[DllImport("User32")]
static extern int ReleaseDC(int handle, int dvcContext);
///
/// Создает новый контекст воспроизведения OpenGL.
/// Контекст воспроизведения соответствует устройству с заданным контекстом.
/// Контекст воспроизведения имеет тот же формат пикселя, что и заданный контекст устройства.
///
///
/// Идентификатор контекста устройства
///
///
/// При успешном завершении возвращает идентификатор контекста воспроизведения,
/// в противном случае 0
///
[DllImport("OPENGL32.DLL")]
static extern int wglCreateContext(int dvcContext);
///
/// Уничтожает контекст воспроизведения
///
///
/// Идентификатор контекста воспроизведения
///
///
/// При успешном завершении возвращает TRUE, в противном случае FALSE.
///
[DllImport("OPENGL32.DLL")]
static extern bool wglDeleteContext(int rndContext);
///
/// Производит обмен содержимого переднего и заднего буферов,
/// если формат пикселя указанного
/// контекста устройства включает задний буфер (двойная буферизация)
///
///
/// Идентификатор контекста устройства
///
///
/// При успешном завершении возвращает TRUE, в противном случае FALSE.
///
[DllImport("GDI32")]
static extern bool SwapBuffers(int dvcContext);
///
/// Делает указанный контекст воспроизведения OpenGL текущим контекстом
/// для данного подпроцесса (нити).
/// Все последующие вызовы команд OpenGL, сделанные в этом подпроцессе,
/// будут выполняться на устройстве
/// с указанным контекстом. Функция может использоваться так же для того, чтобы текущий
/// контекст воспроизведения перестал быть текущим
///
///
/// Идентификатор контекста устройства
///
///
/// Идентификатор контекста воспроизведения. Если это значение 0,
/// то текущий контекст воспроизведения перестает быть текущим.
/// В этом случае второй параметр игнорируется.
///
///
/// При успешном завершении возвращает TRUE, в противном случае FALSE.
///
[DllImport("OPENGL32.DLL")]
static extern bool wglMakeCurrent(int dvcContext, int rndContext);
#endregion
///
/// Вводит исполняемый модуль в адресное пространство вызываемого процесса
///
///
name="funcname">
/// Имя исполняемого модуля
///
///
/// При успешном завершении возвращает идентификатор (хэндл) загруженного модуля,
/// в противном случае 0
///
[DllImport("Kernel32")]
public static extern int LoadLibrary(String funcname);
#endregion
///
/// Вызывает метод wglMakeCurrent для данных контекстов устройства и воспроизведения
///
///
/// Результат, возвращаемый методом wglMakeCurrent
///
public bool MakeCurrent()
{
return wglMakeCurrent(deviceContext, renderContext);
}
///
/// Вызывает метод SwapBuffers для данного контекста устройства
///
///
/// Возвращает результат метода SwapBuffers
///
public bool SwapBuffers()
{
return SwapBuffers(deviceContext);
}
///
/// Определяет идентификатор данного окна, создает контекст устройства,
/// контекст воспроизведения и делает контекст воспроизведения текущим.
///
///
name="control">
/// данное окно
///
public glPort(Control control)
{
// Получение контекста устройства
if (0 == (deviceContext = GetDC(controlHandle = (int)control.Handle)))
throw new Exception("Контекст устройства для данного окна не определен.");
// загрузка библиотеки OpenGL
if (openGLdllHandle == 0)
if (0 == (openGLdllHandle = LoadLibrary("OpenGL32.DLL")))
throw new Exception("Библиотека OPENGL32 не включена в процесс.");
// получение индекса требуемого формата пикселя
int pixelFormatIndex = ChoosePixelFormat(deviceContext, pixelFD);
if (0 == pixelFormatIndex)
throw new Exception("Формат пикселей не определен.");
// установка формата пикселя для данного контекста устройства
if (!SetPixelFormat(deviceContext, pixelFormatIndex, pixelFD))
throw new Exception("Формат пикселей не установлен.");
// создание контекста воспроизведения OpenGL для данного контекста устройства
if (0 == (renderContext = wglCreateContext(deviceContext)))
throw new Exception("Контекст воспроизведения не установлен.");
// контекст воспроизведения делается текущим
if (!wglMakeCurrent(deviceContext, renderContext))
throw new Exception("Контекст не установлен текущим.");
}
///
/// Уничтожает контекст воспроизведения и освобождает контекст устройства текущего окна
///
public void Dispose()
{
// контекст воспроизведения перестает быть текущим
if (!wglMakeCurrent(0, 0))
throw new Exception("Контекст не установлен нулем.");
if (renderContext > 0)
// уничтожается контекст воспроизведения
if (!wglDeleteContext(renderContext))
throw new Exception("Контекст воспроизведения не освобожден.");
if (deviceContext > 0)
// освобождается контекст устройства
if (0 == ReleaseDC(controlHandle, deviceContext))
throw new Exception("Контекст устройства не освобожден.");
renderContext = deviceContext = 0;
}
}
Перенесите этот код и ознакомьтесь с комментариями. Скомпилируйте решение.
К ссылкам проекта gl3D добавьте ссылку на библиотеку GL (контекстное меню над пунктом References проекта gl3D, команда Add references…, вкладка Projects).
Для использования класса glPort с панелью panelGL перейдите к редактированию файла главной формы проекта f3D.cs.
В заголовке файла добавьте ссылку на библиотеку GL командой using GL;
В тело класса f3D добавьте раздел "Рабочие поля и свойства" с описанием поля port
#region Рабочие поля и свойства
///
/// Хранит текущий порт воспроизведения команд OpenGL
///
glPort port;
#endregion
В тело конструктора формы (метод f3D) после операторов установки размеров формы добавьте оператор создания объекта port = new glPort(panelGL); Этот оператор должен создать контекст воспроизведения команд OpenGL на панели panelGL сразу же после создания формы и основных инициализирующих действий.
Выберите окно дизайнера и в окне Properties для формы f3D назначьте обработчик событию FormClosed (вкладка с изображением молнии содержит обработчики событий), дважды щелкнув по полю справа.
Среда откроет тело обработчика этого события с именем f3D_FormClosed. Добавьте в него код освобождения контекстов port.Dispose(); Этот код освободит контексты после закрытия формы. Обработчик поместите в отдельный раздел (region), назвав этот раздел «Обработчики формы»
В тело класса формы f3D добавьте раздел "Методы воспроизведения" с описанием метода RenderFrame
#region Методы воспроизведения
///
/// Устанавливает воспроизводимую сцену и копирует буферы
///
void RenderFrame()
{
if (!port.SwapBuffers())
throw new Exception("Не выполнен обмен буферов.");
}
#endregion
В окне Properties найдите объект panelGL и добавьте обработчик события Paint.
В тело обработчика добавьте оператор вызова созданного метода RenderFrame();
Этот вызов перенесет содержимое заднего буфера панели PanelGL в передний буфер, передав тем самым изображение на экран.
Обработчик panelGL_Paint поместите в раздел "Обработчики panelGL" так, что результат редакции будет выглядеть следующим образом
#region Обработчики panelGL
private void panelGL_Paint(object sender, PaintEventArgs e)
{
RenderFrame();
}
#endregion
Активируйте проект. Если все сделано верно, должны увидеть черную панель.
Пройдите по коду проекта шагами с помощью команды отладчика Step Into из меню Debug. Эта процедура позволит увидеть последовательность выполнения операторов проекта.
Чтобы понять, как работает механизм реакции на ошибки в созданном коде, в библиотеке GL закройте комментаторскими скобками /* … */ строки загрузки библиотеки OpenGL в теле конструктора glPort. Это строки
if (openGLdllHandle == 0)
if (0 == (openGLdllHandle = LoadLibrary("OpenGL32.DLL")))
throw new Exception("Библиотека OPENGL32 не включена в процесс.");
Активируйте проект. Результатом должно быть появление окна сообщения об ошибке типа "Контекст воспроизведения не установлен".
Вновь пройдите по шагам код проекта командой Step Into.
Уберите комментаторские скобки и вернитесь к работающей версии проекта.
Тест рубежного контроля
Что описывает класс PIXELFORMATDESCRIPTOR?
Что делает метод SetPixelFormat?
Каковы параметры метода MakeCurrent?
Что делает метод CreateContext?
Что возвращает метод ChoosePixelFormat?
Как используется метод SwapBuffers?
Как сопоставить контексты воспроизведения двум различным панелям?
Укажите верную последовательность использования методов, перечисленных в вопросах 2-5.
Почему необходимо вызывать метод RenderFrame в обработчике перерисовки панели?
Опишите последовательность выполнения методов в форме f3D на протяжении всего жизненного цикла формы.
^ Класс команд OpenGL. Очистка буфера цвета
В этом разделе
Создается класс команд OpenGL, методы которого будут служить оболочками процедур и функций библиотеки OpenGL.
Применяются команды очистки буфера цвета ClearColor и Clear.
Панель имеет черный цвет, так как по умолчанию цвет всех пикселей в буфере цвета черный – все биты буфера равны нулю. Команды OpenGL позволяют устанавливать произвольный цвет заполнения буфера цвета. Это цвет очистки сцены, или фон изображения.
Откройте библиотеку классов GL и опишите новый статический класс с именем gl, в который будут помещаться методы, отвечающие командам OpenGL. Поместите в класс gl члены, регулирующие цвет заполнения буфера цвета. Эти члены будут объединены областью, названной "Очистка буферов". Описание класса gl примет вид
public static class gl
{
#region Очистка буферов
///
/// Определяет значения цветов в буферах цвета.
/// По умолчанию все 4 составляющих цвета равны нулю
///
///
/// количество красного от 0 до 1
///
///
/// количество зеленого от 0 до 1
///
///
/// количество синего от 0 до 1
///
///
/// количество альфа-компоненты от 0 до 1, участвующей в определении эффекта прозрачности
///
[DllImport("OPENGL32.DLL", EntryPoint = "glClearColor")]
public static extern void ClearColor(float red, float green, float blue, float alpha);
///
/// Идентифицирует буфер цвета в методах Clear и PushAttrib.
///
public const int COLOR_BUFFER_BIT = 0x00004000;
///
/// Очищает буферы внутри порта вывода изображения
///
///
/// Выражение, идентифицирующее буферы, которые должны быть очищены.
/// Четыре маски COLOR_BUFFER_BIT, DEPTH_BUFFER_BIT,
/// ACCUM_BUFFER_BIT и STENCIL_BUFFER_BIT могут быть связаны оператором | (или)
///
[DllImport("OPENGL32.DLL", EntryPoint = "glClear")]
public static extern void Clear(int mask);
#endregion
}
Везде в дальнейшем методы и постоянные, относящиеся к командам OpenGL, будут размещаться в этом классе
В классе формы f3D опишите постоянную цвета, которым будет очищаться буфер цвета
#region Constants
///
/// Хранит цвет фона - цвет очистки буфера цвета (темно-синий)
///
static Color clearColor = Color.FromArgb(0, 0, 51);
#endregion
Опишите так же два новых метода InitGL и BuildFrame. Метод InitGL поместите в раздел "Ctr" следом за описанием конструктора и в него поместите вызов метода, который устанавливает цвет очистки сцены, ее фон
///
/// Инициализирует некоторые атрибуты OpenGL.
///
void InitGL()
{
// Цвет фона темно синий
gl.ClearColor((float)clearColor.R / 255, (float)clearColor.G / 255,
(float)clearColor.B / 255, (float)clearColor.A / 255);
}
Метод BuildFrame будет воспроизводить команды OpenGL, формирующие изображение. Добавьте описание метода BuildFrame к разделу "Методы воспроизведения". Поместите в него команду очистки буфера цвета
///
/// Устанавливает воспроизводимую сцену с помощью команд OpenGL
///
void BuildFrame()
{
// Очистка буферов
gl.Clear(gl.COLOR_BUFFER_BIT);
}
В тело конструктора формы f3D после создания объекта класса glPort добавьте оператор вызова метода InitGL так, что тело конструктора примет вид
public f3D()
{
InitializeComponent();
// Операторы, делающие форму квадратной со стороной side,
// равной минимальной стороне дисплея.
// Класс Screen представляет дисплей или несколько дисплеев.
// Статическое свойство PrimaryScreen класса Screen возвращает главный дисплей
// Свойство Bounds возвращает прямоугольник границ дисплея
int side = Math.Min(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Size = new Size(side, side);
port = new glPort(panelGL);
InitGL();
}
В тело метода RenderFrame() перед командой обмена буферов SwapBuffers добавьте вызов метода BuildFrame() так, что тело метод RenderFrame() примет вид
void RenderFrame()
{
BuildFrame();
if (!port.SwapBuffers())
throw new Exception("Не выполнен обмен буферов.");
}
Убедитесь, что после этой редакции панель стала темно синей. Пройдите пошагово код проекта, уяснив последовательность выполнения операторов.
Тест рубежного контроля
Для чего служит описанный класс gl?
Какой метод определяет цвет фона изображения?
Какой метод очищает буфер цвета, заполняя его заданным фоном?
В какой последовательности следует использовать методы ClearColor, Clear, SwapBuffers?
^ Структура буферов. Методы Get
В этом разделе Вы узнаете
О структуре буферов, хранящих информацию о пикселях экрана
О том, как считывать информацию о состоянии OpenGL
Информация о каждом пикселе хранится в различных областях памяти – буферах цвета, глубины, трафарета, буфере-аккумуляторе. Каждый буфер имеет стандартную структуру. Он состоит из битовых плоскостей. В каждой битовой плоскости хранится часть информации обо всех пикселях, выводимых на экран. На битовой плоскости столько же ячеек, сколько пикселей на экране. В каждой ячейке битовой плоскости может храниться только единичка или ноль – один бит информации. Отсюда название плоскости. Сколько битовых плоскостей в конкретном буфере, столько битов информации о каждом пикселе содержит буфер. Так, если в буфере две битовые плоскости, то на каждый пиксель приходится два бита информации, т.е. может быть 4 типа пикселей, отличающихся числами-индексами 0, 1, 2, 3. В общем случае в буфере с n битовыми плоскостями каждый пиксель может иметь 2n индексов со значениями от 0 до 2n – 1. К примеру, если в буфере красного цвета (Red) 8 битовых плоскостей, то каждый пиксель может иметь 28 = 256 интенсивностей красного в своем цвете.
^ Метод Get. Получение информации о состоянии OpenGL
Ответы на любые вопросы о текущем состоянии настроек OpenGL можно получить, используя метод Get из библиотеки OpenGL.
Метод Get позволяет получить, в частности, информацию об объеме всех буферов, на которые рассчитан формат пикселя. Добавьте в класс gl библиотеки GL раздел "Методы Get и их аргументы" со следующим содержанием
#region Методы Get и их аргументы
// Аргументы метода Get, для определения числа битовых плоскостей
// в буферах цвета RED,GREEN,BLUE,ALPHA
public const int RED_BITS = 0x0D52;
public const int GREEN_BITS = 0x0D53;
public const int BLUE_BITS = 0x0D54;
public const int ALPHA_BITS = 0x0D55;
// Аргумент метода Get, для определения числа битовых плоскостей в буфере глубины
public const int DEPTH_BITS = 0x0D56;
// Аргумент метода Get, для определения числа битовых плоскостей в буфере трафарета
public const int STENCIL_BITS = 0x0D57;
// Аргументы метода Get для определения числа битовых плоскостей в буфере-аккумуляторе
public const int ACCUM_RED_BITS = 0x0D58;
public const int ACCUM_GREEN_BITS = 0x0D59;
public const int ACCUM_BLUE_BITS = 0x0D5A;
public const int ACCUM_ALPHA_BITS = 0x0D5B;
///
/// Возвращает значения параметра с именем prmName в виде массива типа float.
///
[DllImport("OPENGL32.DLL")]
static extern void glGetFloatv(int prmName, float[] parameters);
///
/// Возвращает одно или несколько значений, отвечающих указанному типу параметра.
///
///
/// Символьная постоянная, обозначающая имя параметра,
/// значения которого следует возвратить.
///
///
/// Длина массива возвращаемых значений
///
///
/// Массив значений
///
public static float[] Get(int prmName, int arrayLength)
{
float[] resultArray = new float[arrayLength];
glGetFloatv(prmName, resultArray);
return resultArray;
}
#endregion
Добавьте в метод InitGL формы f3D оператор вывода в строку статуса информации о числе битовых плоскостей буферов цвета, глубины, трафарета и аккумулятора
// Сведения о буферах
stLabel.Text = stLabel.Text +
" Color: Red: " + gl.Get(gl.RED_BITS, 1)[0] +
" Green: " + gl.Get(gl.GREEN_BITS, 1)[0] +
" Blue: " + gl.Get(gl.BLUE_BITS, 1)[0] +
" Alpha: " + gl.Get(gl.ALPHA_BITS, 1)[0] +
" Depth: " + gl.Get(gl.DEPTH_BITS, 1)[0] +
" Stencil: " + gl.Get(gl.STENCIL_BITS, 1)[0] +
" Acc: Red: " + gl.Get(gl.ACCUM_RED_BITS, 1)[0] +
" Green: " + gl.Get(gl.ACCUM_GREEN_BITS, 1)[0] +
" Blue: " + gl.Get(gl.ACCUM_BLUE_BITS, 1)[0];
Посмотрите результат.
^ Метод GetString.
В библиотеке OpenGL есть метод GetString, позволяющий, в частности, получить сведения о версии библиотеки, установленной на компьютере, ее производителе и микросхеме, ответственной за визуализацию команд OpenGL (так называемый Renderer). Добавьте в раздел "Методы Get и их аргументы" класса gl библиотеки GL описание
///
/// Имя объекта-аргумента GetString для определения версии OpenGL.
///
public const int VERSION = 0x1F02;
///
/// Имя объекта-аргумента GetString для определения производителя OpenGL.
///
public const int VENDOR = 0x1F00;
///
/// Имя объекта-аргумента GetString для определения имени визуализатора OpenGL.
/// Возвращаемое имя специфично для конкретной аппаратной платформы компьютера.
///
public const int RENDERER = 0x1F01;
///
/// Возвращает указатель на объект с именем name.
///
[DllImport("OPENGL32.DLL")]
static extern IntPtr glGetString(int name);
///
/// Возвращает строку с объектом с именем name.
///
public static string GetString(int name)
{
IntPtr i = glGetString(name);
return Marshal.PtrToStringAnsi(i);
}
Добавьте к предыдущей редакции метода InitGL оператор вывода в строку статуса информации о версии, производителе и визуализаторе так, ч
еще рефераты
Еще работы по разное
Реферат по разное
Вкр на тему «Компьютерная игра для обучения языку ассемблер школьников старших классов» Введение
18 Сентября 2013
Реферат по разное
Муниципальное общеобразовательное учреждение средняя общеобразовательная школа №67 Железнодорожного района города Ростова-на-Дону
18 Сентября 2013
Реферат по разное
Модель уровней самоидентификации личности
18 Сентября 2013
Реферат по разное
Програма всебічного розвитку дитини "Крок за кроком"
18 Сентября 2013