Скачать пример программы (.rar, 151k)
Один из способов улучшения качества синтезированного изображения является полноэкранное сглаживание или <устранение ступенчатости> (anti-aliasing), подавляющей <лестничный эффект> (aliasing). Благодаря бурному развитию аппаратных ускорителей 3-х мерной визуализации этот метод стал широко использоваться в системах интерактивной визуализации. В этой статье на небольшом примере будет рассмотрена реализация полноэкранного сглаживания с использованием библиотеки OpenGL. Описанный способ будет работать на большинстве современных ускорителей, производства как фирмы NVIDIA, так и ATI.
Лестничный эффект значительно снижает качество интерактивной визуализации. Особенно это заметно если сцена содержит большое количество тонких объектов и линий. Поэтому даже частичное устранение этого эффекта резко повышает общее качество визуализации и делает его более приятным для глаз, т.к. подавляется раздражающее <дрожание> пикселей.
Одним из самых эффективных способов его подавления является полноэкранное сглаживание. В современных графических ускорителях полноэкранное сглаживание реализуется методом мултисэмплирования (multi-sampling). В этом случае, внутри каждого пикселя вместо одной точки вычисляется сразу несколько, значения цветов которых смешиваются. Количество точек определяет режим мультисэмплирования. Сейчас многими ускорителями поддерживаются 2-х, 4-х и 6-и точечные режимы.
В этой статье описывается два способа включения поддержки полноэкранного сглаживания при работе с библиотекой OpenGL с использованием компонента UtilsGL из библиотеки GML.
Предложенный пример реализован под MVSC 6.0 c использованием библиотеки GMLib, а именно ее компонента UtilsGL версии 1.0.1. Для запуска приложения потребуется компьютер с операционной системой Windows ME, 2000 или XP с установленным графическим акселератором, поддерживающим полноэкранное сглаживание методом мульти-сэмплинга. (Например, ATI Radeon 9600,9700,9800 или GeForce FX ).
Для понимания примера необходимы базовые знания библиотек MFC и OpenGL.
Компонент UtilsGL из библиотеки GML разработан специально для упрощения процедуры создания контекста OpenGL с требуемыми свойствами. Он состоит из:
Обычную схему создания контекста OpenGL можно представить так:

Рис 1 Стандартная схема создания контекста OpenGL
Процедура создания окна и получения HWND относительно проста и хорошо описана в MSDN и других источниках, поэтому в данной статье подробнее не рассматривается.
Более детально сейчас будет рассмотрена схема создания контекста OpenGL с использованием gml::GLRC. До создания контекста необходимо создать окно и проверить полученное значение hWnd на корректность.
Функция Create из gml::GLRC создает стандартное окно с двойной буферизацией и обычными параметрами:
bool Create()
{
int nPixelFormat = 0;
DWORD flags;
flags = PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER; // Must Support Double Buffering
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof (PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
flags,
PFD_TYPE_RGBA, // Request An RGBA Format
24, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
1, // Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
32, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
pfd.cAlphaBits = 8;
nPixelFormat = ChoosePixelFormat( m_dc, &pfd ); // Выбираем Правильный формат пикселя
VERIFY( SetPixelFormat( m_dc, nPixelFormat, &pfd ) ); // Устанавливаем выбранный формат
m_glrc = wglCreateContext( m_dc ); // Создаем контекст
return MakeCurrent(); // Делаем его текущим
}
Таким образом, при использования gml::GLRC вся процедура создания окна записывается следующим образом:
// :
// Мы создали hWnd и проверили на правильность
// У нас определен член класса нашей программы Program
// gml::GLRC* m_rc;
// Которому при инициализации присваивается NULL
// Теперь надо его создать правильно
m_rc = new gml::GLRC( hWnd );
if( !m_rc->Create() )
{
// произошла ошибка про создании контекста -- обработать
}
// Теперь надо инициализировать OpenGL значениями и параметрами которые необходимы нам в дальнейшем
InitGL();
// После чего мы можем дальше работать с OpenGL как захотим
// ...
Для визуализации сцены в обработчике OnPaint необходимо сделать контекст текущим, отрисовать сцену, а затем вызвать SwepBuffers() для переключения буфера экрана и вывода изображения на экран.
void Program::OnPaint()
{
m_rc->MakeCurrent();
// Работаем с OpenGL - наш Rendering Pipeline
m_rc->SwapBuffers();
}
Главное отличие данной схемы от стандартной заключается в необходимости проверки контекста на возможность использования полноэкранного сглаживания в режиме мульти-сэмплинга. Для этого после создания контекста проверяется формат пикселя. Однако, по спецификации Microsoft функция SetPixelFormat() может быть вызвана только один раз для каждого окна (hWnd). Это было сделано для поддержки многопоточных приложений, но значительно затрудняет реализацию полноэкранного сглаживания.
Существует два различных способа решения этой проблемы. Мы можем либо создать текущее окно заново, либо создать дополнительно, временное окно для
Это наиболее широко используемый вариант, подходящий для небольших программ или для проектов, в которых визуализация результата является второстепенным требованием и есть возможность встроить поддержку полноэкранного сглаживания внутрь кода создания/удаления основного окна.
//:
// Создаем окно в два прохода
HWND hWnd = CreateWindowEx( /*:*/ )
if( hWnd == 0 )
{
// Ошибка
}
// Создаем экземпляр GLRC
m_rc = new gml::GLRC( hWnd );
if( m_sMultisampleModes. m_bMultisampleSupported )
{
// Создадим контекст с использованием полноэкранного сглаживания в режиме мульти-сэмплинга 4x
if(!m_rc->CreateMultisampled( m_bMultisampleSupported.SetMultisample4x() ) )
{
// Ошибка при создании контекста
}
}
if( !m_rc->Create() )
{
// Ошибка
}
// ...
// Теперь надо инициализировать и проверить возможность полноэкранного сглаживания
// Для этого необходим еще один член класса:
// sMultisampleModes m_sMultisampleModes;
// который используется для сохранения возможностей и pixel format-ов
// ...
// При первом заходе:
bool arbMultisampleSupported = m_rc->IsMultisampleSupported();
if( arbMultisampleSupported )
{
m_sMultisampleModes = m_rc->GetMultisampleModes();
// Теперь надо уничтожить и создать заново окно.
}
else
{
// Сглаживание не поддерживается, следовательно работаем без него
}
// ...
// При втором начинаем работу как обычно
// ...
Осталось только включить режим полноэкранного сглаживания
//На этапе либо инициализации включаем
//glEnable( GL_MULTISAMPLE_ARB );
// А потом выключаем с помощу glDisable();
// Либо динамически при необходимости
// (динамическое включение/выключение поддерживается не всеми видеокартами).
Разработчики ARB сделали режим GL_MULTISAMPLE_ARB динамическим, те он может быть включен и отключен в процессе визуализации. Однако, ввиду особенностей аппаратной реализации полноэкранного сглаживания, при отключении его во время визуализации, графический ускоритель продолжит работать в том же режиме, поэтому скорость визуализации останется прежней, но синтезируемое изображение будет не сглаженным.
Таким образом, отключить полноэкранное сглаживание невозможно с помощью функции glDisable. Необходимо создать окно программы заново с отключенной поддержкой сглаживания с помощью функции GLRC::Create(), а не GLRC::CreateMultisampled().
Данный метод подходит для случаев, когда необходимо определить аппаратные возможности компьютера без отключения основного окна, или нет доступа к процедуре создания/удаления основного окна.
// Основное окно должно поддерживать полноэкранное сглаживание но ему необязательно входить в этот режим.
// Создадим временное окно, в котором ничего не будет рисоваться. Используем временное окно для получения структуры sMultisampleModes
// Для этого вызовем специальную функцию, внутри которой и создается временное окно. В
// качестве возвращаемого значения мы получаем структуру sMultisampleModes.
m_ sMultisampleModes = CheckForMultisample( /*:*/ );
// Переключаемся в режим полноэкранного сглаживания
// Заставляем главное окно перестроится, например, с помощью функции this->Rebuild()
this->Rebuild();
// Далее как и в методе 1
|
<?xml:namespace prefix = v /> |
Без полноэкранного сглаживания |
|
|
Полноэкранное сглаживание в режиме мульти-сэмплирования 2х |
|
|
Полноэкранное сглаживание в режиме мульти-сэмплирования 4х |
|
|
Полноэкранное сглаживание в режиме мульти-сэмплирования 6х |
1. "OpenGL Multisample", GDC2002, http://developer.nvidia.com/object/gdc_ogl_multisample.html
Комментарии
Отправить комментарий