Білборд
- Рішення №1 : 2д спосіб
- Рішення №2 : 3д спосіб
- Рішення №3 : Фіксований 3д розмір
- Рішення №4 : Тільки вертикальний поворот
Білборд це 2д річ в трьохвимірному світі. Не 2д меню поверх всього, не 3д площина, яку Ви можете повертати - це щось проміжне, як “смужка життя” в більшості ігор.
Їх відрізняє те, що вони позиціонуються в визначених місцях, але їх орієнтація розраховується так, що б вони були завжди повернуті лицем до камери.
Рішення №1 : 2д спосіб
Це спосіб дуже простий.
Просто розрахуйте положення на екрані і показуйте 2д текст (дивіться туторіал 11) в цій позиції.
// Все це вже було пояснено в 3 туторіалі. Нічого нового.
glm::vec4 BillboardPos_worldspace(x,y,z, 1.0f);
glm::vec4 BillboardPos_screenspace = ProjectionMatrix * ViewMatrix * BillboardPos_worldspace;
BillboardPos_screenspace /= BillboardPos_screenspace.w;
if (BillboardPos_screenspace.z < 0.0f){
// Об'єкт за камерою, не показуємо.
}
Та-да!
З позитивного - цей метод дуже простий і білборд буде мати одні й тіж розміри не залежно від відстані до камери. Але 2д текст завжди відображається поверх всього іншого і це може/буде спотворювати процес малювання.
Рішення №2 : 3д спосіб
Цей спосіб зазвичай значно кращий і не сильно складніший.
Ціль в тому, що б тримати меш вирівняним по відношенню до камери, навіть коли камера переміщується:
Вми можете бачити проблему в розрахунку правильної матриці моделі, але це все рівно дуже просто.
Ідея в тому, що кожний кут білборда знаходиться в центрі, зміщеного векторами камери вгору на вниз:
Звичайно, ми знаємо тільки позицію центра білборда в світових координатах, тому ми також потребуємо векторів “вгору” та “праворуч” для камери в цих координатах.
В просторі камери вектор вгору це (0,1,0), Для отримання світових координат, просто домножте на матрицю, що перетворює простір камери в світові координати, що насправді є інвертованою матрицею виду.
Ось простий спосіб це зробити:
CameraRight_worldspace = {ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]}
CameraUp_worldspace = {ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]}
Як тільки у нас це є, дуже легко розрахувати кінцеву позицію вершини:
vec3 vertexPosition_worldspace =
particleCenter_wordspace
+ CameraRight_worldspace * squareVertices.x * BillboardSize.x
+ CameraUp_worldspace * squareVertices.y * BillboardSize.y;
particleCenter_worldspace
як видно з імені, позиція центру білборду. Вона вказана в uniform vec3.squareVertices
це оригінальний меш.squareVertices.x
is -0.5 для лівих вершин, які в результаті переміщуються вліво відносно камери (через*CameraRight_worldspace
)BillboardSize
- це розмір в світових координатах білборда, отримується через іншу uniform змінну.
Для запису, ось як squareVertices
отримано:
// VBO містить 4 вершини частинок.
static const GLfloat g_vertex_buffer_data[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
};
Рішення №3 : Фіксований 3д розмір
Як Ви можете побачити вище, розмір білборда змінюється відповідно до відстані від камери. Це очікуваний результат в деяких випадках, але в інших (таких як смужка життя), Ви можете хотіти зафіксувати розмір.
Так як зміщення між центром і межами білборда повинні бути фіксованими в просторі екрану, ось що ми будемо робити - розрахуємо позицію центра в координатах екрану і змістимо їх.
vertexPosition_worldspace = particleCenter_wordspace;
// Отримаємо центр екрана для центру частинки
gl_Position = VP * vec4(vertexPosition_worldspace, 1.0f);
// Тут ми повинні самостійно зробити перспективний поділ.
gl_Position /= gl_Position.w;
// Перемістимо вершину в екранних координатах. Там не потрібні вектори камери.
gl_Position.xy += squareVertices.xy * vec2(0.2, 0.05);
Пам’ятайте, що на цьому етапі малювання, Ви знаходитись в нормалізованих координатах пристрою, тобто в межах -1..1 по обох осях, це не пікселі!
Якщо Вам потрібен розмір в пікселях, це просто - використовуйте (ScreenSizeInPixels / BillboardSizeInPixels)
, а не BillboardSizeInScreenPercentage
.
Рішення №4 : Тільки вертикальний поворот
Деякі системи моделюють далекі дерева і лампи як білборди. Але Ви точно не хочете, що б Ваші дерева були скрученими - вони повинні бути вертикальними. Отже потрібна гібридна система, яка буде повертати тільки навколо однієї вісі.
Але це вже вправа для читача!