#include <glew/glew.h>
#ifdef _WIN32
#include <glew/wglew.h>
#pragma comment(lib, "glew/glew32.lib")
#endif
OpenGL Setup for GLSL
спецификациях и реестре расширений.
Господа, и как выясняется, дамы. Эта тема прилично описана в Lighthouse 3D, да и много где еще. Теперь вот и здесь будет, благо тема небольшая и отдельной статьи не требует. Настроек проекта не будет, равно как и иллюстраций, поясняющих работу конвейера OpenGL. Работаем при помощи удобной библиотечки GLEW. Обращаю внимание, что пропущены всяческие обязательные подготовительные действия - такие, как создание окна приложения, установка формата отображения и прочих буферов, получение контекста рисования и установка, если необходимо, контекста версии (для OpenGL 3.0 и выше).
Вначале, немного о подключении GLEW.
Выполнять инициализацию библиотеки, нужно после описанных выше манипуляций с окном, контекстом рендеринга и т.д. Телодвижений, призванных корректно завершить работу с библиотекой, выполнять не требуется.
Работу с шейдерами, целесообразно начать с получения поддерживаемой картой\драйверами версии GLSL.
Выглядеть это будет примерно так:
Согласно спецификации, результирующая строка [FONT="Courier New"]GLSL_version[/FONT] будет иметь единый для всех вендоров формат "major.minor[.release] [vendor info]" - откуда легко выяснить поддерживаемую версию.
По просьбам трудящихся, интересующихся, сомневающихся и просто не желающих копаться в
Господа, и как выясняется, дамы. Эта тема прилично описана в Lighthouse 3D, да и много где еще. Теперь вот и здесь будет, благо тема небольшая и отдельной статьи не требует. Настроек проекта не будет, равно как и иллюстраций, поясняющих работу конвейера OpenGL. Работаем при помощи удобной библиотечки GLEW. Обращаю внимание, что пропущены всяческие обязательные подготовительные действия - такие, как создание окна приложения, установка формата отображения и прочих буферов, получение контекста рисования и установка, если необходимо, контекста версии (для OpenGL 3.0 и выше).
Вначале, немного о подключении GLEW.
Код:
Выполнять инициализацию библиотеки, нужно после описанных выше манипуляций с окном, контекстом рендеринга и т.д. Телодвижений, призванных корректно завершить работу с библиотекой, выполнять не требуется.
Код:
GLenum glew_result = glewInit();
if (glew_result != GLEW_OK)
{
std::cerr << glewGetErrorString( glew_result ) << std::endl;
exit( 1 );
}
if (glew_result != GLEW_OK)
{
std::cerr << glewGetErrorString( glew_result ) << std::endl;
exit( 1 );
}
Работу с шейдерами, целесообразно начать с получения поддерживаемой картой\драйверами версии GLSL.
Выглядеть это будет примерно так:
Код:
std::string GLSL_version;
if (GLEW_VERSION_2_0 || (GLEW_ARB_shading_language_100 &&
GLEW_ARB_shader_objects &&
GLEW_ARB_fragment_shader &&
GLEW_ARB_vertex_shader))
{
if (GLEW_VERSION_2_0)
GLSL_version = reinterpret_cast<const char*>
(glGetString( GLEW_VERSION_2_0
? GL_SHADING_LANGUAGE_VERSION : GL_SHADING_LANGUAGE_VERSION_ARB ));
if (GLSL_version == NULL)
if (glGetError() == GL_INVALID_ENUM)
// Предположительно, поддерживается первоначальная
// версия GLSL 1.00 (в ревизии 51 спецификации - "1.051")
GLSL_version = "1.051";
else
// Другая ошибка, но обрабатывать её мы здесь не будем
exit( -1 );
}
else
// Собственно, ни версия OpenGL 2.0, ни необходимые расширения
// не поддерживаются. Стало быть, никакой GLSL нам не светит.
exit( -1 );
if (GLEW_VERSION_2_0 || (GLEW_ARB_shading_language_100 &&
GLEW_ARB_shader_objects &&
GLEW_ARB_fragment_shader &&
GLEW_ARB_vertex_shader))
{
if (GLEW_VERSION_2_0)
GLSL_version = reinterpret_cast<const char*>
(glGetString( GLEW_VERSION_2_0
? GL_SHADING_LANGUAGE_VERSION : GL_SHADING_LANGUAGE_VERSION_ARB ));
if (GLSL_version == NULL)
if (glGetError() == GL_INVALID_ENUM)
// Предположительно, поддерживается первоначальная
// версия GLSL 1.00 (в ревизии 51 спецификации - "1.051")
GLSL_version = "1.051";
else
// Другая ошибка, но обрабатывать её мы здесь не будем
exit( -1 );
}
else
// Собственно, ни версия OpenGL 2.0, ни необходимые расширения
// не поддерживаются. Стало быть, никакой GLSL нам не светит.
exit( -1 );
Согласно спецификации, результирующая строка [FONT="Courier New"]GLSL_version[/FONT] будет иметь единый для всех вендоров формат "major.minor[.release] [vendor info]" - откуда легко выяснить поддерживаемую версию.
Код:
// Количество строк в шейдере
int num_shad_str;
// Исходный код шейдера
const char** shad_str;
// Массив длин строк в тексте кода шейдера
int* lens_shad_str;
// тут загружаем исходный код шейдера.
// Надо определить количество и длины строк исходника,
// но можно и обойтись. Как - смотрите спецификации.
...
// в нашем примере будет вершинный (GL_VERTEX_SHADER) шейдер
if (GLEW_VERSION_2_0)
// Работаем с функциями OpenGL версии 2.0
{
// создаем шейдер
GLuint shader = glCreateShader( GL_VERTEX_SHADER );
// устанавливаем источник исходного кода шейдера
glShaderSource( shader, num_shad_str, shad_str, lens_shad_str );
// компилируем шейдер
glCompileShader( shader );
// создаём программный модуль шейдера
GLuint program = glCreateProgram();
// присоединяем шейдер к модулю
glAttachShader( program, shader );
// прилинковываем модуль
glLinkProgram( program );
// используем полученную шейдерную программку
glUseProgram( program );
}
else if (GLEW_ARB_shading_language_100 &&
GLEW_ARB_shader_objects &&
GLEW_ARB_fragment_shader &&
GLEW_ARB_vertex_shader)
// Работаем через ARB расширения
{
// создаем шейдер
GLhandleARB shader = glCreateShaderObjectARB( GL_VERTEX_SHADER );
// устанавливаем источник исходного кода шейдера
glShaderSourceARB( shader, num_shad_str, shad_str, lens_shad_str );
// компилируем шейдер
glCompileShaderARB( shader );
// создаём программный модуль шейдера
GLhandleARB program = glCreateProgramObjectARB();
// присоединяем шейдер к модулю
glAttachObjectARB( program, shader );
// прилинковываем модуль
glLinkProgramARB( program );
// используем полученную шейдерную программку
glUseProgramObjectARB( program );
}
int num_shad_str;
// Исходный код шейдера
const char** shad_str;
// Массив длин строк в тексте кода шейдера
int* lens_shad_str;
// тут загружаем исходный код шейдера.
// Надо определить количество и длины строк исходника,
// но можно и обойтись. Как - смотрите спецификации.
...
// в нашем примере будет вершинный (GL_VERTEX_SHADER) шейдер
if (GLEW_VERSION_2_0)
// Работаем с функциями OpenGL версии 2.0
{
// создаем шейдер
GLuint shader = glCreateShader( GL_VERTEX_SHADER );
// устанавливаем источник исходного кода шейдера
glShaderSource( shader, num_shad_str, shad_str, lens_shad_str );
// компилируем шейдер
glCompileShader( shader );
// создаём программный модуль шейдера
GLuint program = glCreateProgram();
// присоединяем шейдер к модулю
glAttachShader( program, shader );
// прилинковываем модуль
glLinkProgram( program );
// используем полученную шейдерную программку
glUseProgram( program );
}
else if (GLEW_ARB_shading_language_100 &&
GLEW_ARB_shader_objects &&
GLEW_ARB_fragment_shader &&
GLEW_ARB_vertex_shader)
// Работаем через ARB расширения
{
// создаем шейдер
GLhandleARB shader = glCreateShaderObjectARB( GL_VERTEX_SHADER );
// устанавливаем источник исходного кода шейдера
glShaderSourceARB( shader, num_shad_str, shad_str, lens_shad_str );
// компилируем шейдер
glCompileShaderARB( shader );
// создаём программный модуль шейдера
GLhandleARB program = glCreateProgramObjectARB();
// присоединяем шейдер к модулю
glAttachObjectARB( program, shader );
// прилинковываем модуль
glLinkProgramARB( program );
// используем полученную шейдерную программку
glUseProgramObjectARB( program );
}
Написанное следует воспринимать как некий псевдокод, поскольку общие переменные [FONT="Courier New"]shader[/FONT] и [FONT="Courier New"]program [/FONT]объявляются здесь внутри неких локальных областей видимости.
Код:
...
if (GLEW_VERSION_2_0)
{
// отсоединяем шейдер от программного модуля.
// к модулю может быть присоединено несколько
// шейдеров, поэтому и нужна эта функция
glDetachShader( program, shader );
// удаляем шейдер
glDeleteShader( shader );
// если больше шейдеров нет,
// то можно удалить и программный модуль
glDeleteProgram( program );
}
else if (GLEW_ARB_shading_language_100 &&
GLEW_ARB_shader_objects &&
GLEW_ARB_fragment_shader &&
GLEW_ARB_vertex_shader)
{
// отсоединяем шейдер от программного модуля.
// к модулю может быть присоединено несколько
// шейдеров, поэтому и нужна эта функция
glDetachObjectARB( program, shader );
// удаляем шейдер
glDeleteObjectARB( shader );
// если больше шейдеров нет,
// то можно удалить и программный модуль
glDeleteObjectARB( program );
}
if (GLEW_VERSION_2_0)
{
// отсоединяем шейдер от программного модуля.
// к модулю может быть присоединено несколько
// шейдеров, поэтому и нужна эта функция
glDetachShader( program, shader );
// удаляем шейдер
glDeleteShader( shader );
// если больше шейдеров нет,
// то можно удалить и программный модуль
glDeleteProgram( program );
}
else if (GLEW_ARB_shading_language_100 &&
GLEW_ARB_shader_objects &&
GLEW_ARB_fragment_shader &&
GLEW_ARB_vertex_shader)
{
// отсоединяем шейдер от программного модуля.
// к модулю может быть присоединено несколько
// шейдеров, поэтому и нужна эта функция
glDetachObjectARB( program, shader );
// удаляем шейдер
glDeleteObjectARB( shader );
// если больше шейдеров нет,
// то можно удалить и программный модуль
glDeleteObjectARB( program );
}
Если знаете названия файлов драйверов других вендоров - напишите.
Код:
// для линковки
// GetFileVersionInfo, GetFileVersionInfoSize, VerQueryValue
#pragma comment(lib, "version.lib")
...
std::string icd_version;
try
{
LPSTR _tmp = (LPSTR)malloc( sizeof(CHAR) * MAX_PATH );
GetSystemDirectory( _tmp, MAX_PATH );
std::string icd_path( _tmp );
free( _tmp );
WIN32_FIND_DATA file_data;
std::string icd_file = icd_path + "\\nvoglnt.dll";
HANDLE hFind = FindFirstFile( icd_file.c_str(), &file_data );
if (hFind == INVALID_HANDLE_VALUE)
{
icd_file = icd_path + "\\atioglxx.dll";
hFind = FindFirstFile( icd_file.c_str(), &file_data );
if (hFind == INVALID_HANDLE_VALUE)
icd_file.clear();
}
if (!icd_file.empty())
{
FindClose( hFind );
DWORD dummy;
DWORD size = GetFileVersionInfoSize( icd_file.c_str(), &dummy );
if (size)
{
void* buff = malloc( size );
GetFileVersionInfo( icd_file.c_str(), 0, size, buff );
DWORD len;
VS_FIXEDFILEINFO* ffi;
if (VerQueryValue( buff, TEXT("\\"), (LPVOID*)(&ffi), (PUINT)(&len)) )
{
std::stringstream ss;
ss << HIWORD(ffi->dwProductVersionMS) << "."
<< LOWORD(ffi->dwProductVersionMS) << "."
<< HIWORD(ffi->dwProductVersionLS) << "."
<< LOWORD(ffi->dwProductVersionLS);
icd_version = ss.str();
}
free( buff );
}
}
else
{
// файл драйвера неизвестен. доработать по вкусу
}
}
catch(...)
{
// Critical error during getting information about OpenGL ICD Driver.
// Action cancelled.
}
// GetFileVersionInfo, GetFileVersionInfoSize, VerQueryValue
#pragma comment(lib, "version.lib")
...
std::string icd_version;
try
{
LPSTR _tmp = (LPSTR)malloc( sizeof(CHAR) * MAX_PATH );
GetSystemDirectory( _tmp, MAX_PATH );
std::string icd_path( _tmp );
free( _tmp );
WIN32_FIND_DATA file_data;
std::string icd_file = icd_path + "\\nvoglnt.dll";
HANDLE hFind = FindFirstFile( icd_file.c_str(), &file_data );
if (hFind == INVALID_HANDLE_VALUE)
{
icd_file = icd_path + "\\atioglxx.dll";
hFind = FindFirstFile( icd_file.c_str(), &file_data );
if (hFind == INVALID_HANDLE_VALUE)
icd_file.clear();
}
if (!icd_file.empty())
{
FindClose( hFind );
DWORD dummy;
DWORD size = GetFileVersionInfoSize( icd_file.c_str(), &dummy );
if (size)
{
void* buff = malloc( size );
GetFileVersionInfo( icd_file.c_str(), 0, size, buff );
DWORD len;
VS_FIXEDFILEINFO* ffi;
if (VerQueryValue( buff, TEXT("\\"), (LPVOID*)(&ffi), (PUINT)(&len)) )
{
std::stringstream ss;
ss << HIWORD(ffi->dwProductVersionMS) << "."
<< LOWORD(ffi->dwProductVersionMS) << "."
<< HIWORD(ffi->dwProductVersionLS) << "."
<< LOWORD(ffi->dwProductVersionLS);
icd_version = ss.str();
}
free( buff );
}
}
else
{
// файл драйвера неизвестен. доработать по вкусу
}
}
catch(...)
{
// Critical error during getting information about OpenGL ICD Driver.
// Action cancelled.
}
Код не комментирую, идея и так понятна. На выходе в [FONT="Courier New"]icd_version[/FONT] - версия драйвера OpenGL.
Здесь можно посмотреть альтернативный вариант.
Для чего вообще это нужно? Ну, иногда бывает нужно. Кто знает, чего вы там пишете ;)
Продолжение, может быть последует...