Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
💸 Как сделать бизнес проще, а карман толще?
Тот, кто работает в сфере услуг, знает — без ведения записи клиентов никуда. Мало того, что нужно видеть свое раписание, но и напоминать клиентам о визитах тоже.
Проблема в том, что средняя цена по рынку за такой сервис — 800 руб/мес или почти 15 000 руб за год. И это минимальный функционал.
Нашли самый бюджетный и оптимальный вариант: сервис VisitTime.⚡️ Для новых пользователей первый месяц бесплатно. А далее 290 руб/мес, это в 3 раза дешевле аналогов. За эту цену доступен весь функционал: напоминание о визитах, чаевые, предоплаты, общение с клиентами, переносы записей и так далее. ✅ Уйма гибких настроек, которые помогут вам зарабатывать больше и забыть про чувство «что-то мне нужно было сделать». Сомневаетесь? нажмите на текст, запустите чат-бота и убедитесь во всем сами! Використання графічної бібліотеки opengl 4 страница
Перш за все у програмі оголошується масив даних текстури:
static GLubyte checkImage[64][64][4];
Другим кроком ініціалізується масив текстури: void CMain:: MakeCheckImage() {for(int i=0; i< 64; i++) { // текстура має розмір 64 x 64 for(int j=0; j< 64; j++) { int c=((((i& 0x8)==0)^((j& 0x8))==0))*255; checkImage[i][j][0]=(GLubyte)c; checkImage[i][j][1]=(GLubyte)c; checkImage[i][j][2]=(GLubyte)c; checkImage[i][j][3]=(GLubyte)255; }}}
Нарешті у функції OnOpenGLFirst() здійснюється визначення параметрів текстури і визначення її координат одночасно із побудовою графічних об’єктів. Ця функція наведена у прикладі 12.5.
Приклад 12.5 – Приклад програми із накладенням текстур void CMain:: OnOpenGLFirst() { glRotatef(360.0*hspos/100, 0, 1, 0); // 3D-scrolling around y glRotatef(360.0*vspos/100, 1, 0, 0); // 3D-scrolling around x glTranslatef(0.0, -3.0, 0.0); glLineWidth(2.0); glBegin(GL_LINES); // побудова координатних осей glColor3f(1.0, 0.0, 0.0); glVertex3f(25.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f); // вісь X glColor3f(0.0, 1.0, 0.0); glVertex3f(0.0f, 25.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f); // вісь Y glColor3f(0.0, 0.0, 1.0); glVertex3f(0.0f, 0.0f, 25.0f); glVertex3f(0.0f, 0.0f, 0.0f); // вісь Z glEnd(); glColor4f(0.0, 0.0, 1.0, 0.0); glEnable(GL_DEPTH_TEST); // увімкнення тесту глибини glEnable(GL_TEXTURE_2D); // увімкнення використання текстур // увімкнення взаємодії текстури і примітиву glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); MakeCheckImage(); // ініціалізація масиву текстур // визначення властивостей текстури glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); glBegin(GL_POLYGON); // побудова сторони призми glTexCoord2i(0, 0); glVertex3i(4, -2, 0); glTexCoord2i(0, 1); glVertex3i(4, 4, 0); glTexCoord2i(1, 1); glVertex3i(0, 4, 0); glTexCoord2i(1, 0); glVertex3i(0, -2, 0); glEnd(); glBegin(GL_POLYGON); glTexCoord2i(0, 0); glVertex3i(4, 4, 0); glTexCoord2i(0, 1); glVertex3i(0, 4, 0); glTexCoord2i(1, 1); glVertex3i(0, 4, 6); glTexCoord2i(1, 0); glVertex3i(4, 4, 6); glEnd(); glBegin(GL_POLYGON); glTexCoord2i(0, 0); glVertex3i(4, -2, 6); glTexCoord2i(0, 1); glVertex3i(4, 4, 6); glTexCoord2i(1, 1); glVertex3i(0, 4, 6); glTexCoord2i(1, 0); glVertex3i(0, -2, 6); glEnd(); glBegin(GL_POLYGON); glTexCoord2i(0, 0); glVertex3i(0, -2, 6); glTexCoord2i(0, 1); glVertex3i(0, -2, 0); glTexCoord2i(1, 1); glVertex3i(4, -2, 0); glTexCoord2i(1, 0); glVertex3i(4, -2, 6); glEnd(); glBegin(GL_POLYGON); glTexCoord2i(0, 0); glVertex3i(4, -2, 0); glTexCoord2i(0, 1); glVertex3i(4, 4, 0); glTexCoord2i(1, 1); glVertex3i(4, 4, 6); glTexCoord2i(1, 0); glVertex3i(4, -2, 6); glEnd(); glBegin(GL_POLYGON); glTexCoord2i(0, 0); glVertex3i(0, -2, 0); glTexCoord2i(0, 1); glVertex3i(0, 4, 0); glTexCoord2i(1, 1); glVertex3i(0, 4, 6); glTexCoord2i(1, 0); glVertex3i(0, -2, 6); glEnd(); glDisable(GL_TEXTURE_2D); // вимкнення режиму застосування текстур } Результат виконання функції наведено на рисунку 12.7. У функції OnOpenGLFirst() спочатку будуються координатні осі. Потім командою glEnable(GL_DEPTH_TEST) вмикається тест глибини. Далі активується режим застосування текстур: glEnable(GL_TEXTURE_2D). За необхідністю вмикаються режими взаємодії текстури із об’єктом, на який вона наноситься. Виклик MakeCheckImage() ініціалізує масив текстури у вигляді шахової дошки. Застосування функції glTexImage2D() визначає основні параметри текстури – двовимірна, рівень деталізації – 1, внутрішній формат RGBA, розміри – 64 x 64, ширина межі – 0, формат зображення RGBA, тип даних текстури - беззнаковий типу byte, покажчик на масив даних текстури – checkImage:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage);
Надалі, під час побудови площин призми одночасно вказуються і координати текстур. Визначення вершин координат текстур і вказання вершин контурів здійснюється у напрямі руху стрілки годинника.
а) б) Рисунок 12.7 – Використання режимів накладення текстур (а – з увімкненою функцією glTexEnv(), б – із вимкненою glTexEnv())
12.6.3 Використання текстур на основі растрових зображень У попередньому пункті розглядалися засоби побудови та використання простих текстур. Однак такий підхід навряд чи задовольнить усіх бажаючих використати тривимірну комп’ютерну графіку. Значно цікавіше окремо створювати растрові зображення і надалі використовувати їх для накладання на графічні об’єкти. З якихось причин у [4] використання растрових зображень для формування текстур не описується зовсім, а у [5] описується у досить заплутаний спосіб. Наше завдання полягає у описі послідовності простих дій програміста із використання текстур із одночасним визначенням необхідних команд OpenGL. Для завантаження файлів текстур версія OpenGL, реалізована у Microsoft Visual C++, використовує функцію auxDIBImageLoad():
AUX_RGBImageRec* auxDIBImageLoad(const char *file);
Єдиним параметром функції є рядок із іменем файла. Функція повертає покажчик на спеціальний тип AUX_RGBImageRec, який характеризує область пам’яті, до якої завантажується текстура. Разом із такою функцією завантаження використовується функція int gluBuild2DMipmaps(GLenum target, GLint components, GLint width,GLint height, GLenum format, GLenum type, const void *data);
Параметрами функції є: target – тип цільової текстури (має бути GL_TEXTURE_2D); components – кількість компонентів кольору у текстурі (має дорівнювати 1, 2, 3, або 4); width та height – ширина та висота зображення тестури, відповідно; format – формат піксельних даних (має приймати значення: GL_COLOR_INDEX, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_RGB, GL_RGBA, GL_BGR_EXT, GL_BGRA_EXT, GL_LUMINANCE, або GL_LUMINANCE_ALPHA); type – тип даних текстури (приймає значення GL_UNSIGNED_BYTE, GL_BYTE, GL_BITMAP, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, або GL_FLOAT); data – покажчик на дані зображення, що зберігаються у пам’яті. В принципі порядок використання текстур суттєво не змінюється, змінюються лише застосовувані функції. Зазначимо, що у [5] наголошується на невідповідності форматів *.bmp-файлів та формату RGB і для виправлення пропонується розробити спеціальну функцію Rgb2Bgr() для перетворення формату. Однак операції накладення текстур із використанням функцій auxDIBImageLoad() та gluBuild2DMipmaps() не виявляють спотворення кольорів, у чому шановний читач може довідатися власноруч із наведених нижче прикладів. Для завантаження текстур з *.bmp-файла у програмі додатково необхідно: 1) визначити дескриптор завантажуваного файла у якості глобальної змінної, наприклад:
AUX_RGBImageRec *pImage;
2) у конструкторі головного вікна програми завантажити файл (або файли) із зображеннями текстур:
pImage=auxDIBImageLoad(" greenstone.bmp"); // файл – з системного каталога Windows
3) безпосередньо перед використанням текстури створити її функцією gluBuild2DMipmaps():
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, pImage-> sizeX, pImage-> sizeY, GL_RGB, GL_UNSIGNED_BYTE, pImage2-> data);
4) дозволити використання текстур і, одночасно вказуючи координати текстури і вершин об’єкта, здійснити накладення текстури. Приклад 12.6 є cкороченим і модифікованим варіантом прикладу 12.5. Результат його використання наведений на рисунку 12.8.
Приклад 12.6 – Використання растрового зображення для формування текстури
void CMain:: OnOpenGLFirst() { ………………………………. glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, pImage-> sizeX, pImage-> sizeY, GL_RGB, GL_UNSIGNED_BYTE, pImage-> data); glBegin(GL_POLYGON); glTexCoord2i(0, 0); glVertex3i(4, -2, 0); glTexCoord2i(0, 1); glVertex3i(4, 4, 0); glTexCoord2i(1, 1); glVertex3i(0, 4, 0); glTexCoord2i(1, 0); glVertex3i(0, -2, 0); glEnd(); ……………………………….. // інші прямокутники не показані glDisable(GL_TEXTURE_2D); }
Рисунок 12.8 – Використання растрового зображення для формування текстури
Приклади 12.5 і 12.6 мають досить об’ємний код, тому одразу виникає бажання застосувати текстуру до складеного об’єкта, що будується однією функцією. Але під час побудови складеного об’єкта ми не матимемо змоги вказувати координати текстури (як і координати вершин об’єкта). З цієї причини необхідно шукати інші шляхи. Таким окремим шляхом накладання текстур на складені об’єкти є використання так званих квадратичних об’єктів, що у OpenGL описують поверхні другого порядку. Таким поверхням у OpenGL відповідає ряд команд: // побудова циліндра void gluCylinder(GLUquadricObj *qobj, GLdouble baseRadius, GLdouble topRadius, GLdouble height, GLint slices, GLint stacks); де baseRadius – радіус основи цидіндра, topRadius – радіус верхньої основи, height – висота, slices – кількість дискретних складових навколо осі Z, stacks – кількість дискретних складових вздовж осі Z. Параметри сфери є схожими. // побудова сфери void gluSphere(GLUquadricObj *qobj, GLdouble radius, GLint slices, GLint stacks);
Параметри сфери є схожими. radius є радіусом сфери.
// побудова диска void gluDisk(GLUquadricObj *qobj, GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops);
Серед параметрів – внутрішній та зовнішній радіуси (innerRadius та outerRadius відповідно)
// побудова сегменту диска void gluPartialDisk(GLUquadricObj *qobj, GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops, GLdouble startAngle, GLdouble sweepAngle);
Характерними параметрами є loops – кількість концентричних кіл – елементів дискретизації диска, початкове та кінцеве значення кутів (startAngle та sweepAngle, відповідно). Першим параметром усіх квадратичних функцій виступає покажчик на квадратичний об’єкт, що має тип GLUquadricObj. Квадратичні об’єкти створюються за допомогою функції gluNewQuadric(). Встановлення режиму накладення текстур на квадратичні об’єкти забезпечує функція gluQuadricTexture(): void gluQuadricTexture(GLUquadricObj *quadObject, GLboolean textureCoords);
де перший параметр – покажчик на квадратичний об’єкт, другий – ознака необхідності генерації текстурних координат (приймає значення GL_TRUE або GL_FALSE). З урахуванням зазначених особливостей та завантаживши файл “winnt.bmp” можна змінити текст функції OnOpenGLFirst() на текст записаний у прикладі 12.7. У даному прикладі використовується функція побудови диска, до якого саме і застосовується текстурне зображення, завантажуване з файла. Рисунок 12.9 демонструє результат виконання програми.
Приклад 12.7 – Застосування текстури до квадратичного об’єкта (диск) void CMain:: OnOpenGLFirst() { ………………………………….. GLUquadricObj *m_quadObj; // оголошення покажчика на квадратичний об’єкт m_quadObj=gluNewQuadric(); // створення нового покажчика gluQuadricTexture(m_quadObj, GL_TRUE); // дозвіл на використання текстур glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, pImage-> sizeX, pImage-> sizeY, GL_RGB, GL_UNSIGNED_BYTE, pImage-> data); gluDisk(m_quadObj, 0.0, 5.0, 80, 80); // побудова квадратичного об’єкта glDisable(GL_TEXTURE_2D); }
Рисунок 12.8 – Квадратичний об’єкт (диск) із накладеною текстурою
Під час роботи з текстурами інколи доводиться змінювати їх розміри. Функція gluScaleImage() виконує роботу із масштабування текстур.
void gluScaleImage (GLenum format, GLint widthin, GL heightin, GLenum typein, const void *datain, GLint widthout, GLint heightout, GLenum typeout, void *dataout);
Параметр format використовує значення GL_RGB або GL_RGBA, що визначають формат зберігання інформації. Параметри widthin, heightin, widhtout, heightout встановлюють розміри вхідного та вихідного зображень. За допомогою параметрів typein та typeout задається тип елементів масивів, розташованих за адресами datain та dataout. Використовуються GL_UNSIGNED_BYTE, GL_SHORT, GL_INT та інші типи даних. Результат роботи функції заноситься в область пам’яті, на яку вказує параметр dataout. Насамкінець зазначимо, що хоча описані методи використання текстур неодмінно функціонують для завантаження графічних файлів будь-якого рівня складності, слід все-таки обмежувати якість і розмір текстурних зображень. Такі обмеження особливо ефективні під час моделювання динамічних сцен.
12.7 Реалізація ефектів освітлення
12.7.1 Світло та освітлення у OpenGL Для створення реалістичних зображень необхідно визначати як власти-вості самого об’єкта, так і властивості середовища, у якому він знаходиться. До першої групи властивостей належать способи нанесення текстур, визначення прозорості об’єкта та властивостей матеріалу, з якого зроблено об’єкт. До другої групи належать кількість та властивості джерел освітлення, рівень прозо-рості середовища, модель джерел освітлення. Апроксимація світла та освітлення реалізовані у OpenGL у такий спосіб, що світло можна розкласти на червоний, зелений та синій компоненти у відповідності до формату RGB. Колір джерела світла характеризується сумою червоного, зеленого та синього компонентів світла, що випромінюється джерелом, а матеріал поверхні у свою чергу характеризується відсотками червоного, зеленого та синього компонентів, віддзеркалених у різних напрямках [4]. У моделі освітлення OpenGL світло на сцені виходить з декількох джерел, кожен з яких може бути увімкненим та вимкненим. Джерела світла можуть виходити з певного напрямку або положення, інші – бути розсіяними по сцені. У моделях освітлення OpenGL джерела світла мають впливати на поверхні, що поглинають або відбивають світло. Матеріал може випромінювати власне світло (наприклад, фара автомобіля), може відбивати або розсіювати частину світла в усіх напрямках (поверхня дзеркала). Модель освітлення OpenGL розглядає освітлення у складі чотирьох незалежних компонентів: розсіяного (або фонового) світла (ambient), дифузної (diffuse), дзеркальної (specular) та емісійної (emission) складових. Розсіяне освітлення формується світлом, напрям якого неможливо визначити. Зокрема освітлення будь-якої кімнати має значну складову розсіяного світла з тієї причини, що значна частина світла, яке досягає ока людини, перед тим була віддзеркалена великою множиною поверхонь. Дифузна складова є світлом, що походить з одного напрямку, тому ця складова є більш яскравою, коли падає прямо на поверхню, і менш яскравою, коли світло сковзає поверхнею. Як тільки таке світло стикається з поверхнею, воно рівномірно розсіюється в усіх напрямках і зберігає рівномірну яскравість незалежно від положення спостерігача. Будь-яке світло, що походить з певного місця або напрямку, міститиме дифузну складову. Дзеркальна складова походить з певного напряму і під час зіткнення з поверхнею віддзеркалюється у певному напрямку. Наприклад, лазерний промінь при зіткненні з високоякісним дзеркалом потерпає майже 100-відсоткове відбиття. Металічні і (і меншою мірою) пластикові поверхні мають значну компоненту відбиття. У доповнення до розсіяної, дифузної та дзеркальної складових, колір матеріалу може бути емісійним, таким, що імітує світло, яке надходить від об’єкта. У моделі освітлення OpenGL емісійне світло поверхні додає яскравості об’єкта, але на таку емісійну складову не можуть впливати інші джерела світла. Емісійна складова не додає додаткового світла у загальну сцену.
12.7.2 Визначення джерел світла Джерела освітлення OpenGL-програм мають декілька властивостей: колір, положення та напрямок і встановлюються за допомогою команди glLight*(): void glLight[i f] (GLenum light, GLenum pname, GLfloat param); void glLight[i f] (GLenum light, GLenum pname, GLfloat *params);Параметр light визначає ідентифікатор джерела освітлення. Ідентифікатори знаходяться у діапазоні імен GL_LIGHT0 – GL_LIGHT7. Таким чином кількість джерел освітлення зазвичай обмежується вісьмома. Для роботи з командою glLight*() необхідно задати значення параметра, а потім встановити його для необхідного джерела світла. Параметр pname означає вибір параметра, значення якого встановлюється у третьому аргументі – param (або params). У таблиці 12.10 вказуються та коментуються характерні значення pname.
Таблиця 12.10 – Опис значень параметра pname команди glLight*()
Під час розробки OpenGL-програм джерела світла звичайно визначаються у функціях, що забезпечують ініціацію параметрів роботи програми. Як тільки відповідні джерела освітлення визначені, вони можуть бути увімкнені і використані. Загальна освітленість сцен OpenGL-програми вмикається командою glEnable():
glEnable(GL_LIGHTNING); Після увімкнення світла можна окремо активізувати необхідні раніше визначені джерела освітлення, наприклад:
glEnable(GL_LIGHT0);
Визначення параметрів джерела світла показує приклад 12.8.
Приклад 12.8 – Визначення параметрів світла
GLfloat light_ambient[]={1.0, 0.0, 1.0, 1.0}; GLfloat light_diffuse[]={1.0, 0.0, 1.0, 1.0}; GLfloat light_specular[]={1.0, 1.0, 1.0, 0.0}; GLfloat light_position[]={1.0, 1.0, 1.0, 0.0}; glLightfv (GL_LIGHT0, GL_POSITION, light_ambient); glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv (GL_LIGHT0, GL_POSITION, light_position); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0);
Як видно з прикладу, OpenGL дозволяє асоціювати з джерелом освітлення три різних параметри: GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR. Параметр GL_AMBIENT належить до RGBA-інтенсивності розсіяного світла, що додається до сцени певним джерелом. Інший параметр – GL_DIFFUSE най-більше відповідає тому, що називають кольором світла. Він встановлює колір дифузного світла, що додається певним джерелом у сцену. Третій параметр – GL_SPECULAR впливає на колір найбільш яскраво освітленої частини об’єктів (наприклад, відблиск на поверхні скляної пляшки). Для досягнення найбільшої реалістичності слід встановлювати GL_SPECULAR рівним GL_DIFFUSE [4]. Джерело світла може розміщуватися нескінченно далеко або близько відностно сцени. Нескінченно далекі джерела освітлення належать до направлених (directional) джерел, при цьому промені світла можна вважати паралельними. Саме таким джерелом можна вважати Сонце. Другий тип називають позиційним (positional) з тієї причини, що його точне положення на сцені визначає напрям променів світла. Прикладом позиційного джерела є настільна лампа. Для реальних джерел освітлення інтенсивність світла зменшується зі збільшенням відстані від джерела. Для направленого світла, що знаходиться нескінченно далеко, немає сенсу вмикати загасання. Загасання світла використовується для позиційних джерел. OpenGL забезпечує загасання світла відповідно до такої формули: ; де d – відстань між положенням джерела світла та вершиною, kc = GL_CONSTANT_ATTENUATION, kl = GL_LINEAR_ATTENUATION, kq = GL_QUADRATIC_ATTENUATION. Ці параметри можна встановити у різні, відмінні від замовчуваних, значення, наприклад:
GLfloat spot_direction[]={-1.0, -1.0, 0.0}; glLightfv (GL_LIGHT0, GL_CONSTANT_ATTENUATION, 2.0); glLightfv (GL_LIGHT0, GL_LINEAR_ATTENUATION, 1.0); glLightfv (GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 1.5); Позиційне джерело світла можна примусити функціонувати як прожектор (spotlight). Це дозволить обмежити конусом випромінюване світло і простерігати лише зону, обмежену конусом. Для створення прожектора необхідно визначити межі конуса світла. За межами конусу світло не розповсюджуватиметься. За замовчуванням контролюючий параметр GL_SPOT_CUTOFF дорівнює 180 градусів. Це як раз означає розповсюдження світла в усіх напрямках. Для визначення прожектора також необхідно задавати напрям світла прожектора – вісь конуса світла. Значення кута і прожектора та його вісь задаються такою послідовністю команд:
glLightfv (GL_LIGHT0, GL_SPOT_CUTOFF, 45.0); glLightfv (GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);
За замовчуванням напрям прожектора встановлюється у (0.0, 0.0, -1.0), що означає випромінення світла вздовж негативного напрямку осі Z. Цей фактор необхідно враховувати під час визначення джерел світла. Інтенсивність розповсюдження світла всередині конуса можна контролювати, встановлюючи коефіцієнт загасання, описаний вище, також, за допомогою параметра GL_SPOT_EXPONENT, для керування концентрацією світла всередині конуса. Інтенсивність світла має найвище значення в центрі конуса і загасає за формулою cos eα, де α – кут між віссю та напрямом від джерела світла до освітлюваної вершини. Як вже зазначувалося під час визначення команди glLight*(), у програмі можна визначити до 8-ми джерел світла. Для цього необхідно вказати відповідні ідентифікатори, наприклад:
glLightfv (GL_LIGHT1, GL_DIFFUSE, light_diffuse); glLightfv (GL_LIGHT1, GL_POSITION, light_position); glEnable (GL_LIGHT1);
Джерело світла можна формувати одночасно з об’єктом сцени або камерою і, таким чином, прив’язати його до об’єкта або камери. З іншого боку, можна сформувати стаціонарне джерело світла, що знаходитиметься на місці поки інші об’єкти переміщуються. Якщо положення джерела світла задається командою glLight*(), перед визначенням положення віртуальної камери (наприклад, за допомогою команди glLookAt()), вважатиметься, що координати (0, 0, 0) джерела знаходитимуться у точці спостереження і положення джерела світла визначатимуться відносно положення спостерігача. Розглянемо ще один приклад. Припустимо, що у програмі необхідно визначити джерело світла із властивостями прожектора. У точці розташування джерела світла розташуємо сферу, що на сцені позначатиме джерело освітлення, а на певній відстані від джерела освітлення побудуємо диск. Кут конуса світла прожектора регулюватиметься за допомогою горизонтальної смуги прокручування головного вікна програми. Текст коду обробника OnOpenGLFirst() наведено у прикладі 12.9, а її результат дії програми – на рисунку 12.9. Зазначимо, що попередньо встановлено чорний колір фону:
glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Приклад 12.9 – Визначення параметрів прожектора
void CMain:: OnOpenGLFirst() { glRotatef(225, 1, 1, 0); // обертання сцени glRotatef(360.0*vspos/100, 0, 1, 1); // обертання навколо осей Y та Z glTranslatef(3.0, 3.0, 0.0); // переміщення сцени GLfloat emission[]={1.0, 0.0, 0.0, 0.0}; // червоний колір емісії об’єктів glMaterialfv(GL_FRONT, GL_EMISSION, emission); // увімкнення емісії GLfloat light_position[]={0.0, 0.0, 10.0, 1.0}; // розташування джерела світла GLfloat light_diffuse[]={1.0, 1.0, 1.0, 1.0}; // білій колір світла прожектора GLfloat spot_direction[]={0.0, 0.0, -1.0, 1.0}; // напрям прожектора glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); // встановлення кольору світла glLightfv (GL_LIGHT0, GL_POSITION, light_position); // встановлення положення джерела glLightfv (GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction); // встановлення напряму glLightf (GL_LIGHT0, GL_SPOT_CUTOFF, hspos-50.0); // встановлення кута прожектора glEnable (GL_LIGHTING); // загальне увімкнення освітлення фону glEnable (GL_LIGHT0); // увімкнення джерела світла GLUquadricObj *m_quadObj; // оголошення квадратичного об’єкта m_quadObj=gluNewQuadric(); // створення квадратичного об’єкта gluDisk(m_quadObj, 0.0, 5.0, 80, 80); // побудова диску glPushMatrix(); glTranslatef(0.0, 0.0, 10.0); auxSolidSphere(0.5); // побудова сфери glPopMatrix(); }
Рисунок 12.9 – Зміна освітлення диска у залежності від кута прожектора 12.7.3 Властивості матеріалів Модель освітлення OpenGL виконує також таку апроксимацію, відповідно до якої колір матеріалу залежить від відсоткового входження червоного, зеленого та синього кольорів, що відбиваються освітленим матеріалом. Подібно до світла, матеріали мають різні складові розсіяного, дифузного та дзеркального компонентів кольору, що визначають колір неосвітленого об’єкта, дифузну та дзеркальну складові матеріалу. Коефіцієнт розсіяного відбиття матеріалу складається з розсіяної складової кожного джерела світла, коефіцієнт дифузного відбиття складається з дифузної, а коефіцієнт дзеркального відбиття – з дзеркальної складових. Коефіцієнти розсіяного та дифузного відбиття визначають колір матеріалу є зазвичай схожими і, практично, ідентичними. Для встановлення параметрів поточного матеріалу використовується команда glMaterial*():
void glMaterial [i f] (GLenum face, GLenum pname, GLtype param); void glMaterial [i f] v (GLenum face, GLenum pname, GLtype *params);
Параметр face визначає тип граней, для яких встановлюється матеріал, і приймає значення GL_FRONT, GL_BACK або GL_FRONT_AND_BACK. За допомогою цих функцій можна визначити розсіяний, дифузний та дзеркальний кольори матеріалу, також колір ступеня дзеркального відобра-ження та інтенсивність випромінювання світла, якщо об’єкт має світитися. Який саме параметр визначатиметься значенням param залежить від значення pname. Значення констант властивостей матеріалу описуються у таблиці 12.9. З опису виходить, що виклик невекторного варіанта команди можливий лише за умов встановлення ступеня дзеркального відбиття матеріалу, а векторна версія має використовуватися в усіх інших випадках.
|