Сообщений 0 Оценка 525 [+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).
Создание любого 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 в битмап с заданным форматом данных. |
Сообщений 0 Оценка 525 [+1/-0] Оценить |