WORD nVersion; // Номер версии
DWORD dwFlags; /* Битовые флаги, определяющие устройство и интерфейс, с которым совместим формат пикселей (табл. 1)
*/
BYTE iPixelType; /* Режим, используемый для изображения цветов. Доступны два значения флага: PFD_TYPE_RGBA - цвет каждого пикселя определяется четырьмя значениями: красным, зеленым, синим и альфа; PFD_TYPE_COLOR INDEX - цвет каждого пикселя определяется индексом в специальной таблице цветов
*/
BYTE cColorBits;// Число битовых плоскостей в каждом буфере // цвета
BYTE cRedBits; // Число битовых плоскостей красного в каждом
// буфере RGBA
BYTE cRedShift;// Смещение от начала числа битовых плоскостей // красного в каждом буфере RGBA
BYTE cGreenBits;
BYTE cGreenShift;
BYTE cBlueBits;
BYTE cBlueShift;
BYTE cAlphaBits;
BYTE cAlphaShift;
BYTE AccumBits; // Число битовых плоскостей в буфере аккумуля- // тора
BYTE cAccumRedBits; // Число битовых плоскостей красного в бу- // фере аккумулятора
BYTE cAccumGreenBits;
BYTE cAccumBlueBits;
BYTE cAccumAlphaBits;
BYTE cDepthBits; |
// Размер буфера глубины (ось z) |
BYTE cStencilBits; |
// Размер буфера трафарета |
BYTE cauxBuffers; |
// Число вспомогательных буферов |
BYTE iLayerType; |
// Может принимать одно из следующих значе- |
|
// ний: |
|
// PFD MAIN_PLANE, |
// PFD OVERLAY_PLANE // PFD_UNDERLAY_PLANE
BYTE bReserved;
DWORD dwLayerMask; // Игнорируется
DWORD dwVisibleMask; // Индекс или цвет прозрачности нижней // плоскости
DWORD dwDamageMask; // Игнорируется
} PIXELFORMATDESCRIPTOR;
Рассмотрим поля этой структуры:
Таблица 1
-----------------------------------------------------------------
Значение Назначение
-----------------------------------------------------------------
PFD_DRAW_TO_WINDOW Разрешено рисование в окне или на поверхности устройства
PFD_DRAW_TO_BITMAP
PFD_SUPPORT_GDI PFD_SUPPORT_OPENGL PFD_GENERIC_FORMAT
Разрешено рисование в битовый массив в памяти
Поддерживается рисование GDI
Поддерживается рисование OpenGL
Формат пикселей поддерживается программной реализацией GDI, называемой также основной реализацией. Если этот флаг не установлен, то формат пикселей поддерживается драйвером устройства или оборудования
PFD_NEED_PALETTE |
Для управления палитрой |
устройства |
|||
|
используются пиксели RGBA. Логическая |
||||
|
палитра требуется для получения |
луч- |
|||
|
шего результата для этого типа предс- |
||||
|
тавления пикселей (в |
частности, |
для |
||
|
проведения гамма-коррекции цветов). |
||||
|
Цвета в палитре должны быть определе- |
||||
|
ны соответственно |
в полях cRedBits, |
|||
|
cRedShift, |
cGreenBits, |
cGreenShift, |
||
|
cBlueBits и cBlueShift. Палитра долж- |
||||
|
на быть создана и инициализирована в |
||||
|
контексте |
устройства до вызова функ- |
|||
|
ции wglMakeCurrent |
|
|
|
|
PFD_NEED_SYSTEM_PALETTE Используется системой со специальным оборудованием для OpenGL, которое поддерживает только одну палитру устройства. Для таких систем используются специальные ускорители и они должны иметь фиксированный размер и порядок, например 3-3-2, при работе в режиме RGB, или должны совпадать с логической палитрой в режиме индексации цветов. При установленном этом флаге вызов функции SetSystemPaletteUse
приводит к отображению "один к одному" логической и системной палитр. Если оборудование для OpenGL поддерживает несколько палитр, и драйвер устройства отводит для них место, нет необходимости устанавливать этот флаг точно так же, как он не устанавливается для основного формата пикселей
PFD_DOUBLEBUFFER Поддерживается режим двойной буферизации.
PFD_SWAP_LAYER_BUPFERS Показывает, может ли устройство менять местами отдельные уровни с форматами пикселей, которые включают верхние и нижние плоскости при двойной буферизации. В противном случае
46
все уровни рассматриваются как единая группа. При установленном этом флаге можно использовать функцию wglSwaplayerBuffers
-----------------------------------------------------------------
Основная реализация OpenGL в Windows поддерживает 24 различных фор мата пикселей. Несмотря на то что каждый формат идентифицируется индексом от 1 до 24, они не являются постоянными, и поэтому никогда нельзя полагаться на порядок индексов. Формат пикселей характеризуется некоторыми свойствами, основным из которых является число битов на пиксел.
Исходно поддерживаются пять битовых плоскостей: 32, 24, 16, 8 и 4 бита на пиксель. Эти пять и еще три формата пикселей, определяемые драйвером дисплея, рассматриваются как внутренний (native) формат. Остальные 16 поровну делятся между организацией других битовых плоскостей и поддержкой битовых массивов (они рассматриваются не как внутренний формат). Все внутренние форматы представлены в таблице:
|
|
Таблица 2 |
----------------------------------------------------------------- |
||
Режим |
Буферизация |
Размер буфера глубины |
----------------------------------------------------------------- |
||
PFD_TYPE_RGBA |
Одинарная |
32 |
|
Одинарная |
16 |
|
Двойная |
32 |
|
Двойная |
16 |
PFD_TYPE_COLOR_INDEX |
Одинарная |
32 |
|
Одинарная |
16 |
|
Двойная |
32 |
|
Двойная |
16 |
----------------------------------------------------------------- |
||
Для работы с этой структурой в Win32 реализованы четыре функции. Контекст устройства может поддерживать несколько форматов пикселей, которые в Windows NT и Windows 95 идентифицируются по значению индекса. При этом текущим может быть только один формат. Прежде чем установить некоторый желательный формат пикселей, необходимо направить системе запрос - поддерживает ли она его. Сделать это можно при помощи функции
int ChoosePixelFormat( HDC hdc,
const PIXELFORMATDESCRIPTOR *ppfd);
Функция просматривает, в контексте устройства hdc, поддерживаемые форматы пикселей, и выбирает наиболее совпадающий с описанным в структуре, на которую указывает ppfd. Поля структуры описаны выше, поэтому здесь остановимся только на дополнительных сведениях (ограничениях) об их использовании.
Если в поле dwFlags структуры установлены какие-либо флаги, то функция учитывает их при поиске лучшего совпадения. Для того чтобы в дальнейшем при работе не возникало никаких неожиданностей, лучше всего задавать их в явном виде. Если для флагов можно не указывать никакого значения, то в поле iPixelType обязательно
должно быть установлено значение либо PFD_TYPE_RGBA, либо PFD_TYPE_COLORINDEX, определяющее метод, используемый для отображения цветов, - тройка RGB или индекс в палитре, соответственно. Аналогично, в поле iLayerType в явном виде следует указать одно из возможных значений - PFD_MAIN_PLANE, PFD_OVERLAY_PLANE или
PFD_UNDERLAY_PLANE, определяющих "рабочий слой". Значения, зада-
ваемые в полях cColorBits, cAlphaBits, cAccumBits, cDepthBits, cStencilBits и cAuxBuffer, должны быть больше или равны нулю. Значения в остальных полях при поиске не учитываются. В случае успешного завершения функция возвращает индекс формата пикселей (начиная с 1), наиболее полно удовлетворяющего заданным параметрам. В случае ошибки возвращается 0.
Вызов этой функции гарантирует, что OpenGL будет работать с форматом пикселей, поддерживаемым устройством, на которое будет осуществляться вывод изображения. Например, если хотелось бы использовать 24-разрядный буфер RGB цветов, а контекст устройства поддерживает только 8-разрядный, то функция возвратит формат пикселей именно с 8-разрядным буфером RGB цветов.
После того как найден формат пикселей, наиболее полно совпадающий с требуемым, можно (и нужно) установить его в контексте устройства:
BOOL SetPixelFormat( HDC hdc,
int iPixelFormat,
CONST PIXELFORMATDESCRIPTOR *ppfd);
Рассмотрим фрагмент кода, демонстрирующий установку наиболее типичных значений формата пикселей:
//Объявление функции с аргументами, задаваемыми по умолчанию
BOOL Create //Класс COpenGL
( CWnd* pWnd,
//Работаем с тройками цветов, а не с палитрами
int iPixelType |
= PFD_TYPE_RGBA, |
|
|
DWORD dwFlags |
= PFD_DOUBLEBUFFER |
| // |
Двойная буферизация |
|
PFD_SUPPORT_OPENGL |
| // |
Поддержка OpenGL |
|
PFD DRAW_TO_WINDOW |
// |
Рисуем в ОКНО |
);
BOOL COpenGL::Create (CWnd* pWnd, int iPixelType, DWORD dwFlags)
{
//Если не создано окно, то рисовать будет некуда
ASSERT(pWnd) ;
//Обязательно нужно указать,
//в каком виде представляются цвета
ASSERT ((iPixelType == PFD_TYPE_RGBA) || (iPixelType == PFD_TYPE_COLORINDEX));
//Создаем структуру
PIXELFORMATDESCRIPTOR pfd;
//Поскольку не все поля этой структуры значимы,
//устанавливаем их в 0
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
// Заполняем значимые поля структуры PIXELFORMATDESCRIPTOR
// |
|
|
pfd.nSize |
= sizeof(PIXELFORMATDESCRIPTOR); |
|
pfd.nVersion |
= 1; |
// Номер версии |
pfd.dwFlags |
= dwFlags; |
|
pfd.iPixelType |
= iPixelType; |
|
pfd.cColorBits |
= 64; |
// красный, зеленый и синий цвета |
47
pfd.cAlphaBits |
= 64; |
// компонента альфа цвета |
pfd.cAccumBits |
=64; |
// буфер аккумулятора |
pfd.cDepthBits |
=64; |
// буфер глубины |
pfd.cStencilBits |
= 64; |
// трафарет |
pfd.iLayerType |
= PFD_MAIN_PLANE; // тип плоскости |
|
...
//Создаем контекст устройства
//m_pdc = new CClientDC (pWnd);
//Выбираем наиболее подходящий формат пикселей
int nPixelFomat = ChoosePixelFormat (m_pdc->m_hDC, &pfd); if(nPixelFormat == 0)
{
MessageBox{"Ошибка при выборе формата пикселей"); return FALSE;
}
//После того как от системы получен формат пикселей, наиболее
//точно совпадающий с запрошенным, устанавливаем его
//
BOOL bResult = SetPixelFormat (m_pdc->m_hDC, nPixelFormat, &pfd);
if(!bResult)
{
MessageBox("Ошибка при установке формaта пикселей"); return FALSE;
}
...
return TRUE;
}
Две оставшиеся функции DescribePixelFormat и GetpixelFormat
позволяют получить информацию о текущих параметрах и индексе формата пикселей соответственно
int DescribePixelFormat( HDC hdc,
int iPixelFormat, UINT nBytes,
LPPIXELFORMATDESCRIPTOR ppfd);
Функция позволяет получить информацию о параметрах формата пикселей, заданного индексом iPixelFormat, для контекста устройства hdc. Полученная информация записывается в структуру PIXELFORMATDESCRIPTOR, определенную указателем ppfd и имеющую размер nBytes. При успешном завершении функция возвращает максимальный доступный индекс формата пикселей и нулевое значение в противном случае. Если требуется определить только максимальное значение индекса, то в качестве параметра ppfd можно использовать NULL.
int GetPixcelFormat(HDC hdc)
При успешном завершении функция возвращает индекс текущего формата пикселей в контексте устройства hdc и 0 - в случае неудачи.
УСТАНОВКА ТЕКУЩЕГО КОНТЕКСТА ВОСПРОИЗВЕДЕНИЯ
Для работы с контекстом воспроизведения в Win32 API реализованы следующие функции
HGLRC wglCreateContext(HDC hdc);
Функция создает новый контекст воспроизведения OpenGL, который подходит для рисования на устройстве, определенном дескриптором hdc. При успешном завершении функция возвращает дескриптор созданного контекста воспроизведения OpenGL и NULL - в случае неудачи.
Создавать можно произвольное число контекстов воспроизведения, но для того, чтобы можно было работать с графикой OpenGL, необходимо установить единственный текущий контекст воспроизведения потока. Сделать это можно при помощи функции:
BOOl wglMakeCurrent(
HDC hdc,
HGLRC hglrc);
Параметр hdc определяет контекст устройства. Это необязательно тот же самый контекст, который использовался при создании контекста воспроизведения, но он должен иметь тот же самый формат пикселов. Второй параметр hglrc определяет контекст воспроизведения ОреnGL. Перед тем как установить новый текущий контекст воспроизведения, ОреnGL сбрасывает предыдущий контекст воспроизведения и заменяет его на новый. Этот механизм задействован для того, чтобы жестко выполнялось требование о том, что текущим в потоке может быть только один контекст воспроизведения. Более того, попытка сделать один и тот же контекст воспроизведения текущим для нескольких потоков приведет к ошибке. Приложение может осуществлять рисование в нескольких потоках. При этом оно должно использовать для каждого из них различные текущие контексты воспроизведения.
Самое удобное место для создания контекста воспроизведения - это обработчик сообщения WM_CREATE, где эти две функции обычно и используются.
BOOL COpenGL::Create (CWnd* pWnd, int iPixelType, DWORD dwFl.ags)
{
// Создаем и делаем текущим контекст воспроизведения if (CreateGLContext (m_pdc) ==FALSE) return -1; return 0;
}
BOOL CPrimView::CreateGLContext (HDC hdc)
{
HGLRC hrc;
// Создаем контекст воспроизведения
if((hrc =::wglCreateContext(m_pdc->m_hDC)) == NULL)
//He удалось создать контекст воспроизведения return FALSE;
//Делаем контекст воспроизведения текущим if(::wglMakeCurrent(hdc, hrc) == FALSE) return FALSE; return TRUE;
}
При желании можно сделать так, что ни один из контекстов воспроизведения не будет текущим. Эта ситуация возникает, например, перед завершением работы - прежде чем удалить контекст воспроизведения, необходимо, чтобы он никем не использовался. Для этого
48
достаточно выполнить следующий вызов:
::wglMakeCurrent (NULL, NULL);
ЗАВЕРШЕНИЕ РАБОТЫ С OPENGL
Как уже не раз отмечалось, одним из правил программирования для Windows является следующее: прежде чем закончить работу - "убери" за собой. В применении к рассматриваемому вопросу это означает, что перед окончанием работы с потоком необходимо удалить контекст воспроизведения. Для этой цели используется функция:
BOOL wglDeleleContext(HGLRC hglrc)
В качестве параметра hglrc используется дескриптор контекста воспроизведения, который необходимо удалить.
После того как удален контекст воспроизведения, следует удалить и ассоциированный с ним контекст устройства.
Текущий контекст воспроизведения можно узнать, если воспользоваться функцией:
HGLRC wglGetCurrentContext()
которая возвращает дескриптор текущего контекста воспроизведения или NULL, если такового нет.
Дескриптор контекста устройства, ассоциированного с контекстом воспроизведения можно получить при помощи функции
HOC wglGetCurrentDC()
Если поток не имеет текущего контекста воспроизведения, функция возвращает NULL.
Ниже приведен фрагмент кода, иллюстрирующий корректное завершение работы с OpenGL.
void COpenGLView::Destroy()
{
if(m_hrc)
{
//Запрашиваем текущий контекст воспроизведения if(m_hrc ==::wglGetCurrentContext())
//Делаем его не текущим
::wglMakeCurrent (NULL, NULL);
//Удаляем контекст воспроизведения
::wglDeleteContext (m_hrc) ; m_hrc = NULL;
}
//Удаляем контекст рабочей области if (m_pdc)
delete m_pdc;
//Для корректного завершения работы
//передаем управления вверх по иерархии
CView::OnDestroy();
}
Структура приложения, использующего OpenGL:
+--------------------------------------- |
+ |
¦ - Получить контекст устройства |
¦ |
¦ - Создать контекст воспроизведения, ¦
¦используя этот контекст устройства ¦
¦ - Сделать его текущим |
|
¦ |
|
||
+---------- |
^---------------------------- |
|
|
+ |
|
|
¦ |
WM_CREATE |
|
|
|
+ |
---------------- |
+ |
+------------- |
|
+ |
¦ Цикл обработки ¦ WM_PAINT |
¦Вызовы команд¦ |
||||
¦ |
сообщений |
+------------- |
> |
OpenGL |
¦ |
+ |
---------------- |
+ |
+------------- |
|
+ |
|
¦ |
WM_DESTROY |
|
|
|
+---------- |
V------------------------- |
|
|
+ |
|
¦ - Сделать контекст |
|
¦ |
|
||
¦ |
воспроизведения не текущим |
|
¦ |
|
|
¦ - Освободить контекст устройства, |
¦ |
|
|||
¦ |
связанный с контекстом |
|
¦ |
|
|
¦ |
воспроизведения |
|
¦ |
|
|
¦ - Удалить контекст воспроизведения ¦ |
|
||||
+------------------------------------ |
|
|
|
+ |
|
Для того чтобы можно было работать с OpenGL в Windows NT и Windows 95, необходимо выполнить следующие требования:
1.В функции PreCreateWindow установить для окна стили
WS_CLIPCHILDREN и WS_CLIPSIBLINGS.
2.В обработчике сообщения WM_CREATE необходимо установить формат пикселей (функции ChoosePixelFormat и SetPixelFormat),
создать контекст воспроизведения (функция wglCreateContext} и сделать его текущим (функция wglMakeCurrent).
3.В обработчике сообщения WM_DESTROY обеспечить удаление контекста воспроизведения (функции wglMakeCurrent и wglDeleteConlext). Кроме перечисленных выше действий необходимо подключить к проекту библиотеки opengl32.1ib и glu32.iib, а также включить заголовочные файлы gl\gl.h и gl\glu.h. Лучше всего это сделать в файле stdafx.h.
ВЕРШИНЫ И СИСТЕМА КООРДИНАТ
Вершина - это точка в трехмерном пространстве. Для описания трехмерного объекта достаточно трех координат. Чтобы учесть влияние перспективы, было предложено описывать точку на плоскости трехэлементным вектором, а в пространстве - четырехэлементным. В этом случае говорят, что точка представлена однородными координатами. Для ее определения в библиотеке реализована команда:
void glVertex[2 3 4][s i f d](type coord) void glVertex[2 3 4][s i f d]v(type coord)
Вызов любой команды glVertex определяется четырьмя координатами: х, у, z и w. При этом соблюдается следующее соглашение: вызов gIVertex2 задает координаты х и у, координата z полагается равной 0, а w - 1; вызов glVertex3 задает координаты х, у и z, a w полагается равной 1; вызов gIVerlex4 задает все четыре координаты.
Примитивы OpenGL
Примитив - это фигура, такая как точка, линия, многоугольник, прямоугольник пикселей или битовый массив, которая рисуется, хранится и которой манипулируют как единым объектом. Другими словами, примитивы - это те элементы, из которых строятся графические образы любой степени сложности. Они определяются группами из одной или нескольких вершин, каждая из которых имеет ассоцииро-
49
ванные с ней данные:
Текущий цвет - задает цвет, который вместе с условиями освещения определяет результирующий цвет вершины. Цвет задается командами glColor для режима RGBA и glIndex для индексного режима.
Текущая позиция растра - используется для определения координат растра при работе с пикселями и битовыми массивами. Задается ко-
мандой glRasterPos.
Текущая нормаль - определяет вектор нормали, ассоциированный с отдельной вершиной, и задает ориентацию содержащей ее поверхности в трехмерном пространстве. Для указания нормали в OpenGL реализована команда gINormal.
Текущие координаты текстуры - определяют местоположение в карте текстуры, которая ассоциируется с вершиной объекта. Задаются ко-
мандой gITexCoord.
Примитив или группа однотипных примитивов, к которым относятся точки, линии, связанные линии, замкнутые линии, треугольники, связанные треугольники с общим ребром, связанные треугольники с общей вершиной, четырехугольники, связанные четырехугольники и многоугольники, определяются внутри командных скобок glBegin/glEnd:
void glBegin (GLenum mode) void glEnd()
Параметр mode указывает примитивы, которые создаются из вершин, определенных между этими командами. Доступными являются следующие символьные константы (n - номер текущей вершины, а N - общее число вершин).
-----------------------------------------------------------------
Значение mode Описание
-----------------------------------------------------------------
GL_POINTS |
Каждая |
вершина |
рассматривается |
как |
||
|
отдельная точка, параметры которой |
не |
||||
|
зависят |
от параметров остальных |
заданных |
|||
|
точек. |
При этом вершина n определяет |
||||
|
точку n. Рисуется N точек |
|
|
|||
GL_LINES |
Каждая |
пара |
вершин |
рассматривается |
как |
|
|
независимый отрезок. Первые две вершины |
|||||
|
определяют |
первый отрезок, следующие |
две |
|||
|
- второй отрезок и т- д., вершины (2n -1) |
|||||
|
и 2n определяют отрезок n. Всего рисуется |
|||||
|
N/2 линий. Если число вершин нечетно, |
то |
||||
|
последняя просто игнорируется. |
|
|
|||
GL_LINE_STRIP |
В этом режиме рисуется последовательность |
|||||
|
из одного или нескольких связанных |
|||||
|
отрезков. Первая вершина задает начало |
|||||
|
первого отрезка, а вторая - конец первого, |
|||||
|
который является также началом второго. |
В |
||||
|
общем случае, вершина n {n > 1) определяет |
|||||
|
начало |
отрезка n |
и конец отрезка (n-1). |
|||
|
Всего рисуется (N-1) отрезок. |
|
|
|||
GL_LINE_LOOP |
Этот режим |
аналогичен предыдущему, |
за |
|||
|
исключением |
того, |
что последняя |
вершина |
||
|
является |
началом отрезка, концом которого |
||||
|
служит |
первая вершина. Вершины n и |
(n+1) |
||||||
|
определяют |
отрезок n. При этом |
последний |
||||||
|
отрезок определяется вершинами N и 1. |
||||||||
|
Всего рисуется N отрезков. |
|
|
|
|||||
GL_TRIANGLES |
Каждая |
тройка вершин рассматривается |
как |
||||||
|
независимый треугольник. Если число вершин |
||||||||
|
не кратно 3, то оставшиеся (одна или две) |
||||||||
|
вершины |
игнорируются. |
Всего рисуется N/3 |
||||||
|
треугольника. |
|
|
|
|
|
|||
GL_TRIANGLE_STRIP |
В |
этом |
режиме рисуется группа |
связанных |
|||||
|
треугольников, имеющих общую грань. Первые |
||||||||
|
три вершины определяют первый треугольник; |
||||||||
|
вторая, |
третья и четвертая - второй и |
т. |
||||||
|
д. Всего рисуется (N-2) треугольника. |
|
|||||||
GL_TRIANGLE_FAN |
В |
этом |
|
режиме |
также |
рисуется |
группа |
||
|
связанных треугольников. Первые три верши- |
||||||||
|
ны определяют первый треугольник; |
|
первая, |
||||||
|
третья и четвертая - второй и т. д. Верши- |
||||||||
|
ны 1, (n+1) и (n+2) определяют треугольник |
||||||||
|
n. Всего рисуется (N-2) треугольника |
|
|||||||
GL_QUADS |
Каждая |
|
группа |
из |
четырех |
|
вершин |
||
|
рассматривается как |
независимый четыреху- |
|||||||
|
гольник. Вершины (4n-3), (4n-2), (4n-1) и |
||||||||
|
4n определяют четырехугольник n. Если чис- |
||||||||
|
ло вершин не кратно 4, |
то оставшиеся (од- |
|||||||
|
на, две или три) вершины игнорируются. |
||||||||
|
Всего рисуется N/4 четырех угольника. |
|
|||||||
GL_QUAD_STRIP |
Рисует |
|
связанную |
|
группу |
||||
|
четырехугольников. Первые четыре вершины |
||||||||
|
определяют |
первый |
четырехугольник; |
||||||
|
третья, четвертая, пятая и шестая вершины |
||||||||
|
- |
второй |
и т. д. Всего рисуется |
|
(N-2)/2 |
||||
|
четырехугольника |
|
|
|
|
|
|||
GL_POLYGON |
Рисует |
отдельный выпуклый многоугольник, |
|||||||
|
заданный вершинами от 1 до N |
|
|
|
|||||
ОСНОВНЫЕ ЭТАПЫ ОБРАБОТКИ ВЕРШИН И АССОЦИИРОВАННЫХ С НИМИ ТЕКУЩИХ ЗНАЧЕНИЙ
После того как установлен формат пикселей, т. е. - библиотека OpenGL присоединена к Windows, необходимо определить такой цвет, который лучше всего воспринимается в качестве фона. Осуществляется это при помощи команды
void glСlеагСоlог(
GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
Эта команда определяет красный, зеленый, синий и альфа компоненты цвета, которые используются при очистке буферов цвета. Значения аргументов red, green, blue и alpha ограничены диапазоном [0, 1] и по умолчанию установлены в 0.
После того как значение цвета определено, установить его можно командой
void glClear(GLbitfield mask);
mask - определяет очищаемые буферы, которые могут задаваться при
50