Сканування обличчя Voxel (спрощення сітки, можливо, використання жадібного)


9

Редагувати: Це лише для мого власного досвіду навчання, я не задаю це питання.

Це стосується місцевого двигуна, подібного до Minecraft. Я зберігаю блоки в шматках (16x256x16 блоків в шматку). Коли я генерую шматок, я використовую кілька процедурних прийомів для встановлення місцевості та розміщення предметів. Під час генерації я зберігаю один 1D масив для повного блоку (суцільного чи ні) та окремого 1D масиву суцільних блоків.

Після покоління я повторюю суцільні блоки, перевіряючи своїх сусідів, тому генерую лише обличчя блоків, у яких немає суцільних сусідів. Я зберігаю, які обличчя потрібно генерувати у своєму власному списку (це 6 списків, один на можливе обличчя / нормальний). Під час візуалізації фрагменту я рендую всі списки в поточному відрізку камери та лише списки, спрямовані до камери, у всіх інших фрагментах. Я роблю це, зберігаючи всі 6 списків в одному буфері, після чого я просто змінюю діапазони, які малюю.

Використовуючи 2D атлас з цим маленьким шейдерним трюком, який запропонував Ендрю Рассел, я хочу повністю об'єднати подібні обличчя разом. Тобто, якщо вони знаходяться в одному списку (однаковий звичайний), примикають один до одного, мають однаковий рівень освітлення і т. Д. Я знаю, що все одно закінчусь прямокутниками, але це може легко зменшити кількість вершин на 50% або краще, якщо мої оцінки правильні.

Моє припущення полягає в тому, щоб кожен з 6 списків був відсортований за віссю, на якій вони опираються, а потім за іншими двома осями (список у верхній частині блоку буде відсортований за значенням Y, потім X, Z).

Тільки за допомогою цього я міг би досить легко об'єднати смужки обличчя, але я прагну об'єднати більше, ніж просто смужки разом, коли це можливо. Я читав цей жадібний алгоритм обміну повідомленнями, але у мене виникають багато проблем з його розумінням.

Отже, моє запитання: виконувати злиття граней, як описано (ігноруючи, чи це погана ідея для динамічного рельєфу / освітлення), чи є, можливо, алгоритм, який простіше реалізувати? Я б також із задоволенням прийняв відповідь, яка розглядає мене через жадібний алгоритм набагато простішим способом (посилання чи пояснення).

Я не проти незначного зниження продуктивності, якщо це легше здійснити або навіть якщо це лише трохи краще, ніж просто робити смужки. Я хвилююся, що більшість алгоритмів зосереджуються на трикутниках, а не на квадратиках та використовують 2D атлас таким, яким я є, я не знаю, що я міг би реалізувати щось трикутник на основі моїх нинішніх навичок.

PS: Я вже збиваю зріст за шматок, і як описано, я також зрізую обличчя між суцільними блоками. Я ще не оклюзію, і ніколи.

* Редагувати: Я реалізував свою власну маленьку техніку, яка, ймовірно, має назву, але я просто проходжу свої 6 списків, відсортованих за осями, на яких вони опираються, за типом блоку, а потім за рівнем освітлення. Я повторюю їх, створюючи нові прямокутники, коли я йду, і вирощую їх одночасно (з великим ухилом до певної осі). Це, безумовно, не є оптимальним, але він дуже швидкий, і це знижує кількість вершин у середньому на 50%. Коментар Byte56 - це шафа, яку я вважаю справжньою відповіддю, але я не можу вибрати її для відповіді / щедрості.

Ось мій швидкий і спрощений спосіб вирішення цієї проблеми ПІСЛЯ генерування повного початкового рельєфу без особливої ​​оптимізації. Якщо припустити, що всі задані квадрати - це одне і те ж зображення, рівень освітлення, нормальний тощо. Кожен колір - це інший квадратик, який я б представляв. З моїми списками, відсортованими таким чином, як вони є, це дуже простий / швидкий підхід.


Після всіх ваших оптимізацій ви все ще стикаєтеся з проблемами продуктивності? Ви спробували профайлювати код, щоб побачити, де проблеми?
MichaelHouse

@ Byte56 О, це, безумовно, зовсім не проблема продуктивності. Можливо, це буде в майбутньому, коли я намагаюся поставити те, що я вчу, використовувати для реальної гри. Поки що я просто хочу вчитися. Я нічого не заявив про це, тому що я, мабуть, отримую менше допомоги, якщо просто хочу навчитися речам просто навчитися їх.
Mythics

Я відчуваю, що я також повинен сказати, що якщо я дійсно намагаюся зробити належну гру з цим, я хочу, щоб видимий світ був ВЕЛИЧЕЗНИМ. Я не хотів би, щоб персонаж був 2 блоки високими і 1 блок шириною, як Minecraft та багато інших, але більше схожий на 3 блоки шириною / довгою та 6-9 висотою. Напевно, статична місцевість, хоча.
Mythics

1
Ах, добре Тім. Дякую за пояснення. Я провів деякі дослідження цього, коли я робив двигун для своєї гри. Оскільки мій пейзаж динамічний, я не думав, що варто коштувати виставу щоразу, коли щось змінюється. Однак у цій статті ви можете знайти деяке використання щодо максимальної проблеми прямокутника. По суті, це алгоритм, про який ви говорите, для об'єднання подібних облич (можливо, не жадібно, але оптимально). Удачі!
MichaelHouse

@ Byte56 Спасибі, я дуже вдячний. Це, безумовно, ближче до того алгоритму, який я шукаю, якщо не на місці. Мені доведеться трохи попрацювати з цим, щоб побачити, чи зможу я отримати один максимальний прямокутник за один пробіг. Я можу трохи заробити це за це, оскільки, думаю, і питання, і детальна відповідь можуть допомогти багатьом іншим у майбутньому.
Міфіки

Відповіді:


4

Ви хочете робити смужки, або, в кращому випадку, прямокутники. Немає інших фігур, які будуть вам вирішувані чи корисні.

Я також хотів би зазначити, що, зберігаючи 6 списків за шматок, ви в будь-який момент ви будете використовувати 5 списків із шматок у кардинальних напрямках і принаймні 3 у кожному другому. Ви витрачаєте час тут, коли відеокарта не тільки може зробити цю оптимізацію за вас, але навіть якщо ви зробили це самостійно, вам було б краще тримати всі обличчя в одному місці і порівнювати нормальне з напрямком до фотоапарат (Research DOT продукт векторів).

Посилання CaptainRedMuff на жадібну мережу, яку ви вже бачили, - це відповідь на вашу проблему. З цього також повинно бути зрозуміло, що ви закінчите сітки "Stripy", але вони ідеально ефективні, і прийти з чимось більш оптимальним буде складніше, і ви заявили, що жадібна сітка вже занадто складна.

Якщо у вас виникають проблеми з роботою з одним куском, це змушує мене думати, що щось інше сильно не так.

Першим моїм припущенням буде те, що ви занадто часто викликуєте операцію малювання. Ви можете лише сказати графічній карті, щоб вона малювала від 50 до 400 ~ разів за секунду, залежно від обладнання. Скільки дзвінків до .setData або .draw ____ Примітивів ви робите?


Прямокутники - це те, що я хочу. Byte56 пов’язав алгоритм, набагато простіший у дотриманні, ніж жадібний, але я не можу прийняти коментар як відповідь. Я припускав, що він прокоментував це замість того, що він посилався лише на алгоритм, а не на його пояснення. Я не знаю, що ви маєте на увазі щодо моїх списків. У мене зазвичай 1-2 розіграші на шматок. Мої списки зберігаються в одному буфері за шматок. Я змінюю діапазони для малювання на кадр. Я можу помилитися, але надсилання непотрібних даних в GPU видається контрпродуктивним. Додатковий розіграш або два за шматок здається кращим, ніж надсилати більше даних в gpu і примушувати їх також скорочувати.
Mythics

У мене немає проблем з продуктивністю. Мені просто подобається вчитися цим речам. Я відредагую своє питання, щоб сказати це, але, як я також сказав Byte56, я отримую менше допомоги, якщо те, що я намагаюся зробити, насправді не вирішує проблему. Щоб відповісти на ваше запитання, я нараховую щонайменше 200-260 фрагментів на кадр. Це досить поширені 500ish DrawIndexedPrimitive на кадр. Я регулярно отримую 100-130 FPS без vsync, роблячи 65000 дзвінків в секунду. Я не намагаюся бути грубим, але мало, що ти сказав, має для мене сенс. Я, можливо, не розумію, тому, будь ласка, розкажіть, якщо я неправильно зрозумів. Може, це стосується XNA?
Міфіки

Ах, вибачте, я мав на увазі сказати за кадр, а не за секунду. Ви наближаєтесь до верхньої межі там, і якщо ви лише на місцевості, ви майже закінчилися.
Філ

Я поставив +1 вашій відповіді, оскільки це зробило мене думкою про декілька вдосконалень, які я міг би внести, але нічого спільного з цим питанням. Крім того , я думав , що я повинен поділитися відповідь від Nathan Ріда про можливу граничної виклик відтворення лінії
Mythics

Мені доведеться знайти прочитану статтю, в якій цитуються 400-500 як обмеження. Швидкий google мені не допоміг.
Філ

0

Стаття, на яку ви посилаєтесь, насправді не дає алгоритму для створення сітки; в ньому зазначено спосіб оцінки можливих рішень.

Однак, як правило, стаття дає хороший підсумок: 1) наївне рішення є поганим; 2) є оптимальне рішення, але писати та бігати потрібно багато часу, 3) швидке відмовлення дає набагато кращі результати ( і це все, що робить Minecraft) і, нарешті, 4) може бути розумніше рішення (жадібний алгоритм).

«Рішення», яке ви маєте на увазі в образі у вашому запитанні, - жадібний алгоритм. Здається, ваше питання полягає в тому, "чи правильно я реалізував його рішення?" на що я повинен відповісти: "він не дав рішення; ви просто вирішили це самі".

Чи може ваше рішення бути кращим? Мех. Звичайно. Напевно, не варто. Я думаю, що відключення оклюзії або ЛПЗ буде кращими наступними кроками. Minecraft витрачає велику кількість циклів, малюючи поверхню навіть під землею, а також малюючи широкі мережі печерних та шахтних систем, коли ви знаходитесь на поверхні. Після того, як ви отримаєте гарну розбивку сітки, так, позбавлення від затемнених поверхонь може стати хорошою справою - але (наприклад, як правило, швидше дозволити вашій відеокарті робити відкидання фонової поверхні, ніж робити це на процесорі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.