Принцип побудови тіней досить простий. Все, що видно з позиції джерела світла, то освітлено, решта ж перебуває в тіні.
Принцип роботи можна розділити на два етапи:
1. Збереження в текстуру глибини сцени з позиції джерела світла. Таку текстуру називають shadow map.
2. Рендер сцени з тінями, з використанням даних, отриманих на першому етапі.
У прикладі статті ці два етапи винесені в окремі функції RenderToShadowMap () і RenderShadowedScene ().
У прикладі буде використано два варіанти рендеринга тіней, що відрізняються реалізацією. Відмінність варіантів полягає в тому, що в першому випадку ми глибину будемо зберігати в текстуру за допомогою шейдера і при накладенні тіні на сцену робити порівняння з текстурою вручну. У другому випадку рендер проводиться відразу в текстуру глибини без участі шейдеров в цьому процесі, а для порівняння використовується режим порівняння текстури, що звільняє нас від ручного порівняння в шейдера.
Ініціалізація шейдеров і моделі тривіальна, ви можете в них розібратися самостійно, тому описувати її не буду. А ось ініціалізацію текстур варто описати докладніше.
Почнемо з розгляду обох варіантів рендеринга тіней:
Варіант # 1: Прикріпити текстуру до FBO як буфер кольору. Для тесту глибини використовуємо рендер-буфер.
У цьому випадку нам доведеться проводити запис глибини за допомогою шейдера. Плюс полягає в тому, що ми можемо записувати глибину так, як нам заманеться. Чи можемо зберігати щось ще, крім глибини, в інші компоненти текстури, якщо вона у нас не однокомпонентна.
Варіант # 2: Прикріпити текстуру до FBO як буфер глибини. Буфер кольору не використовується.
Тут нам вже не потрібен шейдер, щоб зберегти глибину. Просто Рендер сцену.
Обидва варіанти мають як свої плюси, так і мінуси.
Ініціалізація для варіанту # 1
Почнемо з ініціалізації для варіанту # 1. Створимо текстуру, яка буде прикріплена як буфер кольору:
Я думаю, деяких пояснень вимагає використовуваний формат текстури.
Почнемо з битности. Чим нижче бітность, тим нижче точність. Тому, при малих бітах, більше уваги варто приділити площинах відсікання, потрібно ближню і дальню площині розташувати якомога ближче до сцени, особливо ближню. Інакше можуть з'явиться неприємні артефакти через брак точності. В даному прикладі я буду використовувати 16 біт. Хоча успіхів можна досягти і з 8 бітної текстурою.
Передостанній аргумент type. у функції glTexImage2D (). не має в даному випадку ніякого значення, і типи розставлені для краси.
Тепер створимо рендер-буфер, він нам потрібен для тесту глибини: