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

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

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

Добавлен: 09.06.2020

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

Скачиваний: 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

определяет

тип

элементов

этого