Расширения
С каждым новым
поколеним видеоадаптеров, производительность GPU растет, позволяя
рендерить все больше треугольников и больше пикселей. Однако часто нужна не
только чистая производительность. NVIDIA и AMD, а также и Intel периодически
вводят в свои видеокарты новую функциональность. Вот некоторые примеры:
ARB_fragment_program
В далеком 2002 году, GPU не имели вершинных или фрагментных
шейдеров. Все было захардкоджено в микросхемах видеоадаптера. Это называлось Fixed-Function
Pipeline (FFP). Поэтому в 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 !
В результате вы получите сообщение об ошибке и точное местонахождение
проблемы.
- Расширения OpenGL полезны даже в современном OpenGL 3.3
- Используйте ARB_debug_output!
Как работать с расширениями – сложный способ
Способ «вручную». Мы сами проверяем существует ли в системе
данное расширение с помощью такого вот кода(взято из OpenGL вики)
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 (расширения EXT часто превращаются в ARB после некоторого времени).
- NV/AMD/INTEL : расширения производителей
Работа с Расширениями
Проблема
К примеру, вам нужно в вашем OpenGL 3.3 приложении рендерить
много длинных линий. Вы можете написать свой вершинный шейдер, который будет
все делать за вас, или можете использовать расширение GL_NV_path_rendering
которое сделает всю грязную работу за вас.
if ( GLEW_NV_path_rendering ){
glPathStringNV( ... ); // Рисуем нашу фигуру. Все очень просто!
}else{
// Какое еще Else? На старых
видеокартах NVIDIA или AMD или INTEL вам все равно нужно писать этот код!
}
Когда использовать расширение, а когда нет
Разработчики обычно прибегают к использованию расширений,
когда прирост производительности или качество рендеринга превышают мучение от
поддержки двух веток одного и того же функционала.
Например, в игре Braid(2D игра где вы можете путешествовать во
времени) есть всякие эффекты искривления пространства, которые просто не
рендерятся на старом железе.
С OpenGL 3.3 и выше, у вас уже есть 99% того, что жизненно
необходимо, но все же иногда расширения очень выручают, например, GL_AMD_pinned_memory,
или несколько лет назад было очень тяжело без GL_ARB_framebuffer_object(используется
для рендеринга в текстуру), которое может сделать результирующую картинку в
десять раз лучше.
Однако если вам нужно поддерживать старое оборудование, то
на нем не будет работать OpenGL 3+, поэтому вам придется работать лишь с OpenGL
2, и вам не придется даже предполагать, что у вас есть всякие удобные новые
расширения.
Вывод
Расширения OpenGL могут предоставить некоторые новые
возможности, если это позволяет ваше оборудование. И хотя в самом ядре OpenGL
есть огромное количество функционала и расширения обычно нужны лишь для
каких-то особенных фич, очень желательно знать про их наличие и уметь с ними
работать.
Что можно почитать по этому поводу
- debug_output tutorial by Aks Вы можете пропустить шаг 1, благодаря GLEW.
- The OpenGL extension registry. Библия разработчика. Все спецификации по расширениям.
- GLEW The OpenGL Extension Wrangler Library
- gl3w
Комментариев нет:
Отправить комментарий