Урок 12. Расширения OpenGL


Расширения


С каждым новым поколеним видеоадаптеров, производительность 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 есть огромное количество функционала и расширения обычно нужны лишь для каких-то особенных фич, очень желательно знать про их наличие и уметь с ними работать.

Что можно почитать по этому поводу


Комментариев нет:

Отправить комментарий