Log of Alprog
1.19K subscribers
98 photos
91 links
加入频道
Умер король. Трое наследников поссорились и разделились на 3 страны. Они договорились, что через 3 поколения их правнуки проголосуют, объединяться ли назад в одно королевство или жить дальше отдельно.

В каждой из стран все 3 поколения была постоянная рождаемость (у каждого в стране одинаковое количество детей, бездетных нет). Все правнуки дожили до голосования. Жители двух стран были единогласно ЗА, а третьего — ПРОТИВ. И получилась НИЧЬЯ.

Злые языки шепчут, что обязательно был инцест. Докажите, что это не так.
👍3👎1
👎1
👎1
Тяжёлые выборы #1: чёртовы оси

В разработке своего движка иногда нужно делать такие выборы, которые со стороны кажутся плёвыми и не особо важными, а на деле их не так-то легко и сделать.

Типичный пример — это кодстайл. Любой дурак знает, что не важно, какой он, главное, чтобы он был один и везде. Но обычно такого выбора и нет — мы просто юзаем тот стиль, который уже есть на проекте или в движке. И совсем другое дело, когда перед тобой действительно стоит полная свобода выбора: тебя начинает метать из стороны в сторону, как сумасшедшего. Потому что это повлияет на то, как ты будешь писать код всю дорогу и это будет не данное упавшее свыше, а твоё собственное решение. Хочется сделать удобно, чтобы не жалеть потом.

На самом деле с кодстайлом я до сих пор не определился до конца, но зато, похоже, наконец-то выбрал систему координат. Я трижды менял её, но сейчас, надеюсь, что это уже финальная версия.

1. Изначально я положил XYZ самым привычным для себя образом: Right-Up-Forward. Так было по умолчанию в классическом DirectX, так сделано в Unity и так сейчас у меня на работе (Clausewitz engine). Это также NDC в большинстве GAPI (кроме вулкана), так что это такой крепкий default для 3D.

Но мой движок в первую очередь предназначен для TopDown игр, а Y-up, как известно, не очень для этого подходит. Я уже делал TopDown игру в такой системе координат (Encased на Unity) и это влекло за собой некоторое количество неудобств:

Во-первых, чтобы не заниматься постоянной перестановкой y и z из Vector2 в Vector3 и обратно, боясь рано или поздно опечататься, мне пришлось завести довольно искусственный VectorXZ и использовать везде его. Он абсолютно такой же как Vector2, но с полями xz вместо xy.

Во-вторых, в такой системе координат по-честному вращение вокруг вертикальной оси должно идти по часовой стрелке. Но мы, естественно, пихали z вместо y во все тригонометрические функции и делали вид, что так и надо. У нас всё начинало вращаться против часовой стрелки, как в школьной тетрадке, но вообще это довольно грешноватенько так делать.

2. Первый логический шаг по улучшению ситуацию — это перейти на z-up, как в Blender. VectorXZ больше не нужен. Вращение по честному начинает идти против часовой стрелки. Красота!

Но я не захотел на этом останавливаться. В получившейся схеме меня бесит, что Y-координата моей тайловой карты смотрит на север, и это не совпадает с тем, как работают координаты в TextureSpace и ScreenSpace. Не знаю, как вас, а меня бесят эти бесконечные перевороты текстур по вертикали. Я хочу работать с тайловой картой по правилам GUI: прибавлять Size спрайта целиком в положительную сторону. Потому что когда нужно прибавлять Width, но отнимать Height — это чистой воды дичка.
👍3👎1
3. Чтобы достичь этого, я расположил X на восток, а Y на юг. Получилась довольно упоротая комбинация Right-Back-Up. По крайней мере я никогда такую не встречал. Какое-то время я пытался привыкнуть к такому расположению, но здесь ровно та же проблема, почему я ненавижу систему координат Godot или XNA: Back это положительное направление.

По моему глубокому убеждению, положительными осями должен быть Right, а не Left; Up, а не Down; и особенно, мать твою, Forward, а не Backward. Сколько бы я не смотрел код чуваков, у которых Z+ это back, там всегда какое-то упоротое двоемыслие начинается. То они направление на камеру называют Forward вместо Back, то выворачивают гизмо наизнанку, чтобы синяя палка в негативную сторону смотрела. Словом ты уже не знаешь, чего ждать и кому верить. Да и в целом во всех формулах с участием Z уродский минус появляется, о котором надо постоянно помнить. Лучше его в кодобазу вообще не впускать. Только плюс, только вперёд.

4. И тут (после мучительных качелей туда-сюда), я в итоге пришёл к анриловской схеме Forward-Right-Up. Дефолтное положение камеры становится -90°, но зато исчезает проклятый минус. Бонусом, по умолчанию все объекты становятся ориентированы forward-ом на восток, а не север. Что, типа, более привычно, так как 0° в школьной тетрадке мы рисуем вправо.

Буквально единственный недостаток, который я в этом во всём вижу, это то, что углы будут считаться по часовой стрелке, а не как на уроке математики. Но всё GUI и многие 2D игры зачастую работают с такими углами, и ни у кого жопа не отваливается. Учитывая, сколько других проблем это решает, это довольно малая жертва.
👍12👎1
Иронично, но изначально я считал схему Unreal одной из самых упоротых, но по итогу сам к ней пришел.

Но зато я остался верен более нативной для DX левосторонней системе координат. Как видите, microsoft-бой однажды — навсегда microsoft-бой.

Ну и, кстати, забыл упомянуть одну из самых главных киллер-фич левосторонней системы: я правша. А это значит, что когда у меня в руке мышь, левой рукой гнуть пальцы банально удобнее. Впрочем, надо бы обзавестись распечатанной на 3D-принтере гизмой осей.
👍8👎1
Проблема праворукой системы координат в том, что даже если определиться, какая ось смотрит вверх, там существует ещё куча вариантов с лево/право и вперёд/назад.

Тим Суини на днях твитнул, что Unreal Engine будет переезжать с координат FRU на LUF. Типа, Right-handed Y-up это стандарт в индустрии. Ну не знаю, насколько это прям стандарт. Тем более именно LUF. По мне так лучше уж RUB выбирать. Он вроде чаще используется в приложениях, если ноги из OpenGL растут.

Иронично, но я в своём движке буду занимать квадрат Анрила теперь в одиночку, хе-хе
👍3
Последнее время активно работаю над движком для Crunch House. Пока занимаюсь всякими техническими штуками: Deferred Shading, MSAA, Тени. В планах как минимум ещё TAA, Motion Blur, Bloom, SSAO, SSR. Возможно, для виртуального мира игры эти настройки нужно будет разблокировать по мере улучшения движка, который надо будет создавать в самой игре.

Дошёл вот до создания персонажей. Референс это в первую очередь RimWorld и Prison Architect, но скрещенный с Portal Bridge Construction. То есть я хочу такие же простые 2D-силуэты, но реально торчащие в 3D, с некоторой толщиной и отбрасывающие корректные тени.

Думаю, какой подход подойдёт лучше: либо генерить настоящую геометрию, либо квад с Alpha-To-Coverage.
Настоящая геометрия хорошо подходит для создания туловища, круглой головы и рук. Но вот для всяких пропсов и причёсок генерировать геометрию из изображения не так удобно. Квад с прозрачностью, конечно, сильно проще, но тогда сложнее сделать нормальную толщину. Что думаете?
Тяжёлые выборы #2

С днём, когда моё MS-бойство серьёзно пошатнулось.

Несмотря на то, что я сейчас пишу исключительно под винду и только на DirectX12, я в итоге перешёл во многом на OpenGL конвенции: Right-handed координаты и Bottom-left текстуры.

Да-да, это ещё один пост про чёртовы оси, и я их снова изменил.

Во всех бедах я по-прежнему продолжаю винить Сильвестра Лакруа и прочих составителей учебников по математике 18 века, повадившихся рисовать ось «Y» вверх. Именно они обрекли многие поколения школьников на страдания, всякий раз когда им требуется теперь отступить место для графика в школьной тетрадке.

А ведь у них была историческая возможность развернуть «Y» вниз, и тогда бы это удобно встраивалось в европейское письмо слева-направо и сверху-вниз (а положительные углы шли бы по часовой стрелке). А ведь направление письма сверху-вниз определило ещё и направление скроллинга страницы, и направление обновления монитора, а это, в свою очередь, повлияло и на систему координат большинства графических редакторов и файловых форматов.

Но увы. Они решили направить ось ординат наверх, и это во многом предопределило разброд и шатание по вертикале между DX и GL, между GUI и World Space.

Моя приверженность левосторонней системе координат и TopLeft-текстурам произрастала из приоритета консистентности над математичностью. Мне важно, чтобы мировые координаты росли туда же, куда и текстурные. И чтобы «X» вёл себя точно так же, как и «Y»: нет ничего более раздражающего, чем флип только одного компонента. А поскольку координаты графических редакторов (Paint, Photoshop) это своего рода данность, то я подсознательно выстраивал всё остальное под них.

И до поры до времени я был готов мириться с тем, что это нематематично: ну, подумаешь, повороты в игре будут идти в другую сторону. Задокументировать и забыть. Но я сдался на утилитах для 2D геометрии. Функции типа «площадь под кривой» или «IsClockwise» для многоугольника обычно предполагают, что мы смотрим на оси как принято в математике. Но если в моём движке большую часть времени мы смотрим на оси с обратной стороны (X — вправо, Y — вниз), то либо надо функции переименовывать, либо всегда держать в голове, что их значения перевёрнуты для геймплея. И всегда нужно помнить, где именно инвертировано внутри, а где — предполагается инвертировать на выходе. Это просто невозможный оверхед, который непременно приведёт к путанице, и к тому, что ты сам в какой-то момент перестанешь доверять названиям собственных функций.

Масла в огонь добавило то, что большинство DCC экспортят увишку по умолчанию как Bottom-Left и то же самое предполагает MikkTSpace — по сути стандарт тангент-спейса.

И тут я снова задумался: а такая уж ли данность координаты графических редакторов? Я большую часть жизни использую Paint.Net. Как оказалось, проект давно закрыл исходники, но у него есть open-source клон Pinta. Который, по моему мнению, начиная с версии 2.0 тоже пошёл куда-то не туда, уродуя интерфейс. Но в общем я форкнул себе старую версию Pinta и перевернул там отображаемые координаты. И жить сразу стало веселее.

DirectX я тоже перенастроил так, чтобы он как будто нативно был Bottom-Left. Для этого я переворачиваю текстуры при загрузке и ставлю отрицательную высоту у вьюпорта при рендере-в-текстуру. И получается, что он семплит и рендерит как будто по правилам OpenGL, не нужно ничего флипать в шейдерах. Всё растёт в одном направлении, всё консистентно.

Уж не знаю, делает ли так кто-нибудь ещё: обычно все переворачивают текстуры в OpenGL, чтобы они были как в DirectX, а я вот сделал наоборот всё. В RenderDoc, конечно, всё отображается вверх-ногами, но там, слава богу, есть кнопочка отзеркалить изображение.

А ещё у меня всё ещё Z-up. Надеюсь это менять не буду. Господи, когда же я уже буду игру делать, а не оси вертеть туда-сюда?
🤣18👍6