SDL2 и GLEW, невозможно получить правильную версию OpenGL при использовании SDL_GL_SetAttribute()

Я использую SDL2 для взаимодействия с ОС и GLEW для загрузки функций OpenGL. Первоначально у меня были вызовы SDL_GL_SetAttribute() между созданием окна и созданием контекста. Я заметил, что мои вызовы SDL_GL_SetAttribute() малоэффективны, поэтому я перечитал документацию и обнаружил, что " Запрошенные атрибуты должны быть установлены перед созданием окна OpenGL". Если я попытаюсь это сделать, мне удастся получить только контекст OpenGL 1.1 (тот, который поставляет Microsoft). Если я вообще не вызываю SDL_GL_SetAttribute(), я без проблем получаю контекст 4.4.

Я заметил одну странную вещь: мои вызовы SDL_GL_GetAttribute() после создания контекста возвращают неточные значения. Если я не устанавливаю какие-либо атрибуты, я получаю:

SDL GL Context Major Version: 2
SDL GL Context Minor Version: 1
SDL GL Context Profile: Unknown
SDL GL Accelerated Visuals: True
SDL GL Double Buffering: True
SDL GL Depth Size: 24
----------------------------------------------------------------
Graphics Successfully Initialized
OpenGL Info
  Version: 4.4.0
  Vendor: NVIDIA Corporation
  Renderer: GeForce GT 650M/PCIe/SSE2
   Shading: 4.40 NVIDIA via Cg compiler
----------------------------------------------------------------

Если я выполню установку всех атрибутов, я получу:

SDL GL Context Major Version: 3
SDL GL Context Minor Version: 1
SDL GL Context Profile: Compatibility
SDL GL Accelerated Visuals: True
SDL GL Double Buffering: True
SDL GL Depth Size: 32
----------------------------------------------------------------
Graphics Successfully Initialized
OpenGL Info
    Version: 1.1.0
     Vendor: Microsoft Corporation
   Renderer: GDI Generic
    Shading: (null)
----------------------------------------------------------------

Обратите внимание, что в первом случае SDL говорит, что у меня контекст 2.1, а на самом деле я получаю контекст 4.4. Во втором случае он говорит, что у меня есть контекст 3.1 (то, что я просил), хотя на самом деле у меня есть контекст 1.1.

Мой текущий код установки (который соответствует тому, что описано в этом руководстве). Проверка ошибок опущена для краткости.

СДЛ

SDL_Init(SDL_INIT_VIDEO);

// Request compatibility because GLEW doesn't play well with core contexts.
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); 
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); 
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32); 

SDL_Window * window = SDL_CreateWindow("Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL);

SDL_GLContext context = SDL_GL_CreateContext(window);

SDL_GL_MakeCurrent(window, context)

// Print what the OS actually gave us for each value we requested.
SDL_GL_GetAttribute(/* ... */);

Непосредственно за ним следует GLEW

glewExperimental = GL_TRUE;
GLenum result = glewInit();
if(result != GLEW_OK)
{
  // Handle & print error
}

if(GLEW_VERSION_1_1)
{
  printf("----------------------------------------------------------------\n");
  printf("Graphics Successfully Initialized\n");
  printf("OpenGL Info\n");
  printf("    Version: %s\n", glGetString(GL_VERSION));
  printf("     Vendor: %s\n", glGetString(GL_VENDOR));
  printf("   Renderer: %s\n", glGetString(GL_RENDERER));
  printf("    Shading: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
  printf("----------------------------------------------------------------\n");
}
else
{
  printf("Unable to get any OpenGL version from GLEW!");
}

if(!GLEW_VERSION_3_1)
{
  // Handle & print error
}

person Peter Clark    schedule 16.03.2014    source источник
comment
Вы пытаетесь получить 32-битный буфер глубины, тогда как по умолчанию выбран 24-битный. По этой причине вы можете получить этот запасной вариант для средства визуализации MS. Другое дело, что вы запрашиваете контекст профиля совместимости 3.1, которого вообще нет - профили были введены в 3.2. Я бы порекомендовал протестировать с GL 3.2 или установить маску профиля на 0 для чего-то ‹= 3.1.   -  person derhass    schedule 16.03.2014
comment
Даже на графических процессорах, поддерживающих 32-битные буферы глубины, они, как правило, не предоставляют эти форматы пикселей для использования с кадровым буфером по умолчанию в Microsoft Windows. Если вам действительно нужен 32-битный буфер глубины, самый портативный способ сделать это — использовать FBO.   -  person Andon M. Coleman    schedule 16.03.2014
comment
@derhass Я совсем забыл, что ядро ​​​​/ совместимость - это конструкция 3.2+, спасибо! Похоже, что SDL2 в порядке с запросом, несмотря ни на что. Это был запрос буфера глубины.   -  person Peter Clark    schedule 16.03.2014
comment
@ AndonM.Coleman Вот оно! Спасибо за подробный ответ, который вы сделали, это действительно помогает заполнить пробелы в проблеме, с которой я столкнулся на моей интегрированной карте Intel. Я получаю 16-битный буфер глубины, но у моего отложенного рендерера есть FBO с 32-битным буфером глубины. Я думал, что если он не будет поддерживаться, мой FBO не сможет его получить. Не стесняйтесь оставлять свой комментарий в качестве ответа, и я приму его.   -  person Peter Clark    schedule 16.03.2014


Ответы (1)


Во-первых, чтобы быть полностью ясным, GL 3.1 технически имеет понятие совместимости в форме расширения, называемого GL_ARB_compatibility. Если это расширение присутствует в вашей строке расширений, то функции, отмеченные как устаревшие в спецификации GL 3.0, по-прежнему можно будет использовать. Если его нет, то вещи, которые устарели в GL 3.0, на самом деле удалены в 3.1. С этой целью существует разветвленная версия спецификации GL 3.1, которая имеет дело именно с этим расширением.

Однако это не то же самое, что контекстный профиль. Вы не можете активно запрашивать совместимость в 3.1, вы можете обнаружить это поведение только постфактум. Таким образом, как указывает Дерхас, нет смысла запрашивать контекст «профиля совместимости» 3.1 (или любого другого профиля).


Что еще более важно, 32-битные буферы глубины не поддерживаются широко для кадрового буфера по умолчанию в Microsoft Windows. Некоторые драйверы позволяют вам выбрать формат пикселей с 32-битным буфером глубины и по-прежнему получать аппаратную реализацию, но чаще всего вы возвращаетесь к программной реализации GDI от Microsoft.

Такое поведение происходит даже на графических процессорах, которые на самом деле поддерживают 32-битные буферы глубины, и наиболее переносимый способ приблизиться к приложению, которое действительно требует 32-битного буфера глубины, — это использовать объект кадрового буфера.

person Andon M. Coleman    schedule 16.03.2014
comment
Просто чтобы уточнить, является ли рекомендуемым методом сделать весь рисунок, который я бы сделал, с буфером кадра по умолчанию в FBO (с его собственным буфером цвета и буфером глубины), а затем просто скопировать мои результаты в буфер по умолчанию? Кроме того, разумно/приемлемо ли запрашивать отсутствие буфера глубины для буфера кадров по умолчанию? Кажется, это работает, но я хочу быть уверен. Кроме того, спасибо за разъяснения по контекстным профилям. - person Peter Clark; 17.03.2014
comment
Да, вы можете создать буфер кадра по умолчанию без буфера глубины. На самом деле, если вы хотите перенести результаты FBO в кадровый буфер по умолчанию, вам нужно будет только скопировать цветовой буфер. Вы также можете нарисовать текстурированный четырехугольник поверх окна просмотра (обычно это немного быстрее, но вы не можете копировать некоторые буферы, такие как трафарет, таким образом), чтобы отображалось содержимое. - person Andon M. Coleman; 17.03.2014