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

  • УДК 004.92(076)

  • ISBN 5-85546-193-9

  • ПОДКЛЮЧЕНИЕ БИБЛИОТЕК; КОНТЕКСТ

  • ОБЩИЙ ВИД ПРОГРАММЫ Цель работы

  • Основные понятия, используемые в данной лабораторной

  • Порядок выполнения работы

  • Е. А. Снижко, Н. А. Флерова


    Скачать 0.57 Mb.
    НазваниеЕ. А. Снижко, Н. А. Флерова
    Дата02.11.2018
    Размер0.57 Mb.
    Формат файлаpdf
    Имя файлаelr00490.pdf
    ТипПрактикум
    #55262
    страница1 из 7
      1   2   3   4   5   6   7

    Е.А. СНИЖКО, Н.А. ФЛЕРОВА,
    А.В. ВОРОНЦОВ
    ПРОГРАММИРОВАНИЕ
    КОМПЬЮТЕРНОЙ ГРАФИКИ
    С ИСПОЛЬЗОВАНИЕМ
    БИБЛИОТЕКИ OPENGL
    Лабораторный практикум

    Министерство образования и науки Российской Федерации
    Балтийский государственный технический университет "Военмех"
    Институт систем управления
    Кафедра информационных систем и компьютерных технологий
    Е.А. СНИЖКО, Н.А. ФЛЕРОВА, А.В. ВОРОНЦОВ
    ПРОГРАММИРОВАНИЕ
    КОМПЬЮТЕРНОЙ ГРАФИКИ
    С ИСПОЛЬЗОВАНИЕМ
    БИБЛИОТЕКИ OPENGL
    Лабораторный практикум
    Санкт-Петербург
    2006

    УДК 004.92(076)
    С53
    С53
    Снижко, Е.А.
    Программирование компьютерной графики с использованием библиотеки ОpenGL: лаб. практи- кум / Е.А. Снижко, Н.А. Флерова, А.В. Воронцов;
    Балт. гос. техн. ун-т. – СПб., 2006. – 88 с.
    ISBN 5-85546-193-9
    Приведено описание комплекса лабораторных работ по курсу «Компьютерная графика» с упором на про- граммную генерацию изображений средствами кросс- платформенной графической библиотеки OpenGL. Cо- держится необходимый справочный материал, связанный с использованием библиотеки.
    Для студентов специальности 230102, имеющих на- выки программирования на C++ или Delphi.
    УДК 004.92(076)
    Р е ц е н з е н т канд. пед. наук, доц. каф. информатики и ВТ
    Тульского гос. пед. ун-та Ю. М. Мартынюк
    Утверждено
    редакционно-издательским
    советом университета
    ISBN 5-85546-193-9
    © Авторы, 2006
    © БГТУ, 2006

    3
    П Р Е Д И С Л О В И Е
    Практикум содержит семь лабораторных работ, отражающих основные возможности программирования графики с использо- ванием кроссплатформенной библиотеки OpenGL.
    В настоящее время наиболее известны графические библио- теки DirectX и OpenGL. Первая является внутренним стандартом фирмы Microsoft и сильно привязана к операционной системе
    Windows. Библиотека OpenGL является открытым международ- ным стандартом, поэтому ей отдано предпочтение при составле- нии данного практикума.
    Теоретические сведения, относящиеся к алгоритмическому аспекту графического вывода, отражены в конспекте лекций
    «Компьютерная геометрия и графика» и в практикуме не рас- сматриваются. В указаниях к лабораторным работам имеются ссылки на лекции, содержащиеся в конспекте, а также на допол- нительные источники информации по данной теме.
    Для выполнения лабораторных работ студенты должны иметь навыки программирования на языке C++, а также первона- чальные знания об операционной системе Windows и особенно- стях программирования под Windows. Хотя библиотека OpenGL является кроссплатформенной, т.е. не зависит от операционной системы, в работах предусматривается использовать возможно- сти именно Windows как наиболее распространенной.
    Все задания практикума могут быть выполнены также на ос- нове среды визуального программирования Delphi. Некоторые различия в синтаксисе отдельных команд комментируются в тек- сте соответствующими сносками. В приложении 1 приведен код минимальной программы с использованием библиотеки OpenGL на языке C++; приложение 2 содержит три варианта кодов мини- мальной программы на Delphi.
    Каждая работа включает набор обязательных и дополнитель- ных заданий. Обязательные задания выполняются в соответствии с вариантом, дополнительные могут быть предложены препода- вателем в индивидуальном порядке.
    При защите работы студенты должны представить работо- способные программы по каждому заданию, отчет, содержащий исходные коды разработанных программ и ответы на контроль- ные вопросы.

    4
    Лабораторная работа № 1
    ПОДКЛЮЧЕНИЕ БИБЛИОТЕК; КОНТЕКСТ
    УСТРОЙСТВА, КОНТЕКСТ ВОСПРОИЗВЕДЕНИЯ;
    ОБЩИЙ ВИД ПРОГРАММЫ
    Цель работы – создание программы-заготовки для работы с библиотекой ОpenGL.
    Необходимые теоретические сведения
    Для использования библиотеки OpenGL требуются навыки программирования на C++, а также знания основ событийного программирования на уровне операционной системы Windows
    1
    Для выполнения работы необходимо иметь представление об основных принципах формирования изображения на экране, о современных стандартах и интерфейсах программирования ком- пьютерной графики (лекция 17), знать особенности представле- ния цвета в цветовой модели RGB (лекция 4) [7].
    Основные понятия, используемые в данной лабораторной
    работе: контекст устройства, контекст воспроизведения, формат пикселя.
    Контекст графического устройства (Device Context) указы- вает плоскость отображения, на которую осуществляется графи- ческий вывод: окно программы на экране дисплея, страница принтера или другое место, куда может быть направлен графиче- ский вывод. Если программа вызывает различные графические функции, такие как рисование точек, линий, фигур и др., необхо- димо указывать идентификатор контекста (hdc – handle of device context) и координаты. Смысл использования контекста устрой- ства заключается в том, что вывод на различные устройства осу- ществляется одними и теми же функциями, изменяется лишь зна- чение hDC. Контекст устройства является структурой, которая определяет комплект графических объектов и связанных с ними
    1
    Лабораторные работы могут выполняться в среде визуального программи- рования Delphi.

    5 атрибутов и графические режимы, влияющие на вывод. При со- ставлении программы необходимо получить это числовое значе- ние перед рисованием, а после рисования освободить контекст.
    В OpenGL существует понятие контекст воспроизведения
    (контекст рендеринга), аналогичное понятию «контекст устрой- ства». Графическая система OpenGL также нуждается в ссылке на устройство, на которое будет осуществляться вывод. Это специ- альная ссылка на контекст воспроизведения – величина типа
    HGLRC (handle openGL rendering context, ссылка на контекст воспроизведения OpenGL) – hRC.
    Прежде чем установить контекст воспроизведения, сервер
    OpenGL должен получить детальные характеристики используе- мого оборудования. Эти характеристики хранятся в специальной структуре – описание формата пикселя. Формат пикселя опреде- ляет конфигурацию буфера цвета и вспомогательных буферов.
    Порядок выполнения работы
    Программа, которая будет создана в результате выполнения данной работы, должна осуществлять следующие действия: соз- давать пустое окно для графического вывода средствами openGL; устанавливать все необходимые параметры графического вывода; реагировать на нажатие клавиши для закрытия окна и за- вершения работы. Для демонстрации графического вывода в кон- це работы в окне будет построено некоторое изображение. Соз- данная программа явится основой для выполнения всех после- дующих работ.
    1.
    Создайте новое приложение в Visual C++.
    2.
    Добавьте для сборки проекта библиотеки OpenGL. Для этого:

    в меню Project/setting, выберите закладку LINK;

    в строке "Object/Library Modules" добавьте строку "OpenGL32.lib GLu32.lib GLaux.lib";

    для завершения щелкните левой клавишей мыши по кнопке OK.
    3.
    Введите в текст кода следующие строки (они сообщают компилятору, какие библиотечные файлы следует использовать):

    6
    #include
    //
    Заголовочный файл для
    Windows
    #include
    //
    Заголовочный файл для библиотеки
    OpenGL32
    #include
    //
    Заголовочный файл для библиотеки
    GLu32
    #include
    //
    Заголовочный файл для библиотеки
    GLaux
    4.
    Инициализируйте все переменные, которые будут ис- пользованы в программе.
    Первые две строки устанавливают контекст воспроизведения
    (рендеринга) и контекст устройства. Контекст Рендеринга
    OpenGL определен как hRC и связывает вызовы OpenGL с окном
    Windows. Для того чтобы рисовать в окне, необходимо создать контекст устройства Windows, который определен как hDC. Кон- текст устройства связывает окно с GDI. Контекст воспроизведе- ния связывает OpenGL с контекстом устройства: static HGLRC hRC;
    //
    Постоянный контекст рендеринга static HDC hDC;
    //
    Приватный контекст устройства
    GDI
    5.
    Объявите массив для отслеживания нажатия клавиш на клавиатуре (указанный ниже способ позволяет отслеживать на- жатие нескольких клавиш одновременно):
    BOOL keys[256];
    //
    Массив для процедуры обработки клавиатуры
    6.
    В следующей секции кода будут произведены все на- стройки для OpenGL. Эта процедура может быть вызвана только после того, как будет создано окно OpenGL. Установим цвет, ко- торым будет очищен экран. Все значения могут быть в диапазоне от 0.0f до 1.0f, при этом 0.0 самый темный, а 1.0 самый светлый.
    Первые три параметра определяют цвет в модели RGB: первый - интенсивность красного, второй – зеленого, третий – синего.
    Наибольшее значение – 1.0f – является самым ярким значением данного цвета. Последний параметр – альфа-значение (прозрач- ность) – пока будет равен 0.0f:

    7
    GLvoid
    InitGL(GLsizei
    Width,
    GLsizei
    Height)
    //
    Вызвать после создания окна
    GL
    { glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    //
    Очистка экрана в
    черный цвет
    }
    7.
    Следующая секция кода – функция масштабирования сцены, вызываемая OpenGL всякий раз, когда изменяется размер окна. Даже если размеры окна не изменяются (например, в пол- ноэкранном режиме), эта процедура все равно должна быть вы- звана хотя бы один раз (обычно во время запуска программы), так как сцена масштабируется, основываясь на ширине и высоте отображаемого окна:
    GLvoid ReSizeGLScene(GLsizei Width, GLsizei Height)
    { if (Height==0)
    //
    Предотвращение деления на ноль
    ,
    //
    если окно слишком мало
    Height=1; glViewport(0, 0, Width, Height);
    //
    Сброс текущей области вывода и
    //
    перспективных преобразований
    }
    8.
    Следующая секция предназначена для рисования сцены.
    Впоследствии код будет добавляться именно в эту секцию про- граммы. Пока запишем в этой секции только команду для очист- ки экрана цветом, который мы определили выше. Команды рисо- вания будут следовать за ней:
    GLvoid DrawGLScene(GLvoid)
    { glClear(GL_COLOR_BUFFER_BIT);
    // очистка экрана
    }
    9.
    Одна из важнейших секций кода устанавливает парамет- ры окна Windows, формат пикселя, обрабатывает сообщения при изменении размеров окна, при нажатии на клавиши и при закры- тии программы.

    8
    Первые четыре строки делают следующее. Переменная hWnd является указателем на окно. Переменная message – сообщения, передаваемые программе системой. Переменные wParam и
    lParam содержат информацию, которая посылается вместе с со- общением, например такая, как ширина и высота окна:
    LRESULT CALLBACK WndProc(
    HWND hWnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
    Код между скобками устанавливает формат пикселей, кото- рый определяет параметры вывода в окно. Большая часть кода игнорируется, но тем не менее необходима:
    {
    RECT
    Screen;
    // используется позднее для размеров окна
    GLuint PixelFormat; static PIXELFORMATDESCRIPTOR pfd=
    { sizeof(PIXELFORMATDESCRIPTOR),
    //
    Размер этой структуры
    1,
    //
    Номер версии
    PFD_DRAW_TO_WINDOW |
    //
    Формат для
    Окна
    PFD_SUPPORT_OPENGL |
    //
    Формат для
    OpenGL
    PFD_DOUBLEBUFFER,
    //
    Формат для двойного буфера
    PFD_TYPE_RGBA,
    //
    Требуется
    RGBA формат
    16,
    //
    Выбор
    16 бит глубины цвета
    0, 0, 0, 0, 0, 0, //
    Игнорирование цветовых битов
    0,
    // нет буфера прозрачности
    0,
    //
    Сдвиговый бит игнорируется
    0,
    //
    Нет буфера аккумуляции
    0, 0, 0, 0,
    //
    Биты аккумуляции игнорируются
    16,
    // 16 битный
    Z- буфер
    (
    буфер глубины
    )
    0,
    //
    Нет буфера трафарета
    0,
    //
    Нет вспомогательных буферов
    PFD_MAIN_PLANE,
    //
    Главный слой рисования
    0,
    //
    Резерв
    0, 0, 0
    //
    Маски слоя игнорируются
    };

    9
    Следующая секция предназначена для обработки системных сообщений: выход из программы, нажатие клавиш, перемещение окна и т.д., каждая секция "case" обрабатывает свой тип сообще- ния: switch (message)
    //
    Тип сообщения
    {
    WM_CREATE указывает программе, что сообщение должно быть создано. Сначала следует запросить DC (контекст устройст- ва) для окна – без него рисование в окне невозможно. Затем за- прашивается формат пикселя. Компьютер будет выбирать фор- мат, который полностью совпадает с запрашиваемым форматом или наиболее близок к нему
    2
    : case WM_CREATE: hDC = GetDC(hWnd);
    //
    Получить контекст устройства для окна
    PixelFormat = ChoosePixelFormat(hDC, &pfd);
    //
    Найти ближайшее совпадение для формата пикселей
    Если подходящий формат пикселя не найден, будет выведено сообщение об ошибке: if (!PixelFormat)
    {
    MessageBox(0,"
    Не найден подходящий формат пикселя
    .",
    "
    Ошибка ",MB_OK|MB_ICONERROR);
    3
    PostQuitMessage(0);
    //
    Это сообщение говорит
    , что
    // программа должна завершиться break;
    //
    Предотвращение повтора кода
    }
    Если подходящий формат найден, компьютер будет пытаться установить формат пикселя для контекста устройства. Если фор- мат пикселя не может быть установлен по какой-то причине, поя- вится соответствующее сообщение:
    2
    В программе на C++ указатель записан в виде &pfd, в программе на Delphi следует записать @pfd.
    3
    В Delphi вместо символа «|» используется «or».

    10 if(!SetPixelFormat(hDC,PixelFormat,&pfd))
    {
    MessageBox(0,"
    Формат пикселя не установлен
    .",
    "
    Ошибка ",MB_OK|MB_ICONERROR);
    PostQuitMessage(0); break;
    }
    Если код записан, как показано выше, будет создан контекст устройства(DC) и установлен подходящий формат пикселя.
    Далее следует создать Контекст Рендеринга (RC), для этого
    OpenGL использует DC. Функция wglCreateContext захватывает
    Контекст Рендеринга и сохраняет его в переменной hRC. Если по какой-то причине Контекст Рендеринга недоступен, должно поя- виться сообщение об ошибке: hRC = wglCreateContext(hDC); if(!hRC)
    {
    MessageBox(0,"
    Контекст воспроизведения не создан
    .",
    "
    Ошибка ",MB_OK|MB_ICONERROR);
    PostQuitMessage(0); break;
    }
    Необходимо сделать активным Контекст Рендеринга, для то- го чтобы можно было рисовать в окне средствами OpenGL. Если по какой-либо причине это невозможно, должно появиться сооб- щение об ошибке: if(!wglMakeCurrent(hDC, hRC))
    {
    MessageBox(0,"
    Невозможно активизировать
    GLRC.",
    "
    Ошибка ",MB_OK|MB_ICONERROR);
    PostQuitMessage(0); break;
    }
    10.
    Создадим область рисования OpenGL. С помощью функ- ции GetClientRect можно определить ширину и высоту окна. По- сле того как ширина и высота окна получены, инициализируем экран OpenGL. Это достигается при помощи вызова функции
    InitGL с шириной и высотой окна в качестве параметров:

    11
    GetClientRect(hWnd, &Screen);
    InitGL(Screen.right, Screen.bottom); break;
    11.
    Следующий фрагмент кода необходим для уничтожения окна. Он использует сообщения WM_DESTROY и WM_CLOSE.
    Программа будет посылать это сообщение при выходе из программы по нажатию
    ALT-F4 или при ошибке
    (PostQuitMessage(0)).
    Функция ChangeDisplaySettings(NULL,0) восстанавливает разрешение рабочего стола (делая его таким, каким оно было до перехода в полноэкранный режим).
    Функция ReleaseDC(hWnd,hDC) уничтожает контекст уст- ройства окна.
    Перечисленные действия уничтожают окно OpenGL: case WM_DESTROY: case WM_CLOSE:
    ChangeDisplaySettings(NULL, 0); wglMakeCurrent(hDC,NULL); wglDeleteContext(hRC);
    ReleaseDC(hWnd,hDC);
    PostQuitMessage(0); break;
    12.
    Опишем обработку сообщений, возникающих при нажа- тии клавиш.
    Сообщение WM_KEYDOWN возникает всякий раз при нажа- тии клавиши. Клавиша, которая была нажата, сохраняется в пе- ременной wParam. При нажатии клавиши элемент массива, соот- ветствующий коду нажатой клавиши, принимает значение TRUE: case WM_KEYDOWN: keys[wParam] = TRUE; break;
    Сообщение WM_KEYUP вызывается всякий раз при отпуска- нии клавиши. Клавиша, которая отжата, также сохраняется в пе- ременной wParam. При отпускании клавиши соответствующий элемент массива принимает значение FALSE: case WM_KEYUP: keys[wParam] = FALSE; break;

    12 13.
    В завершении программы следует обработать изменение размеров окна. Даже при запуске программы в полноэкранном режиме этот код необходим, без него экран OpenGL не появится.
    Всякий раз сообщение WM_SIZE посылается Windows с дву- мя параметрами: новая ширина и новая высота экрана. Эти пара- метры сохранены в LOWORD(lParam) и HIWORD(lParam). Вызов функции ReSizeGLScene изменяет размеры экрана, т.е. передает высоту и ширину в эту секцию кода: case WM_SIZE:
    ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); break;
    Следующий код необходим для обработки Windows всех по- ступивших сообщений и завершения процедуры: default: return (DefWindowProc(hWnd, message, wParam, lParam));
    } return (0);
    }
    14.
    Следующая процедура необходима для создания и реги- страции окна Windows: int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,int nCmdShow)
    {
    MSG msg;
    //
    Структура сообщения
    Windows
    WNDCLASS wc;
    //
    Структура класса
    Windows
    // для установки типа окна
    HWND hWnd;
    //
    Сохранение дескриптора окна
    Флаги стиля CS_HREDRAW и CS_VREDRAW служат для пе- рерисовки окна при его перемещении. CS_OWNDC создает скры- тый DC для окна, т.е. DC не может использоваться совместно не- скольким приложениями. WndProc – процедура, которая перехва- тывает сообщения для программы. Свойство hIcon установлено равным нулю, т.е. иконка окна не нужна; для мыши используется стандартный указатель. Фоновый цвет не имеет значения (мы ус- тановим его в GL). Если меню в этом окне не требуется, то уста- новим его значение в NULL. Имя класса – это любое имя:

    13 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc
    = (WNDPROC) WndProc; wc.cbClsExtra
    = 0; wc.cbWndExtra
    = 0; wc.hInstance
    = hInstance; wc.hIcon
    = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground
    = NULL; wc.lpszMenuName
    = NULL; wc.lpszClassName
    = "OpenGL WinClass";
    Если при регистрации класса произошла ошибка, появится соответствующее сообщение: if(!RegisterClass(&wc))
    {
    MessageBox(0,"
    Ошибка регистрации класса окна
    .",
    "
    Ошибка ",MB_OK|MB_ICONERROR); return FALSE;
    }
    Создадим окно. Однако OpenGL будет вызвана только после того, как будет послано сообщение WM_CREATE. Флаги
    WS_CLIPCHILDREN и WS_CLIPSIBLINGS требуются для OpenGL и должны быть добавлены именно здесь: hWnd = CreateWindow(
    "OpenGL WinClass",
    "
    Это минимальная программа
    OpenGL",
    //
    Заголовок вверху окна
    WS_POPUP |
    WS_CLIPCHILDREN |
    WS_CLIPSIBLINGS,
    0, 0,
    //
    Позиция окна на экране
    640, 480,
    //
    Ширина и
    высота окна
    NULL,
    NULL, hInstance,
    NULL);
    Далее производится обычная проверка на ошибки. Если окно по какой-то причине не было создано, то сообщение об ошибке следует вывести на экран. При этом генерируется окно с сообще- нием об ошибке и предложением завершить программу:

    14 if(!hWnd)
    {
    MessageBox(0,"
    Ошибка создания окна
    .",
    "
    Ошибка ",MB_OK|MB_ICONERROR); return FALSE;
    }
    Для того чтобы можно было перейти в полноэкранный ре- жим, необходимо следовать правилу: ширина и высота в полно- экранном режиме должны совпадать с шириной и высотой, кото- рые установлены для окна вывода:
    DEVMODE dmScreenSettings;
    //
    Режим работы memset(&dmScreenSettings, 0, sizeof(DEVMODE));
    //
    Очистка для хранения установок dmScreenSettings.dmSize
    = sizeof(DEVMODE);
    //
    Размер структуры
    Devmode dmScreenSettings.dmPelsWidth
    = 640;
    //
    Ширина экрана dmScreenSettings.dmPelsHeight = 480;
    //
    Высота экрана dmScreenSettings.dmFields = DM_PELSWIDTH |
    DM_PELSHEIGHT;
    //
    Режим
    Пикселя
    ChangeDisplaySettings(&dmScreenSettings,
    CDS_FULLSCREEN);
    //
    Переключение в
    полный экран
    Функция ShowWindow показывает созданное окно.
    Функция UpdateWindow обновляет окно, SetFocus делает его активным и вызывает wglMakeCurrent(hDC,hRC), чтобы убедить- ся, что Контекст Рендеринга не освобожден:
    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);
    SetFocus(hWnd);
    Для того чтобы программа не завершала свою работу сразу же после отрисовки изображения, создадим бесконечный цикл.
    Для выхода из цикла можно использовать нажатие клавиши ESC.
    При этом программе будет отправлено сообщение о выходе и она прервется:

    15 while (1)
    {
    //
    Обработка всех сообщений while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
    { if (GetMessage(&msg, NULL, 0, 0))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    } else
    { return TRUE;
    }
    }
    Функция DrawGLScene вызывает ту часть программы, кото- рая фактически рисует объекты OpenGL. Пока оставим эту часть секции пустой, все что будет сделано – очистка экрана черным цветом.
    SwapBuffers(hDC) – очень важная команда. Мы имеем окно с установленной двойной буферизацией. Это означает, что изобра- жение рисуется на скрытом окне (называемым буфером). Затем с помощью команды переключения буферов скрытый буфер копи- руется на экран. При этом получается плавная анимация без рыв- ков и зритель не замечает процесс рисования объектов:
    DrawGLScene();
    //
    Нарисовать сцену
    SwapBuffers(hDC);
    //
    Переключить буфер экрана if (keys[VK_ESCAPE]) SendMessage(hWnd,WM_CLOSE,0,0);
    //
    Если
    ESC - выйти
    }
    }
    Важно отметить, что этот код не будет скомпилирован на Cи, он должен быть сохранен как .CPP файл.
    15.
    Скомпилируйте и выполните проект. Итак, наша програм- ма создает окно, размером 640х480, очищает его черным цветом и ожидает нажатия клавиши ESC (Alt+F4) для закрытия окна.
    16.
    Попробуйте нарисовать что-либо в этом окне. Добавьте в раздел DrawGLScene() следующий код:

    16
    { glClear(GL_COLOR_BUFFER_BIT); // очистка экрана glPointSize(2); //
    размер точки glBegin(GL_POINTS); glColor3d(1,0,0); glVertex3d(-0.45,-0.4,0); // первая точка glColor3d(0,1,0); glVertex3d(0.4,0.4,0);
    // вторая точка glColor3d(0,0,1); glVertex3d(-0.35,0.4,0);
    // третья точка glEnd();
    }
    17.
    Скомпилируйте и выполните проект. Сохраните результат вашей работы в своей папке. Этот шаблон будет использоваться в дальнейшей работе.
      1   2   3   4   5   6   7


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