extracted_text:
КОМПЬЮТЕРНАЯ ГРАФИКА
лабораторный
практикум

ЛАБОРАТОРНАЯ РАБОТА №1
OpenGL: инициализация, построение двумерных примитивов в отдельном окне

    Цель работы
Изучить  алгоритм
инициализации OpenGL для Windows,
получить практические навыки создания оконного приложения для вывода графических
изображений, созданных с помощью OpenGL.
Теоретическая информация

Использование библиотеки OpenGL требует навыков
программирования на C++, а также знания основ событийного программирования на
уровне операционной системы Windows. Однако, авторы не ставят своей целью
ограничивать выбор программных и аппаратных средств для выполнения работ по
компьютерной графике, поэтому в приложении приведены дополнительно варианты
инициализации OpenGL для различных ситуаций: с использованием библиотеки glut,
языков С# и Delphi, для ОС Linux.
Для выполнения работы так же необходимо иметь
представление о современных стандартах и интерфейсах программирования
компьютерной графики, об основных принципах формирования изображения на экране
компьютера, о составе графической библиотеки OpenGL.
Основные
понятия, используемые в данной лабораторной работе: контекст устройства,
контекст воспроизведения, формат пиксела, синтаксис команд OpenGL,
примитивы OpenGL.
Контекст графического устройства
(Device Context)
указывает плоскость отображения, на которую осуществляется графический вывод:
окно программы на экране дисплея, страница принтера или другое место, куда
может быть направлен графический вывод. Если программа вызывает различные графические
функции, такие как рисование точек, линий, фигур и др., необходимо указывать
идентификатор контекста (hdc
– handle of
device context)
и координаты. Смысл использования контекста устройства заключается в том, что
вывод на различные устройства осуществляется одними и теми же функциями,
изменяется лишь значение hDC.
«Контекст устройства является структурой, которая определяет комплект
графических объектов и связанных с ними атрибутов и графические режимы,
влияющие на вывод».  При составлении программы необходимо получить это числовое
значение перед рисованием, а после рисования – освободить контекст.
В OpenGL
существует понятие контекст воспроизведения (контекст рендеринга),
аналогичное понятию контекст устройства. Графическая система OpenGL
также нуждается в ссылке на устройство, на которое будет осуществляться вывод.
Это специальная ссылка на контекст воспроизведения – величина типа HGLRC
(handle openGL
rendering context,
ссылка на контекст воспроизведения OpenGL)
- hRC.
Алгоритм инициализации OpenGL
Основная задача
инициализации – синхронизировать 2 контекста: hRC
(контекст OpenGL) и hDC
(контекст окна), чтобы всё, что будет нарисовано OpenGL,
отображалось в окне.
Графически алгоритм
инициализации OpenGL можно представить следующим
образом (рис. 1).
Рассмотрим его подробнее.
1.
Подключение заголовочных файлов.
В зависимости от системы
программирования набор подключаемых библиотек может быть различным.
Если вы используете
Delphi, то всё необходимое для работы с OpenGL находится в модуле OpenGL.dcu.

Рисунок 1. Обобщенный
алгоритм инициализации OpenGL

Код на языке Delphi
uses OpenGL;

Если вы используете С++ Builder,
то подключать придётся несколько файлов:
·
gl.h
и glu.h содержат прототипы основных функций OpenGL определённых в opengl32.dll
и glu32.dll;
·
glaux.h
содержит вспомогательные (auxiliary) функции (glaux.dll).
Код на языке C++
#include <GL/gl.h>;
#include <GL/glu.h>;
#include <GL/glaux.h>;

Для инициализации в Microsoft Visual Studio необходимо
подключить следующие библиотеки:
 #include <windows.h>  // Заголовочный файл для Windows#include <gl\gl.h>    //Заголовочный файл для библиотеки OpenGL32 #include <gl\glu.h>   // Заголовочный файл для библиотеки GLu32 #include <gl\glaux.h>// Заголовочный файл для библиотеки GLaux

2.
Объявить глобальные переменные для контекста устройства
и контекста воспроизведения
Код на Delphi
var    hRC : HGLRC;  hDC :  HDC;

Код на языке C++
static HGLRC hRC;           // Постоянный контекст рендерингаstatic HDC hDC;       // Приватный контекст устройства GDI

3.
       Создание контекста устройства и установка
подходящего формата пикселей.
Прежде чем получить контекст воспроизведения, сервер OpenGL
должен получить детальные характеристики используемого оборудования. Эти характеристики
хранятся в специальной структуре – описание формата пикселя. Формат пикселя
определяет конфигурацию буфера цвета и вспомогательных буферов, а также то, как
OpenGL будет выводить изображение в окно. Эти характеристики хранятся в
специальной структуре, тип которой PixelFormatDescriptor
(описание
формата пикселей). Рассмотрим данную операцию более подробно. Выполняется она в
два приема:
Ø
подбирается один
из доступных в системе форматов пикселей, наиболее подходящий нашим нуждам,
Ø
затем этот формат
и назначается устройству воспроизведения.
Задание всех необходимых требований выполняется в структуре PixelFormatDescriptor, которая содержит более 30 полей. Все мы их рассматривать
не будем, остановимся на самых важных:
·
nSize
Как и многие структуры в
Windows это поле должно содержать размер самой структуры, проще всего его
инициализировать оператором sizeof().
·
nVersion
Для текущей реализации
должно быть установлено в 1.
·
dwFlags
Битовые флаги,
определяющие устройство и интерфейс, с которым совместим буфер пикселей данного
формата. Рассмотрим основные из них:
Ø    PFD_DRAW_TO_WINDOW –
разрешено рисование в окне или поверхности устройства.
Ø    PFD_DRAW_TO_BITMAP –
р \азрешено рисование в битовый образ в памяти.
Ø
PFD_SUPPORT_GDI –
буфер поддерживает рисование с использованием GDI. Этот флаг нельзя использовать
с флагом PFD_DOUBLEBUFFER.
Ø
PFD_SUPPORT_OPENGL –
буфер поддерживает OpenGL рисование.
Ø
PFD_DOUBLEBUFFER –
поддерживается режим двойной буферизации. Нельзя использовать совместно с
флагом PFD_SUPPORT_GDI.
Ø
PFD_SWAP_COPY –
поддерживается ли копирование из внеэкранного буфера на первичную (видимую
поверхность). Обмен не влияет на внеэкранную поверхность, а копирует
изображение из нее на первичную.
В стандартном
запросе на формат рисования в dwFlags устанавливаются следующие
флаги: для вывода графических объектов в окно необходимо выставить флаг
PFD_DRAW_TO_WINDOW; буфер кадра поддерживает вывод через OpenGL -
PFD_SUPPORT_OPENGL;  и, так как мы используем два буфера (Back и Front), то
устанавливаем флаг PFD_DOUBLEBUFFER. Рассмотрим двойную буферизацию
подробнее.  Обычно
в трёхмерных сценах каждый видимый кадр строится заново. То есть, в каждом
кадре полностью перерисовывается вся видимая графика. Построение кадра может
происходить следующим образом. Сначала весь кадр очищается, а потом
последовательно выводятся трёхмерные графические объекты. Такое действие
происходит несколько раз в секунду. Количество этих перерисовок в секунду
называют FPS (frames per second). Если мы будем стирать и
рисовать в видимой части экрана, то мы будем видеть мигание и мерцание наших
рисующихся и стирающихся объектов.
Для
исключения этого неприятного эффекта, пользуются следующим способом. Весь кадр
полностью строят в невидимой части видеопамяти адаптера. Эту часть называют
Back Buffer. После того, как все графические объекты выведены, вся эта невидимая
часть копируется в видимую область видеопамяти, называемую Front Buffer. Т.е.
происходит так называемая смена буферов, что и составляет эффект двойной
буферизации и позволяет выполнять анимацию изображений без ненужных эффектов.
 Если ваше
приложение выводит графику на весь экран, а не в окно, то можно избежать
копирования буфера, переключая указатель на видимую часть в видео памяти. Такой
эффект называют Flip. Понятно, что он работает быстрее, чем копирование буфера,
но нам данный способ не подходит.
·
iPixelType
Определяет режим, используемый
для отображения цветов: значение PFD_TYPE_RGBA - цвет каждого пикселя
определяется 4 значениями – красным, зеленым, синим и альфа;
PFD_TYPE_COLORINDEX - цвет задается индексом в таблице цветов (палитре).
·
cColorBits
Количество бит (битовых
плоскостей) цвета. Фактически глубина цвета. Здесь указывается желаемая
глубина цвета (bpp – bits per pixel, 8, 15,  16, 24, 32; список
поддерживаемых значений зависит от драйверов и варьируется в зависимости от видеоплаты).
·
cRedBits cRedShift cGreenBits cGreenShift
cBlueBits cBlueShift cAlphaBits cAlphaShift
Биты R,G,B,A составляющих
и их смещения от начала битовых плоскостей, т.е. порядок следования цветовых
компонент: RGBA или ABGR.  Например, если глубина цвета равна 32,  cRedBits = 8
и cRedShift = 16, то это означает, что под красную составляющую будет выделен
один байт (8 бит) и в двойном слове глубины (32 бита) она будет занимать биты с
16 по 23 (отсчет бит идет с нуля).
·
cDepthBits
Размер (глубина) буфера
глубины (Z-буфер). Обычные значения 16, 24, 32 бит. Z-буфер
используется в трехмерной графике, и его разрядность влияет на точность
вычислений операций с глубиной сцены. Недостаточная глубина Z-буфера будет
приводить к ошибкам визуализации сцены, например, более дальний объект будет
вылезать сквозь ближний. Глубина сцены задается как отношение задней плоскости
отсечения к передней плоскости. Подробнее о механизмах построения трехмерных
сцен, а так же алгоритмах работы с Z-буфером мы поговорим позднее.
·
cStencilBits
Размер (глубина)
буфера трафарета. Буфер
трафарета используется во многих продвинутых техниках рисования, например, для
расчета стенсильных теней и пр. Однако на современных видеоплатах его
разрядность, как правило, ограничена 8 битами. К тому же в большинстве случаев
аппаратно акселерируется буфер трафарета только в режиме 32bpp, поэтому,
например, в режиме 16bpp любое обращение к буферу трафарета будет сильно тормозить
рендеринг всей сцены.
Шаблон инициализации
полей объекта типа структура PixelFormatDescriptor
приведен
ниже:
{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                  // Маски слоя игнорируются    };

Код на языке Delphi
function SetDCPixelFormat (DC: HDC): integer;
var
  pfnum: integer;
  pfd: PIXELFORMATDESCRIPTOR;
begin
  fillchar(pfd, sizeof(pfd), 0);
    pfd.nVersion := 1;
  pfd.nSize := sizeof(pfd);
  pfd.dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
  pfd.iPixelType := PFD_TYPE_RGBA  {выбираем формат пикселей}
  pfnum := ChoosePixelFormat(DC, @pfd);
  {если вернули 0, значит ошибка}
  if pfnum = 0 then exit;
  {устанавливаем формат пикселей}
  SetPixelFormat(DC, pfnum, @pfd);
  Result := pfnum;End;
Следующая секция
предназначена для обработки системных сообщений: выход из программы, нажатие
клавиш, перемещение окна и т.д., каждая секция "case"
обрабатывает свой тип сообщения.
switch (message)      // Тип сообщения{ case WM_CREATE:hDC = GetDC(hWnd);    // Получить контекст устройства для окнаPixelFormat = ChoosePixelFormat(hDC, &pfd);// Найти ближайшее совпадение для формата пикселей

WM_CREATE указывает программе, что сообщение должно быть создано.
Сначала следует запросить DC (контекст устройства) для окна –
без него рисование в окне невозможно. Затем  запрашивается формат пикселя.
Функция ChoosePixelFormat (<контекст устройства>,
<указатель на структуру >) возвращает номер одного из доступных в системе
форматов пикселей. Компьютер
будет выбирать формат, который полностью совпадает или наиболее близок к запрашиваемому
формату[1].
Если подходящий формат пикселя не найден, будет выведено сообщение об
ошибке.
    if (!PixelFormat)   {   MessageBox(0,"Не найден подходящий формат пиксела.",                     "Ошибка",MB_OK|MB_ICONERROR);[2]   PostQuitMessage(0);// Это сообщение говорит, что программа должна завершится   break;      // Предотвращение повтора кода     }
Если подходящий формат найден, необходимо установить его для устройства
рисования с помощью функции SetPixelFormat.
Если формат пикселя не может быть установлен по какой-то причине, появится
сообщение об ошибке, что формат пикселя не установлен.
    if(!SetPixelFormat(hDC,PixelFormat,&pfd))         {         MessageBox(0,"Формат пиксела не установлен.",                            "Ошибка",MB_OK|MB_ICONERROR);         PostQuitMessage(0);         break;   }
Если код записан, как показано выше, будет создан контекст устройства
(hDC), и установлен подходящий формат пикселя. Рекомендуется
все эти действия выполнять в отдельной функции, дав ей значимое имя, например, SetWindowPixelFormat или SetDCPixelFormat.
4.
Создание контекста воспроизведения
Если удалось установить
пиксельный формат, то можно перейти к  созданию просчитывающего контекста
(rendering context) OpenGL. Для этого выполняется вызов функции
wglCreateContext(<контекст
воспроизведения>),
которая определяет контекст
воспроизведения OpenGL, подходящий для
рисования на устройстве, определённом дескриптором hRC. При
успешном завершении функция возвращает дескриптор созданного контекста
воспроизведения OpenGL, и NULL
– в случае неудачи.
hRC = wglCreateContext(hDC);   if(!hRC)   {   MessageBox(0,"Контекст воспроизведения не создан.",                     "Ошибка",MB_OK|MB_ICONERROR);   PostQuitMessage(0);   break;   }

Текущий контекст
воспроизведения потока должен быть единственным. Следующая функция позволяет
определить контекст воспроизведения для контекста устройства.
wglMakeCurrent(hDC,
hRC)
В
результате у нас получилась функция создания GL контекста рисования:
Код на языке Delphi
function CreateContext(DC: HDC): boolean;
var
  hrc: HGLRC;
begin
  Result := false;
  //Проверим входные параметры
  if DC = 0 then exit;
  //создаем GL   if SetWindowPixelFormat(hDC, 32, 0, 0) = 0 then exit;
  {теперь можно создать контекст GL}
  rc := wglCreateContext(hDC);
   if rc = 0 then exit;
  {назначаем GL контекст текущим}
  wglMakeCurrent(hDC, hrc); OneTimeSceneInit;
 Result := true;
end; Код на языке C++ void __fastcall TForm1::FormCreate(TObject *Sender)
{
   hDC = GetDC(Handle);
   if (!SetupPixelFormat(hDC)) Close();
   hRC = wglCreateContext(hDC);
   wglMakeCurrent(hDC, hRC);}
5.
Отрисовка.
Теперь можно перейти
непосредственно к отрисовке объектов сцены с помощью OpenGL. В этой части программы мы
будем использовать функции OpenGL для отрисовки конкретных графических сцен. Более подробно
об этом будет сказано ниже. Пока запишем в этой секции только
команду для очистки экрана цветом, который мы определили выше. Команды рисования
будут следовать за ней.
Область вывода в OpenGL
задается командой
             glViewPort
(0, 0, ClientWidth,
ClientHeight),
где первые два параметра
задают положение левого верхнего угла окна вывода, параметры ClientWidth,
ClientHeight определяют размер окна в
экранных координатах. Центр полученной области вывода имеет координаты (0, 0).
Координаты изменяются в диапазоне [-1; 1] по каждой оси.
По умолчанию центр
системы координат находится в центре окна вывода, а максимальное значение
координат по осям определено в диапазоне [-1; 1].
Если содержимое буфера
кадра изменяется в процессе регенерации изображения, то зритель может увидеть
совершенно нежелательные эффекты, например, дерганье изменяющейся картинки.
Эту проблему решают  использованием
стандартной технологии организации компьютерной анимации – двойной буферизации.
Такой подход подразумевает использование двух буферов кадра: рабочего
(переднего) и фонового (заднего). Рабочий буфер – это тот, из которого
выполняется регенерация изображения на экране, а в фоновом буфере изображение
формируется программой. С помощью специальных функций из прикладной программы
функции буферов можно переключать, что позволяет наблюдать плавную анимационную
сцену.
Если при установке
формата пикселя был установлен режим двойной буферизации (флаг PFD_DOUBLEBUFFER),
то изображение готовится в фоновом буфере, и  необходимо обеспечить перезапись
содержимого фонового буфера в рабочий. Для этого можно использовать функцию
             BOOL
glSwapBuffers
(HDC
hdc)
Благодаря тому, что OpenGL реализован по модели
клиент-сервер, помимо рассмотренной функции для вывода созданного изображения
можно воспользоваться командой
VOID glFlush (void)
 Функция glFlush, определенная в библиотеке  gl.h,
инициирует выполнение всех ожидающих команд OpenGL, которые обычно выстраиваются
в очередь и выполняются пакетами с целью оптимизации производительности. Этот
принцип может варьироваться для различного аппаратного обеспечения, драйверов и
реализаций OpenGL, однако все действия должны завершаться “в конечное время”, что
и позволяет реализовать команда glFlush .
В общем виде эту секцию кода можно записать так.
GLvoid DrawGLScene(GLvoid){   glViewPort (0, 0, ClientWidth, ClientHeight),   glClear(GL_COLOR_BUFFER_BIT);   // очистка экрана    glSwapBuffers (hDC);}
Позднее мы добавим сюда функции OpenGL для
отрисовки примитивов.

6.
Освобождение
контекстов.
При завершении работы
необходимо, чтобы контекст никем не использовался. Для этого достаточно
выполнить вызов функции:
 wglMakeCurrent(0,0);
//освободить контекст
Завершая работу с OpenGL необходимо удалить контекст воспроизведения. Для этой
цели используется функция:
wglDeleteContext(hRC);
После того как удалён
контекст воспроизведения, следует удалить и ассоциированный с ним контекст
устройства.
Код на Delphi:
procedure TForm1.FormDestroy(Sender:
TObject);
begin
  wglMakeCurrent(0,0); //освободить
контекст
wglDeleteContext(hrc)//удалить
контекст воспроизведения;
ReleaseDC(Handle,dc);// удалить
контекст устройства
end;
Код
на С++
void __fastcall
TForm1::FormDestroy(TObject *Sender)
{
        wglMakeCurrent(0,0);
        wglDeleteContext(hGLRC);
        ReleaseDC(Handle, hDC);
        Form1->Close();
}
Итак, если собрать
воедино все полученные факты и написать свою первую программу с использованием
графической библиотеки OpenGL,
то у вас получится некая программа-шаблон, которую потом можно будет усложнять
путем добавления различных функций (см. раздел Дополнительный
материал). Т.е. достаточно один раз правильно написать шаблон и
инициализировать OpenGL под вашу ОС и язык программирования, и больше к этой
теме можно будет не возвращаться.
Синтаксис команд OpenGL
Однако, если
мы остановимся на этом, то результат программы нас не удовлетворит. Потому как мы
пишем программу для отрисовки графики! А где графика в этом шаблоне?
Поэтому мы
добавим немножко информации уже непосредственно про OpenGL, чтобы ваша первая
программа могла что-то нарисовать. А вы могли это увидеть, обрадоваться (все не
зря!), и вдохновиться на новые свершения.
Итак,
приступим.
В OpenGL
полное имя команды имеет вид:
type glName[1 2
3 4][b s i f d ub us ui][v] (type1 arg1,…,typeN argN)
где:

gl

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

Name

имя команды

[1 2 3 4]

число аргументов команды

[b s i f d ub us ui]

тип аргумента (см. таблица 1)

[v]

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

Символы в
квадратных скобках в некоторых названиях не используются. Например, команда
glVertex2i() описана как базовая в библиотеке OpenGL и использует в качестве
параметров два целых числа, а команда glColor3fv() использует в качестве
параметра указатель на массив из трех вещественных чисел.
Если имя команды
заканчивается на v (векторная
форма), то аргументом её служит указатель на массив значений. Например: Если
последние три символа в имени команды 3fv,
то её аргумент – адрес массива трёх вещественных чисел.
Использования
нескольких вариантов каждой команды можно частично избежать, применяя
перегрузку функций языка C++. Но интерфейс OpenGL не рассчитан на конкретный
язык программирования, и, следовательно, должен быть максимально универсален.

Таблица 1
Возможные типы аргументов

Символ

Обозначение
типа
в
  OpenGL

Расшифровка

b

GLbyte

Байтовый

s

GLshort

Короткий
целый

i

GLint

Целый

d

GLdouble

Вещественный
  двойной точности

f

GLfloat

вещественный

ub

GLubyte

Байтовый,
  беззнаковый

us

GLushort

Короткий целый
  беззнаковый

ui

GLuint

Целый

  беззнаковый

Почти всегда
предпочтительно использовать команду в вещественной форме, поскольку OpenGL
хранит
данные в вещественном формате.
Примитивы OpenGL
Все изображения строятся
из отдельных примитивов, которые описываются с помощью набора вершин (Vertex).
Примитивами OpenGl являются точки
(одиночные вершины), линии (пары вершин), треугольники (три вершины),
четырехугольники (четыре вершины) и полигоны (3 и более вершин).
Для указания на отрисовку
одного или нескольких примитивов необходимо использовать так называемые командные
скобки библиотеки OpenGl,
которые  представляют собой специальные функции (не путать с  операторными
скобками языков программирования!). Ошибка при использовании командных скобок
не распознается компилятором, но может привести к непредсказуемым результатам
работы программы.
Командные скобки в общем
виде записываются следующим образом:
   glBegin
(mode)
… // вершины и их атрибуты
glEnd;
где mode
определяет
правило соединения перечисленных вершин в графический примитив (см. таблица 2).
Вершины
задаются своими координатами (количество координат зависит от пространства
изображения) с помощью команд
 glVertex{2,3,4}{s,i,f,d}(koord1, koord2, …)
Внутри
командных скобок могут находиться любые операторы языка программирования и
многие функции OpenGL. Подробнее о процессе и функциях рисования можно будет
прочитать в Лабораторной работе №2 настоящего пособия.
Пример:
Отрисовка трех точек в
двумерной системе координат.
  glBegin(GL_POINTS);
   glColor3d(1,0,0);
   glVertex2d(-4.5,4);
// первая точка
   glColor2d(0,1);
   glVertex2d(-4,4);
// вторая точка
   glColor3d(0,0,1);
   glVertex2d(-3.5); //
третья точка
  glEnd();

Таблица 2
Возможные значения параметра mode

mode

Описание

GL_POINTS

Рисует N
  точек.
Каждый вызов glVertex задает отдельную
  точку.

GL_LINES

Рисует N/2
  линий.
Каждая пара вершин задает отрезок.

GL_LINE_STRIP

Рисуется ломаная из N - 1 отрезков.
  Вершина  N и N+1
  определяют отрезок N
  ломаной.

GL_LINE_LOOP

Рисуется ломаная, причем ее последняя
  точка соединяется с первой. Механизм отрисовки тот же, что и в GL_LINE_STRIP.

GL_TRIANGLES

Рисуется N/3 треугольников. Каждые три вершины
  N, N+1,
  N+2 определяют треугольник N.

GL_TRIANGLE_STRIP

Рисуется N-1  треугольников. Рисуются
  треугольники с общей стороной. Для нечетного N,
  элементы N, N+1,
  N+2 определяют треугольник N.

GL_TRIANGLE_FAN

Рисуется N - 2 треугольников. Рисует
  группу соединенных в одной вершине треугольников. Один треугольник
  определяется для каждого элемента после двух предыдущих. Два последних
  элемента соединяются с первым.

GL_QUADS

Рисуется  N/4 четырехугольника. Каждые
  четыре вершины задают четырехугольник.

GL_QUAD_STRIP

Рисуются четырехугольники с общей
  стороной, соединяя чётные элементы с чётными, а нечётные с нечётными.

GL_POLYGON

Рисуется полигон. Вершины полигона
  определяются элементами от 1 до N-го.

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

Рисунок 2.
 Примитивы OpenGL

Методика
выполнения лабораторной работы
В течение занятия необходимо:
1)
изучить
теоретическую
информацию, предлагаемую в данном пособии;
2)
сформировать
собственную блок-схему инициализации OpenGL,
в зависимости от используемого программного обеспечения (примеры вариантов
инициализации см. в разделе «Дополнительный материал» к данной лабораторной
работе);
3)
выполнить
инициализацию OpenGL;
4)
выполнить
отрисовку типовых графических примитивов согласно варианту задания.
Варианты
заданий

1.      Выполнить
инициализацию OpenGL и
отрисовать 4 точки, два треугольника и полигон.
2.      Выполнить
инициализацию OpenGL и
отрисовать 3 точки, треугольник, ленту треугольников и два четырехугольника.
3.      Выполнить
инициализацию OpenGL и
отрисовать две линии, ломаную, 2 треугольника и квадрат.
4.      Выполнить
инициализацию OpenGL и
отрисовать 5 точек, 2 ломаные, ленту треугольников и полигон.
5.      Выполнить
инициализацию OpenGL и
отрисовать 2 полигона из 6 вершин каждый, две замкнутые линии из 5 вершин и 3
точки.
6.      Выполнить
инициализацию OpenGL и
отрисовать 2 четырехугольника, 2 треугольника и 5 точек.
7.      Выполнить
инициализацию OpenGL и
отрисовать 2 отрезка, 3 треугольника и полигон.
8.      Выполнить
инициализацию OpenGL и
отрисовать 3 треугольника, ленту треугольников, ленту четырехугольников и 1
точку.
9.      Выполнить
инициализацию OpenGL и
отрисовать все примитивы по одному разу.
10.  Выполнить инициализацию OpenGL и отрисовать 2 полигона из 5
вершин каждый, две замкнутые линии из 7 вершин и 2 точки.
11.  Выполнить инициализацию OpenGL и отрисовать 1 четырехугольник,
2 треугольника, 4 точки и 1 отрезок.
12.  Выполнить инициализацию OpenGL и отрисовать 3 точки, 2
треугольника, ленту треугольников и четырехугольник.
13.  Выполнить инициализацию OpenGL и отрисовать 6 точек, треугольник,
ленту треугольников и ленту четырехугольников.
14.  Выполнить инициализацию OpenGL и отрисовать 3 полигона,
треугольник, ленту четырехугольников и 2 точки.
15.  Выполнить инициализацию OpenGL и отрисовать 2 полигона из 5
вершин каждый, две ломаные из 7 вершин и 2 треугольника.

Содержание отчета
Результатом выполнения лабораторной
работы должен стать отчет (в печатном и электронном вариантах), состоящий из
следующих пунктов:
1)
 постановка задачи;
2)
 блок-схема
инициализации;
3)
 программный
код предлагаемого решения;
4)
 скриншоты
результатов работы программы.
Отчет лабораторной работы должен
быть произведен студентом преподавателю в срок до начала следующего
лабораторного занятия. Во время занятия преподавателю необходимо предоставить:
·
отчет
о лабораторной работе (в печатном виде);
·
программную
реализацию решения.
Оценка (в баллах) выставляется за устный
отчет студента по предоставленным преподавателю материалам.
Пример выполнения лабораторной работы
Постановка задачи:
1.
Выполнить
инициализацию OpenGL.
2.
 Изобразить
 точки, линии, треугольник, многоугольники (минимум 5 различных примитивов).

Листинг программы:
//------------------------------------------------------------
#include
<vcl.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <Gl/glaux.h>
#pragma hdrstop

#include "Unit1.h"
//------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
HGLRC hGLRC;
//контекст воспроизведения (связь с WinExplorer);
HDC
hDC; //контекст окна (устройства) вывода;
//------------------------------------------------------------
//функция,
устанавливающая параметры контекста воспроизведения OpenGL;
void SetDCPixelFormat(HDC dc)
{
        int pfnum;
        PIXELFORMATDESCRIPTOR pfd;

        pfd.nSize=sizeof(pfd); //размер
структуры;
        pfd.nVersion=1;
        pfd.dwFlags=
//битовые
флаги:

PFD_DRAW_TO_WINDOW
|| //рисование в окне

PFD_SUPPORT_OPENGL || //поддержка
буфером
OpenGL
              PFD_DOUBLEBUFFER;     //двойная
буферизация;
     pfd.iPixelType=PFD_TYPE_RGBA;  //режим
отображения
цветов

 pfnum=ChoosePixelFormat(hDC,
&pfd); //предлагаемый
формат;
 SetPixelFormat(hDC,
pfnum, &pfd);
//устанавливаем формат
};
//------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
  hDC=GetDC(Handle);
  SetDCPixelFormat(hDC); //устанавливаем
параметры
OpenGL;

hGLRC=wglCreateContext(hDC);//создаем контекст воспроизведения;

wglMakeCurrent(hDC,hGLRC); //определяем контекст воспроизведения;
}
//------------------------------------------------------------
void __fastcall TForm1::FormClick(TObject *Sender)
{

glClearColor(0.1,0.1,0.1,0); //очищение экрана и заполнение цветом;

glViewport(0,0,ClientWidth,ClientHeight); //область
вывода;

glColor3f(1, 1, 1);
glBegin(GL_POINTS);
                glVertex2f(-0.6, -0.55); ;
                glVertex2f(-0.55, -1);
                glVertex2f(-0.5, -0.55);
                glVertex2f(0.6, -0.55);
                glVertex2f(0.55, -1);
                glVertex2f(0.5, -0.55);
        glEnd();
glColor3d(1,0,0);
glBegin(GL_TRIANGLES);
// рисуем треугольник

glVertex3d(-4,2,0);

glVertex3d(-3,2.9,0);

glVertex3d(-2,2,0);
 glEnd();
glBegin(GL_TRIANGLE_STRIP); // рисуем
ленту треугольников
  glColor3d(0,1,0);
  glVertex3d(1,2,0);
  glVertex3d(0,2.9,0);
  glVertex3d(-1,2,0);
  glVertex3d(0,1.1,0);
 glEnd();
SwapBuffers(hDC);
}
//------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
        wglMakeCurrent(0,0);
        wglDeleteContext(hGLRC);
        ReleaseDC(Handle, hDC);
        Form1->Close();
}

Дополнительный материал
Инициализация OpenGL в Microsoft Visual Studio ‘13

// initOpenGL.cpp: определяет точку входа для приложения.
#include "stdafx.h"
#include "initOpenGL.h"
#include <math.h>
/* Добавим свои переменные
******************/
/*ссылка на поверхность рисования на которой будет все рисование
*********/
HDC hDC;
/*ссылка
на OpenGL через которую будем передавать параметр **/
HGLRC hGLRC;
/*ссылка
на окно в котором будет происходить рисование ******/
HWND hWnd;
/************************************************************/
#define
MAX_LOADSTRING 100
//
Глобальные переменные:
HINSTANCE hInst;                      // текущий экземпляр
TCHAR szTitle[MAX_LOADSTRING];         // Текст строки заголовка
TCHAR szWindowClass[MAX_LOADSTRING];// имя класса главного окна
//
Отправить объявления функций, включенных в этот модуль кода:
ATOM               MyRegisterClass(HINSTANCE hInstance);
BOOL               InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
     UNREFERENCED_PARAMETER(hPrevInstance);
     UNREFERENCED_PARAMETER(lpCmdLine);

     // TODO: разместите код здесь.
     MSG msg;
     HACCEL hAccelTable;

     // Инициализация глобальных строк
     LoadString(hInstance, IDS_APP_TITLE, szTitle,
MAX_LOADSTRING);
     LoadString(hInstance, IDC_INITOPENGL, szWindowClass,
MAX_LOADSTRING);
     MyRegisterClass(hInstance);

     // Выполнить инициализацию приложения:
     if (!InitInstance (hInstance, nCmdShow))
     {
         return FALSE;
     }
     hAccelTable = LoadAccelerators(hInstance,
MAKEINTRESOURCE(IDC_INITOPENGL));
     // Цикл основного сообщения:
     while (GetMessage(&msg, NULL, 0, 0))
     {
     if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
         {
              TranslateMessage(&msg);
              DispatchMessage(&msg);
         }
     }
     return (int) msg.wParam;
}
//
//  ФУНКЦИЯ: MyRegisterClass()
//  НАЗНАЧЕНИЕ: регистрирует класс окна.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
     WNDCLASSEX wcex;
     wcex.cbSize = sizeof(WNDCLASSEX);
     wcex.style              = CS_HREDRAW | CS_VREDRAW;
     wcex.lpfnWndProc    = WndProc;
     wcex.cbClsExtra         = 0;
     wcex.cbWndExtra         = 0;
     wcex.hInstance      = hInstance;
     wcex.hIcon              = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INITOPENGL));
     wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
     wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
     wcex.lpszMenuName   = MAKEINTRESOURCE(IDC_INITOPENGL);
     wcex.lpszClassName  = szWindowClass;
     wcex.hIconSm       = LoadIcon(wcex.hInstance,
MAKEINTRESOURCE(IDI_SMALL));
     return RegisterClassEx(&wcex);
}
//
//   ФУНКЦИЯ: InitInstance(HINSTANCE, int)
//
НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно.
//
КОММЕНТАРИИ:
//
В данной функции дескриптор экземпляра сохраняется в глобальной переменной,
 //
а также  создается и выводится на экран главное окно программы.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Сохранить дескриптор экземпляра в
глобальной переменной
   hWnd = CreateWindow(szWindowClass, szTitle,
WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance,
NULL);
   if (!hWnd)
   {
      return FALSE;
   }

/*Весь код инициализации будет находиться здесь **********/

PIXELFORMATDESCRIPTOR pfd = {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_SUPPORT_OPENGL |
        PFD_DRAW_TO_WINDOW |
        PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32,
        0, 0, 0, 0, 0, 0,
        0,
        0,
        0,
        0, 0, 0, 0,
        16,
        0,
        0,
        PFD_MAIN_PLANE,
        0,
        0, 0, 0,
   };

/************************************************************/
   /*получаем ссылку на поверхность где будем рисовать */
   hDC = GetDC(hWnd);
   /*Задаем параметры точек*/
   int pixelFormat = ChoosePixelFormat(hDC, &pfd);
   /*задаем параметры точки*/
   SetPixelFormat(hDC, pixelFormat, &pfd);
   /*сообщаем OpenGL где будем рисовать*/
   hGLRC = wglCreateContext(hDC);
   /*создаем контекст рисования*/
   wglMakeCurrent(hDC, hGLRC);
   /*****************************************************/
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);
   return TRUE;
}
//
//  ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
//
НАЗНАЧЕНИЕ:  обрабатывает сообщения в главном окне.
//
WM_COMMAND -
обработка меню приложения
//
WM_PAINT   - закрасить главное окно
//
WM_DESTROY - ввести
сообщение о выходе и вернуться.
//

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
     int wmId, wmEvent;
     PAINTSTRUCT ps;
     HDC hdc;
     switch (message)
     {
     case WM_COMMAND:
         wmId    = LOWORD(wParam);
         wmEvent = HIWORD(wParam);
         // Разобрать выбор в меню:
         switch (wmId)
         {
         case IDM_ABOUT:
              DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX),
hWnd, About);
              break;
         case IDM_EXIT:
              DestroyWindow(hWnd);
              break;
         default:
              return DefWindowProc(hWnd, message, wParam,
lParam);
         }
         break;
     case WM_PAINT:
         hdc = BeginPaint(hWnd, &ps);
     // выполняем отрисовку примитивов
/************************************************************/
         glClear(GL_COLOR_BUFFER_BIT);
         glColor3ub(145, 30, 66);
         glBegin(GL_TRIANGLES);
         glVertex2f(0.0f, 0.8f); //верхняя вершина
         glVertex2f(-0.1f, 0.4f); //левая вершина
         glVertex2f(0.1f, 0.4f); //правая вершина
         glEnd();
         //рисуем прямоугольник
         glColor3ub(220, 380, 52);
         glRectf(-0.1f, -0.4f, 0.1f, 0.4f);
         glBegin(GL_POLYGON);
         glColor3f(1.0, 0.0, 0.0);
         glVertex2f(0.1, -0.4);
         glVertex2f(0.2, -0.7);
         glVertex2f(0.05, -0.5);
         glVertex2f(-0.05, -0.5);
         glEnd();
         glBegin(GL_POLYGON);
         glVertex2f(-0.05, -0.5);
         glVertex2f(-0.2, -0.7);
         glVertex2f(-0.1, -0.4);
         glVertex2f(0.1, -0.4);
         glEnd();
         glFlush();
         SwapBuffers(hDC);
         EndPaint(hWnd, &ps);
              break;
     case WM_DESTROY:
         PostQuitMessage(0);
         break;
     default:
         return DefWindowProc(hWnd, message, wParam, lParam);
     }
     return 0;
}

// Обработчик сообщений для окна "О программе".
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam,
LPARAM lParam)
{
     UNREFERENCED_PARAMETER(lParam);
     switch (message)
     {
     case WM_INITDIALOG:
         return (INT_PTR)TRUE;

     case WM_COMMAND:
         if (LOWORD(wParam) == IDOK || LOWORD(wParam) ==
IDCANCEL)
         {
              EndDialog(hDlg, LOWORD(wParam));
              return (INT_PTR)TRUE;
         }
         break;
     }
     return (INT_PTR)FALSE;
}

Инициализация OpenGL с использованием GLUT
Существует  специальная
мультиплатформенная библиотека, позволяющая сократить алгоритм инициализации OpenGL. И называется эта библиотека – GLUT. Эта
библиотека обеспечивает единый интерфейс для работы с окнами вне зависимости от
платформы, поэтому структура приложения, приведенная ниже,  остается неизменной
для операционных систем Windows, Linux и многих других.
Минимальная программа,
которая создает окно и что-нибудь рисует там, состоит из следующих шагов:
1. Инициализация GLUT
2. Установка параметров
окна.
3. Создание окна.
4. Установка функций,
отвечающих за рисование в окне и изменение формы окна.
5. Вход в главный
цикл GLUT.
Рассмотрим все 5 пунктов
подробнее.
Сначала необходимо скачать
библиотеку glut.h с официального сайта OpenGL
и подключить ее:
 #include
<GL/glut.h>
1. Инициализация GLUT
производится командой:
void glutInit(int
*argcp, char **argv);
где *argcp
–
указатель на количество аргументов в командной строке, а **argv
– указатель на массив аргументов. Обычно эти значения берутся из главной
функции программы: int main(int argc, char *argv[]).
2.  Установка
параметров окна.
Прежде всего, необходимо указать размеры окна:
void glutInitWindowSize(int
width, int height);
где width – ширина окна в
пикселях, height – высота окна в пикселях. По умолчанию размеры окна 300x300.
Далее задать
положение создаваемого окна относительно верхнего левого угла экрана с помощью
функции:
void glutInitWindowPosition(int
x, int y);
Необходимо
также установить для окна режим отображения информации, т. е. установить
для окна такие параметры, как: используемая цветовая модель, количество
различных буферов, и т.д. Для этого в используется функция:
void glutInitDisplayMode
(unsigned int mode);
В  качестве
аргумента в эту функцию необходимо передать
одну
из следующих констант (см. таблица 3)
или их
комбинацию (с
помощью побитового ИЛИ).
Таблица 3

Константа

Значение

GLUT_RGB

Для отображения
  графической информации используются 3 компоненты цвета RGB

GLUT_RGBA

То же что и RGB, но
  используется также 4 компонента ALPHA (прозрачность)

GLUT_INDEX

Цвет задается не с
  помощью RGB компонентов, а с помощью палитры. Используется для старых дисплеев,
  где количество цветов, например, 256

GLUT_SINGLE

Вывод в окно
  осуществляется с использованием 1 буфера. Обычно используется для
  статического вывода информации

GLUT_DOUBLE

Вывод в окно
  осуществляется с использованием 2 буферов. Применяется для анимации, чтобы
  исключить эффект мерцания

GLUT_ACCUM

Использовать также
  буфер накопления (Accumulation Buffer). Этот буфер применяется для создания
  специальных эффектов, например отражения и тени

GLUT_ALPHA

Использовать буфер
  ALPHA. Этот буфер, как уже говорилось, используется для задания 4-го
  компонента цвета – ALPHA. Обычно применяется для таких эффектов, как
  прозрачность объектов и антиалиасинг

GLUT_DEPTH

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

GLUT_STENCIL

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

GLUT_STEREO

Этот флаг используется
  для создания стереоизображений. Используется редко, так как для просмотра
  такого изображения нужна специальная аппаратура

Механизм
двойной буферизации устанавливается в процессе инициализации аргументом функции
glutInitDisplayMode(). Вместо константы GLUT_SINGLE нужно задать константу
GLUT_DOUBLE. Переключение буферов выполняется функцией glutSwapBuffers(). Все
операторы формирования изображения включатся в функцию display(), но при
использовании двойной буферизации в этой функции сначала нужно очистить рабочий
буфер, вызвав команду glClear(), а последним оператором вызвать функцию
переключения буферов glutSwapBuffers().
Например:

void glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE);
3.
Создание окна.
После того как окно установлено,
необходимо его создать:
int glutCreateWindow(const
char *title);
Эта функция создаёт окно
с заголовком, который передается ей в качестве параметра, и возвращает HANDLER
окна в виде числа int, который затем  используется для последующих операций над
этим окном, таких как изменение параметров окна и закрытие окна.
4.
Установка функций, отвечающих за рисование в окне и изменение формы окна.
Функция для рисования,
которая всегда будет вызываться операционной системой, чтобы нарисовать
(перерисовать) содержимое окна:
void glutDisplayFunc(void
(*func)(void));
аргумент этой
функции – указатель на функцию, которая будет отвечать за рисование в
окне. Например, чтобы функция void Draw(void), определенная в вашей программе,
отвечала за рисование в окне, надо присоединить ее к GLUT следующим образом:
glutDisplayFunc(Draw);
Функция, отслеживающая
изменения окна:
void glutReshapeFunc(void
(*func)(int width, int height));
аргумент которой  –
это указатель на функцию, отвечающую за изменение размеров окна, которая должна
принимать два параметра width и height, соответственно ширина и высота
нового (измененного) окна.
5. Вход в главный
цикл GLUT.
Этот цикл запускает на
выполнение и обеспечивает взаимосвязь между операционной системой и теми
функциями, которые отвечают за окно, получают информацию от устройств
ввода/вывода. Для того, чтобы перейти в главный цикл GLUT, надо указать:
void glutMainLoop(void);
Команда glFlush()
гарантирует, что команда рисования будет выполнена немедленно,  а не сохранена
в буфере.
Функции библиотеки GLUT
реализуют так называемый событийно-управляемый механизм. Это означает, что есть
некоторый внутренний цикл, который запускается после соответствующей
инициализации и обрабатывает одно за другим все события, объявленные во время
инициализации. К событиям относятся: щелчок мыши, закрытие окна, изменение
свойств окна, передвижение курсора, нажатие клавиши, и «пустое» (idle) событие,
когда ничего не происходит. Для проведения периодической проверки совершения
того или иного события надо зарегистрировать функцию, которая будет его
обрабатывать.
void
glutKeyboardFunc(void (*func)(unsigned int key, int x, int y);
Определяет функцию
(func), которая вызывается, когда нажата клавиша на клавиатуре. Возвращаемые
параметры:
key – сгенерированный
клавиатурой ASCII код;
x,y – координаты положения мыши в координатах отображаемого
окна, в момент, когда была нажата кнопка на клавиатуре.
void
glutMouseFunc(void (*func)(int button, int state, int x, int y));
Определяет функцию (func),
которая вызывается, когда кнопка мыши нажата или отпущена. Возвращаемый
функцией параметр button может принимать значения GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON,
или GLUT_RIGHT_BUTTON. Значение параметра state есть GLUT_UP или GLUT_DOWN в
зависимости от того, была ли кнопка мыши нажата или отпущена,  x and y
параметры указывают на координаты в текущем окне, где находилась мышь в момент
нажатия или отпускания кнопки.
void
glutMotionFunc(void (*func)(int x, int y));
Определяет функцию (func),
которая вызывается, когда указатель мыши перемещается в пределах окна при
нажатой одной или более кнопке,    x and y параметры указывают на координаты в
текущем окне, где находилась мышь в момент начала события void
glutPostRedisplay(void);
Отмечает текущее окно как
требующее перерисовки. На следующем шаге работы программы будет вызвана
функция, зарегистрированная в glutDisplayFunc().
void
glutIdleFunc (void (*func) (void));
glutIdleFunc() задает
функцию, которая будет вызываться каждый раз, когда нет событий от
пользователя.

Пример
инициализации с Glut
Программа выполняет
инициализацию Opengl и отрисовывает чайник с
помощью специальной встроенной функции glutSolidTeapot(width). Так как в сцене будет отрисован
трехмерный предмет, то, соответственно, необходимо добавить в алгоритм
инициализации установки для определения трехмерной сцены. В тексте программы
все соответствующие строки закомментированы для лучшего понимания процесса. На
данном этапе этого достаточно. Сам механизм определения и расчета трехмерных
сцен подробно будет рассмотрен позднее.
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#include <GL/glut.h>
void resize(int
width,int height)
{
}
void  display(void)
{
       glColor3d(1,1,0);      // установка цвета
  glutSolidTeapot(0.8); //отрисовка чайника
     glFlush();
}
void init(void)
{
/*данная часть кода имеет смысл при использовании
трехмерной сцены и освещения; в случае двумерной отрисовки можно использовать
установки по умолчанию, а эту функцию из программы исключить, потому что каждая
строка кода должна быть понятна разработчику и ее использование должно быть
аргументировано */
 glEnable(GL_LIGHTING);
//включаем режим расчета освещения
 glEnable(GL_LIGHT0);
//включаем источник света
      glEnable(GL_DEPTH_TEST);
//включаем режим проверки
                             //глубины сцены
 glClearColor (0.0, 0.0, 0.0, 0.0);
 glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT);
  //обращаемся к матрице проекций
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
//приводим ее к единичному виду
    //устанавливаем заданный параллелепипед видимости
      glOrtho(-5.0,5.0,-5.0,5.0,2.0,12.0);

     //определяем положение наблюдателя (камеры)
      gluLookAt( 0,0,5,
0,1,0, 0,1,0 );
//обращаемся к модельно-видовой матрице
 glMatrixMode( GL_MODELVIEW); }
int main(int argc,char ** argv)
{
  glutInitDisplayMode(GLUT_SINGLE|
GLUT_RGB | GLUT_DEPTH);
  glutInitWindowPosition(50,10);
  glutInitWindowSize(400,400);
  glutCreateWindow(«Hello»);
  glutReshapeFunc(resize);
  init();
   glutDisplayFunc(display);
  glutMainLoop();
  return 0;
  }

Контрольные
вопросы
1.
Что понимается
под контекстом устройства?
2.
Что представляет
собой контекст воспроизведения?
3.
Какие основные
фрагменты должна содержать минимальная программа OpenGL.
4.
Что входит в
понятие формат пиксела?
5.
Какие
библиотечные файлы должны быть подключены к программе для работы с OpenGL?
6.
Какая цветовая
модель используется при определении цвета в данной программе?
7.
Какие параметры
следует указать, чтобы цвет фона был зеленым?
8.
 Для чего нужна
функция масштабирования сцены?
9.
В какой секции
кода можно записывать команды рисования сцены?
10.
 Какое правило
необходимо соблюдать, чтобы иметь возможность перехода в полноэкранный режим?

ЛАБОРАТОРНАЯ
РАБОТА №2
OpenGL: Разработка приложения для визуализации
связного набора двумерных примитивов

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

Теоретическая информация

Использование функций glBegin и glEnd
Функции для рисования
заключаются между командными скобками glBegin
и glEnd.
Командные скобки библиотеки OpenGl
представляют собой специальные функции (не имеющие никакого отношения к операторным
скобкам языков программирования). Ошибка при использовании командных скобок не
распознается компилятором, но может привести к непредсказуемым результатам
работы программы.
Внутри командных скобок
могут находиться любые операторы языка и многие функции OpenGL.
Главное назначение командных скобок – задание режима (примитива) для команд glVertex
(вершина), определяющих координаты вершин для рисования примитивов OpenGL.
Аргументами функции glBegin
могут быть стандартные константы OpenGl,
определяющие примитивы библиотеки: GL_POINTS,
GL_LINES,
GL_LINE_STRIP,
GL_LINE_LOOP,
GL_TRIANGLES,
GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN,
GL_QUADS,
GL_QUAD_STRIP,
GL_POLYGON.
В программе имена констант должны быть записаны именно так: в верхнем регистре.
Команды, устанавливающие размер
точки, толщину и тип линии, включение и отключение режима
сглаживания (англ. anti-aliasing)
должны стоять вне командных скобок.

Включение и отключение режимов в Opengl
Для установки (включения)
 специализированных режимов обработки и вывода изображений в Opengl,
необходимо использовать функцию glEnable()
с соответствующей константой в качестве аргумента. Для отключения режима  –
соответственно,  функцию glDisable()
с той же константой.
Функции glEnable/glDisable включают/выключают множество опций, но
следует учитывать, что некоторые опции влекут за собой большие вычисления и,
следовательно, изрядно затормаживают приложение, поэтому без надобности не
стоит их включать.

Вывод точек
Рассмотрим рисование
точек. Точки представляют собой одиночные вершины. Вершина является
атомарным графическим примитивом OpenGL и определяет точку, конец отрезка, угол
многоугольника и т.д. Все остальные примитивы формируются с помощью задания
вершин, входящих в данный примитив. Например, отрезок определяется двумя
вершинами, являющимися концами отрезка.
С каждой вершиной
ассоциируются ее атрибуты.
В число основных атрибутов входят:
·    размер;
·    положение вершины в пространстве;
·    цвет вершины;
·    вектор нормали;
·    координаты текстуры
Рассмотрим
каждый из атрибутов подробнее.
Атрибуты точек
·    Размер
Когда вы отрисовываете
точку, ее размер по умолчанию равен одному пикселю. Для изменения размера точки
используется функция
 void glPointSize(GLfloat size),
где size – натуральное число,
определяющее размер точки в пикселях.
Поддерживаются не все размеры, поэтому следует проверять, доступен
ли размер, который вы задаете для точки. Чтобы найти диапазон размеров и наименьший
интервал между ними, применяется следующий код:
GLfloat sizes[2];//
диапазон размеров поддерживаемых точек
GLfloat step;   //
поддерживаемый инкремент размеров точек
// Получаем диапазон
размеров поддерживаемых точек
// и размер шага
glGetFloatv(GL_POINT_SIZE_RANGE,sizes);
glGetFloatv(GL_POINT_SIZE_GRANULARITY,&step);

Здесь массив размеров будет содержать два элемента – наименьшее и
наибольшее возможное значение glPointsize. Кроме того, шаг переменной будет
равен наименьшему шагу, возможному между размерами точек. Спецификация OpenGL
требует поддержки только одного размера точек – 1,0. Программная реализация
OpenGL от Microsoft, например, позволяет менять размер точек от 0,5 до 10,0 с
минимальным размером шага 0,125. Задание размера, не входящего в диапазон, не
интерпретируется как ошибка. Вместо этого используется наибольший или
наименьший поддерживаемый размер, ближайший к заданному значению. Точки, в
отличие от других геометрических объектов, не меняются при делении на
коэффициент перспективы. Т.е. они не становятся меньше при удалении от точки
наблюдения, и не становятся больше при приближении к наблюдателю. Точки всегда
являются квадратными. Даже используя glPointsize для увеличения размера точек,
вы просто получите большие квадраты! Чтобы увидеть круглые точки, нужно
использовать механизм сглаживания, о котором будет сказано ниже.
·    Положение вершины в пространстве
Для рисования вершины
используется команда glVertex,
с
помощью которой и задаются координаты для отрисовки.
В общем виде команда записывается следующим образом
void glVertex[2 3 4][s i f d] (type coords)либо
void
glVertex[2 3 4][s
i f
d]v
(type *coords)
Если точка должна быть
изображена на плоскости, то для определения ее положения необходимы две
координаты. В этом случае используется функция с двумя аргументами, например
 glVertex2f(0,
0)
 Буква f
в названии данной функции определяет тип ее аргументов, в данном случае это
вещественные числа типа float.

Если для отрисовки
используется трехмерная сцена, то точка в пространстве определяется либо тремя
координатами, например:
glVertex3f(0.5,
0.3,-0.7),
либо четырьмя
координатами:
glVertex4f(0.5,
0.3,-0.7, 0.5)
На самом деле, каждая из
этих команд задает четыре координаты для одной вершины: x, y, z, w, так
называемые однородные координаты. Такой подход необходим для управления
объектом в трехмерном объеме, но мы об этом поговорим позже. А сейчас вам
достаточно знать, что, в зависимости от суффикса, программист может
самостоятельно задавать определенную часть из 4 возможных координат, а остальные
устанавливаются компилятором по умолчанию: координата z устанавливается равной
0, координата w – равной 1.
Координатные оси
расположены так, что точка (0,0) находится в центре экрана, ось x направлена
влево, ось y – вверх, а ось z – из экрана. Это расположение осей мировой
системы координат, в которой задаются координаты вершин объекта, другие системы
координат будут рассмотрены позже.
Команды glVertex
должны размещаться между командными скобками. При этом
количество точек может быть любым, зависящим от режима отрисовки примитива (см.
ниже).
Аргументом функции glBegin
для рисования точек является константа GL_POINTS.

·
Цвет
Цвет отдельных вершин или
примитивов может устанавливаться как вне командных скобок, так и внутри них.
Для установки цвета используется команда
      void glColor[3 4][b s i f] (GLtype components)

void glColor[3 4][b s i f]v (GLtype components).
Цифра 3 или 4 в суффиксе
команды означает число аргументов. В случае, если установлен при инициализации
флаг RGB, то цвет формируется как
сумма 3 components:
красного, зеленого и синего цветов в указанной пропорции. Если же был
установлен флаг RGBA, то первые три
параметра задают R, G, B компоненты цвета, а последний параметр будет определять
коэффициент непрозрачности (альфа-компонента), с помощью которого можно управлять
интенсивностью цвета в изображении.
 Если в названии команды
указан тип ‘f’ (float), то значения всех параметров должны принадлежать отрезку
[0,1], при этом по умолчанию значение альфа-компоненты устанавливается равным
1.0, что соответствует полной непрозрачности. Тип ‘ub’ (unsigned byte)
подразумевает, что значения должны лежать в отрезке [0,255].
По умолчанию значения
компонент задаются в виде вещественных чисел в интервале [0; 1], например
glColor3f(0.3f,
0.5f, 0.1f)
Компоненты цвета могут
быть заданы и в целочисленной форме, предельным значением в этом случае будет
являться максимальное 8-битное целое без знака, например, белый цвет будет
записан следующим образом:
                      glColor3i(214748647,
214748647,  214748647).
Однако предпочтительно
использовать команду в вещественной форме, т.к. OpenGL
хранит данные именно в вещественном формате.

Таблица значений аргументов для задания основных цветов :
glColor3f(0.0, 0.0, 0.0);           black
glColor3f(1.0, 0.0, 0.0);           red
glColor3f(0.0, 1.0, 0.0);           green
glColor3f(1.0, 1.0, 0.0);           yellow
glColor3f(0.0, 0.0, 1.0);           blue
glColor3f(1.0, 0.0, 1.0);           magenta
glColor3f(0.0, 1.0, 1.0);           cyan
glColor3f(1.0, 1.0, 1.0);           white

Вершинам можно назначать
различные цвета, и, если включен соответствующий режим, то будет проводиться
линейная интерполяция цветов по поверхности примитива.  Opengl
позволяет управлять процессом смешивания цветов с помощью функции
void glShadeModel
(GLenum  mode)
где при  mode = GL_SMOOTH  интерполяция включается (установка по
умолчанию), а при mode = GL_FLAT,
– отключается.
Остальные атрибуты –
вектор нормали и текстурные координаты – будут рассмотрены позже, в
соответствующих темах.
Примеры рисования точек:
 // рисуем точки
  glPointSize(2);

  glBegin(GL_POINTS);
   glColor3d(1,0,0);
   glVertex3d(-4.5,4,0); // первая
точка
   glColor3d(0,1,0);
   glVertex3d(-4,4,0);   // вторая
точка
   glColor3d(0,0,1);     // третья
   glVertex3d(-3.5,4,0);
  glEnd();

// десять точек по
диагонали
glBegin (GL_POINTS);
For i := 0 to 9 do
glVertex2f (i / 5 - 1, i / 5 - 1);
glEnd;

          //сто точек со случайными координатами и цветами
glBegin (GL_POINTS);
For i := 1 to 100 do begin
glColor3f (random, random, random);
 glVertex2f (random * 2 - 1, random * 2-1);
end;
glEnd;

Еще один интересный
пример,  для реализации которого необходимо в разделе private описать две переменные:

xpos: GLfloat; // координаты курсора в системе координат OpenGL

ypos:
GLfloat;
Затем создать обработчик события MouseMove формы
xpos: = 2 * X / ClientWidth - 1;
ypos: = 2 * (ClientHeight - Y) / ClientHeight - 1;
Refresh; // перерисовываем окно

В обработчике события
Paint необходимо описать локальную целочисленную переменную i и содержательную
часть кода привести к виду

For
i: = 1 to 30 do begin // тридцать точек
glColor3f (random, random, random); // случайного цвета
glBegin (GL_POINTS}; // со случайными координатами
glVertex2f
(xpos + 0. 2 * random * sin (random (360)),
ypos + 0. 2 * random * cos (random (3 60)));
glEnd;
end;

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

Вывод  линий
Для рисования линий
существует три режима: одиночные линии, ломаная, замкнутая ломаная.
Одиночная линия
определяется двумя вершинами. Если требуется нарисовать несколько одиночных
линий, то между командными скобками должны быть описаны координаты пар вершин,
т.е. количество команд glVertex
между командными скобками должно быть четным. В случае, если количество вершин
нечетно – последняя вершина игнорируется.
Аргументом функции glBegin
для рисования одиночных линий является константа GL_LINES.
Если требуется нарисовать
ломаную линию, то в командных скобках используют константу GL_LINE_STRIP.
Вершины, перечисленные между командными скобками, интерпретируются следующим
образом: конечная точка первой линии является начальной точкой следующего звена
ломаной и т.д. Количество вершин может быть как четным, так и нечетным.  Ширина
и тип ломаной линии задаются так же, как и для одиночных линий.
Для рисования замкнутой
ломаной аргументом функции glBegin
должна быть установлена константа GL_LINE_LOOP.
Последний отрезок замкнутой ломаной в качестве начала имеет последнюю вершину
списка, а в качестве конца – первую вершину.
Для линий Вы также можете
изменять ширину, цвет, размер, сглаживание. Если вы зададите разные цвета для
начала и конца линии, то ее цвет будет переливающимся. OpenGL по умолчанию
делает интерполяцию.
Для задания толщины линии
используется команда glLineWidth().
Аргументом является натуральное число, определяющее толщину в пикселах. Так же,
как и при установке размера точки, команду установки толщины линии записывают
за пределами командных скобок.
Для изменения типа линии
используется команда
void
glLineStipple (GLint factor, GLushort pattern)
Первый
аргумент factor
– это масштабный множитель, а второй pattern
представляет собой шестнадцатеричную константу[3],
определяющую шаблон штриховки (побитовым способом). Например, если его значение
равно 255(0x00FF), то, чтобы вычислить задаваемую маску, переведем число в
двоичную систему счисления: 0000000011111111, т.е. всего 16 бит. Старшие восемь
установлены в ноль, значит, тут линии не будет. Младшие установлены в единицу,
тут будет рисоваться линия. Если первый параметр, определяющий, сколько раз повторяется
каждый бит, установить равным 2, то накладываемая маска будет выглядеть так:
00000000000000001111111111111111
Важно: команда glLineStipple
должна
быть указана вне операторных скобок.
ПРИМЕР:
glColor3f(1.0, 0.0,
0.0);      // Установили красный цвет
glEnable(GL_LINE_SMOOTH);//
Включение режима сглаживания
glLineWidth(3);      //
Установили толщину линии 3 пиксела
glLineStipple(1, 0xF0F0);      //
Тип линии – пунктирная
glEnable(GL_LINE_STIPPLE);//
Разрешить изменение типа линии
glBegin(GL_LINES);        //
Режим рисования – одиночные линии
glVertex2f(-0.5,
-0.7);   // Начало первой линии
glVertex2f(0.0, 0.0);     //
Конец первой линии
glVertex2f(0.1, 0.9);     //
Начало второй линии
glVertex2f(0.3,
-0.5);         // Конец второй линии
glEnd();                  //
Конец рисования
glDisable(GL_LINE_SMOOTH);//
Отключение режима сглаживания

Вывод треугольников
Для рисования отдельных
треугольников константа командных скобок: GL_TRIANGLES.
Количество вершин, перечисленных между командными скобками должно быть кратно
трем. Каждые три вершины определяют  треугольник (рис. 3), поэтому лишние
вершины в списке игнорируются.

                   а2

  а1                             а3
Рисунок
3.  Отрисовка треугольника

Лента
треугольников GL_TRIANGLE_STRIP
используется,
если изображение может быть построено с помощью нескольких треугольников,
имеющих смежные стороны (рис. 4).
Здесь сторона  a2a3
является общей стороной для первого и второго треугольников, сторона a3a4
– общей стороной второго и третьего треугольников и т.д. Если такую фигуру
описывать с помощью одиночных треугольников, то необходимо задавать координаты
всех вершин всех треугольников: a1,
a2,
a3,
a2,
a3,
a4,
a3,
a4,
a5,
a4,
a5,
a6
– всего 12 вершин. Использование ленты треугольников позволяет не дублировать
вершины при описании их координат. Изображенная на рисунке фигура может быть
представлена лентой треугольников, координаты вершин перечисляются в следующем
порядке: a1,
a2,
a3,
a4,
a5,
a6
– достаточно 6 вершин.

В
случае, если треугольники имеют одну общую вершину, целесообразно использовать «веер
треугольников» GL_TRIANGLE_FAN
(рис.
5). При описании вершин первой в списке должна стоять общая вершина (а1), а
остальные вершины в списке распределяются следующим образом: первые три вершины
определяют первый треугольник; первая, третья и четвертая – второй; первая,
четвертая и пятая – третий; и т.д. Если в списке имеется N
вершин, то будет изображено N-2
треугольника.
Схематично порядок обхода
вершин при отрисовке разного типа треугольников можно представить следующим
образом (рис. 6):

Рисунок 6.
 Обход вершин треугольников
Вывод четырехугольников
Константа командных
скобок для рисования отдельных четырехугольников: GL_QUADS.
                                   а

Рисунок
7.  Отрисовка четырехугольника

Четырехугольник
определяется группой из 4-х вершин, следовательно, количество вершин,
записанных между командными скобками, должно быть кратно 4. Каждая четверка
вершин определяет отдельный четырехугольник. Лишние вершины игнорируются.
Если изображение
создается из связанных четырехугольников (каждая пара четырехугольников имеет
общую сторону), то используется примитив «лента четырехугольников» - GL_QUAD_STRIP
(рис.8).

Рисунок
8.  Примеры применения ленты четырехугольников

Четырехугольник задается
для каждой, кроме двух первых, пары вершин. Вершины 2n-1, 2n, 2n+2 и 2n+1
задают четырехугольник n. Всего отобразится (N-2)/2 четырехугольников. Заметим,
что порядок сборки связных четырехугольников отличается от порядка,
применяемого для независимых четырехугольников.
Порядок обхода вершин
четырехугольников представлен на рисунке 8: а – независимые четырехугольники, б
– лента четырехугольников.

Рисунок
9.  Порядок обхода вершин четырехугольников
Рисование
полигонов
Для рисования
многоугольников в командных скобках используется константа GL_POLIGON.
При этом вершины, указанные между командными скобками, определяют выпуклый
многоугольник.
 Многоугольник
строится из связанных треугольников с общей вершиной, в качестве общей вершины
берется первая вершина списка (см. рисунок 5: Веер треугольников).

Список
вершин для данного многоугольника: a1,
a2,
a3,
a4,
a5,
a6,
a7
(рис. 10).
Важное уточнение: При отрисовке
многоугольников следует иметь в виду наличие лицевых (передних) и обратных
(задних) граней у каждой поверхности.
Грань считается лицевой,
если вершины перечисляются в направлении против часовой стрелки (в положительном
направлении для левосторонней системы координат), и обратной, если обход вершин
производится по часовой стрелке (в отрицательном направлении для левосторонней
системы координат).
Opengl
предоставляет
возможность управлять тем, какой тип граней отображать на экране. Для этого
сначала надо установить соответствующий режим вызовом команды glEnable (GL_CULL_FACE),
а затем выбрать тип отображаемых граней с помощью команды
void glCullFace (GLenum
mode),
при  mode  = GL_FRONT
из изображения удаляются все лицевые грани,
 при mode  =
GL_BACK – из изображения удаляются все обратные грани (установка по умолчанию).
Построение
невыпуклых полигонов
Важно запомнить: базовые
команды OpenGL предназначены для построения только выпуклых фигур, поэтому
сложные фигуры чаще всего рисуются этапами, по частям.
При  необходимости
изобразить невыпуклый многоугольник, достаточно представить его как набор
выпуклых многоугольников, каждый из которых описывается в своих командных
скобках. Например, отрисовка фигуры (рис. 11),  возможна только с помощью разбиения
ее на набор выпуклых полигонов, показанных на рисунке с помощью цвета.

Рисунок
11. Отрисовка невыпуклого многоугольника

Следовательно, фигура
может быть описана как 2 примитива типа GL_POLIGON.
 Оптимальным будет разбиение невыпуклой фигуры на треугольники, поскольку
построение треугольников, как правило, реализовано на аппаратном уровне.
Режим вывода
многоугольников
Многоугольники можно
отрисовать в нескольких видах: в точечном, в контурном виде (без заливки), и с
заливкой. Для задания способа рисования  используется функция
void PolygonMode (
enum face, enum mode ),
где
face устанавливает тип многоугольников и может
принимать значения
·
 GL_FRONT –
для лицевых граней;
·
GL_BACK – для обратных
граней;
·
GL_FRONT_AND_BACK для всех граней.
mode указывает, как будет рисоваться многоугольник.
·
GL_POINT – при таком режиме
будут отображаться только вершины многоугольников.
·
GL_LINE – при таком режиме
многоугольник будет представляться набором отрезков.
·
GL_FILL – при таком режиме
многоугольники будут закрашиваться текущим цветом с учетом освещения, и этот
режим установлен по умолчанию.
Описанная команда помещается перед командными
скобками.
Пример:
 glColor3f(0,1.0,0);
 glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
 glBegin(GL_TRIANGLES);
 glVertex2dv(xy2[0]);
 glVertex2dv(xy2[1]);
 glVertex2dv(xy2[2]);
 glEnd();
 glPolygonMode(GL_BACK,GL_LINE);
 glBegin(GL_TRIANGLE_FAN);
 glVertex2dv(xy2[3]);
 glVertex2dv(xy2[4]);
 glVertex2dv(xy2[5]);
 glVertex2dv(xy2[6]);
 glEnd();
Массив
xy2 описан как
double
xy2[10][2];
и
проинициализирован функцией coords2
(вызывается в main):
void
coords2()
{
 double
ip2, *ipart2=&ip2;
 for(int
i=0;i<zx;i++)

for(int j=0;j<2;j++)
 xy2[i][j]=modf(pow(3.14,random(7)),ipart2);
}

Включение и отключение режима
сглаживания
Для установки режима
сглаживания, впрочем, как и для установки любого другого режима в Opengl,
перед командными скобками необходимо вызвать функцию glEnable()
с соответствующей константой в качестве аргумента, а после командных скобок –
функцию glDisable() с
той же константой.
Говоря непосредственно о
режиме сглаживания, выбор константы определяется примитивом, сглаживание
которого должно быть включено (или отключено):

·
GL_POINT_SMOOTH
(сглаживание для точек),
·
GL_LINE_SMOOTH
(сглаживание линий),
·
GL_POLYGON_SMOOTH
(сглаживание для полигонов).

Зачем нужен этот режим? Например, размер, заданный в glPointSize, не
является точным размером точки в пикселях, а приблизительным диаметром
окружности, содержащей все пиксели, используемые для рисования точки. Вы
указываете OpenGL рисовать точки как улучшенные (т.е. маленькие, закрашенные
окружности), разрешая их сглаживание. Эта технология вместе со сглаживанием
линий относятся к категории защиты от наложения (antialiasing). Защита от
наложения – это
технология, позволяющая сглаживать зазубренные края и округлять углы (рис. 12).

а)                                                                                б)
Рисунок
12.  Отрисовка точек с:
а
– отключенным режимом сглаживания,
б
– включенным режимом
сглаживания

Режимы закрашивания
для многоугольников
Если при отрисовке
многоугольников для разных вершин примитивов были заданы различные цвета, то
фигуры окрашиваются градиентно, т.е. с плавным переходом цветов от вершины к
вершине (рис.13). Это происходит из-за того, что по умолчанию способ сглаживания
(смешивания, тонирования) задан плавным.

Рисунок
13.  Градиентное закрашивание

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

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

Варианты
заданий
1.      Построить точки, расположенные в вершинах правильного
n-угольника. Установить режим
сглаживания для точек. Экспериментально определить максимальный размер точки,
при котором возможно сглаживание.
2.      Используя примитив для вывода линий нарисовать
правильный n-угольник. Изменить тип и
ширину линий.
3.      Используя примитив для вывода ломаной линии
нарисовать фигуру, изображенную на рис.1 (см. таблица 4).
4.      Используя примитив для вывода замкнутой
ломаной нарисовать фигуру, изображенную на рис.2 (см. таблица 4).
5.      Построить фигуру, изображенную на рис.2 (см.
таблица 4), разбив ее на треугольники (каждый треугольник окрашен случайным
цветом). Выполните три варианта построений с использованием примитивов:
         А)  треугольник;
         Б)  лента треугольников;
         В)  веер треугольников.
6.      Используя примитив для вывода многоугольников
построить правильный n-угольник.
7.      Построить невыпуклый многоугольник,
изображенный на рис.3, представив его в виде совокупности отдельных многоугольников,
назначив каждому многоугольнику свой цвет. Посмотреть результат работы
программы для различных способов тонирования.
8.      Изменить программу предыдущей задачи таким
образом, чтобы
·
лицевые
грани изображались только вершинами;
·
лицевые
грани изображались закрашенными, а обратные – линиями;
Таблица 4

Вариант 1

N=5

Вариант 2

N=7

Вариант 3

N=6

Вариант 4

N=4

Вариант 5

N=8

Содержание отчета

Результатом выполнения лабораторной
работы должен стать отчет (в печатном и электронном вариантах), состоящий из
следующих пунктов:
1)     постановка
задачи;
2)    перечень
функций Opengl, использованных в
предлагаемом решении;
3)
блок-схема
алгоритма отрисовки сцены;
4)
программный
код предлагаемого решения;
5)
скриншоты
результатов работы программы.
Отчет лабораторной работы должен
быть произведен студентом преподавателю в срок до начала следующего
лабораторного занятия. Во время занятия преподавателю необходимо предоставить:
·
отчет
о лабораторной работе (в печатном виде);
·
программную
реализацию решения.
Оценка (в баллах)  выставляется за устный
отчет студента по предоставленным преподавателю материалам.

Пример выполнения лабораторной работы

Программа отрисовывает двумерную
картинку. Для экономии места здесь приводится только часть функции, отвечающая
непосредственно за отрисовку объектов. Данный фрагмент кода встраивается в
шаблон программы, который был приведен в предыдущей лабораторной работе.
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
               glClearColor(0,
100, 130, 255);

              //домик
              glColor3ub(255,
0, 0);
              glBegin(GL_TRIANGLES);//крыша
              glVertex2f(-0.6f,
0.6f); //верхняя
вершина
              glVertex2f(-0.9f,
0.2f); //левая
вершина
              glVertex2f(-0.3f,
0.2f); //правая
вершина
              glEnd();
              glColor3ub(0,
0, 255);
              glBegin(GL_POLYGON);//стена
              glVertex2f(-0.79f,
0.2f);
              glVertex2f(-0.79f,
-0.4f);
              glVertex2f(-0.41f,
-0.4f);
              glVertex2f(-0.41f,
0.2f);
              glEnd();
              glColor3ub(100,
130, 255);
              glBegin(GL_POLYGON);//окно
              glVertex2f(-0.7f,
0.1f);
              glVertex2f(-0.7f,
-0.15f);
              glVertex2f(-0.5f,
-0.15f);
              glVertex2f(-0.5f,
0.1f);
              glEnd();
              glColor3ub(0,
0, 255);
              glLineWidth(5);
              glBegin(GL_LINES);//рама окна
              glVertex2f(-0.6f,
0.1f);
              glVertex2f(-0.6f,
-0.15f);
              glVertex2f(-0.6f,
0.0f);
              glVertex2f(-0.5f,
0.0f);
              glEnd();

         GLfloat the;//окно в
крыше
         GLfloat pi = acos(-1.0);
         GLfloat radius = 2.0f; // радиус
         GLfloat step = 0.5f; // чем больше шаг тем
хуже диск
              glColor3ub(100,
130, 255);
              glBegin(GL_TRIANGLE_FAN);
              for (GLfloat a = 0.0f; a <
360.0f; a += step) {
                   theta
= 2.0f * pi * a / 180.0f;
                   glVertex2f(radius
* cos(theta)/50-0.6f, radius * sin(theta)/25+0.4f);
              }
              glEnd();

              //ёлки-иголки
              float x = 0.0f, y=0.0f;
              for (int i = 0; i < 4; i++)
              {
                   glColor3ub(0,
150, 0);
                   glBegin(GL_TRIANGLES);
                   glVertex2f(0.0f,
0.5f-y);
                   glVertex2f(-0.1f-x,
0.3f-y);
                   glVertex2f(0.1f+x,
0.3f-y);
                   glEnd();
                   x +=
0.05f; y += 0.15;
              }
              x = 0.0f,
y = 0.0f;
              for (int i = 0; i < 4; i++)
              {
                   glColor3ub(0,
100, 0);
                   glBegin(GL_TRIANGLES);
                   glVertex2f(0.3f,
0.6f - y);
                   glVertex2f(0.2f
- x, 0.4f - y);
                   glVertex2f(0.4f
+ x, 0.4f - y);
                   glEnd();
                   x +=
0.03f; y += 0.12;
              }
              glColor3ub(150,
100, 0);
              glLineWidth(50);
              glBegin(GL_LINES);
              glVertex2f(0.0f,
-0.1f);
              glVertex2f(0.0f,
-0.35f);
              glVertex2f(0.3f,
0.1f);
              glVertex2f(0.3f,
-0.1f);
              glEnd();
              glColor3ub(255,
237, 0);
              glBegin(GL_TRIANGLE_FAN);
              for (GLfloat a = 0.0f; a <
360.0f; a += step) {
                   the
= 2.0f * pi * a / 180.0f;
glVertex2f(radius*cos(theta)/20+0.8f,radius*sin(the)/10+0.6f);
              }
              glEnd();
              glLineWidth(50);
               glBegin(GL_LINES);
              glVertex2f(0.5f,
0.6f);
              glVertex2f(0.68f,
0.6f);
              glVertex2f(0.55f,
0.35f);
              glVertex2f(0.7f,
0.5f);
              glVertex2f(0.6f,
0.1f);
              glVertex2f(0.72f,
0.4f);
              glVertex2f(0.75f,
0.05f);
              glVertex2f(0.8f,
0.35f);
              glVertex2f(0.9f,
0.35f);
              glVertex2f(0.98f,
0.15f);
              glVertex2f(0.6f,
0.9f);
              glVertex2f(0.7f,
0.72f);
              glEnd();

              SwapBuffers(hDC);
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:

PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return
0;
}

Скриншот работы программы:

Дополнительный материал

//
отрисовка диска 1 вариант
void drawCircle(float
x, float y, float
r, int amountSegments)
{
         glBegin(GL_LINE_LOOP);
         for (int i = 0; i < amountSegments; i++)
         {
              float angle = 2.0 * 3.1415926 * float(i) /
float(amountSegments);
              float dx = r * cosf(angle);
              float dy = r * sinf(angle);
              glVertex2f(x + dx, y + dy);
         }
         glEnd();

}

/*********************************************************/

//
отрисовка диска 2 вариант
GLfloat theta;
GLfloat pi = 3.14f;
GLfloat radius = 0.1f; // радиус
GLfloat step = 3.0f; // чем
больше шаг, тем хуже диск
//
рисуем диск по часовой стрелке GL_CW
glBegin(GL_TRIANGLE_FAN);
for (GLfloat a = 0.0f; a < 360.0f; a += step)
 {
     theta = 1.0f * pi * a / 180.0f;
     glColor4f(a / 360.0f, 1.0f, 1.0f - a / 360.0f, 1.0f);
     glVertex2f(radius * cos(theta)/2, radius * sin(theta));
}
glEnd();

/**********************************************************/

// десять точек по диагонали
glBegin
(GL_POINTS);
For i := 0 to 9 do
glVertex2f (i / 5 - 1, i / 5 - 1);
glEnd;
/*********************************************************/

//100 точек со случайными координатами и цветами:
glBegin (GL_POINTS);
For i := 1 to 100 do begin
glColor3f (random, random, random); glVertex2f (random * 2 - 1, random *
2-1);
end;
glEnd;

/*********************************************************/

// точки
рядом с курсором при движении
xpos:
GLfloat; // координаты курсора в системе координат
OpenGL ypos: GLfloat;

//
создать обработчик события MouseMove формы
xpos: = 2 * X / ClientWidth - 1;
ypos: = 2 * (ClientHeight - Y) / ClientHeight - 1;
Refresh; // перерисовываем окно
// в
обработчике Paint описать локальную целочисленную
//переменную
i и
For
i: = 1 to 30 do
begin // тридцать точек
glColor3f (random, random, random); //
случайного цвета
glBegin (GL_POINTS};
 // со
случайными координатами вокруг курсора
glVertex2f (xpos + 0. 2
* random * sin (random (360)),
ypos + 0. 2 * random * cos (random (3 60)));
glEnd;
end;
/*Если
все сделано правильно, то при движении курсора по поверхности формы рядом с
курсором должно появляться облачко разноцветных точек. Обратите внимание, что
обработчик движения мыши заканчивается вызовом Refresh -
принудительной перерисовкой окна при каждом движении курсора.*/

/**********************************************************/

Кроме рассмотренных
стандартных примитивов в библиотеках GLU и GLUT описаны более сложные фигуры,
·
такие,
как сфера, цилиндр, диск (в GLU)
·
и
сфера, куб, конус, тор, тетраэдр, додекаэдр, икосаэдр, октаэдр и, внезапно,  чайник
(в GLUT).

Рисунок 14. Чайник из библиотеки giut.h

Автоматическое наложение
текстуры предусмотрено только для фигур из библиотеки.
Например, чтобы
нарисовать сферу или цилиндр, надо сначала создать объект специального типа
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.
Важно отметить, что для корректного
построения перечисленных примитивов необходимо удалять невидимые линии и
поверхности, для чего надо включить соответствующий режим вызовом команды
glEnable (GL_DEPTH_TEST).
Контрольные
вопросы
1.
Что
такое командные скобки, каково их назначение?
2.
Какие
константы библиотеки OpenGL
могут быть параметрами функции glBegin?
3.
Что
такое антиэлайзинг (anti-aliasing),
для чего он служит?
4.
Какие
режимы существуют для рисования линий?
5.
Какие
режимы существуют для изображения треугольников, чем они различаются?
6.
Что
такое выпуклые и невыпуклые многоугольники?
7.
Каким
образом можно построить невыпуклый многоугольник?
8.
Чем
отличаются лицевые и обратные грани?
9.
Какая
команда изменяет способ тонирования?
10.
Какие
режимы вывода многоугольников вам известны? В каком месте программы должна быть
записана команда, изменяющая режим вывода многоугольников?

Список литературы

1)    Тарасов И. Opengl в России. – Режим доступа :   http://www.helloworld.ru/texts/comp/games/opengl/opengl2/index.html;
(скачать : http://www.read.in.ua/book120840/?razdel=11&p=47).

2)    OpenGL. – Режим доступа : https://www.opengl.org.
3)    Верма Р. Д.
Введение в Opengl . – Москва : Горячая линия – Телеком,
2015. – 303 с.
4)    Баяковский Ю.М., Игнатенко А.В., Фролов
А.И. Графическая библиотека OpenGL.:  Учебно-методическое пособие. – Москва :
ВМиК МГУ, 2003. – 132 с.
5)    Гайдуков С. Профессиональное программирование трехмерной
графики на С++. – Санкт-Петербург : БХВ-Петербург, 2004. – 736 с.
6)     Боресков А.
Графика трехмерной компьютерной игры на основе OpenGL.
– Москва : Диалог-МИФИ, 2005.
7)    Херн Д., Бейкер
М. Компьютерная графика и стандарт OpenGL. – Москва :
ИД «Вильямс», 2005.
8)
Программирование
компьютерной графики средствами OpenG :  Документация, статьи, советы. – Режим
доступа : opengl.gamedev.ru.

Оглавление
ВВЕДЕНИЕ. 3
OpenGL: инициализация, построение двумерных примитивов
в отдельном окне  6
Теоретическая
информация. 6
Методика
выполнения лабораторной работы. 25
Варианты
заданий. 25
Содержание
отчета. 26
Пример
выполнения лабораторной работы. 27
Дополнительный
материал. 30
Контрольные
вопросы.. 43
OpenGL:
Разработка приложения для визуализации связного набора двумерных примитивов. 44
Теоретическая
информация. 44
Методика
выполнения лабораторной работы. 62
Варианты
заданий. 62
Содержание
отчета. 64
Пример
выполнения лабораторной работы. 65
Дополнительный
материал. 69
Контрольные
вопросы.. 72
Список
литературы.. 73

Скачано
с www.znanio.ru

[1]
В программе на C++ указатель записан в виде &pfd, в программе на Delphi следует
записать @pfd.

[2]
В Delphi вместо  символа «|»  используется «or».

[3]
В Delphi шаблон запишется в виде, например $F0F0.

file_name: 3. КОМПЬЮТЕРНАЯ ГРАФИКА.doc

alt: Эту часть называют Back Buffer

alt: Сдвиговый бит игнорируется 0, //

alt: Затем запрашивается формат пикселя

alt: OneTimeSceneInit ; Result := true ; end ;

alt: Позднее мы добавим сюда функции

alt: End (); Таблица 2 Возможные значения параметра mode mode

alt: Методика выполнения лабораторной работы

alt: PFD _ DRAW _ TO _ WINDOW || //рисование в окне

alt: Vertex 3 d (-2,2,0); glEnd (); glBegin(GL_TRIANGLE_STRIP); // рисуем ленту треугольников glColor3d(0,1,0); glVertex3d(1,2,0); glVertex3d(0,2

alt: Дополнительный материал Инициализация

alt: Инициализация глобальных строк

alt: IconSm = LoadIcon(wcex

alt: Инициализация OpenGL с использованием

alt: Создание окна. После того как окно установлено, необходимо его создать : int glutCreateWindow(const char *title);

alt: Enable ( GL _ LIGHTING ); //включаем режим расчета освещения glEnable (

alt: Контрольные вопросы 1.

alt: ЛАБОРАТОРНАЯ РАБОТА №2 OpenGL:

alt: Команды, устанавливающие размер точки, толщину и тип линии, включение и отключение режима сглаживания ( англ

alt: For i: = 1 to 30 do begin // тридцать точек glColor3f (random, random, random); // случайного цвета glBegin (GL_POINTS}; // со случайными координатами glVertex2f…

alt: Здесь сторона a 2 a 3 является общей стороной для первого и второго треугольников, сторона a 3 a 4 – общей стороной второго и третьего…

title: КОМПЬЮТЕРНАЯ ГРАФИКА


extracted_text:
Муниципальное казенное
общеобразовательное учреждение
средняя общеобразовательная школа
с.Бельск, Черемховский район, Иркутская область.

Внеурочное занятие
на тему: «Пернатая радуга в комнате»
Учитель: Непотачева Мария Владимировна
Направление: Общеинтеллектуальное
Вид деятельности: Игра
Цель:
Задачи:
Систематизировать
знания детей о
Способствовать
формированию мыслительных операций, развитию речи, умению аргументировать свои
высказывания, логически мыслить.
Воспитывать
бережное отношение к домашним питомцам, чувство ответственности за тех, кого
приручили.
Форма: Путешествие

Этап

Задача

Деятельность
  учителя

Деятельность
  учеников

Формы
Методы
Средства

Результат

I.Организационно-мотивационный

Мотивирование
  учебной деятельности и вхождение в деятельность на занятии.

Приветствует
  детей. Проверяет готовность к занятию.
Настраивает
  детей на познавательную деятельность.
Здравствуйте,
  ребята. Посмотрите в окно. Какой замечательный солнечный день. У меня
  отличное настроение. А у вас? Кто радостно настроен на новые открытия и
  приключения? (поднимите солнышко).
Кому
  грустно и тоскливо? (тучку)
  Тихонечко положите руку на голову, погладьте себя и
  скажите: «У меня всё получится!» Замечательно, молодцы! Теперь вы готовы
  работать, и я вам желаю больших успехов.

Приветствуют
  учителя.

Оценивают
  своё эмоциональное состояние.

Настраиваются
  на работу.

Фронтальная
Словесный
Самооценка

Карточки
  с изображением солнышка и тучки.

П.
  Создание положительного отношения к обучению.
Р.
  Умение организовать своё рабочее место.
Л.
  Умение выражать свои эмоции.

II.Организационно-исполнительский

1.
  Целеполагание.

2.Организация
  деятельности.

III.Итог занятия.

Рефлексия

Сформулировать
  тему, поставить цель.

Организовать
  деятельность

Ребята, послушайте и отгадайте загадку:

Все пираты с ним ходили,
 На плече его носили,
Кто же это, угадай
Это точно … (Попугай)
  Догадались, о ком будем говорить?
Встречаются ли попугаи у нас в природных условиях?
Где вы можете встретить их?

Ребята, скажите, какие попугаи?
- С чем можно сравнить попугаев?

- Предположите, какая тема нашего занятия?

На экране тема занятия «Пернатая
  радуга в комнате»
Сегодня
  мы будем отгадывать загадки, развивать грамотную речь,  воспитывать бережное
  отношение к домашним питомцам.
Я предлагаю отправиться в путешествие на
  волшебный остров.
А
  на чём же мы отправимся в путешествие? Об этом мы узнаем после того, как
  выполним задание. У вас на партах  лежат листы -раскраски  и карандаши. Раскрасьте рисунки. У вас есть три
  минуты.
Учитель засекает время.
Время
  закончилось.
Поднимите
  вверх и покажите свои работы.
Посмотрите,
  какие красивые корабли у вас получились. Нравятся ли вам ваши корабли?
По-моему,
  все корабли отличные. Молодцы.
В
  путешествие мы отправляемся на двух кораблях. Для этого разделимся на две
  группы-команды. (По ряду парт)
Вспомним
  правила работы в группе. (напоминает правила)
Итак,
  вперёд к приключениям.
Учитель
  читает стихотворение:
Ветер
  по морю гуляет и кораблик подгоняет,
Он
  бежит себе в волнах на раздутых парусах.
Мы
  приближаемся к острову попугаев. Ребята, на острове случилась беда. Злой
  волшебник заколдовал всех попугайчиков, теперь они стали невидимыми. Давайте
  поможем им.
Учитель
  даёт задание для двух групп.
У каждой
  группы есть черно-белый рисунок.
Раскрасьте
  его, придумайте имя, составьте небольшой рассказ.  У вас есть 5 минут.
Время вышло.
Организует представление работы.

Что
  в работе группы было сложным?
Молодцы! Справились с заданиями.
Вы все активно работали.
Ребята, скажите пожалуйста, вам понравилось
  наше путешествие?
- О каких птицах мы поговорили?
 Я
  буду называть фразу, если верное утверждение, то вы встаете, если нет, то
  сидите.
-
  Попугаю нужна клетка.
-
  Попугая можно выгуливать на поводке.
-
  Попугаю нужен специальный корм.
-
  С попугаем можно не заниматься.
-
  Какой сделаем вывод?

Ребята,
  на доске есть волшебное дерево.
Кому
  сегодня было легко и интересно?
(прикрепите
  красного попугая)
Кому
  было  некомфортно и возникали трудности? (синего).

Слушают
  загадку.
Отвечают
  хором (Попугай)

О
  попугаях.
Отвечают:
  Нет, не встречаются.
В
  зоомагазине, зоопарке, дома в клетке.
Ответы:
  красивые, яркие.
С
  радугой.

Формулируют
  тему
Радуга
  в доме
ставят
  цель.

Выполняют
  задание. Раскрашивают корабли.

Да,
  очень красивые.

Делятся
  на группы
Вспоминают
  правила работы в группе.
Группы
  обходят вокруг своих рядов парт и садятся на место. Изображают движение
  корабля.

Слушают
  задание.
Раскрашивают,
  составляют рассказ.

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

Встают

Сидят

Встают

Сидят

Нужно быть ответственным за домашнего питомца.

Подходят
  к доске прикрепляют попугайчиков.

Фронтальная
Словесный

Слайд
  презентации
(Изображение
  попугая)

Фронтальная
Словесный

Слайд
  презентации

Индивидуальная
Практический

Листы-раскраски,
  карандаши.
Самооценка

Работа
  в группе
Словесный

Практический

Распечатаный
  чёрно-белый рисунок

Самооценка

Картинки
  попугайчиков красного и синего цвета.
Изображение
  дерева.

К.
  умение слушать и выполнять задания учителя

Р.
  Умение спланировать свои действия

К.Умение
  работать в группе.
П.Определение
  общей цели и путей её достижения

К.
  Умение договариваться о распределении функций и ролей в совместной
  деятельности.
Умение
  сравнивать, анализировать.

К.
  Готовность слушать собеседника, умение строить предложения.

П.Умение
  делать выводы.
Умение
  соотносить результаты с поставленной целью.

Л.
  Выражать свое отношение.

file_name: Пернатая радуга в комнате.docx

alt: Этап Задача Деятельность учителя

alt: Целеполагание. 2

alt: III. Итог занятия.

alt: Сформулировать тему, поставить цель

title: Конспект внеурочного занятия. Пернатая радуга в комнате.


extracted_text:
Ұйымдастырылған оқу
әрекетінің технологиялық картасы

Білім беру саласы: Шығармашылық.
Ұйымдастырылған оқу
іс-әрекетінің түрі: Сурет салу
Тақырыбы: Ұлттық баскиімді әшекелейміз.
Мақсаты: ұлттық баскиімдерді ажыраты білуге; ою-өрнек
элементтерін үшбұрышқа орналыстыра үйрету; көз
мөлшерін дамыту; бастаған ісін аяғына дейін жеткізуге
тәрбиелеу.
        Қолданылатын
көрнекі құралдар:
Қажетті құрал-жабдықтар: сурет дәптері, гуашь,
қылқалам, су сүлгі, үнтаспа, баяу әуенді
күйтабақ, доп.
Сөздік жұмыс: сәукеле, әшекейле, өрнекте.

Оқу іс-әрекетінің кезеңдері

Педагогтің іс-әрекеті

Балалардың іс-әрекеті

Мотивациялық
  қозғалушылық

Педагог алдын ала жасалған көрмедегі ұлттық
  баскиімдерді балаларға көрсетіп, салыстыртады.
Шеңберге тұрып балаларғадопты лақтырады;
  педагог жекеше түрде айтқан сөзге балалар сол
  сөздің көше түрін айтып жауап береді
(тақия-тақиялар, етік-етіктер).

Балалар ұлттық баскиімдерді естеріне түсіреді,
  әңгімелейді.

Ұйымдастырушылық - әдістемелік

Педагог қазақтың
  ұлттық киімдері туралы әңгімелейді. Балалрдың
  анық сойлеулерін қадағалайды.
«Сырмақты әшекейле» дидактикалық
  ойыны.
Педагог балалардын үшбұрышқа
  ұқсас заттарды атауды сұрайды.
Сәукеле туралы түсінік береді.
Педагог ұлттық баскиім- сәукелені
  әшекелеуді ұсынады (сәукелені қиып дайындап беруіне
  болады).
Салыну жолдары:
Алдымен үшбұрыш сызып алынады,
  төмен жағына сызық жүргізіледі, төбесіне
  үкі салынады. Балалардың қалаулары бойынша ашық
  түстерімен жұмыс жасалады. Дайын сәукелені жуан қарай
  гуашпен боятып, сәл кепенен кейін жіңішке
  қылқаламның ұшымен әдемі ою- өрнектер
  салып, өздері қалаған түспен әшекейлетеді.
  «Қызғалдақ» және «толқын» өрнектерін
  салуды ұсынады.

Балалар сұраққа толық жауап береді.
Киімдерді атайды, неден жасалғанын қайда киетінін айтады.
(Көрмені топтағы палас үстіне немесе үстел
  үстіне ұйымдастыруға болады.)
Балалар қылқаламдарын суға салып, ыдыстың
  шетіне сүртіп, бояумен қылқаламның ұшымен
  жұмыс жасайды.
Қандай түспен, қылқаламмен, қай жерін
  бояп жатқандарын айтады.

Рефлекциялық-түзетушілік

Балалардың жұмыстарына талдау жасалады. Жұмыстарды
  көрмеге іледі.

Балалар жақсы жасалған сәукелені атап
  көрсетеді.

Күтілетін нәтиже:
Біледі: ұлттық баскиімдерді ажыратуды.
Игереді: ою-өрнек элементтерін үшбұрышқа орналастыруды.
Менгереді: көз мөлшерін дамыту, бастаған ісін аяғына дейін
жеткізуді.

file_name: тема 31Ұлттық баскиімді әшекелейміз.doc

alt: Білім беру саласы: Шығармашылық

воспитательная работа

group: Дисциплины

title: ТЕХНОЛОГИЧЕСКИЕ КАРТЫ