Тривимірна графіка своїми руками, світ пк, видавництво «відкриті системи»

ARUBA INSTANT WI-FI: ПРОСТІ, ПОТУЖНІ, ДОСТУПНІ

Відомості про функціонування бібліотеки
Бібліотеку OpenGL можна сприймати як автомат, який в кожен момент часу знаходиться в деякому стані і відповідно до нього виконує одержувані запити. Іншими словами, у бібліотеки є набір внутрішніх змінних, значення яких використовуються при виклику її функцій. Значення цих змінних можна міняти, домагаючись тим самим потрібної дії відповідної функції. Наприклад, процедура

змінить поточне значення кольору на синій. Після виконання цієї команди все створювані об'єкти будуть синього кольору.
Для забезпечення ефекту анімації, тобто руху об'єктів і зміни їх властивостей, виконується постійне оновлення картинки. Швидкість перемальовування сцени (кількість разів на секунду) залежить насамперед від продуктивності графічного процесора і, звичайно, від покладених на нього завдань. Відповідно змінюється швидкість відтворення. Щоб забезпечити рівномірне відтворення ролика, оновлення можна штучно сповільнити, прив'язавши його до системних годинах.
Механізм поновлення в циклі реалізується з використанням чотирьох функцій:
void init (void); - це дії, що виконуються попередньо, до запуску основного циклу, наприклад ініціалізація змінних, установка параметрів;
void reshape (int, int); - це дії, пов'язані з масштабуванням сцени, що здійснюються при зміні розмірів вікна;
void display (void); - основна частина, промальовування всіх об'єктів, що знаходяться на сцені;
void idle (void); - функція викликається на кожному витку циклу. Як правило, її завдання - це збільшення лічильника, що є еквівалентом часу, і виклик display.
Далі ми передаємо бібліотеці покажчики на ці функції і запускаємо основний цикл.
Файли проекту і сам код (файл OpenGLSample.cpp) ви можете знайти на доданому до журналу «Світ ПК-диску».

Висновок основних форм
Спочатку створимо небо і землю.
Для цього використовуємо метод створення графічних примітивів через набори вершин. Координати вершин задаються процедурою
glVertex3d (GLdouble x, GLdouble y, GLdouble z),
де GLdouble - тип, що перетворюється в double і назад.
Вершини об'єднуються в об'єкт за допомогою конструкції:
glBegin (GLenum mode);
glVertex3d (x1, y1, z1);
.
glVertex3d (xn, yn, zn);
glEnd ();

Тут параметр mode визначає спосіб трактування списку вершин. Ось деякі з його значень:
GL_POINTS - створюється набір точок;
GL_TRIANGLES - трійки вершин задають окремі трикутники;
GL_QUADS - четвірки вершин задають окремі чотирикутники.

Зауваження про координатах
Аби не заглиблюватися в теорію, можна сказати, що насправді нам байдужі абсолютні значення координат, а істотні лише співвідношення між ними. Проектувати сцену можна в будь-яких найбільш зручних числах. Скорегувати положення камери допоможе процедура glViewPort ().
Земля буде являти собою прямокутник, що лежить в площині y = 0, небо нам знадобиться у вигляді двох прямокутників - один в площині z = -length, інший горизонтально в площині z = height. Отже,

void DrawGround () glColor3f (1.0,1.0,1.0);
glBegin (GL_QUADS);
glVertex3d (width, -1.0, length);
glVertex3d (width, -1.0, -length);
glVertex3d (-width, -1.0, -length);

glVertex3d (-width, -1.0, length);

glVertex3d (width, -1.0, -length);
glColor3f (0.10,0.20,0.30);
glVertex3d (width, height, -length);
glVertex3d (-width, height, -length);
glColor3f (0.35,0.65,0.99);
glVertex3d (-width, -1.0, -length);

glColor3f (0.10,0.20,0.30);
glVertex3d (width, height, -length);
glVertex3d (-width, height, -length);
glVertex3d (-width, height, length);
glVertex3d (width, height, length);
glEnd ();
>
Тут колір задається в форматі RGB в дійсних числах з відрізка [0,1]. При використанні прозорості можливо завдання кольору в форматі RGBA за допомогою процедури glColor4d (r, g, b, alpha).
Власне, на цьому принципі - завдання вершин і осмислення груп вершин як деяких об'єктів - і грунтується графічне моделювання. Для створення складних об'єктів, таких як моделі людей, хмар, трави, доводиться ставити велику (іноді астрономічне) число вершин, причому обчислення координат робиться вручну. Але не впадайте у відчай, розробки по автоматизації цього процесу вже ведуться.

освітлення
Під освітленням розуміється зміна кольору зафарбовування об'єкта в залежності від його розташування по відношенню до джерела світла. За замовчуванням є одне джерело розсіяного світла, але можна додавати і нові, зі своїм становищем, кутом розсіювання, кольором та іншими параметрами. Освітлення включається процедурою glEnable (GL_LIGHTING) і вимикається за допомогою glDisable (GL_LIGHTING).
Освітленість об'єкта, вид відкидаються їм тіней і його власна затененность залежать від напрямку нормалей до вершин, а також від матеріалу об'єкта.
Нормалі задаються процедурою glNormal3d (x, y, z), що використовується перед glVertex3d ().
Для присвоєння об'єкту матеріалу потрібно перед промальовуванням вершин викликати такі процедури:

GLfloat emissive [4] = <0.0f,0.0f,0.0f,0.0f>;
GLfloat diffuse [4] = <0.98f,0.836f,0.35f,1.0f>;
GLfloat specular [4] = <0.0f,0.0f,0.0f,0.0f>;
GLfloat ambient [4] = <0.98f,0.836f,0.35f,1.0f>;
glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, emissive);
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 10);
glEnable (GL_COLOR_MATERIAL);

Після промальовування об'єкта потрібно вимкнути параметр:

При використанні бібліотеки OpenGL слід дотримуватися простого правила - повертати всі змінені характеристики в початковий стан відразу після використання. Це заощадить вам масу часу і сил, а оптимізацією і видаленням непотрібних команд можна зайнятися на завершальному етапі, коли вже точно відомо, що ніяких змін в проект вноситися не буде.

текстурування
Накладання текстури робить об'єкт реалістичним і барвистим, а також дозволяє домогтися деяких спеціальних ефектів. Як текстур можна використовувати зображення у форматі BMP. Ми будемо застосовувати функції завантаження текстур, реалізація яких наведено у файлі BmpLoad.cpp. Ось як проводиться робота з текстурою:

  1. Створюється масив textures [NTEXT] значень типу GLuint, куди за допомогою процедури glGenTextures (NTEXT, textures) записуються ідентифікатори. За ним згодом будуть викликатися «прив'язані» до них текстури.
  2. У байтовий масив зчитується вміст файлу, потім масив завантажується у внутрішній ресурс бібліотеки (див. Процедуру OpaqTexture), при цьому встановлюється зв'язок останнього з обраним значенням id ідентифікатора текстури.
  3. При виклику glBindTexture (GL_TEXTURE_2D, id); в бібліотеці поточним встановлюється саме цей текстурний об'єкт.

Перетворимо землю в пустелю.
У нас є BMP-файл із зображенням піску. Завантажуємо його за наведеним вище алгоритмом і «натягуємо» на прямокутник землі. Для цього використовуємо процедуру glTexCoord2d (i, j), де i і j - текстурні координати, що відображають текстуру на квадрат [0,1] x [0,1]. Далі необхідно викликати glVertex, і до цієї вершини буде «пришпилена» зазначена точка текстури. Тоді вона буде плавно «розмазана» за великим прямокутника. Але нам потрібно зробити так, щоб текстура багаторазово розмножилася по всій землі. Для цього треба малювати землю не суцільним прямокутником, а у вигляді матриці, що складається з маленьких прямокутників, на кожен з яких «натягнута» текстура. Будемо описувати смуги прямокутників, встановлюючи GL_QUAD_ STRIP в glBegin. Ця дія об'єднує пару точок в відрізок, приєднує їх до попередньої парі і трактує всю четвірку як чотирикутник, потім приєднує до нього наступну пару і т.д. У підсумку виходить смуга.
Опис землі виглядає наступним чином:

glNormal3d (0.0, 1.0, 0.0);
int k = (int) (width / length);
glBindTexture (GL_TEXTURE_2D, textures [0]);
for (int i = 0; i Розташування необхідних файлів в системі

Схожі статті