Главная страница
Навигация по странице:

  • Рис. 1 Битовая матрица символа Т Внимание

  • glClipPlane

  • Внимание

  • GL_CLEAR 0 GL_SET 1 GL_COPY s GL_COPY_INVERTED !s GL_NOOP d GL_INVERT !d GL_AND

  • GL_OR_REVERSE s|!d GL_OR_INVERTED !s|d Для разрешения подобного режима работы необходимо отработать команду glEnable() с аргументом GL_COLOR_LOGIC_OP

  • GL_SHORT , GL_INT , GL_FLOAT

  • GL_VERTEX_ARRAY ДЛЯ МАССИВА ВЕРШИН GL_NORMAL_ARRAY Для массива нормалей GL_COLOR_ARRAY Для массива цветов GL_TEXTURE_COORD_ARR

  • 1 шаг

  • 4 шаг

  • 3 С. А. Васильев opengl компьютерная графика


    Скачать 491.09 Kb.
    Название3 С. А. Васильев opengl компьютерная графика
    Дата23.03.2018
    Размер491.09 Kb.
    Формат файлаpdf
    Имя файлаvasilev.pdf
    ТипУчебное пособие
    #39231
    страница3 из 9
    1   2   3   4   5   6   7   8   9
    1 шаг: Кодировочные числа разместим в оперативной памяти.
    GLubyte BitMap[24] = {
    0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,
    0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0xff,0xc0,0xff,0xc0};
    0xff, 0xc0
    0xff, 0xc0
    0x0c, 0x00
    0x0c, 0x00
    0x0c, 0x00
    0x0c, 0x00
    0x0c, 0x00
    0x0c, 0x00
    0x0c, 0x00
    0x0c, 0x00
    0x0c, 0x00
    0x0c, 0x00
    Рис. 1 Битовая матрица символа Т
    Внимание! Битовый образ записывается в массив снизу вверх и справа налево.
    2 шаг: Указываем OpenGL, что пиксели битового образа в памяти будут выровнены по байту:

    19
    glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
    3 шаг: Определяем текущую позицию на экране: glRasterPos2i (120, 120);
    4 шаг: Рисуем на экране битовый образ: glBitmap (16, 12, 0.0, 0.0, 0.0, 0.0, BitMap);
    По этой команде будет выведен точечный рисунок, взятый по адресу BitMap, размером 16
    ×12 и без уточнения координат точки привязки, так как третий и четвертый параметр – (0.0, 0.0). Судя по пятому и шестому параметру (0.0, 0.0) текущая точка на экране после вывода битового образа не изменит своих координат.
    Для изучения пятого и шестого параметров команды glBitmap() рассмотрим еще один пример с этим же символом. Допустим, теперь необходимо сформировать строку из трех одинаковых символов.
    Код программы этой операции имеет вид: glClear(GL_COLOR_BUFFER_BIT); // Очищаем буфер цвета glColor3f (1.0, 1.0, 1.0); // Выбираем белый цвет glRasterPos2i (120, 120); // Текущая позиция экрана glBitmap (16, 12, 0.0, 0.0, 16.0, 0.0, BitMap); //1 символ glBitmap (16, 12, 0.0, 0.0, 16.0, 0.0, BitMap); //2 символ glBitmap (16, 12, 0.0, 0.0, 16.0, 0.0, BitMap); //3 символ
    Если потребуется вывести в строке разные символы, то для этого формируются несколько масси- вов точечных рисунков символов, например BitMap_A, BitMap_B и т.д. Следующий фрагмент програм- мы выводит символы A, B и C в одну строчку. glBitmap (16, 12, 0.0, 0.0, 16.0, 0.0, BitMap_A); glBitmap (16, 12, 0.0, 0.0, 16.0, 0.0, BitMap_B); glBitmap (16, 12, 0.0, 0.0, 16.0, 0.0, BitMap_C).
    Расстояние межу битовыми образами символов будет равно нулю, так как последующая позиция символа отличается от предыдущей на 16 (пятый параметр), что соответствует длине битового образа.
    Но на экране расстояние между символами мы будем все же наблюдать, лишь только потому, что при кодировке символа межсимвольное расстояние зарезервировано в его битовом образе (справа от симво- ла 6 столбцов) (см. рис. 1).
    5.8 Отсечение областью экрана
    Часто на практике требуется вывести графический примитив в рамках определенной прямоуголь- ной области экрана. Если часть объекта выходит за рамки этой области, то она не выводится на экран.
    Эту задачу решает тест отсечения, задаваемый командой void glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
    Эта команда задает прямоугольник отсечения: x и y – оконные координаты левой нижней угол об- ласти отсечения, width и height – ширина и высота этой области. Все параметры задаются в пикселях. В первый раз, когда контекст воспроизведения подсоединяется к окну, x и y принимают значения (0, 0), а
    width и height – его ширину и высоту.
    Для разрешения и запрещения отсечения используются команды glEnable() и glDisable() с парамет- ром GL_SCISSOR_TEST.
    Если выполнить команду glScissor(0, 0, 0, 0), то будет заблокирован вывод графики на экран, так как любая выводимая точка будет выходить за рамки отведенной области.
    5.9 Отсечение объектов плоскостями
    OpenGL предоставляет возможность разработчикам обрезать графические 3D объекты. В качестве секущей плоскости используется плоскость, заданная коэффициентами уравнения вида A x + B y + C z +
    D = 0. Напомним, вектор {A, B, C} – задает нормаль к плоскости. Для отсечения используется команда void glClipPlane (GLenum plane,const GLdouble*equation)
    Параметр plane определяет одну из шести (точнее – GL_MAX_CLIP_PLANES) секущих плоско- стей и может принимать следующие символьные значения: GL_CLIP_PLANEi, где i – целое число от 0 до 5 (GL_MAX_CLIP_PLANES-1). Параметр equation – указатель на массив из четырех значений (A, B,
    C и D), задающих уравнение плоскости. Внимание: Данный вектор указывает своим направлением на

    20
    оставшуюся часть объекта после отсечения. Для разрешения работы с подобными плоскостями необхо- димо выполнит команду glEnable() с аргументом GL_CLIP_PLANEi. Отключение секущей плоскости происходит после команды glDisable() с соответствующим аргументом.
    Рассмотрим пример отсечения некоторого объекта двумя плоскостями. Первая плоскость отсекает полупространство для которого x < 1 и вторая плоскость отсекает полупространство для которого y < 0

    // Коэффициенты A, B, C и D для первой плоскости отсечения
    GLdouble Pl0[] ={1.0, 0.0 ,0.0 ,1.0};
    // Коэффициенты A, B,C и D для второй плоскости отсечения
    GLdouble Pl1[] ={0.0 ,1.0 ,0.0 ,0.0};
    // Идентифицируем первую плоскость отсечения glClipPlane(GL_CLIP_PLANE0, Pl0);
    // Идентифицируем вторую плоскость отсечения glClipPlane(GL_CLIP_PLANE1, Pl1);
    // Включаем отсечение первой плоскостью glEnable (GL_CLIP_PLANE0);
    // Включаем отсечение второй плоскостью glEnable (GL_CLIP_PLANE1);
    // Здесь выводим объект …

    Следует помнить, что параметры секущей плоскости автоматически изменяются в соответствии с модельными и видовыми преобразованиями. И еще, вектор нормали (A, B, C) не должен быть обяза- тельно перпендикулярен осям, как в нашем примере.
    5.10 Логические операции при выводе объекта
    При поступлении значений объекта в буфер кадра в OpenGL обозначаются несколько интересных ситуаций: либо эти значения просто замещают существующие, либо происходит логическая операция между данными, которые находятся в соответствующем месте буфера кадра c поступающими данными.
    Задание логической операции определяется командой void glLogicOp(GLenum
    opcode
    ).
    Параметр opcode задает логическую операцию и может принимать следующие значения (принятые обозначения: s – значение бита источника, d – значение бита приемника).
    Opcode
    Логическая операция
    GL_CLEAR
    0
    GL_SET
    1
    GL_COPY
    s
    GL_COPY_INVERTED
    !s
    GL_NOOP
    d
    GL_INVERT
    !d
    GL_AND
    s&d
    GL_NAND
    !(s&d)
    GL_OR
    s|d
    GL_NOR
    !(s|d)
    GL_XOR
    s^d
    GL_EQUIV
    !(s^d)
    GL_AND_REVERSE
    s&!d
    GL_AND_INVERTED
    !s&d
    GL_OR_REVERSE
    s|!d
    GL_OR_INVERTED
    !s|d
    Для разрешения подобного режима работы необходимо отработать команду glEnable() с аргументом
    GL_COLOR_LOGIC_OP для полноцветного цветового режима. Выключается режим командой glDis-

    21
    able()с таким же аргументом. Напомним, логическая операция выполняется побитно над данными.
    6 РИСОВАНИЕ ГОТОВЫХ 3D ОБЪЕКТОВ
    Рассмотренные выше графические примитивы являются базовыми элементами для построения графических замыслов. Но в библиотеке GLU, которая реализована в виде модуля glu32.dll, описаны более сложные графические объекты, такие как сфера, цилиндр, диск и часть диска.
    Для построения подобных примитивов необходимо создать указатель на quadric-объект с помощью команды gluNewQuadric(), а после рисования удалить вызовом функции gluDeleteQuadric. Схема рисо- вания выглядит следующим образом:
    GLUquadricObj *quadric_obj; quadric_obj=gluNewQuadric();
    // вызов команды рисования графического объекта GLU gluDeleteQuadric(quadric_obj).
    Рассмотрим команды рисования графических объектов отдельно: void gluSphere (GLUquadricObj *quadric_obj,
    GLdouble radius,
    GLint slices,
    GLint stacks)
    Данная команда строит сферу с центром в начале координат и радиусом radius. Число разбиений сферы вокруг оси z задается параметром slices, а вдоль оси z параметром stacks. Внимание! Интересный эффект можно получить от сферы если задавать значения последних двух параметров из ряда величин:
    2, 3, 4 и т.д. void gluCylinder (GLUquadricObj *quadric_obj,
    GLdouble baseRadius, GLdouble topRadius,
    GLdouble height,
    GLint slices,
    GLint stacks)
    Эта команда строит цилиндр без оснований (кольцо), продольная ось параллельна оси z, заднее ос- нование имеет радиус baseRadius, и расположено в плоскости z = 0, переднее основание имеет радиус
    topRadius и расположено в плоскости z = height. Внимание! Если задать один из радиусов равным нулю, то будет построен конус. Параметры slices и stacks имеют тот же смысл, что и в командеgluSphere.
    Внимание! при увеличении значения stacks (больше двух) улучшается эффект сглаживания интерполя- ционной закраски поверхности. void gluDisk (GLUquadricObj *quadric_obj,
    GLdouble innerRadius, GLdouble outerRadius,
    GLint slices,
    GLint loops)
    Данная команда строит плоский диск (т.е. круг) с центром в начале координат и радиусом
    outerRadius. Если значение innerRadius ненулевое, то в центре диска будет находиться отверстие радиу- сом innerRadius. Параметр slices задает число разбиений диска вокруг оси z, а параметр loops число кон- центрических окружностей, перпендикулярных оси z. void gluPartialDisk (GLUquadricObj *quadric_obj,
    GLdouble innerRadius, GLdouble outerRadius,
    GLint slices,
    GLint loops,
    GLdouble startAngle, GLdouble sweepAngle);
    Отличие этой команды от предыдущей заключается в том, что она строит сектор круга, начальный и конечный углы которого отсчитываются против часовой стрелки от положительного направления оси
    y и задаются параметрами startAngle и sweepAngle. Внимание! Углы задаются в градусах.
    Кроме этих готовых графических объектов в OpenGL можно использовать объекты предоставлен- ные библиотекой GLUT: сфера, куб, конус, тор, тетраэдр, додекаэдр, икосаэдр, октаэдр и чайник. Для детального изучения команд моделирования подобных объектов рекомендуем обратиться к соответст- вующей документации.

    22
    7 РАБОТА С МАССИВАМИ ВЕРШИН И ИХ АТРИБУТОВ
    При моделировании объектов с большим количеством вершин можно не вызывать многократно ко- манду glVertex* (), а воспользоваться командой: void glVertexPointer (GLint s, GLenum t, GLsizei st, const GLvoid*p)
    Данная команда задает массив с координатами вершин. Здесь s – количество координат в каждой вершине и должно быть установлено в 2, 3 или 4. Параметр t задаеттип значения для координаты в мас- сиве и может принимать одну из следующих символьных констант GL_SHORT, GL_INT, GL_FLOAT и GL_DOUBLE. Параметр st принимает значение смещения в байтах между координатами соседних последовательных вершин. Если st равно нулю, то это означает, что координаты вершин расположены последовательно в массиве. Иногда удобно в массиве располагать не только значения координат вер- шин, но и некоторые сопутствующие атрибуты (текстурные координаты, нормали вершин, значения цвета и т.д.). В этом случае параметр st позволяет "раздвинуть" координаты вершин в массиве и оставить мес- та для дополнительных данных. Параметр p является указателем на координаты первой вершины в мас- сиве.
    Такой подход к организации вершин объекта позволяет повысить скорость передачи данных в
    OpenGL, что, в конечном счете, положительно влияет на скорость рисования этих объектов на экране.
    Аналогично можно организовать массивы нормалей, цветов и текстурных координат. Для это су- ществуют соответствующие команды: void glNormalPointer (GLenum t , GLsizei s, const GLvoid *p) void glColorPointer (GLint s, GLenum t, GLsizei st, const GLvoid *p)
    void glTexCoordPointer(GLint s, GLenum t, GLsizei st, const GLvoid*p)
    Чтобы разрешить работу с подобными массивами, необходимо вызвать команду glEnableClientState() с соответствующим аргументом:
    Аргумент
    Назначение
    GL_VERTEX_ARRAY
    ДЛЯ МАССИВА
    ВЕРШИН
    GL_NORMAL_ARRAY
    Для массива нормалей
    GL_COLOR_ARRAY
    Для массива цветов
    GL_TEXTURE_COORD_ARR
    AY
    Для текстовых коор- динат
    Для запрещения работы с массивом используется команда –glDisableClientState с соответствующим аргументом.
    После того как требуемые массивы сформированы и работа с ними разрешена, воспроизведение примитива осуществляется вызовом команды void glDrawArrays (GLenum mode, GLint first, GLsizei count)
    Эта команда осуществляет воспроизведение примитива, заданного параметром mode (см. команду glBegin/glEnd). Всего отображается count элементов, начиная с номера, указанного параметром first.
    Для отображения единственного параметра примитива используется команда void glArrayElement (GLint index)
    Параметр index задает номер отображаемого элемента примитива.
    Кстати, внутренний механизм работы команды glDrawArrays() основан на последовательном вы- полнении команды glArrayElement() count раз, начиная с first примитива.
    Для закрепления материала рассмотрим простой пример. Пусть требуется нарисовать с помощью glDrawArrays() пятиугольник с различными цветами вершин. Рассмотрим выполнение этой задачи по шагам:
    1 шаг: Объявляем массивы вершин (v) и цвета (c).
    GLfloat V[5][2]; // Для x и y
    GLfloat C[5][3]; // Для R, G и B
    2 шаг: Заполняем массив (v) исходными значениями координат вершин пятиугольника и массив (c)

    23
    атрибутами цвета.
    V[0][0] = 0.0; V[0][1] = 2.0; C[0][0] = 1.0; C[0][1] = 0.0; C[0][2] = 0.0;
    V[1][0] = 2.0; V[1][1] = 1.0; C[1][0] = 0.0; C[1][1] = 1.0; C[1][2] = 0.0;
    V[2][0] = 1.5; V[2][1] = –1.0; C[2][0] = 0.0; C[2][1] = 0.0; C[2][2] = 1.0;
    V[3][0] = –1.5; V[3][1] = –1.0; C[3][0] = 0.0; C[3][1] = 0.5; C[3][2] = 0.0;
    V[4][0] = –2.0; V[4][1] = 1.0; C[4][0] = 1.0; C[4][1] = 0.5; C[4][2] = 1.0;
    3 шаг: Указываем OpenGL, что данные этих массивов будут использоваться командами glVertex-
    Pointer и glColorPointer для размещения в специализированных внутренних массивах вершин и цветов. glVertexPointer(2, GL_FLOAT, 0, V); glColorPointer(3, GL_FLOAT, 0, C);
    4 шаг: Разрешаем работать OpenGL с внутренним массивом вершин и массивом цветов. glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY);
    5 шаг: Рисуем пятиугольник. glDrawArrays(GL_POLYGON, 0, 5);
    6 шаг: Делаем недоступными массивы вершин и цветов glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY);
    Вот и все.
    Если воспользоваться третьем параметром команды gl*Pointer, то подобную задачу можно выпол- нить более компактно. Для этого разместим исходные данные на вершины и их цветов в перебежку
    (вершина, цвет, вершина, цвет т т.д.) в одном одномерном массиве:
    GLfloat VC[] = { 0.0, 2.0, 1.0, 0.0, 0.0,
    2.0, 1.0, 0.0, 1.0, 0.0,
    1.5, –1.0, 0.0, 0.0, 1.0,
    –1.5, –1.0, 0.0, 0.5, 0.0,
    –2.0, 1.0, 1.0, 0.5, 1.0 };
    Далее вызываем команды glVertexPointer и glColorPointer: glVertexPointer(2,GL_FLOAT, 5*sizeof(GLfloat), &VC[0]); glColorPointer(3, GL_FLOAT, 5*sizeof(GLfloat), &VC[2]);
    Обратите внимание на то, что массив вершин будет набираться с первого элемента массива VC по два значения типа float c шагом 5*sizeof(GLfloat). На правильность выбранного шага подсказывает тот факт, что порядковые номера одноименных данных в массиве VC отличаются друг ото друга на 5. А так как тип элементов массива float, то и смещение определяется выражением 5*sizeof(GLfloat). Первые два числа в массиве всегда относятся к вершине объекта, а начиная с третьего, точнее с номера 2, так как нумерация элементов в массиве идет с номера – 0, параметры цвета соответствующей вершины.
    И в завершении уже знакомые команды: glDrawArrays(GL_POLYGON, 0, 5); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY);
    На экране мы получаем такой же результат, что и в предыдущем примере.
    8 РАБОТА СО СПИСКАМИ ИЗОБРАЖЕНИЙ
    В OpenGL предоставляется возможность объединять группу команд под определенным именем для последующего выполнения. Это обеспечивают списки изображений (дисплейные списки). Они подобны подпрограммам и являются удобным средством для кодирования больших систем со сложной иерархи- ей. Список организуется командами: void glNewList (GLuint list, GLenum mode) void glEndList ()
    Эти команды выглядят, как операторные скобки. Первая команда является заголовком (началом) нового списка изображений. Список заканчивается командой glEndList(). Параметр list представляет со- бой целочисленный идентификатор – имя списка. Параметр mode – символическая константа, опреде- ляющая следующие режимы сборки списка:
    Константа
    Режим сборки списка

    24
    GL_COMPILE
    СПИСОК КОМАНД ТОЛЬ-
    КО КОМПИЛИРУЕТСЯ
    (НАКАПЛИВАЕТСЯ) ДЛЯ
    ВОЗМОЖНОГО ПОСЛЕ-
    ДУЮЩЕГО ИСПОЛЬЗО-
    ВАНИЯ
    GL_COMPILE_AND_EXECU
    TE
    Команды исполняются и толь- ко потом заносятся в список
    OpenGL компилирует список изображений только один раз, после этого он готов к применению.
    Поэтому мы получаем увеличение скорости при использовании списков изображений.
    Порядок, в котором команды располагаются в списке изображений, жестко определяют порядок, в котором они будут выполняться.
    Вызов списка изображений осуществляется командой: void
    1   2   3   4   5   6   7   8   9


    написать администратору сайта