© Георгиевский Анатолий, 23.01.2008

Пример интеграции интерфейса OpenGL в SDL

Пример создания простого приложения с интерфейсом OpenGL.

// описания библиотеки SDL
#include <SDL/SDL.h>

// описаниe функций OpenGL
#include <GL/gl.h>
#include <GL/glu.h>


int main(int argc, char **argv)
{
// инициализация всего-всего
	SDL_Init(SDL_INIT_EVERYTHING);
// задать атрибуты цветности
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
// запросить использование двойной буферизации
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
// создание контекста для вывода OpenGL
	SDL_Surface* drawContext;
	drawContext = SDL_SetVideoMode(1024, 768, 0, 
		SDL_OPENGL | SDL_FULLSCREEN);
   DrawInit(); // инициализация нашей модели
/*
 * На этом окно уже раскрылось, надо придумать зачем
 */
   // цикл обработки событий
   SDL_Event event;
   while (1){
      DrawScene(); // прорисовка модели
// обработка событий от клавиатуры и мышки
      while( SDL_PollEvent( &event ) ){
         swicth (event.type){
// ... обработка событий от мышки и клавки ...
         case SDL_QUIT: // выход из программы
            SDL_Quit(); // завершение работы
            exit(0);
         default:
            break;
         }
      }

      SDL_Delay(interval); // ожидание между сценами 30fps
      SDL_GL_SwapBuffers(); // смена экранов
   }
}

Теперь в модели взаимодействия с OpenGL предлагается сделать две функции: функцию инициализация и функцию обновления прорисовки сцены. Инициализация происходит один раз во время создания окна и задает параметры OpenGL, которые остаются неизменными в процессе работы приложения. Функция прорисовки сцены должна запускаться периодически по таймеру или по готовности данных.

В частности, при инициализации настраивается цвет фона и перспектива изображения.

void DrawInit()
{
  glClearColor (0.0, 0.0, 0.0, 0.0); // цвет фона
  glClearDepth (1.0);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  gluPerspective (64.0, aspect, zNear, zFar);
}

Простейшая трехмерная сцена будет состоять из цветного треугольника. Для каждой вершины задается свой цвет.

void DrawScene()
{
// отображение сцены начинается с очистки буфера экрана
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// инициализация матрицы преобразования координат
  glMatrixMode (GL_MODELVIEW);
  glLoadIdentity (); // загрузка единичной матрицы

// набор преобразований координат для просмотра модели
// приблизить/удалить модель
  glTranslatef (0,0,-sdepth);
// наклон плоскости XY относительно оси Х
  glRotatef (-stheta, 1.0, 0.0, 0.0);
// поворот плоскости XY относительно оси Z
  glRotatef (sphi, 0.0, 0.0, 1.0);
// смещение изображения в плоскости XY
  glTranslatef (-offsetX,-offsetY,0);
// масштабирование координат
  glScalef(scale,scale,scale);

// построить модель
GLfloat red[]  ={1.0,0,0,1.0};
GLfloat green[]={0,1.0,0,1.0};
GLfloat blue[] ={0,0,1.0,1.0};

GLfloat v0[] = {-1.0,-0.7, 0};
GLfloat v1[] = { 0,   1.0, 0};
GLfloat v2[] = { 1.0,-0.7, 0};

   glBegin(GL_TRIANGLS);
    glColor3fv(red);   glVertex3fv(v0);
    glColor3fv(green); glVertex3fv(v1);
    glColor3fv(blue);  glVertex3fv(v2);
   glEnd();
}

Фиг.1. Построенная модель треугольника.

Замечания

Мы успешно протестировали наше приложение в Windows 2000/XP и Linux. При отображении openGL с кластера мы столкнулись с ограничением производительности сети, которая выражается в существенной задержке доставки данных на удаленный терминал, особенно через сеть интернет. Причем, если пропускная способность сети низкая, запросы на прорисовку сцен могут становится в очередь и таким образом задержка прорисовки сцены накапливается. Видимо, с точки зрения приложения если запрос на прорисовку данных отправлен на удаленный терминал, данные считаются доставленными. Чтобы избежать такой ситуации мы рекомендуем не использовать прорисовку сцен по таймеру, а обновлять только по событиям пользовательского интерфейса: по вводу или кнопкам мышки, или по готовности данных.

()