sunLoadingImage
whowedImag
decoration left 1
decoration left 2
transhome
transprojects
transgallery
transarticles
decoration rigth
English
Українська
Show/Hide search bar
black cat logo variable logo
[25 Лип 2012]

Просунуті моделі освітлення

Освітленню по Бліну-Фонгу не вистачає реалістичності. Головною проблемою є те, що освітлення об'єкта не залежить від навколишніх об'єктів: заповнююче освітлення є константним, не розраховується зміна кольору променів світла після відбиття від інших об'єктів, відсутні джерела світла з неточковим розміром і тд. В цьому уроці будуть розглянуті інтерактивні методи для більш точної апроксимації заповнюючого, дифузного та відбитого освітлення, ніж в моделі Бліна-Фонга: півкульне освітлення (hemisphere lighting), освітлення базоване на кубічних текстурах (image-based lighting), а також використання сферичних гармонік (spherical harmonics).
Півкульне освітлення (hemisphere lighting)
Півкульне освітлення використовується для додаткової апроксимації заповнюючого освітлення у сценах, де є явно вираженими два кольори освітлення. Наприклад, сцена під відкритим хмарним небом, де згори об'єкт освітлюється променями світла сіруватого кольору, а знизу відбитими від трави променями світла зеленуватого кольору. Проста модель Бліна-Фонга використовує константне значення для заповнюючого освітлення, і не може відтворити такого ефекту. На зображені показано освітлення об'єктів тільки з допомогою півкульного освітлення, де один колір відповідає кольору неба, а інший - кольору трави.
Півкульне освітлення
Колір кожного фрагмента в півкульному освітленні залежить тільки від орієнтації нормалі у фрагменті (у просторі сцени). Якщо нормаль співпадає за напрямом з орієнтацією верхньої півкулі, то фрагмент буде мати колір неба (отримувати колір тільки від верхньої півкулі). Якщо напрям нормалі повністю протилежний орієнтації верхньої півкулі, то колір буде відповідати кольору трави (колір тільки від нижньої півкулі). В інших випадках відбувається інтерполяція між кольорами півкуль в залежності від того, наскільки нормаль орієнтована до верхньої і до нижньої півкулі. Якщо нормаль перпендикулярна напряму до верхньої півкулі, то колір фрагмента формується як половина кольору неба, і половина кольору землі.
Обєкт і півкулі в півкульному освітленні
Головною проблемою моделі є те, що не враховується самозатінення: частини моделі, які орієнтовані до верхньої півкулі, але знаходяться внизу об'єкта, будуть всерівно освітлені кольором верхньої півкулі, хоч і закриті від верхньої півкулі іншими частинами об'єкта.
Вершинний шейдер для півкульного освітлення:
#version 330

// атрибути
layout(location = 0) in vec3 i_position; // xyz - position
layout(location = 1) in vec3 i_normal; // xyz - normal

// матриці
uniform mat4 u_modelViewProjectionMat;
uniform mat3 u_normalMat;

// параметри півкульного освітлення
uniform vec3 u_topHemisphereDirection;
uniform vec3 u_skyColor;
uniform vec3 u_groundColor;

// дані для фрагментного шейдера
out vec3 o_color;

///////////////////////////////////////////////////////////////////

void main(void)
{
   // нормаль в світові координати
   vec3 N = normalize(u_normalMat * i_normal);
   // косинус між нормаллю і напрямом до верхньої півкулі
   // 1 - нормаль орієнтована точно до верхньої півкулі
   // -1 - нормаль орієнтована точно до нихньої півкулі

   float NdotL = dot(N, u_topHemisphereDirection);
   // перевести з [-1, 1] до [0, 1]
   float lightInfluence = NdotL * 0.5 + 0.5;
   o_color = mix(u_groundColor, u_skyColor, lightInfluence);

   // розрахунок екранної позиції вершини
   gl_Position = u_modelViewProjectionMat * i_position;
}
Фрагментний шейдер для півкульного освітлення:
#version 330

// колір з вершинного шейдера
in vec3 o_color;

// колір у фреймбуфер
out vec4 resultingColor;

void main(void)
{
   resultingColor.xyz = o_color;
   resultingColor.a = 1;
}
Освітлення базоване на зображеннях (image-based lighting)
Дані про інтенсивніть та колір освітлення навколо об'єкта можна зберегти в кубічну текстуру. Кубічні текстури дозволяють зберегти дані про все освітлення навколо об'єкта: багато джерел світла, джерела світла різної форми, кольори об'єктів, що оточують і відбивають світло, а також об'єкти, які затуляють собою джерела освітлення. Стандартна модель освітлення Бліна-Фонга не може врахувати і малої частини цих деталей. При цьому для отримання кольору освітлення в освітлені базованому на зображеннях необхідно провести тільки одну чи дві вибірки з кубічної текстури. Приклад освітлення наведений на наступному зображенні.
Освітлення обєктів методом базованим на зображеннях
Вибірка з кубічних текстур освітлення здійснюється через нормаль N у фрагменті (для заповнюючого і дифузного освітлення), і через відбитий вектор погляду V відносно нормалі N (для відбитого освітлення).
Для дифузного та заповнюючого освітлення можна використати одну кубічну текстуру. Друга кубічна текстура потрібна для збереження інформації про відбите освітлення.
Кубічні текстури зі збереженим освітленням можна отримати з фотографій реального простору, а можна використати рендерінг сцени в кубічну текстуру. Але не все так просто. Дифузне та заповнююче освітлення формується променями світла з усіх сторін півкулі простору, яка орієнтована вздовж нормалі поверхні. Але в кубічній текстурі зробленій з фотографій чи рендера сцени збережено точне освітлення з кожного напряму. Потрібно знайти колір та інтенсивність освітлення з врахуванням половини кольорів з початкової кубічної текстури для кожного текселя кубічної текстури освітлення.
Початкова кубічна текстура, і дві кубічні текстури розмиті фільтром різного радіуса
Але це неможливо зробити в шейдері при збережені швидкодії (необхідна величезна кількість вибірок з кубічної текстури для кожного фрагмента). Потрібно з початкової кубічної текстури розрахувати розмиту текстуру, кожен тексель в якій буде усередненим зваженим значенням усіх інших текселів з відповідної частини початкової кубічної текстури. Приклади розмитих кубічних текстур показані на зображенні. Такі розмиті текстури підійдуть для дифузного та розсіяного освітлення. Для збереження деталей в дифузному освітленні можна враховувати не цілу півкулю значень при розмитті, а, наприклад, тільки напрямки з відхиленням від нормалі до 45 градусів. Для дзеркального освітлення потрібно врахувати меншу кількість значень навколо текселя, а не усі фрагменти півкулі, так як дзеркальне освітлення утворюється тільки відбитими напрямленими променями світла. Підійде усереднення значень з відхиленням від нормалі на 1-10 градусів. Також для різних матеріалів можуть бути необхідні різні рівні розмиття кубічної текстури, в залежності чи матеріал є повністю дзеркальним, чи розмиває відображення.
В наступному уроці показується як з допомогою шейдерів зробити розмивку кубічної текстури як з врахуванням цілої півкулі простору для кожного текселя, так і з врахуванням невеликої кількості текселів навколо напряму. Цей процес можна порівняти з розмиттям двовимірної текстури через фільтр розмиття Гауса.
Так як розмиті текстури не містять високочастотних деталей, то розмір розмитих текстур може бути меншим ніж розмір оригінальних текстур. Для заповнюючого освітлення можна використати текстури з розміром 8-16 текселів. Для дифузного освітлення підійдуть текстури з розміром грані в 32-64 текселя. Для відбитого освітлення можна використати текстури розміром грані в 128 текселів.
Освітлення базоване на зображеннях є хорошим для статичних сцен, для яких можна розрахувати текстури освітлення, і вони не будуть змінюватися. Для динамічних об'єктів потрібно оновляти текстури освітлення при кожному русі об'єкта. Але розмиття текстур освітлення не розраховується в реальному часі. В багатьох випадках текстури освітлення не оновлюються доки не станеться великих змін в сцені. Також розмивку текстури може розраховуватися через обробку тільки малої частини кубічної текстури, а не усіх текселів півкулі.
Вершинний шейдер для освітлення базованого на зображеннях:
#version 330

// атрибути
layout(location = 0) in vec3 i_position; // xyz - position
layout(location = 1) in vec3 i_normal; // xyz - normal
layout(location = 2) in vec2 i_texcoord0; // xy - texture coords

// матриці
uniform mat4 u_modelMat;
uniform mat4 u_viewProjMat;
uniform mat3 u_normalMat;

// позиція камери
uniform vec3 u_cameraPosition;

// дані для фрагментного шейдера
out vec3 o_normal;
out vec3 o_cameraVector;

///////////////////////////////////////////////////

void main(void)
{
   // позиція в світових координатах
   vec4 worldPosition = u_modelMat * vec4(i_position, 1);
   // нормаль в світових координатах
   o_normal = normalize(u_normalMat * i_normal);
   // напрям до камери
   o_cameraVector = normalize(u_cameraPosition - worldPosition.xyz);
   // розрахунок екранної позиції
   gl_Position = u_viewProjMat * worldPosition;
}
Фрагментний шейдер для освітлення базованого на зображеннях:
#version 330

// дані з вершинного шейдера
in vec3 o_normal;
in vec3 o_cameraVector;

// текстури освітлення
layout(location = 0) uniform samplerCube u_ambientTexture;
layout(location = 1) uniform samplerCube u_diffuseTexture;
layout(location = 2) uniform samplerCube u_specularTexture;

// колір у фреймбуфер
out vec4 resultingColor;

//////////////////////////////////

void main(void)
{
   vec3 N = normalize(o_normal);
   // відбитий відносно нормалі вектор погляду
   vec3 R = normalize(reflect(normalize(-o_cameraVector), o_normal));

   // дістати інтенсивності різних компонентів освітлення
   vec3 ambLighting = texture(u_ambientTexture, N).rgb;
   vec3 difLighting = texture(u_diffuseTexture, N).rgb;
   vec3 speLighting = texture(u_specularTexture, R).rgb;

   // комбінація компонентів освітлення
   resultingColor.xyz = ambLighting * 0.4 + difLighting * 0.6 + speLighting * 0.4;
   resultingColor.a = 1;
}
Сферичні гармоніки (Spherical harmonisc)
Сферичні гармоніки можуть використовуватися для апроксимації дифузного та розсіяного освітлення. Цей метод дозволяє в реальному часі без використання кубічних текстур досягти якості дифузного освітлення, як в дифузному освітлені базованому на зображеннях (image-based lighting), де кожен тексель в кубічній текстурі освітлення враховує освітлення з півкулі простору, орієнтованої вздовж напряму, якому відповідає тексель. Похибка між результатами досягнутими через розмиті кубічні текстури та використанням сферичних гармонік є незначною. Параметри кубічної гармоніки можна розрахувати і зберегти з кубічних текстур. Приклад використання сферичних гармонік наведений на зображенні.
Сферичні гармоніки для симуляції дифузного освітлення
Сферичні гармоніки представляють собою проекцію освітлення в частотний простір на сфері. Метод можна розглядати як аналітичну BDRF, коефіцієнти якої задають скільки освітлення надходить з різних сторін простору. Значення освітлення розраховується через комбінацію значень базисних функцій сферичної гармоніки. Базисні функції сферичних гармонік групуються в смуги. Чим більший номер смуги, тим більш високочастотні деталі здатні представити базисні функції смуги. На зображені показано кубічну текстуру з якої розраховуються кубічні гармоніки (перша сфера знизу), перші три смуги кубічних гармонік та комбінацію смуг гармонік (перша сфера зверху), яка і є апроксимацією дифузного освітлення з усіх сторін простору.
Початкова кубічна текстура, смуги сферичних гармонік та лінійна комбінація сферичних гармонік
Смуга з номером 0 містить одну константну базисну функцію. Ця функція не залежить від орієнтації в просторі і є аналогом константного розсіяного освітлення. На зображені це сфера (друга знизу), яка зафарбована в сірий колір.
Смуга з номером 1 містить три лінійні базисні функції. Кожна функція є орієнтованою вздовж однієї з осей X, Y чи Z. При розрахунку освітлення, наприклад, для функції орієнтованої вздовж Y, базисна функція визначає наскільки освітлення з напряму +Y є більшим за освітлення з напряму -Y. Зазвичай це значення є близьким до 1 та додатнім, так як більшість сцен є більш освітленими зверху. На зображені це три сфери (треті знизу). Можна побачити, що кожна з трьох функцій дістала з початкової кубічної текстури колір, який відповідає освітленню зі сторони осей X, Y і Z.
Смуга з номером 2 містить п'ять квадратичних базисних функцій. Функції не є орієнтованими вздовж якоїсь з осей, але визнають освітлення з частин простору, які визначаються комбінацією осей. На зображенні це пять сфер (четверті знизу).
Смуги з більшими номерами визначають ще більш високочастотні деталі ніж смуга 2, але використовуються рідко для апроксимації дифузного освітлення.
Сферичні гармоніки (а саме частини простору для яких визначає освітлення кожна базисна функція) можна візуалізувати з допомогою сфер. Сфера маштабується вздовж нормалі через абсолютне значення функції в точці. В залежності від знаку функції вибирається червоний чи синій колір. Приклад показано на зображенні. Червоними є місця, які стають освітленими при додатньому значенні базисної функції гармоніки, а сині при від'ємному. На зображенні показаний приклад (без маштабування вздовж нормалі).
Області на які ділять простір базисні функції сферичних гармонік
В наступних прикладах використовуються перші три смуги сферичних гармонік для налаштування яких необхідно 9 коефіцієнтів (по одному для кожної базисної функції). Коефіцієнти можуть бути розраховані з кубічних текстур в яких збережено освітлення чи можуть бути підібрані вручну в редакторі сферичних гармонік. Далі коефіцієнти використовуються в шейдері для реконструкції освітлення.
Сферичні гармоніки перших трьох смуг дозволяють відновлювати тільки низькочастотне освітлення, тобто якраз таке, яке потрібно для дифузного і розсіяного освітлення. Для симуляції розмитого відбитого освітлення, можна використати сферичні гармоніки вищого рівня, які дозволяють зберегти більш високочастотні деталі освітлення. Для симуляції чіткого відбитого освітлення сферичні гармоніки не підходять.
Коефіцієнти сферичних гармонік можна налаштовувати вручну. Роблячи коефіцієнт базисної функції ближчим до одиниці та додантім, освітлюється частина об'єкта, яка відповідає додатній частині простору (на попередньому зображенні це червоні частини сфер). Значення 0 відповідає однаковій освітленості обох частин простору, і не додає освітлення. Від'ємні значення коефіцієнта будуть призводити до освітлення відємних частин простору (синіх на зображенні).
Коефіцієнти сферичних гармонік розраховуються окремо для кожного RGB каналу. Тобто потрібно 9 vec3 значень для правильної роботи шейдера. Крім коефіцієнтів (l) сферичних гармонік для відновлення освітлення застосовують константні значення (c), які змінюють вплив різних смуг сферичних гармонік, загальне значення маcштабування інтенсивності освітлення (s) та нормаль в точці поверхні об'єкта (N). Відновлення освітлення можна розраховувати в вершинному шейдері, так як перші три смуги сферичних гармонік не містять високочастотних деталей, які могли б зникнути при їх інтерполяції від вершинного до фрагментного шейдера.
Перевагою сферичних гармонік є те, що необхідно тільки один раз обробити усі текселі кубічної текстури для розрахунку коефіцієнтів сферичних гармонік. Для розмиття кубічної текстури в освітленні базованому на зображеннях (image-based lighting) необхідно для кожного текселя вихідної текстури перебрати половину усіх текселів вхідної текстури. Тобто під час виконання програми обрахувати коефіцієнти сферичних гармонік можна набагато швидше.
Також замість збереження інформації про освітлення в кубічних текстурах, можна зберігати коефіцієнти сферичних гармонік. Якщо необхідно використовувати в шейдері кубічну текстуру, то сферичну гармоніку можна відрендерити в кубічну текстуру з допомогою шейдера, що відновлює освітлення з сферичних гармонік, сфери та камери всередині сфери.
Для отримання сферичних гармонік з кубічної текстури необхідно провести проекцію значень кубічної текстури на базисні функції сферичних гармонік. Це можна зробити числовими методами через обрахунок базисних функцій сферичної гармоніки в напрямку кожного текселя кубічної текстури. Приклад розрахунку сферичної гармоніки з кубічної текстури наведений в наступному уроці.
Також для сферичних гармонік визначені багато операції, серед яких:
  • додавання - додавання двох різних сферичних гармонік (комбінація освітлення)
  • маcштабування - лінійна інтерполяція між різними сферичними гармоніками
  • поворот - поворот сферичних гармонік, що інтерпретується як поворот освітлення. Також для симуляції повороту сферичних гармонік у просторі можна розвертати нормаль в точці поверхні (у напрямі протилежному необхідному повороту освітлення)
  • Вершинний шейдер для реконструкції дифузного освітлення з коефіцієнтів сферичних гармонік:
    #version 330

    // атрибути
    layout(location = 0) in vec3 i_position; // xyz - position
    layout(location = 1) in vec3 i_normal; // xyz - normal

    // матриці
    uniform mat4 u_modelViewProjMat;
    uniform mat3 u_normalMat;

    // дані для фрагментного шейдера
    out vec3 o_color;
    out vec3 o_normal;

    // константи, які використовуються для відтворення освітлення
    const float C1 = 0.429043;
    const float C2 = 0.511664;
    const float C3 = 0.743125;
    const float C4 = 0.886227;
    const float C5 = 0.247708;

    // масштабування відтвореної інтенсивності світла
    uniform float u_scaleFactor;

    // коефіцієнти сферичних гармонік і приклад можливих значень значення
    uniform vec3 u_L00; // vec3(0.79, 0.44, 0.54);
    uniform vec3 u_L1m1; // vec3(0.39, 0.35, 0.60);
    uniform vec3 u_L10; // vec3(-0.34, -0.18, -0.27);
    uniform vec3 u_L11; // vec3(-0.29, -0.06, 0.01);
    uniform vec3 u_L2m2; // vec3(-0.26, -0.22, -0.47);
    uniform vec3 u_L2m1; // vec3(-0.11, -0.05, -0.12);
    uniform vec3 u_L20; // vec3(-0.16, -0.09, -0.15);
    uniform vec3 u_L21; // vec3(0.56, 0.21, 0.14);
    uniform vec3 u_L22; // vec3(0.21, -0.05, -0.30);

    ///////////////////////////////////////////

    // функція проводить відтворення освітлення по нормалі в точці і
    // через коефіцієнти сферичних гармонік

    vec3 sphericalHarmonics(vec3 N)
    {
       return
          // смуга 0, найнижча частота
          C4 * u_L00 +

          // смуга 1, орієнтована вздовж осей
          2.0 * C2 * u_L11 * N.x +
          2.0 * C2 * u_L1m1 * N.y +
          2.0 * C2 * u_L10 * N.z +

          // смуга 2, значення залежать від декількох осей
          C1 * u_L22 * (N.x * N.x - N.y * N.y) +
          C3 * u_L20 * N.z * N.z - C5 * u_L20 +
          2.0 * C1 * u_L2m2 * N.x * N.y +
          2.0 * C1 * u_L21 * N.x * N.z +
          2.0 * C1 * u_L2m1 * N.y * N.z;
    }

    void main(void)
    {
       // нормаль в світові координати
       vec3 N = normalize(u_normalMat * i_normal);
       // розрахувати дифузне освітлення через сферичні гармоніки
       o_color = sphericalHarmonics(N) * u_scaleFactor;
       // розрахувати екранну позицію вершини
       gl_Position = u_modelViewProjMat * vec4(i_position, 1);
    }
    Фрагментний шейдер для освітлення через сферичні гармоніки:
    #version 330

    // дані з вершинного шейдера
    in vec3 o_color;

    // колір у фреймбуфер
    out vec4 resultingColor;

    void main(void)
    {
       // просто вивід кольору
       resultingColor.rgb = o_color;
       resultingColor.a = 1;
    }
    Кожна з розглянутих моделей освітлення може використовуватися як заміна чи доповнення до стандартної моделі затінення.
    Для динамічних об'єктів потрібно обновляти параметри освітлення в залежності від позиції об'єктів. Або можна використовувати різні текстури/кольори/коефіцієнти для різних частин сцени, наприклад, для різних кімнат створюються окремі параметри освітлення. Перед відображенням об'єкта розраховується, які параметри є найближчими до об'єкта. Також можуть використовуватися декілька різних наборів параметрів, які інтерполюються в залежності від відстані об'єкта до позицій в яких визначені параметри. Для збільшення реалістичності можна створити двовимірну чи тривимірну сітку з параметрів освітлення у просторі, і для кожного об'єкта визначати, які параметри використовувати, в залежності від позиції об'єкта.
    Мінусом усіх розглянутих методів є нехтування тим, що частина об'єкту освітлюється навіть коли повинна бути самозатінена.



    Sun and Black Cat- Ігор Дихта (igor dykhta email) © 2007-2014