OpenGL: Программирование под linux: SDL+OpenGL

По просьбе на форуме решил написать простенькую статью о программировании графики под linux.
Собственно, оснавная часть графического (openGL) кода в разных ОС остаётся практически без изменений.
Различаются только способы инициализации программы (точнее, окна). В windows собственно есть только winAPI и различные обёртки под него. В linux же есть две основные оконные библиотеки: gtk и qt4. Если вам интересно, вы можете найти в интернете способы инициализации окна под них. Я же опишу более простой способ: библиотека SDL.

SDL — это кроссплатформенная библиотека, предоставляющая доступ к видео, аудио, сетевому и другому оборудованию.
Нам SDL понадобится для простого создания окна, чтобы нам не пришлось заботится об установленных библиотеках: мы скажем SDL «создай нам окошко», и оно создаст, независимо от того, какая графическая оболочка активна у пользователя: QT или gtk. Мало того, установив эту библиотеку под windows, вы сможете практически без изменения использовать один и тот же код инициализации в обоих системах.

Где её взять?
http://www.libsdl.org/ — официальный сайт проекта, где можно найти всё необходимое.
Но я использую Gentoo Linux, поэтому мне достаточно набрать «emerge libsdl», и библиотека будет установлена. В большинстве других дистрибутивов есть свои менеджеры пакетов, также позволяющие установить что-либо довольно просто.

Начинаем программировать.

Создадим один файлик, main.cpp.
Заметьте, кода для простой инициализации здесь гораздо меньше, чем в windows =)

#include <SDL.h>        // Хидер библиотеки SDL
#include <GL/gl.h>      // Хидеры OpenGL & glu
#include <GL/glu.h>// Сначала напишем простую функцию, которая будет отрисовывать
// цветной треугольник
void Draw()
{
// Перемещаем камеру назад
glTranslatef(0,0, — 5);
// Рисуем треугольник
glBegin(GL_TRIANGLES);
glColor3f(0,1,1);
glVertex3f(1,0,0);
glColor3f(1,0,1);
glVertex3f(1, — 1,0);
glColor3f(1,1,0);
glVertex3f(1,0,0);
glEnd();
}int main()
{
// Инициализируем SDL. В качестве параметра передаём, какие именно
// подсистемы нужно инициализировать. Например, можно указать SDL_INIT_AUDIO
// или SDL_INIT_JOYSTICK для доступа к звуку и джойстику соответственно.
// Ниже я приведу список возможных флагов.// Если произошла ошибка, SDL_Init вернёт «-1»
if(SDL_Init(SDL_INIT_VIDEO) < 0){
// Выводим ошибку
printf(«Error while initializing SDL: %sn»,SDL_GetError());
// и выходим из программы
exit(1);
}

// устанавливаем аттрибуты OpenGL. Их больше, чем здесь, но пока
// нам нужно только эти:
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);    // использовать двойной буфер
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);    // размер в битах цветовых составляющих буфера
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);  // *---
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);   // *---

// Далее создаём окно, указывая его размер, глубину цвета, и флаги.
// Возможные флаги я также перечислю ниже. Для указания нескольких флагов сразу
// перечисляйте их как 'SDL_FULLSCREEN | SDL_OPENGL | ......'
if(SDL_SetVideoMode(640,480,32,SDL_OPENGL) == NULL)
{
printf(«Error while setting up video mode: %sn», SDL_GetError());
exit(1);
}

// Ну а дальше оперируем стандартными функциями OpenGL, которые вам должны
// быть знакомы:
glClearColor(0,0,0,0);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 640/480,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);

// Небольшой цикл программы. Ничего не делает, ждёт нажатия
// escape для завершения.
bool done=false;
SDL_Event event;
while(!done)
{
while(SDL_PollEvent(&event)){
if(event.type == SDL_QUIT)
done=true;
if(event.type == SDL_KEYDOWN)
{
if(event.key.keysym.sym == SDLK_ESCAPE)
done=true;
}
}
Draw();
glFlush();
SDL_GL_SwapBuffers();
}

// Завершаем работу SDL,
SDL_Quit();

return 0;
}

 

Теперь нужно откомпилировать написанное. Возможно, это будет немного сложновато, если вы раньше не программировали под *nix.

Войдите в шелл (терминал, xterm/console), перейдите в директорию, где лежит файл main.cpp
Строка для компиляции:

g++ main.cpp lGL lGLU lSDL I/usr/include/SDL o prog

Разберём по пунктам.
g++ — Команда компилятору
main.cpp — только что написанный файл
— lGL — линковка библиотеки GL
— lGLU — линковка библиотеки GLU
— lSDL — линковка библиотеки SDL
— I/usr/include/SDL — указываем путь к инклудам SDL. Он может различатся в разных системах, в таком случае вам нужно найти его самостоятельно.
— o prog — Указываем, как должен называтся обьект на выходе.

После выполнения этой команды, если не произошло ошибок, в этой же директории должен появится бинарный файл «prog». Запустите его, набрав «./prog», и любуйтесь своей программой =)

Возможные флаги SDL_Init ():
SDL_INIT_TIMER
SDL_INIT_AUDIO
SDL_INIT_VIDEO
SDL_INIT_CDROM
SDL_INIT_JOYSTICK
SDL_INIT_EVERYTHING
SDL_INIT_NOPARACHUTE
SDL_INIT_EVENTTHREAD

Возможные флаги SDL_SetVideoMode ():
SDL_SWSURFACE — создает видео поверхность в оперативной памяти.
SDL_HWSURFACE — создает видео поверхность в памяти видеокарты.
SDL_ASYNCBLIT — использование асинхронного обновления экрана. Обычно это замедляет работу на обычных компьютерах, но значительно ускоряет на многопроцессорных системах.
SDL_ANYFORMAT — обчно, когда указанная глубина цвета невозможна на видеокарте, SDL эмулирует ее с помощью специальной теневой поверхности. Это замедляет работу программы.
Указывая этот флаг, вы запрещаете библиотеке делать такие преобразования и заставляете использовать «неправильную» поверхность в любом случае.
SDL_HWPALETTE — предоставляет программе эксклюзивный доступ к палитре. Без этого флага вы не всегда сможете получить доступ к цветам функциями SDL_SetColors и SDL_SetPalette
SDL_DOUBLEBUF — включает двойной буфер. Это возможно только вместе с флагом SDL_HWSURFACE.
Функция SDL_Flip перключает буферы, обновляя экран. То есть, когда вы рисуете что-либо, то все это отображается на невидимом буфере, а потом буферы переключаются и невидимый становится видимым. Когда двойной буфер недоступен, функция SDL_Flip вызывает функцию SDL_UpdataRects.
SDL_FULLSCREEN — SDL пытается переключиться в полноэкранный режим. Если по каким-либо причинам запрошеный размер экрана не может установиться, то будет выбран следующий больший режим, а изображение будет отцентровано на черном экране.
SDL_OPENGL — создает контекст OpenGL. Перед этим необходимо установить видео атрибуты OpenGL с помощью функции SDL_GL_SetAttribute.
SDL_OPENGLBLIT — также создает контекст OpenGL, но позволяет blitting-операции. Экранная поверхность (2D) может иметь альфа-канал (прозрачность) и должна обновляться только при помощи SDL_UpdateRects.
SDL_RESIZABLE — создает изменяемое окно. Когда пользователь изменяет размер окна, возникает событие SDL_VIDEORESIZE и можно опять вызвать функцию SDL_SetVideoMode, чтобы установить новые размеры окна.
SDL_NOFRAME — если возможно, создает окно без рамки и заголовка. Полноэкранный режим автоматически устанавливает этот флаг.

Понравилась статья? Поделиться с друзьями: