Главная > Документ


Введение

OpenGL является одним из самых популярных прикладных программных интерфейсов (API – Application Programming Interface) для разработки приложений в области двумерной и трехмерной графики.

Стандарт OpenGL (Open Graphics Library – открытая графическая библиотека) был разработан и утвержден в 1992 году ведущими фирмами в области разработки программного обеспечения как эффективный аппаратно-независимый интерфейс, пригодный для реализации на различных платформах. Основой стандарта стала библиотека IRIS GL, разработанная фирмой Silicon Graphics Inc.

На сегодняшний день графическая система OpenGL поддерживается большинством производителей аппаратных и программных платформ. Эта система доступна тем, кто работает в среде Windows, пользователям компьютеров Apple. Свободно распространяемые коды системы Mesa (пакет API на базе OpenGL) можно компилировать в большинстве операционных систем, в том числе в Linux.

Характерными особенностями OpenGL, которые обеспечили распространение и развитие этого графического стандарта, являются:

  • Стабильность. Дополнения и изменения в стандарте реализуются таким образом, чтобы сохранить совместимость с разработанным ранее программным обеспечением.

  • Надежность и переносимость. Приложения, использующие OpenGL, гарантируют одинаковый визуальный результат вне зависимости от типа используемой операционной системы и организации отображения информации. Кроме того, эти приложения могут выполняться как на персональных компьютерах, так и на рабочих станциях и суперкомпьютерах.

  • Легкость применения. Стандарт OpenGL имеет продуманную структуру и интуитивно понятный интерфейс, что позволяет с меньшими затратами создавать эффективные приложения, содержащие меньше строк кода, чем с использованием других графических библиотек. Необходимые функции для обеспечения совместимости с различным оборудованием реализованы на уровне библиотеки и значительно упрощают разработку приложений.

Интерфейс OpenGL

OpenGL состоит из набора библиотек. Все базовые функции хранятся в основной библиотеке, для обозначения которой в дальнейшем мы будем использовать аббревиатуру GL. Помимо основной, OpenGL включает в себя несколько дополнительных библиотек.

Первая из них – библиотека утилитGL(GLUGLUtility). Все функции этой библиотеки определены через базовые функции GL. В состав GLU вошла реализация более сложных функций, таких как набор популярных геометрических примитивов (куб, шар, цилиндр, диск), функции построения сплайнов, реализация дополнительных операций над матрицами и т.п.

OpenGL не включает в себя никаких специальных команд для работы с окнами или ввода информации от пользователя. Поэтому были созданы специальные переносимые библиотеки для обеспечения часто используемых функций взаимодействия с пользователем и для отображения информации с помощью оконной подсистемы. Наиболее популярной является библиотека GLUT (GL Utility Toolkit). Формально GLUT не входит в OpenGL, но de facto включается почти во все его дистрибутивы и имеет реализации для различных платформ. GLUT предоставляет только минимально необходимый набор функций для создания OpenGL-приложения. Функционально аналогичная библиотека GLX менее популярна. В дальнейшем в этом пособии в качестве основной будет рассматриваться GLUT.

Кроме того, функции, специфичные для конкретной оконной подсистемы, обычно входят в ее прикладной программный интерфейс. Так, функции, поддерживающие выполнение OpenGL, есть в составе Win32 API и X Window. На рисунке схематически представлена организация системы библиотек в версии, работающей под управлением системы Windows. Аналогичная организация используется и в других версиях OpenGL.

Архитектура OpenGL

Функции OpenGL реализованы в модели клиент-сервер. Приложение выступает в роли клиента – оно вырабатывает команды, а сервер OpenGL интерпретирует и выполняет их. Сам сервер может находиться как на том же компьютере, на котором находится клиент (например, в виде динамически загружаемой библиотеки – DLL), так и на другом (при этом может быть использован специальный протокол передачи данных между машинами).

GL обрабатывает и рисует в буфере кадра графические примитивы с учетом некоторого числа выбранных режимов. Каждый примитив – это точка, отрезок, многоугольник и т.д. Каждый режим может быть изменен независимо от других. Определение примитивов, выбор режимов и другие операции описываются с помощью команд в форме вызовов функций прикладной библиотеки.

Примитивы определяются набором из одной или более вершин (vertex). Вершина определяет точку, конец отрезка или угол многоугольника. С каждой вершиной ассоциируются некоторые данные (координаты, цвет, нормаль, текстурные координаты и т.д.), называемые атрибутами. В подавляющем большинстве случаев каждая вершина обрабатывается независимо от других.

С точки зрения архитектуры графическая система OpenGL является конвейером, состоящим из нескольких последовательных этапов обработки графических данных.

Команды OpenGL всегда обрабатываются в том порядке, в котором они поступают, хотя могут происходить задержки перед тем, как проявится эффект от их выполнения. В большинстве случаев OpenGL предоставляет непосредственный интерфейс, т.е. определение объекта вызывает его визуализацию в буфере кадра.

С точки зрения разработчиков, OpenGL – это набор команд, которые управляют использованием графической аппаратуры. Если аппаратура состоит только из адресуемого буфера кадра, тогда OpenGL должен быть реализован полностью с использованием ресурсов центрального процессора. Обычно графическая аппаратура предоставляет различные уровни ускорения: от аппаратной реализации вывода линий и многоугольников до изощренных графических процессоров с поддержкой различных операций над геометрическими данными.

Рис. 1. Функционирование конвейера OpenGL




OpenGL является прослойкой между аппаратурой и пользовательским уровнем, что позволяет предоставлять единый интерфейс на разных платформах, используя возможности аппаратной поддержки.

Кроме того, OpenGL можно рассматривать как конечный автомат, состояние которого определяется множеством значений специальных переменных и значениями текущей нормали, цвета, координат текстуры и других атрибутов и признаков. Вся эта информация будет использована при поступлении в графическую систему координат вершины для построения фигуры, в которую она входит. Смена состояний происходит с помощью команд, которые оформляются как вызовы функций.

Синтаксис команд

Определения команд GL находятся в файле gl.h, для включения которого нужно написать

#include

В отличие от стандартных библиотек, пакет GLUT нужно инсталлировать и подключать отдельно. Подробная информация о настройке сред программирования для работы с OpenGL дана в Приложении С.

Все команды (процедуры и функции) библиотеки GL начинаются с префикса gl, все константы – с префикса GL_. Соответствующие команды и константы библиотек GLU и GLUT аналогично имеют префиксы glu (GLU_) и glut (GLUT_)

Кроме того, в имена команд входят суффиксы, несущие информацию о числе и типе передаваемых параметров. В OpenGL полное имя команды имеет вид:

type glCommand_name[1 2 3 4][b s i f d ub us ui][v]
(type1 arg1,…,typeN argN)

Имя состоит из нескольких частей:

gl имя библиотеки, в которой описана эта функция: для базовых функций OpenGL, функций из библиотек GL, GLU, GLUT, GLAUX это gl, glu, glut, aux соответственно.

Command_name имя команды (процедуры или функции)

[1 2 3 4] число аргументов команды

[bsifdubusui] тип аргумента: символ b – GLbyte (аналог char в С\С++), символ i – GLint (аналог int), символ f – GLfloat (аналог float) и так далее. Полный список типов и их описание можно посмотреть в файле gl.h

[v] наличие этого символа показывает, что в качестве параметров функции используется указатель на массив значений

Символы в квадратных скобках в некоторых названиях не используются. Например, команда glVertex2i() описана в библиотеке GL, и использует в качестве параметров два целых числа, а команда glColor3fv() использует в качестве параметра указатель на массив из трех вещественных чисел.

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

Функция glutInit(&argc, argv) производит начальную инициализацию самой библиотеки GLUT.

Команда glutInitDisplayMode(GLUT_RGB) инициализирует буфер кадра и настраивает полноцветный (непалитровый) режим RGB.

glutInitWindowSize(Width, Height) используется для задания начальных размеров окна.

Наконец, glutCreateWindow(";Red square example";) задает заголовок окна и визуализирует само окно на экране.

Затем команды

glutDisplayFunc(Display);

glutReshapeFunc(Reshape);

glutKeyboardFunc(Keyboard);

регистрируют функции Display(), Reshape() и Keyboard() как функции, которые будут вызваны, соответственно, при перерисовке окна, изменении размеров окна, нажатии клавиши на клавиатуре.

Контроль всех событий и вызов нужных функций происходит внутри бесконечного цикла в функции glutMainLoop()

Заметим, что библиотека GLUT не входит в состав OpenGL, а является лишь переносимой прослойкой между OpenGL и оконной подсистемой, предоставляя минимальный интерфейс. OpenGL-приложение для конкретной платформы может быть написано с использованием специфических API (Win32, X Window и т.д.), которые как правило предоставляют более широкие возможности.

Более подробно работа с библиотекой GLUT описана в Приложении А.

Все вызовы команд OpenGL происходят в обработчиках событий. Более подробно они будут рассмотрены в следующих главах. Сейчас обратим внимание на функцию Display, в которой сосредоточен код, непосредственно отвечающий за рисование на экране.

Следующая последовательность команд из функции Display

glClearColor(0, 0, 0, 1);

glClear(GL_COLOR_BUFFER_BIT);

glColor3ub(255,0,0);

glBegin(GL_QUADS);

glVertex2f(left,bottom);

glVertex2f(left,top);

glVertex2f(right,top);

glVertex2f(right,bottom);

glEnd();

очищает окно и выводит на экран квадрат, задавая координаты четырех угловых вершин и цвет.

Обычно приложение OpenGL в бесконечном цикле вызывает функцию обновления изображения в окне. В этой функции и сосредоточены вызовы основных команд OpenGL. Если используется библиотека GLUT, то это будет функция с обратным вызовом, зарегистрированная с помощью вызова glutDisplayFunc(). GLUT вызывает эту функцию, когда операционная система информирует приложение о том, что содержимое окна необходимо перерисовать (например, если окно было перекрыто другим). Создаваемое изображение может быть как статичным, так и анимированным, т.е. зависеть от каких-либо параметров, изменяющихся со временем. В этом случае лучше вызывать функцию обновления самостоятельно. Например, с помощью команды glutPostRedisplay(). За более подробной информацией можно обратиться к приложению A.

Приступим, наконец, к тому, чем занимается типичная функция обновления изображения. Как правило, она состоит из трех шагов:

  1. очистка буферов OpenGL;

  2. установка положения наблюдателя;

  3. преобразование и рисование геометрических объектов.

Очистка буферов производится с помощью команды:

void glClearColor ( clampf r, clampf g, clampf b,
clampf a )

void glClear(bitfield buf)

КомандаglClearColor устанавливает цвет, которым будет заполнен буфер кадра. Первые три параметра команды задают R,G и B компоненты цвета и должны принадлежать отрезку [0,1]. Четвертый параметр задает так называемую альфа компоненту (см. п. ). Как правило, он равен 1. По умолчанию цвет – черный (0,0,0,1).

Команда glClear очищает буферы, а параметр buf определяет комбинацию констант, соответствующую буферам, которые нужно очистить (см. главу 6). Типичная программа вызывает команду

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

для очистки буферов цвета и глубины.

Вершины и примитивы

Вершина является атомарным графическим примитивом OpenGL и определяет точку, конец отрезка, угол многоугольника и т.д. Все остальные примитивы формируются с помощью задания вершин, входящих в данный примитив. Например, отрезок определяется двумя вершинами, являющимися концами отрезка.

С каждой вершиной ассоциируются ее атрибуты. В число основных атрибутов входят положение вершины в пространстве, цвет вершины и вектор нормали.

Положение вершины в пространстве

Положение вершины определяются заданием ее координат в двух-, трех-, или четырехмерном пространстве (однородные координаты). Это реализуется с помощью нескольких вариантов команды glVertex*:

void glVertex[2 3 4][s i f d] (type coords)

void glVertex[2 3 4][s i f d]v (type *coords)

Каждая команда задает четыре координаты вершины: x, y, z, w. Команда glVertex2* получает значения x и y. Координата z в таком случае устанавливается по умолчанию равной 0, координата w – равной 1. Vertex3* получает координаты x, y, z и заносит в координату w значение 1. Vertex4* позволяет задать все четыре координаты.

Цвет вершины

Для задания текущего цвета вершины используются команды :

void glColor[3 4][b s i f] (GLtype components)

void glColor[3 4][b s i f]v (GLtype components)

Первые три параметра задают R, G, B компоненты цвета, а последний параметр определяет коэффициент непрозрачности (так называемая альфа-компонента). Если в названии команды указан тип ‘f’ (float), то значения всех параметров должны принадлежать отрезку [0,1], при этом по умолчанию значение альфа-компоненты устанавливается равным 1.0, что соответствует полной непрозрачности. Тип ‘ub’ (unsigned byte) подразумевает, что значения должны лежать в отрезке [0,255].

Вершинам можно назначать различные цвета, и, если включен соответствующий режим, то будет проводиться линейная интерполяция цветов по поверхности примитива.

Для управления режимом интерполяции используется команда

void glShadeModel (GLenum mode)

вызов которой с параметром GL_SMOOTH включает интерполяцию (установка по умолчанию), а с GL_FLAT – отключает.

Нормаль

Определить нормаль в вершине можно, используя команды

void glNormal3[b s i f d] (type coords)

void glNormal3[b s i f d]v (type coords)

Для правильного расчета освещения необходимо, чтобы вектор нормали имел единичную длину. Командой glEnable(GL_NORMALIZE)можно включить специальный режим, при котором задаваемые нормали будут нормироваться автоматически.

Режим автоматической нормализации должен быть включен, если приложение использует модельные преобразования растяжения/сжатия, так как в этом случае длина нормалей изменяется при умножении на модельно-видовую матрицу.

Однако применение этого режима уменьшает скорость работы механизма визуализации OpenGL, так как нормализация векторов имеет заметную вычислительную сложность (взятие квадратного корня и т.п.). Поэтому лучше сразу задавать единичные нормали.

Отметим, что команды

void glEnable (GLenum mode)

void glDisable (GLenum mode)

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

Операторные скобки glBegin / glEnd

Мы рассмотрели задание атрибутов одной вершины. Однако, чтобы задать атрибуты графического примитива, одних координат вершин недостаточно. Эти вершины надо объединить в одно целое, определив необходимые свойства. Для этого в OpenGL используются так называемые операторные скобки, являющиеся вызовами специальных команд OpenGL Определение примитива или последовательности примитивов происходит между вызовами команд

void glBegin (GLenum mode);

void glEnd (void);

Параметр mode определяет тип примитива, который задается внутри и может принимать следующие значения:

GL_POINTS каждая вершина задает координаты некоторой точки.

GL_LINES каждая отдельная пара вершин определяет отрезок; если задано нечетное число вершин, то последняя вершина игнорируется.

GL_LINE_STRIP каждая следующая вершина задает отрезок вместе с предыдущей.

GL_LINE_LOOP отличие от предыдущего примитива только в том, что последний отрезок определяется последней и первой вершиной, образуя замкнутую ломаную.

GL_TRIANGLES каждые отдельные три вершины определяют треугольник; если задано не кратное трем число вершин, то последние вершины игнорируются.

GL_TRIANGLE_STRIP каждая следующая вершина задает треугольник вместе с двумя предыдущими.

GL_TRIANGLE_FAN треугольники задаются первой вершиной и каждой следующей парой вершин (пары не пересекаются).

GL_QUADS каждая отдельная четверка вершин определяет четырехугольник; если задано не кратное четырем число вершин, то последние вершины игнорируются.

GL_QUAD_STRIP четырехугольник с номером n определяется вершинами с номерами 2n-1, 2n, 2n+2, 2n+1.

GL_POLYGON последовательно задаются вершины выпуклого многоугольника.

Например, чтобы нарисовать треугольник с разными цветами в вершинах, достаточно написать:

GLfloat BlueCol[3] = {0,0,1};

glBegin(GL_TRIANGLES);

glColor3f(1.0, 0.0, 0.0); /* красный */

glVertex3f(0.0, 0.0, 0.0);

glColor3ub(0,255,0); /* зеленый */

glVertex3f(1.0, 0.0, 0.0);

glColor3fv(BlueCol); /* синий */

glVertex3f(1.0, 1.0, 0.0);

glEnd();

Как правило, разные типы примитивов имеют различную скорость визуализации на разных платформах. Для увеличения производительности предпочтительнее использовать примитивы, требующие меньшее количество информации для передачи на сервер, такие как GL_TRIANGLE_STRIP, GL_QUAD_STRIP, GL_TRIAGLE_FAN.

Рис. 2. Примитивы OpenGL



Кроме задания самих многоугольников, можно определить метод их отображения на экране.

Однако сначала надо определить понятие лицевых и обратных граней.

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

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 многоугольники будут представляться набором отрезков.

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.

Дисплейные списки

Если мы несколько раз обращаемся к одной и той же группе команд, то их можно объединить в так называемый дисплейный список (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);

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);

Дисплейные списки в оптимальном, скомпилированном виде хранятся в памяти сервера, что позволяет рисовать примитивы в такой форме максимально быстро. В то же время большие объемы данных занимают много памяти, что влечет, в свою очередь, падение производительности. Такие большие объемы (больше нескольких десятков тысяч примитивов) лучше рисовать с помощью массивов вершин.

Массивы вершин

Если вершин много, то чтобы не вызывать для каждой команду 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 )

Для того, чтобы эти массивы можно было использовать в дальнейшем, надо вызвать команду

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 определяет тип элементов этого массива: GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, а count задает их количество.

Важно отметить, что использование массивов вершин позволяет оптимизировать передачу данных на сервер OpenGL, и, как следствие, повысить скорость рисования трехмерной сцены. Такой метод определения примитивов является одним из самых быстрых и хорошо подходит для визуализации больших объемов данных.



Скачать документ

Похожие документы:

  1. Содержание введение 4 глава 1 основы opengl 6 1 1 основные возможности 6

    Контрольные вопросы
    ... , необходимых для написания интерактивных графических приложений. НасегодняшнийденьграфическаясистемаOpenGLподдерживаетсябольшинствомпроизводителейаппаратных и программныхплатформ. Эта система доступна тем, кто работает ...
  2. МАТЕМАТИКИ И КИБЕРНЕТИКИ ЛАБОРАТОРИЯ КОМПЬЮТЕРНОЙ ГРАФИКИ И МУЛЬТИМЕДИА

    Методическое пособие
    ... , необходимых для написания интерактивных графических приложений. НасегодняшнийденьграфическаясистемаOpenGLподдерживаетсябольшинствомпроизводителейаппаратных и программныхплатформ. Эта система доступна тем, кто работает ...
  3. Предисловие содержание

    Контрольные вопросы
    ... , необходимых для написания интерактивных графических приложений. НасегодняшнийденьграфическаясистемаOpenGLподдерживаетсябольшинствомпроизводителейаппаратных и программныхплатформ. Эта система доступна тем, кто работает ...
  4. Численные решения и инженерные подходы в проектировании и построении вычислительных экспериментов в гидромеханике УДК 519 67

    Документ
    ... , необходимых для написания интерактивных графических приложений. НасегодняшнийденьграфическаясистемаOpenGLподдерживаетсябольшинствомпроизводителейаппаратных и программныхплатформ. Эта система доступна тем, кто работает ...
  5. Численные решения и инженерные подходы в проектировании и построении вычислительных экспериментов в гидромеханике УДК 519 67

    Документ
    ... , необходимых для написания интерактивных графических приложений. НасегодняшнийденьграфическаясистемаOpenGLподдерживаетсябольшинствомпроизводителейаппаратных и программныхплатформ. Эта система доступна тем, кто работает ...

Другие похожие документы..