Tutorial 12 : OpenGL Extensions
Розширення
З кожним новим поколінням, продуктивність графічних карт збільшується, дозволяючи малювати більше трикутників та пікселів. Але продуктивність це не є основною проблемою. NVIDIA, AMD та Intel також покращують їх графічні карти, надаючи нову функціональність. Розглянемо декілька прикладів.
ARB_fragment_program
Повернемося в 2002 рік, GPU ще не мають вершинних та фрагментних шейдерів - все було зашито в мікросхеми. Це називалося Fixed-Function Pipeline (FFP) - «пайплайн» з фіксованими функціями. Таким чином, сама свіжа версія API, а це була OpenGL 1.3 не пропонувала нічого, що можна було назвати чи використовувати як шейдери, тому що вони ще не існували. Але в NVIDIA вирішили, що це було би дуже зручно описувати процес рендеру за допомогою коду, а не сотнями змінних та прапорців, що описують стан системи. Ось чому було створено ARB_fragment_program. Так, тоді не існувало GLSL, але вже можна було писати так:
!!ARBfp1.0 MOV result.color, fragment.color; END
Але що б заставити OpenGL використовувати такий код, нам потрібні спеціальні функції, яких ще не існувало в OpenGL. Але перед поясненнями, розглянемо ще один приклад.
ARB_debug_output
Гаразд, але ARB_fragment_program
дуже стара штука, напевне нам вона більше не потрібна? Добре, але у нас є інші розширення, які бувають дуже зручні. Наприклад ARB_debug_output
, яке додає функціональність, якої немає в OpenGL 3.3, але Ви маєте змогу використовувати його. Це розширення додає такі «токени» як GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
чи GL_DEBUG_SEVERITY_MEDIUM_ARB
, та функції, наприклад DebugMessageCallbackARB
. Чудова особливість цієї функції в тому, що якщо Ви напишете не зовсім коректний код, наприклад:
glEnable(GL_TEXTURE); // Помилка ! Скоріш за все Вам потрібен GL_TEXTURE_2D !
Ви отримаєте повідомлення про помилку та точні координати проблеми. Уроки вивчено:
- Розширення все ще корисні, навіть в свіжому, 3.3 OpenGL
- Використовуйте
ARB_debug_output
! Дивіться посилання нижче.
Отримання розширень - складний спосіб
“Ручний спосіб” перевірки, чи доступне розширення полягає в використанні наступного шматка коду (взято з OpenGL.org wiki):
int NumberOfExtensions;
glGetIntegerv(GL_NUM_EXTENSIONS, &NumberOfExtensions);
for(i=0; i<NumberOfExtensions; i++) {
const GLubyte *ccc=glGetStringi(GL_EXTENSIONS, i);
if ( strcmp(ccc, (const GLubyte *)"GL_ARB_debug_output") == 0 ){
// Це розширення доступно на нашій відеокарті та драйвері
// Спробуємо отримати функцію "glDebugMessageCallbackARB" :
glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) wglGetProcAddress("glDebugMessageCallbackARB");
}
}
Отримання всіх розширень - простий спосіб
Отримати все і одразу достатньо складно. Такі бібліотеки як GLEW, GLee, gl3w спрощують нашу задачу. Наприклад, якщо Ви використовуєте GLEW, то достатньо просто додати виклик glewInit()
після створення Вашого вікна і зручні змінні будуть створені:
if (GLEW_ARB_debug_output){ // Та-дам ! }
(слово обережності : debug_output
є спеціальним, тому що Ви повинні дозволити це при створенні контексту. В GLFW це можна зробити за допомогою glfwOpenWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
)
ARB чи EXT чи …
Ім’я кожного розширення містить інформацію про його доступність:
GL_
: всі платформи;GLX_
: тільки Linux та Mac (X11);-
WGL_
: тільки Windows EXT
: загальне розширення.ARB
: це розширення було затверджено всіма членами OpenGL Architecture Review Board (зазвичай розширення з префіксомEXT
стаютьARB
через якийсь час).NV
/AMD
/INTEL
: Самі говорять за себе =)
Проектування з розширеннями
Проблема
Нехай Вашій OpenGL 3.3 програмі потрібно намалювати якісь дуже великі лінії. Ви можете написати достатньо складний вершинний шейдер для цього чи просто використати GL_NV_path_rendering, яке просто зробить всю складну роботу за Вас.
Ви отримаєте наступний код :
if ( GLEW_NV_path_rendering ){
glPathStringNV( ... ); // Малюємо фігуру, це просто !
}else{
// А інакше ? Вам все ще потрібно намалювати це
// на старих NVIDIA картах, на AMD та на INTEL !
// І Вам потрібно буде це все написати !
}
Вибір ліміту
Зазвичай ми починаємо використовувати розширення, коли виграш від них перевищу біль від підтримки двох версій коду.
Наприклад, Braid (2D гра, де можна подорожувати в часі) містить безліч еффектів зі скручування зображення, коли Ви граєтесь з часом, але вони не працють на старих відеократах.
З OpenGL 3.3 та вище Ви вже маєте 99% інструментів які би Ви хотіли мати. Певні розширення можуть бути дуже корисними, наприклад GL_AMD_pinned_memory
, але це часто не так, як наявність GL_ARB_framebuffer_object
декілька років тому (використовується для рендера в текстуру) робила Вашу гру в 10 разів краще.
Якщо Ви маєте підтримувати старе залізо і OpenGL 3+ для Вас не доступне, то Вам потрібно використовувати другу версію. І Ви не можете надіятись, що всі ці чудові розширення Вам доступні і Вам доведеться з цим справитись.
Для подальшого вивчення, можете перейти за посиланням OpenGL 2.1 версія туторіала 14 - рендер в текстуру, рядок 167, де я вручну перевіряю наявність GL_ARB_framebuffer_object
. Також подивіться сюди FAQ.
Висновок
Розширення OpenGL надають чудову можливість розширити можливості OpenGL на основі можливостей відеокарти.
На сьогоднішній день більшість розширень доступні в ядрі OpenGL, але це важливо знати, що вони працюють і Ви можете використовувати їх в своїх програмах для їх покращення.
Що ще почитати
- Туторіал про debug_output від Aks Ви можете пропустити перший пункт завдяки GLEW.
- The OpenGL extension registry Специфікації для всіх розширень. Біблія.
- GLEW бібліотека розширень OpenGL Wrangler
- gl3w Простий завантажувач OpenGL 3 та 4 “core profile”