Pull to refresh

Comments 14

Примерно по схожей причине, из-за несовершенства графического движка, в старых играх типа Duke Nukem и Doom2 нет больших перепадов высот и этажности зданий.
Вполне себе есть, особенно в сторонних уровнях. Там всего-лишь нельзя увидеть (в думе) или сложно (в дюке) то, что находится под большим углом вниз или вверх.
А ещё Дюку с его портальным движком и этажность проблем не представляла (чего в игре хватало)
В DooM'е, если склероз не врет, не могло быть помещений друг под другом, то есть ни о какой этажности речи не идет, просто разница в высоте.
Так я и указал, что этажность только в Дюке была. В современных портах, кстати, есть и этажность, причём разными способами.
В Дюке да, была, но кривая на тот момент, помню мне в детстве аж голова болела от некоторых искажений из-за несовершенства движка
На КПДВ дым от поезда проходит под стенкой левого тоннеля — после прочтения статьи я знаю куда смотреть :)
Ух ты, точно, полгода на этот дым смотрю и поезда тысячами отправляю, и не видел :) Это можно было бы решить, если верхнюю текстуру тоже разрезать для каждого тоннеля, но будем считать обычные пользователи ничего не заметят :)

Почти все эти проблемы можно было решить, если не присваивать спрайту фиксированную глубину, а, как в 3д, интерполировать её между вершинами спрайта.


zIndex = layerZIndex + pos.x * field.size.width - pos.y

Х и у похожи друг на друга, чем вам не подошло просто z = -(pos.z + pos.x - pos.y)? Для правильного рисования вертикальных элементов можно дополнительно хранить высоту для каждого пикселя, и тогда проблем типа "дерево заслоняет въезд в тоннель, который заслоняет поезд, а поезд заслоняет дерево" вообще не будет. Ну или можно высоту не хранить, просто вершины дерева сделать такими, чтобы оно было реально вертикальным.


С вызовами отрисовки вы что-то намудрили. Если использовать z-координату по назначению, то можно будет рисовать спрайты в произвольном порядке и сгруппировать их по содержанию, и например, за один вызов нарисовать всю землю, (ну будет на ней 1200 полигонов, для видеокарты это совсем не страшно, она и 10 тысяч потянет), ещё одним вызовом — деревья и т.п. (на самом деле, вызовов будет чуть побольше: надо будет включить шейдер, передать видеокарте буфер вершин, установить юниформы и только потом вызывать рисование)

чем вам не подошло просто z = -(pos.z + pos.x — pos.y)

в этом случае как-то еще надо задавать pos.z. Допустим, у меня по слоям именно так и задается (layerZIndex), чтобы рельсы были под поездом, а дым над поездом, временно пренебрежем pos.z. Теперь поясню, почему я умножаю на размер поля. Возьмем две точки (можете смотреть на первую иллюстрацию, ту что не гифка а сетка) с координатами (7,1) и (8,2). По вашей формуле они будут иметь одинаковый z1 = -(7 — 1) и z2 = -(8 — 2), z1=z2=-6 (почему там кстати минус?). В вашем случае их перекрываемость не детерминирована, в моем же позиции по X-координате дается больший «вес», чем по Y-координате и (8,2) будет заведомо «ближе» к камере, чем любая точка с координатой x=7. Изначально я делал именно так как вы описали, так подсказывает логика, но только до первых багов :)
можно дополнительно хранить высоту для каждого пикселя
если такие отрисовки по маске встроены в видеокарту, как например коллизии полигонов в 3d, то будет работать возможно даже быстро. Но в 2d скорее всего такого нет (в SpriteKit точно нет), а такая отрисовка будет тормозить сильнее чем маска если писать вручную. Да и составлять для каждого спрайта вручную карту высоты (а там спрайты каждого куска леса где-то 1000х500, не меньше) — то еще удовольствие. В общем, при всем уважении к вашим статьям и опыту, я понимаю что вы опытный gamedev-разработчик, но в 3d, в 2d есть куча своих сложностей и, как ни странно, во многих вещах 2d тормозит больше 3d
С вызовами отрисовки вы что-то намудрили.
ну и с вызовами отрисовки, возможно, у вас опыт какого-то принципиально другого движка (в 3d, предполагаю, отрисовка более оптимизирована и поверхности рисуются по слоям лучше), а тут абсолютно экспериментально подтверждено — +1 спрайт с иным zPosition дает ровно +1draws, +1draws даже статичного спрайта дает ощутимый минус к fps, а если спрайт еще и движется то на таком разрешении я усаживал iPhone 5 на 30-40 просто движущихся спрайтов с разными zPosition. Я вообще считаю 2d-графику сильно хуже внутри сделанной, чем 3d, а уж обычная иерархия вьюшек даже на айфоне — написана просто убого и страшно с точки зрения производительности.

У нас немного разный подход. Похоже, Вы смотрите на сцену как на холст, на котором можно в каком-то порядке нарисовать спрайты, а я — как на объёмную сцену, на которой можно произвольно располагать и поворачивать прямоугольники с картинками.


Возьмем две точки (можете смотреть на первую иллюстрацию, ту что не гифка а сетка) с координатами (7,1) и (8,2). По вашей формуле они будут иметь одинаковый z1 = -(7 — 1) и z2 = -(8 — 2), z1=z2=-6 (почему там кстати минус?). В вашем случае их перекрываемость не детерминирована...

Да, эти две точки будут иметь одинаковую глубину. И это логично. Если нарисовать множество точек с одинаковой глубиной, то получится горизонтальная прямая. Перекрываться точки они не будут, так как они находятся в разных частях экрана. А вот спрайты — да, могут перекрываться. Как вариант, можно ещё попробовать в нарисовать спрайты с точностью до пикселя, чтобы не было перекрытий или сделать так, чтобы перекрывающиеся части выглядели одинаково. Ну или сделать Вашим сопособом. Минус — типа при меньшей z координате объект становится ближе.


в 2d есть куча своих сложностей и, как ни странно, во многих вещах 2d тормозит больше 3d

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


+1 спрайт с иным zPosition дает ровно +1draws, +1draws даже статичного спрайта дает ощутимый минус к fps, а если спрайт еще и движется то на таком разрешении я усаживал iPhone 5 на 30-40 просто движущихся спрайтов с разными zPosition.

Это уже борьба с особенностями движка начинается. Похоже, его разработчики не планировали рисовать такое большое количество спрайтов. Если смотреть с точки зрения железа, то 600 спрайтов — не предел.


Например, в советах к Unreal Engine пишут:


Triangle count of the entire scene should be <=500k for any view. This has been determined to be the maximum poly count that can hit 30fps on both iPad4 and iPad Air.

Лично мне цифра в 500 тысяч треугольников на сцене кажется слишком большой и более реальным выглядит ограничение в 50-100 тысяч. В любом случае, это на пару порядков больше, чем нужно для рисования шестисот прямоугольников.

Все так, я смотрю именно как на холст, на котором при помощи ухищрений создается иллюзия 3d, а по-другому 2d игры и не работают, можно конечно повернуть спрайт и тут, но что ж это будет за плоское дерево такое :) А если использовать уже ваши подходы в моделированию настоящего 3d-пространства, мы уже выйдем за рамки 2d и будем изобретать Unreal Engine вместо того, чтобы повторить некоторые фишки движка, скажем, Age of Empires 2.

Про горизонтальную прямую почти согласен, но и тут не забывайте что в псевдо-3d не аксонометрия, с которой вы привыкли работать в 3d, а изометрия, так что тут не работают законы перспективы и использовать честные 3d-подходы не всегда целесообразно, да и надо ли — согласитесь, игрушка выглядит как красивое 2d из времен AoE2, только в ретине, а я именно этого и добивался.

По поводу количества же полигонов — я всегда удивлялся, как видеокарты, которые рисуют такие миры в 3d, дохнут от 2d-игрушек и чтобы даже обеспечить плавный скролл в не самом примитивном лэйауте нужно знатно попотеть. Поэтому эмиттер частиц, для которого я думаю в видеокарте куча отдельных конвейеров, она рисует на ура, а 50-60 одновременно движущихся, пусть линейно, спрайтов — уже ложат fps даже на 6 айфоне
Может быть я глупость спрошу, но почему бы не собрать сцену в памяти, и не отрисовать ее разом, как один большой спрайт, вместо того, что бы выводить поочередно все несколько сотен спрайтов?
На это есть несколько причин:
— Объекты (например поезда) движутся относительно сцены, поэтому они должны быть на разных z-позициях и объекты сцены должны быть разными спрайтами
— видеокарта iPhone 5 не держит текстур размером больше где-то 1.5к х 1.5к, так что их приходится резать на несколько частей

А вообще все, что могло быть слито, я конечно же слил в одну большую текстуру. Отдельными спрайтами сцена представлена только там, где игровые объекты попадают за нее, т.е. деревья, здания, тоннели, рельсы, мосты. Их так много в nodes потому что, например, рельсы — это много одинаковых маленьких спрайтов, но на draws это как раз совершенно не влияет, видюха отлично умеет рисовать много одинаковых спрайтов. Да и много разных умеет в один проход, лишь бы у них был одинаковый zPosition.
Sign up to leave a comment.

Articles