Урок 4 - Світло,камера, матеріал! Частина 1
Перша частина уроку з освітлення та матеріалів.
Ще однією важливою темою для графічних програм та ігор є освітлення. Детально зупинятися на фізичному сенсі та математичної моделі освітлення я не буду, подібних статей з описами вистачає на просторах інтернету, наприкінці уроку будуть наведені посилання на деякі з таких статей.
В уроці буде розглянуто створення точкового джерела світла з різними параметрами, яке висвітлюватиме кілька геометричних фігур на сцені з різними матеріалами.
Для цього уроку було вирішено запровадити невелику математичну бібліотеку для полегшення роботи з матрицями та векторами. Основні поняття по матрицях були дані в попередньому уроці, тому ви вже повинні надавати, які матриці використовуються, як вони створюються і як передаються в шейдерну програму.
Математична бібліотека також доповнюватиметься в міру необхідності, як і вихідний код чергового уроку.
У комп'ютерній графіці найчастіше працюють із трьома типами джерел світла:
- Точкове джерело світла (point light)
- Спрямоване джерело світла (directional light)
- Прожектор (spot light)
Як я вже зазначив вище – у цьому уроці буде розглянуто лише перший тип, інші два типи будуть розглянуті у наступному уроці. До точкового джерела світла з деякою похибкою можна віднести звичайну електричну лампочку.
У випадку точкового джерела світла розглядають такі параметри:
- Положення у просторі (position)
- Потужність фонового освітлення (ambient)
- Потужність розсіяного освітлення (diffuse)
- Потужність відбитого освітлення (Specular)
- Коефіцієнти згасання (attenuation)
Точкове джерело випускає промені світла на всі боки, наочно це можна уявити наступним малюнком:
Типи vec3 та vec4 взяті з математичної бібліотеки, це 3х та 4х компонентні вектори з типом float, відповідно. Над цими типами визначено основні векторні операції, такі як додавання, множення тощо.
Використовуючи функціонал мови GLSL ми можемо в шейдері оголосити таку саму структуру даних і потім із програми передати туди параметри точкового джерела освітлення.
Передавати параметри джерела освітлення з програми до шейдера ми будемо наступним чином:
Зауважте, що доступ до елементів структури в шейдері йде за назвою конкретного екземпляра, а не за назвою структури.
Матеріал об'єкту
Крім параметрів джерела освітлення, необхідно також знати як об'єктреагуватимена це освітлення. Об'єкт може світитися, може розсіювати світло, відбивати світло. Все це описують параметри матеріалу, з якого зроблено об'єкт.
Параметри матеріалу тісно пов'язані з параметрами світла. Найчастіше матеріал визначають наступними параметрами:
- Сприйняття фонового освітлення (ambient)
- Сприйняття розсіяного освітлення (diffuse)
- Сприйняття відбитого висвітлення (specular)
- Самостійне світіння (emission)
- Коефіцієнт блиску (shininess)
Додатково до параметрів матеріалу зберігатимемо в ньому текстуру об'єкта:
Також як і передачі параметрів точкового джерела освітлення в шейдері ми створимо структуру зберігання параметрів матеріалу.
За аналогією з передачею параметрів точкового джерела освітлення з програми шейдер ми можемо передавати параметри матеріали:
Камера у графічній сцені представляєстановище спостерігача і те, як він бачить сцену навколо себе. Положення та напрямок погляду задаються матрицею виду (ViewMatrix), а формат відображення задається матрицею проекції (ProjectionMatrix).
У цьому уроці використовується проста камера з можливість переміщення по сцені та огляду навколишнього простору:
Для того, щоб передати набір матриць трансформації вершин в шейдерну програму нам необхідно, крім камери, мати матрицю перетворення об'єкта ModelMatrix, тому функція передачі параметрів камери в шейдерну програму виглядає таким чином:
Як ви можете бачити, ми ввели додаткову матрицю normal, вона необхідна для того, щоб переводити нормалі об'єкта з локальної системи координат об'єкта у світову, це необхідно для розрахунку освітлення у світовій системі координат.
Варто зазначити, що при використанні FFP OpenGL освітлення розраховувалося не у світовій системі координат, а у видовій. На погляд це дуже зручно, т.к. видова система координат пов'язана з камерою, а джерела освітлення зручно задавати у світовій системі координат і саме там і робити весь розрахунок.
Розрахунок освітлення
Для розрахунків освітлення у цьому уроці використовується модель освітлення Фонга (Phong shading). Основний зміст моделі в тому, що підсумкове висвітлення об'єкта складається з трьох компонентів:
- Фонове світло (ambient)
- Розсіяне світло (diffuse)
- Відбите світло (specular)
Додатково до цих параметрів ми додамо власне світіння матеріалу (emission), цей параметр дозволяє підсвітити об'єкт навіть якщо не освітлений жодним джерелом освітлення.
Відповідно кожен із компонентів розраховується з урахуванням параметрів джерела освітлення та матеріалу об'єкта. Більш детальнуінформацію щодо цієї моделі освітлення ви можете отримати у цій нотатці.
Розрахунок освітлення може бути як повершинним (per-vertex lighting), так і попіксельним (per-pixel lighting). У даному уроці ми розглянемо саме піксельне освітлення, воно дозволяє згладити недостатню деталізацію полігональних моделей та більш точно розрахувати освітленість у кожній точці об'єкта. Основний розрахунок попіксельного освітлення відбувається у фрагментному шейдері.
Перш ніж приступати до розрахунку освітлення, необхідно розрахувати і передати деякі параметри вершин з вершинного шейдера у фрагментний:
- Нормаль до поверхні об'єкта у вершині (normal)
- Напрямок падаючого світла від вершини до джерела освітлення (light direction)
- Напрям погляду, від вершини до спостерігача (view direction)
- Відстань від точкового джерела освітлення до вершини (distance)
Нормаль до поверхні об'єкта та напрям падаючого світла використовуються для розрахунку розсіяного (diffuse) та відбитого (specular) світла, проте для розрахунку відбитого світла необхідно ще додатково знати напрям погляду спостерігача. Відстань від вершини до джерела освітлення необхідна розрахунку загального коефіцієнта згасання (attenuation). Вершинний шейдер при цьому буде таким:
Після розрахунку та передачі необхідних параметрів з вершинного шейдера у фрагмент ми можемо порахувати освітленість кожної точки об'єкта. Для цього використовуємо наступний фрагментний шейдер:
У разі обчислення NdotL ми використовуємо функцію max, щоб відкинути негативні значення скалярного твору dot, таке трапляється, коли точка зовсім не висвітлюється. Якщо цього не зважати на розрахунки розсіяної складової освітлення стають некоректними.