Использование OpenGL в .Net

Базовый класс

Автор: Попов Юрий
Опубликовано: 05.07.2004
Версия текста: 1.0

Введение
Аналоги
Быстрый старт
Подробности
Методы

Пример использования
Исходные тексты

Введение

Новые технологии появляются как грибы после дождя, но и старые не спешат уходить со сцены. Из-за этого диалектического процесса часто возникает необходимость «подружить» новое и старое. Представляемый контрол появился на свет благодаря тому, что мне понадобилось использовать «старый добрый» OpenGL в «новом» .Net. Это оказалось совсем не сложно. Разработанный класс OpenGLControl может быть с легкостью использован в качестве базового для любого контрола, в котором необходимо использовать OpenGL.

Аналоги

Одним из наиболее популярных врапперов для OpenGL является CsGL http://csgl.sourceforge.net/. Однако платой за использование CsGL является необходимость распространять вместе с приложением две дополнительные DLL’ки. OpenGLControl свободен от этого недостатка – весь его код содержится в одном файле OpenGLControl.cs, также он имеет более простую и понятную структуру. Недостаток OpenGLControl: импортированы не все функции и константы OpenGL. Необходимые функции вы можете с легкостью импортировать воспользовавшись атрибутом DllImport. Об атрибуте DllImport подробно рассказано в статье Алексея Дубовцева Взаимодействие с DLL. Константы OpenGL описываются как константные члены класса. Описание импортированных функций и констант расположено в начале класса OpenGLControl и для удобства разделено на регионы.

Пример описания функции OpenGL:

[DllImport("opengl32.dll")] publicstaticexternvoid glBegin(uint mode);

Пример описания константы OpenGL:

      public
      const System.UInt32 PFD_DRAW_TO_WINDOW = 0x00000004;

Быстрый старт

Минимальные действия для создания своего контрола, использующего OpenGL

      private
      void UserControl1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
	// Активируем контекст OpenGL
	ActivateContext();

	// Цвет фона - используем свойство BackColor, унаследованное от Control
	glClearColor((float)BackColor.R / 255, (float)BackColor.G / 255, (float)BackColor.B / 255, (float)BackColor.A / 255);
			
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// Смещение по оси Z
	glTranslatef(0, 0, -5);
	// Поворот сцены
	glRotatef(20, 0.3f, -0.4f, 0.2f);

	// Задаем цвет используя свойство ForeColor, унаследованное от Control
	glColor3ub(ForeColor.R, ForeColor.G, ForeColor.B);

	// Рисуем квадрат в плоскости OXY
	glBegin(GL_QUADS);
	glVertex3f(0, 0, 0);
	glVertex3f(1, 0, 0);
	glVertex3f(1, 1, 0);
	glVertex3f(0, 1, 0);
	glEnd();

	// Переключаем буфера
	SwapBuffers();
	// Деактивируем контекст OpenGL
	DeactivateContext();
}


Глобальные настройки конечного автомата OpenGL, которые не будут меняться в процессе работы, удобно выполнять переопределив метод OnInitScene.

Подробности

Активация/деактивация контекста

Активация и деактивация контекста необходима для корректной работы контрола в MDI приложении (или при размещении на форме нескольких контролов). Метод ActivateContext вызывает функцию wglMakeCurrent с параметрами (hdc, hrc) а метод DeactivateContext вызывает ту же функцию, но с параметрами (IntPtr.Zero, IntPtr.Zero).

Структура PIXELFORMATDESCRIPTOR

Создание любого OpenGL-окна начинается с заполнения полей этой структуры. По умолчанию, структура PIXELFORMATDESCRIPTOR инициализируется следующим образом:

nSize = (ushort)Marshal.SizeOf(this);
nVersion = 1;
dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
iPixelType = PFD_TYPE_RGBA;
cColorBits = 24;
cRedBits = 24; cRedShift = 0;
cGreenBits = 24; cGreenShift = 0; 
cBlueBits = 24; cBlueShift = 0;
cAlphaBits = 0; cAlphaShift = 0;
cAccumBits = cAccumRedBits = cAccumGreenBits = cAccumBlueBits = cAccumAlphaBits = 0;
cDepthBits = 32;
cStencilBits = 0;
cAuxBuffers = 0;
iLayerType = 0;
bReserved = 0;
dwLayerMask = dwVisibleMask = dwDamageMask = 0;

Вы можете по-другому инициализировать поля этой структуры, переопределив метод OnPreparePFD.

Методы

Переопределяемые методы

protected virtual void OnPreparePFD(ref PIXELFORMATDESCRIPTOR pfd) Вызывается перед созданием окна OpenGL. Переопределив этот метод, вы можете инициализировать поля структуры PIXELFORMATDESCRIPTOR значениями, отличными, от значений по умолчанию.
protected virtual void OnInitScene() Вызывается сразу после успешного создания окна OpenGL. Переопределив этот метод, вы можете выполнить подготовку сцены OpenGL (например, включить тест глубины или другие глобальные настройки конечного автомата OpenGL, которые не будут меняться в процессе работы). В данном методе не требуется подключать/отключать контекст OpenGL.
protected virtual void OnSetViewport() Вызывается из обработчика события SizeChanged для установки области просмотра (viewport area) окна OpenGL. По умолчанию, область просмотра занимает всю доступную клиентскую область окна. Переопределив этот метод, вы сможете самостоятельно задавать область просмотра. В данном методе не требуется подключать/отключать контекст OpenGL.
protected virtual void SetProjection() Вызывается из обработчика события SizeChanged для установки типа проекции. По умолчанию задается перспективная проекция. Переопределив этот метод, вы сможете самостоятельно задавать тип проекции. В данном методе не требуется подключать/отключать контекст OpenGL.

Общие методы

protected void ActivateContext() Активирует контекст OpenGL.
protected void DeactivateContext() Деактивирует контекст OpenGL.
protected void SwapBuffers() Осуществляет обмен переднего (front) и заднего (rear) буферов.
protected Bitmap ToBitmap() Сохраняет окно OpenGL в битмап с форматом данных System.Drawing.Imaging.PixelFormat.Format24bppRgb.
protected Bitmap ToBitmap(System.Drawing.Imaging.PixelFormat pf) Сохраняет окно OpenGL в битмап с заданным форматом данных.


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