Руководство по работе с графической библиотекой OpenGL. Руководство разработано с учетом опыта чтения курса Компьютерная графика
Скачать 0.66 Mb.
|
sizeof ( pfd )); // заполняем структуру pfd.nSize = sizeof(pfd); pfd . nVersion = 1; // флаги показывают, что мы будем использовать // дублирующую буферизацию OpenGL в этом окне Pfd . dwFlags = Pro_DMW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; // полноцветный буфер цвета (8 бит на канал) pfd. cColorBits = 24; // запрашиваем 16 бит на пиксель для буфера глубины pfd.cDepthBits = 16; pfd . iLayerType = PFD_MAIN_PLANE; int iFormat = ChoosePixelFormat (hDC, &pfd ); SetPixelFormat (hDC, iFormat, &pfd ); Рассмотрим подробнее функции, которые используются для установки формата пикселя: int ChoosePixelFormat ( HDC hdc, CONST PDCELFORMATDESCRIPTOR * ppfd ); 148 Глава П. Использование OPENGL в MFC и VCL Эта функция позволяет по контексту графического устройства найти пиксельный формат, максимально удовлетворяющий нашим требованиям, и возвращает его дескриптор. Например, если запрошен 24-битный буфер цвета, а контекст графического устройства предоставляет только 8-битный буфер, то функция возвратит формат пикселя с 8-битным буфером. Функция SetPixelFormat устанавливает формат пикселя в контекст графического устройства: BOOL SetPixelFormat ( HDC hdc , int iPixelFormat , CONST PrXELFORMATDESCRIPTOR * ppfd ); Поскольку мы используем контекст графического устройства с двойным буфером, OpenGL-рисование в контекст происходит в невидимое на экране место в памяти. Это необходимо для предотвращения мерцания. Для того, чтобы изображение появилось на экране, нужно вызвать следующую функцию: SwapBufiers( hDC ); 11.3. Контекст рисования (render context) Контекст рисования определяет в какой контекст устройства будут направляться команды OpenGL. Например, если в программе есть несколько окон OpenGL, то перед вызовом команд OpenGL необходимо указать окно, в которое будут направлены эти команды. С контекстом рисования ассоциировано текущее состояние OpenGL, текстуры, дисплейные списки и т.п. Создание контекста рисования hRC: HGLRC hRC; hRC = wglCreateContext (hDC); Перед использованием контекста необходимо сделать его текущим: 114- Класс GLRC 149 wglMakeCurrent(hDC, hRC); Далее можно свободно использовать команды OpenGL, не забывая вызывать SwapBuffers после окончания рисования кадра. После использования контекста рисования его нужно освободить (обычно перед освобождением соответствующего контекста устройства): wglDeleteContext (hRC); 11.4. Класс GLRC В п.Б.5 приведен пример класса GLRC, реализующий перечисленные операции. Цикл инициализации и рисования с использованием этого класса выглядит следующим образом: GLRC* m_pGLRC; // 1. инициализация окна m_pGLRC = new GLRC(hWnd) ; bool res = m_pGLRG->Create (); if (! res) Error ("Невозможно„создать„контекст„ОрепСЬ" ); // 2. рисование // (обычно в обработчиках события WM_PAMT) bool res = m_pGLRG->MakeCurrent (); if (! res) Error ( "Невозможно„сделать„контекст„текущим" ); // команды OpenGL glClear(GL_COLOR_BUFFER_BLT | GL_DEPTH_BUFFER_BIT) // завершение кадра m_pGLRG->SwapBuffers () ; 150 Глава П. Использование OPENGL в MFC и VCL // 3. уничтожение окна // (обычно в обработчиках события WM_DEJTROY) m_pGLRG->Destroy () ; delete m_pGLRC; 11.5. Использование OpenGL с MFC Если при создании Windows-приложения используется библиотека MFC, то необходимо встроить инициализацию, освобождение контекстов и рисование OpenGL в различные обработчики унаследованных классов MFC. Данная книга не является руководством по программированию с использованием MFC, поэтому ограничимся советами по использованию OpenGL с этой библиотекой: Код инициализации и рисования теперь должен находиться в методах (или вызываться из этих методов) класса, унаследованного от класса CWnd напрямую или косвенно. Для инициализации OpenGL лучше всего использовать метод OnCreate, для рисования —OnPaint, OnUpdate, OnDraw или OnTimer (это зависит от разных факторов, например, от какого именно класса унаследован класс OpenGL-окна и что именно изображается). Для предотвращения мерцания необходимо перегрузить обработчик сообщения WM_ERASEBKGND, иначе Windows будет заливать фон окна перед вызовом обработчика OnPaint Для освобождения подойдет обработчик OnDestroy, а для обработки изменений размера окна — OnSize. Получить идентификатор окна можно с помощью метода CWnd::GetSafeHwnd. 11.5. Использование OPENGL С MFC 151 Пример класса окна, рисование в которое осуществляется при помощи OpenGL. class OpenGLWindow : public CWnd { public : OpenGLWindow () ; // открытые члены класса private : // закрытые члены класса // сигнатуры этих методов определены заранее MFC // и должны выглядеть именно так afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct ); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnPaintQ; afx_msg void OnDestroy (); // объявление карты сообщений Windows DECLARE_MESSAGE_MAP () // класс для хранения контекстов OpenGL GLRC* m_pGLRC; }; Реализация методов: // конструктор OpenGLWindow : : OpenGLWindow () : m_pGLRC(NULL) { } // заполнение карты сообщений BEGIN_MESSAGE_MAP (OpenGLWindow, CWnd) // стандартные макросы MFC ON_WM_CREATE() ON_WM_PAMT() 152 Глава П. Использование OPENGL в MFC и VCL ON_WM_DESTROY() ON_WM_ERASEBKGND () END_MES3AGE_MAP () // в этом методе реализуем инициализацию afx_msg int OpenGLWindow : : OnCreate ( IPCREATESTRUCT lpCreateStruct) { m_pGLRC = new GLRC(GetSafeHwnd ()); bool res = m_pGLRG->Create (); if (! res) return FALSE; return CWnd: : OnCreate (lpCreateStruct ) ; } // запрещаем заливку фона afx_msg BOOL OpenGLWindow :: OnEraseBkgnd (CDC* pDC) { return FALSE; } // здесь рисуем afx_msg void OpenGLWindow : : OnPaint () { CWnd:: OnPaint (); // делаем текущим m_glRC->MakeCurrent () ; g 1С1 e ar (GL_COLOR_BUFFER_Bir | GL_DEPTH_BUFFER_BrT) ; // рисуем то, что хотим нарисовать <методы рисования OpenGL> 11.6. Использование OPENGL С VCL 153 |