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

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

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

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

Добавлен: 09.06.2020

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

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

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

 26

Как

 

правило

разные

 

типы

 

примитивов

 

имеют

 

различную

 

скорость

 

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

 

на

 

разных

 

платформах

Для

 

увеличения

 

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

 

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

 

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

 

примитивы

требующие

 

меньшее

 

количество

 

информации

 

для

 

передачи

 

на

 

сервер

такие

 

как

 

GL_TRIANGLE_STRIP

GL_QUAD_STRIP

GL_TRIAGLE_FAN.

 

Кроме

 

задания

 

самих

 

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

можно

 

определить

 

метод

 

их

 

отображения

 

на

 

экране

Однако

 

сначала

 

надо

 

определить

 

понятие

 

лицевых

 

и

 

обратных

 

граней

Под

 

гранью

 

понимается

 

одна

 

из

 

сторон

 

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

и

 

по

 

умолчанию

 

лицевой

 

считается

 

та

 

сторона

вершины

 

которой

 

обходятся

 

против

 

часовой

 

стрелки

Направление

 

обхода

 

вершин

 

лицевых

 

граней

 

можно

 

изменить

 

вызовом

 

команды

 

void 

glFrontFace

 (GLenum 

mode

 

со

 

значением

 

параметра

 

mode

 

равным

 

GL_CW 

(clockwise), 

а

 

вернуть

 

значение

 

по

 

умолчанию

 

можно

указав

 

GL_CCW 

(counter-clockwise). 

Чтобы

 

изменить

 

метод

 

отображения

 

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

 

используется

 

команда

 

void 

glPolygonMode

 (GLenum 

face

, Glenum 

mode

 

Параметр

 

mode

 

определяет

как

 

будут

 

отображаться

 

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

а

 

параметр

 

face

 

устанавливает

 

тип

 

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

к

 

которым

 

будет

 

применяться

 

эта

 

команда

 

и

 

может

 

принимать

 

следующие

 

значения

  

GL_FRONT

 

 

 

для

 

лицевых

 

граней

 

GL_BACK

 

 

 

для

 

обратных

 

граней

 

GL_FRONT_AND_BACK

 

для

 

всех

 

граней

 

Параметр

 

mode

 

может

 

быть

 

равен

GL_POINT 

отображение

 

только

 

вершин

 

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

GL_LINE

 

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

 

будут

 

представляться

 

набором

 

отрезков


background image

 27

GL_FILL 

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

 

будут

 

закрашиваться

 

текущим

 

цветом

 

с

 

учетом

 

освещения

и

 

этот

 

режим

 

установлен

 

по

 

умолчанию

 

Также

 

можно

 

указывать

какой

 

тип

 

граней

 

отображать

 

на

 

экране

Для

 

этого

 

сначала

 

надо

 

установить

 

соответствующий

 

режим

 

вызовом

 

команды

 

glEnable

 (GL_CULL_FACE)

а

 

затем

 

выбрать

 

тип

 

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

 

граней

 

с

 

помощью

 

команды

  

void 

glCullFace

 (GLenum 

mode

 

Вызов

 

с

 

параметром

 

GL_FRONT

 

приводит

 

к

 

удалению

 

из

 

изображения

 

всех

 

лицевых

 

граней

а

 

с

 

параметром

 

GL_BACK

 – 

обратных

 (

установка

 

по

 

умолчанию

).  

Кроме

 

рассмотренных

 

стандартных

 

примитивов

 

в

 

библиотеках

 GLU 

и

 GLUT  

описаны

 

более

 

сложные

 

фигуры

такие

 

как

 

сфера

цилиндр

диск

  (

в

 GLU) 

и

 

сфера

куб

конус

тор

тетраэдр

додекаэдр

икосаэдр

октаэдр

 

и

 

чайник

    (

в

 GLUT). 

Автоматическое

 

наложение

 

текстуры

 

предусмотрено

 

только

 

для

 

фигур

 

из

 

библиотеки

 GLU (

создание

 

текстур

 

в

 OpenGL 

будет

 

рассматриваться

 

в

 

главе

 5). 

Например

чтобы

 

нарисовать

 

сферу

 

или

 

цилиндр

надо

 

сначала

 

создать

 

объект

 

специального

 

типа

 GLUquadricObj 

с

 

помощью

 

команды

 

GLUquadricObj* 

gluNewQuadric

(void); 

 

а

 

затем

 

вызвать

  

соответствующую

 

команду

:  

void 

gluSphere

 (GLUquadricObj *

 qobj

, GLdouble

 radius

                GLint

 slices

, GLint

 stacks

 

void

 gluCylinder

 (GLUquadricObj *

 qobj

,  

                  

GLdouble

 baseRadius

                  

GLdouble 

topRadius

,  

                  

GLdouble

 height

GLint

 slices

,  

                  

GLint

 stacks

 

где

 

параметр

 

slices

 

задает

 

число

 

разбиений

 

вокруг

 

оси

 z, 

а

 

stacks

 – 

вдоль

 

оси

 z. 

Более

 

подробную

 

информацию

 

об

 

этих

 

и

 

других

 

командах

 

построения

 

примитивов

 

можно

 

найти

 

в

 

приложении

 

В


background image

 28

2.4. 

Дисплейные

 

списки

 

Если

 

мы

 

несколько

 

раз

 

обращаемся

 

к

 

одной

 

и

 

той

 

же

  

группе

 

команд

то

 

их

 

можно

 

объединить

 

в

 

так

 

называемый

 

дисплейный

 

список

 (display 

list), 

и

 

вызывать

 

его

 

при

 

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

Для

 

того

чтобы

 

создать

 

новый

 

дисплейный

 

список

,  

надо

 

поместить

 

все

 

команды

которые

 

должны

 

в

 

него

 

войти

между

 

следующими

 

операторными

 

скобками

void 

glNewList

 (GLuint 

list

, GLenum 

mode

void 

glEndList 

() 

 

Для

 

различения

 

списков

 

используются

 

целые

 

положительные

 

числа

задаваемые

 

при

 

создании

 

списка

 

значением

 

параметра

 

list

а

 

параметр

 

mode

 

определяет

 

режим

 

обработки

 

команд

входящих

 

в

 

список

GL_COMPILE

 

команды

 

записываются

 

в

 

список

 

без

 

выполнения

 

GL_COMPILE_AND_EXECUTE

 

команды

 

сначала

 

выполняются

а

 

затем

 

записываются

 

в

 

список

 

После

 

того

как

 

список

 

создан

его

 

можно

 

вызвать

 

командой

 

void 

glCallList

 (GLuint 

list

 

указав

 

в

 

параметре

 

list

 

идентификатор

 

нужного

 

списка

Чтобы

 

вызвать

 

сразу

 

несколько

 

списков

можно

 

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

 

командой

 

void 

glCallLists 

(GLsizei 

n

, GLenum 

type

, const GLvoid 

*

lists

 

вызывающей

 

n

 

списков

 

с

 

идентификаторами

 

из

 

массива

 

lists

тип

 

элементов

 

которого

 

указывается

 

в

 

параметре

 

type

Это

 

могут

 

быть

 

типы

 

GL_BYTE

GL_UNSIGNED_BYTE

GL_SHORT

GL_INT

GL_UNSIGNED_INT

 

и

 

некоторые

 

другие

Для

 

удаления

 

списков

 

используется

 

команда

 

void 

glDeleteLists 

(GLint 

list

, GLsizei 

range

 

которая

 

удаляет

 

списки

 

с

 

идентификаторами

 ID 

из

 

диапазона

 

list

 

  ID 

  

list

+

range

-1. 

Пример

glNewList(1, GL_COMPILE); 


background image

 29

  glBegin(GL_TRIANGLES); 
    glVertex3f(1.0f, 1.0f, 1.0f); 
    glVertex3f(10.0f, 1.0f, 1.0f); 
    glVertex3f(10.0f, 10.0f, 1.0f); 
  glEnd(); 
glEndList() 

 

… 

glCallList(1); 

 

Дисплейные

 

списки

 

в

 

оптимальном

скомпилированном

 

виде

 

хранятся

 

в

 

памяти

 

сервера

что

 

позволяет

 

рисовать

 

примитивы

 

в

 

такой

 

форме

 

максимально

 

быстро

В

 

то

 

же

 

время

 

большие

 

объемы

 

данных

 

занимают

 

много

 

памяти

что

 

влечет

в

 

свою

 

очередь

,  

падение

 

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

Такие

 

большие

 

объемы

  (

больше

 

нескольких

 

десятков

 

тысяч

 

примитивов

лучше

 

рисовать

 

с

 

помощью

 

массивов

 

вершин

2.5. 

Массивы

 

вершин

 

Если

 

вершин

 

много

то

 

чтобы

 

не

 

вызывать

 

для

 

каждой

 

команду

 

glVertex*()

удобно

 

объединять

 

вершины

 

в

 

массивы

используя

 

команду

  

void 

glVertexPointer 

(GLint 

size

, GLenum 

type

,  

                      GLsizei 

stride

, void* 

ptr

 

которая

 

определяет

 

способ

 

хранения

 

и

 

координаты

 

вершин

При

 

этом

 

size

 

определяет

 

число

 

координат

 

вершины

  (

может

 

быть

 

равен

 2, 3, 4), 

type 

определяет

 

тип

 

данных

 (

может

 

быть

 

равен

  

GL_SHORT

GL_INT

GL_FLOAT

GL_DOUBLE

). 

Иногда

 

удобно

 

хранить

 

в

 

одном

 

массиве

 

другие

 

атрибуты

 

вершины

,  

тогда

 

параметр

 

stride

 

задает

 

смещение

 

от

 

координат

 

одной

 

вершины

 

до

 

координат

 

следующей

если

 

stride

 

равен

 

нулю

это

 

значит

что

 

координаты

 

расположены

 

последовательно

В

 

параметре

 

ptr

 

указывается

 

адрес

где

 

находятся

 

данные

Аналогично

 

можно

 

определить

 

массив

 

нормалей

цветов

 

и

 

некоторых

 

других

 

атрибутов

 

вершины

используя

 

команды

  

void 

glNormalPointer

 ( GLenum 

type

, GLsizei 

stride

,  

                     void  *

pointer

 ) 

void 

glColorPointer

 ( GLint 

size

, GLenum 

type

,  

                    GLsizei 

stride

, void *

pointer

 ) 


background image

 30

 

Для

 

того

чтобы

 

эти

 

массивы

 

можно

 

было

 

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

 

в

 

дальнейшем

надо

 

вызвать

 

команду

 

void  

glEnableClientState

 (GLenum 

array

 

с

 

параметрами

 

GL_VERTEX_ARRAY

GL_NORMAL_ARRAY

GL_COLOR_ARRAY

 

соответственно

После

 

окончания

 

работы

 

с

 

массивом

 

желательно

 

вызвать

 

команду

 

void 

glDisableClientState

 (GLenum 

array

 

 

с

 

соответствующим

 

значением

 

параметра

 

array.

 

Для

 

отображения

 

содержимого

 

массивов

 

используется

 

команда

 

void 

glArrayElement

 (GLint 

index

 

которая

 

передает

 OpenGL 

атрибуты

 

вершины

используя

 

элементы

 

массива

 

с

 

номером

 

index

Это

 

аналогично

 

последовательному

 

применению

 

команд

 

вида

 

glColor*(…), glNormal*(…), 

glVertex*(…)

 c 

соответствующими

 

параметрами

Однако

 

вместо

 

нее

 

обычно

 

вызывается

 

команда

 

void 

glDrawArrays

 (GLenum 

mode

, GLint 

first

,  

                   GLsizei 

count

 

рисующая

 

count

 

примитивов

определяемых

 

параметром

 

mode

используя

 

элементы

 

из

 

массивов

 

с

 

индексами

 

от

 

first

 

до

 

first

+

count

-1. 

Это

 

эквивалентно

 

вызову

 

последовательности

 

команд

 

glArrayElement()

 

с

 

соответствующими

 

индексами

.  

В

 

случае

если

 

одна

 

вершина

 

входит

 

в

 

несколько

 

примитивов

то

 

вместо

 

дублирования

 

ее

 

координат

 

в

 

массиве

 

удобно

 

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

 

ее

 

индекс

Для

 

этого

 

надо

 

вызвать

 

команду

  

void 

glDrawElements

 (GLenum 

mode

, GLsizei 

count

,  

                     GLenum 

type

, void *

indices

 

где

 

indices

 – 

это

 

массив

 

номеров

 

вершин

которые

 

надо

 

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

 

для

 

построения

 

примитивов

type

 

определяет

 

тип

 

элементов

 

этого