Файл: графическая библиотека opengl.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 09.06.2020

Просмотров: 1708

Скачиваний: 4

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

 76

Глава

 8  

 

Оптимизация

 

программ

 

8.1. 

Организация

 

приложения

  

На

 

первый

 

взгляд

 

может

 

показаться

что

 

производительность

 

приложений

основанных

 

на

 OpenGL, 

определяется

 

в

 

первую

 

очередь

 

производительностью

 

реализации

 

самой

 

библиотеки

 OpenGL. 

Это

 

верно

однако

 

организация

 

всего

 

приложения

 

также

 

очень

 

важна

8.1.1. 

Высокоуровневая

 

оптимизация

  

Обычно

 

от

 

программы

 

под

 OpenGL 

требуется

 

визуализация

 

высокого

 

качества

 

на

 

интерактивных

 

скоростях

Но

как

 

правило

и

 

то

 

и

 

другое

 

сразу

 

получить

 

не

 

удается

Следовательно

необходим

 

поиск

 

компромисса

 

между

 

качеством

 

и

 

производительностью

Существует

 

множество

 

различных

 

подходов

но

 

их

 

подробное

 

описание

 

выходит

 

за

 

пределы

 

этого

 

пособия

Приведем

 

лишь

 

несколько

 

примеров

.  

 

Можно

 

отображать

 

геометрию

 

сцены

 

с

 

низким

 

качеством

 

во

 

время

 

анимации

а

 

в

 

моменты

 

остановок

 

показывать

 

ее

 

с

 

наилучшим

 

качеством

Во

 

время

 

интерактивного

 

вращения

 

(

например

при

 

нажатой

 

клавише

 

мыши

визуализировать

 

модель

 

с

 

уменьшенным

 

количеством

 

примитивов

При

 

рисовании

 

статичного

 

изображения

 

отображать

 

модель

 

полностью

.  

 

Аналогично

объекты

которые

 

располагаются

 

далеко

 

от

 

наблюдателя

могут

 

быть

 

представлены

 

моделями

 

пониженной

 

сложности

Это

 

значительно

 

снизит

 

нагрузку

 

на

 

все

 

ступени

 

конвейера

 OpenGL. 

Объекты

которые

 

находятся

 

полностью

 

вне

 

поля

 

видимости

могут

 

быть

 

эффективно

 

отсечены

 

без

 

передачи

 

на

 

конвейер

 OpenGL 

с

 

помощью

 

проверки

 

попадания

 

ограничивающих

 

их

 

простых

 

объемов

 

(

сфер

 

или

 

кубов

в

 

пирамиду

 

зрения

 

Во

 

время

 

анимации

 

можно

 

отключить

 

псевдотонирование

 

(dithering), 

плавную

 

заливку

текстуры

Опять

-

таки

 

включать

 

все

 

это

 

во

 

время

 

демонстрации

 

статичных

 

изображений

Этот

 


background image

 77

подход

 

особенно

 

эффективен

 

для

 

систем

 

без

 

аппаратной

 

поддержки

 OpenGL. 

8.1.2. 

Низкоуровневая

 

оптимизация

  

 

Объекты

отображаемые

 

с

 

помощью

 OpenGL, 

хранятся

 

в

 

некоторых

 

структурах

 

данных

Одни

 

типы

 

таких

 

структур

 

более

 

эффективны

 

в

 

использовании

чем

 

другие

что

 

определяет

 

скорость

 

визуализации

.  

Желательно

чтобы

 

использовались

 

структуры

 

данных

которые

 

могут

 

быть

 

быстро

 

и

 

эффективно

 

переданы

 

на

 

конвейер

 OpenGL. 

Например

если

 

мы

 

хотим

 

отобразить

 

массив

 

треугольников

то

  

использование

 

указателя

 

на

 

этот

 

массив

 

значительно

 

более

 

эффективно

чем

 

передача

 

его

 OpenGL 

поэлементно

.  

Пример

Предположим

что

 

мы

 

пишем

 

приложение

которое

 

реализует

 

рисование

 

карты

 

местности

Один

 

из

 

компонентов

 

базы

 

данных

 – 

список

 

городов

 

с

 

их

 

шириной

долготой

 

и

 

названием

Соответствующая

 

структура

 

данных

 

может

 

быть

 

такой

:  

struct city 

   float latitute, longitude; /* 

положение

 

города

 */ 

   char *name;                /* 

название

  */ 

   int large_flag;      /* 0 = 

маленький

, 1 = 

большой

 */ 

}; 

 

Список

 

городов

 

может

 

храниться

 

как

 

массив

 

таких

 

структур

Допустим

мы

 

пишем

 

функцию

которая

 

рисует

 

города

 

на

 

карте

 

в

 

виде

 

точек

 

разного

 

размера

 

с

 

подписями

void draw_cities( int n, struct city citylist[] ) 

   int i; 
   for (i=0; i < n; i++)  
     { 
     if (citylist[i].large_flag)  
         glPointSize( 4.0 ); 

     else 
         glPointSize( 2.0 ); 
 
     glBegin( GL_POINTS ); 
     glVertex2f( citylist[i].longitude, 


background image

 78

                 citylist[i].latitude ); 
     glEnd(); 
     /* 

рисуем

 

название

 

города

 */ 

     DrawText(citylist[i].longitude, 
              citylist[i].latitude, 
              citylist[i].name); 
    } 

Это

 

реализация

 

неудачна

 

по

 

следующим

 

причинам

:  

 

glPointSize

 

вызывается

 

для

 

каждой

 

итерации

 

цикла

 

между

 

glBegin

 

и

 

glEnd

 

рисуется

 

только

 

одна

 

точка

 

вершины

 

определяются

 

в

 

неоптимальном

 

формате

.  

Ниже

 

приведено

 

более

 

рациональное

 

решение

:  

  void draw_cities( int n, struct city citylist[] ) 
  { 
      int i; 
      /* 

сначала

 

рисуем

 

маленькие

 

точки

 */ 

      glPointSize( 2.0 ); 
      glBegin( GL_POINTS ); 
      for (i=0; i < n ;i++)  
      { 
         if (citylist[i].large_flag==0) { 
            glVertex2f( citylist[i].longitude, 
                        citylist[i].latitude ); 
        } 
      } 
      glEnd(); 
      /* 

большие

 

точки

 

рисуем

 

во

 

вторую

 

очередь

 */ 

      glPointSize( 4.0 ); 
      glBegin( GL_POINTS ); 
      for (i=0; i < n ;i++)  
        { 
        if (citylist[i].large_flag==1)  
        { 

          glVertex2f( citylist[i].longitude, 
                      citylist[i].latitude ); 
        } 
      } 
      glEnd(); 
     /* 

затем

 

рисуем

 

названия

 

городов

 */ 

   for (i=0; i < n ;i++)  
   { 


background image

 79

     DrawText(citylist[i].longitude, 
              citylist[i].latitude, 
              citylist[i].name); 
   } 

В

 

такой

 

реализации

 

мы

 

вызываем

 

glPointSize

 

дважды

 

и

 

увеличиваем

 

число

 

вершин

 

между

 

glBegin

 

и

 

glEnd

Однако

 

остаются

 

еще

 

пути

 

для

 

оптимизации

Если

 

мы

 

поменяем

 

наши

 

структуры

 

данных

то

 

можем

 

еще

 

повысить

 

эффективность

 

рисования

 

точек

Например

struct city_list  

  int num_cities; /* 

число

 

городов

 

в

 

списке

 */ 

  float *position;/* 

координаты

 

города

 */ 

  char **name;    /* 

указатель

 

на

 

названия

 

городов

 */ 

  float size;     /* 

размер

 

точки

обозначающей

 

город

 */ 

}; 

 

Теперь

 

города

 

разных

 

размеров

 

хранятся

 

в

 

разных

 

списках

Положения

 

точек

 

хранятся

 

отдельно

 

в

 

динамическом

 

массиве

После

 

реорганизации

 

мы

 

исключаем

 

необходимость

 

в

 

условном

 

операторе

 

внутри

 

glBegin/glEnd

 

и

 

получаем

 

возможность

 

использовать

  

массивы

 

вершин

 

для

 

оптимизации

В

 

результате

 

наша

 

функция

 

выглядит

 

следующим

 

образом

void draw_cities( struct city_list *list ) 
  { 
  int i; 
 
  /* 

рисуем

 

точки

 */ 

  glPointSize( list->size ); 
 
  glVertexPointer( 2, GL_FLOAT, 0,  
                   list->num_cities,  
                   list->position ); 
  glDrawArrays( GL_POINTS, 0, list->num_cities ); 
  /* 

рисуем

 

название

 

города

 */ 

  for (i=0; i < list->num_cities ;i++) 
  { 
     DrawText(citylist[i].longitude, 
              citylist[i].latitude 
              citylist[i].name); 
  } 


background image

 80

8.2. 

Оптимизация

 

вызовов

 OpenGL  

Существует

 

много

 

возможностей

 

улучшения

 

производительности

 

OpenGL. 

К

 

тому

 

же

 

разные

 

подходы

 

к

 

оптимизации

 

приводят

 

к

 

разным

 

эффектам

 

при

 

аппаратной

 

и

 

программной

 

визуализации

Например

интерполяция

 

цветов

 

может

 

быть

 

очень

 

дорогой

 

операцией

 

без

 

аппаратной

 

поддержки

а

 

при

 

аппаратной

 

визуализации

 

почти

 

не

 

дает

 

задержек

.  

После

 

каждой

 

из

 

следующих

 

методик

 

следуют

 

квадратные

 

скобки

в

 

которых

 

указан

 

один

 

из

 

символов

обозначающих

 

значимость

 

данной

 

методики

 

для

 

конкретной

 

системы

  

 

[

А

] – 

предпочтительно

 

для

 

систем

 

с

 

аппаратной

 

поддержкой

 

OpenGL  

 

[

П

] – 

предпочтительно

 

для

 

программных

 

реализаций

  

 

[

все

] – 

вероятно

 

предпочтительно

 

для

 

всех

 

реализаций

  

8.2.1. 

Передача

 

данных

 

в

 OpenGL 

В

 

данном

 

разделе

 

рассмотрим

 

способы

 

минимизации

 

времени

 

на

 

передачу

 

данных

 

о

 

примитивах

 

в

 OpenGL 

 

Используйте

 

связанные

 

примитивы

.

 

Связанные

 

примитивы

такие

 

как

 

GL_LINES

GL_LINE_LOOP

GL_TRIANGLE_STRIP

GL_TRIANGLE_FAN

и

 

GL_QUAD_STRIP

 

требуют

 

для

 

определения

 

меньше

 

вершин

чем

  

отдельные

 

линия

 

или

 

многоугольник

Это

 

уменьшает

 

количество

 

данных

передаваемых

 OpenGL [

все

]  

Используйте

 

массивы

 

вершин

На

 

большинстве

 

архитектур

 

замена

 

множественных

 

вызовов

 

glVertex/glColor/glNormal

 

на

 

механизм

 

массивов

 

вершин

 

может

 

быть

 

очень

 

выигрышной

. [

все

]  

Используйте

 

индексированные

 

примитивы

В

 

некоторых

 

случаях

 

даже

 

при

 

использовании

 

связанных

 

примитивов

 

GL_TRIANGLE_STRIP

  (

GL_QUAD_STRIP

вершины

 

дублируются