JMonkeyEngine и пиксельный хаос

Добавлен , опубликован
Меня интересовал мучил интересовал, что можно успеть накодить что-нибудь за обеденный перерыв? Надеюсь теперь и вас будет терзать любопытство, ведь ответа на этот вопрос здесь нет, а есть нечто другое.
Началась эта короткая история с того, что мне захотелось проверить в действии одну занятную идею на счет хранения, передачи и отображения двухмерной поверхности с произвольным пиксельным заполнением.
Не долго думая, идея была дополнена парой свободно распространяемых текстур, 3D движком JmonkeyEngine3.0 и воплощена в простейшую программу, в которой даже камера не двигается.
Если коротко, то формируется двухмерный массив байтов, запекается в текстуру с одним каналом и передается в шейдер вместе с текстурой-атласом, а на выходе мы получаем то, что получаем - текстуру, каждый пиксель которой выбирается с одной из текстур в атласе.
Для модификации состояния "на лету" используется ByteBuffer, на который и завязана промежуточная текстура. Реализованы два способа редактирования - более быстрый на малых операциях, позволяющий изменить состояние конкретного пикселя и более быстрый при массовом редактировании пикселей, позволяющий одной операцией обновить от одного пикселя, до целой строки пикселей.
В тестовом сценарии используется итоговая текстура 2048*2048 пикселя с разбиением на 256 элементов, при размерах окна 1024*768.
Об оптимизации и практическом применении этого добра еще предстоит подумать, но первое что приходит на ум - 2д-платформер с полной разрушаемостью рельефа до отдельного пикселя.
P.S. На самом деле, приведенные выше результаты были получены хоть и за соизмеримое время, но не в результате кодинга на обеденном перерыве и потому не считаются.
P.P.S. Сжатие скриншота в jpeg несколько приукрасило картинку - на практике никакой тени на границе земли и неба не наблюдается, но получилось неплохо, так что я обязательно возьму этот эффект на вооружение.
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
24
10 лет назад
Отредактирован prog
0
Добавил передвижение камеры (немного странное, на QZAD т.к. лень было контроллер камеры свой писать) и столкнулся с неожиданным поведением смешивающего текстуры шейдера на определенном железе. В связи с чем, выкладываю текущую версию в надежде что кто-то её все-же запустит и отчитается о правильности отображения текстур. Архив с текущей версией можно найти ниже в комментариях.
Решено, быть этому 2д-платформером.
Загруженные файлы
0
14
10 лет назад
0
У меня все нормально отображается.
1
33
10 лет назад
1
2д-платформер с полной разрушаемостью рельефа до отдельного пикселя.
Червяки! \o/
0
24
10 лет назад
Отредактирован prog
0
IceFog, спасибо, с этим отчетом счет становится 5 к 1 в пользу конфигураций железа, на которых все работает.
Кет, я не гожусь в художники чтобы нарисовать столь харизматичных персонажей, кроме того у меня на уме сеттинг, более близкий к рпг и более ориентированный на строительство. Но на самом деле я пока абсолютно уверен только в четырех вещах:
1 - это будет 2д платформер с видом сбоку.
2 - там будут деревья и по ним можно будет лазить.
3 - слабым взрывом и другими способами можно будет смести листву с дерева, оставив голый ствол с ветками.
4 - в обязательном порядке будет мультиплеер, но не факт что к срокам конкурса сандбоксов.
Все остальное может и будет меняться в совершенно неожиданных направлениях.
0
33
10 лет назад
0
prog, тоже неплохой набор.
2
24
10 лет назад
Отредактирован prog
2
Добавлен тайл травы и внесены соответствующие корректировки в заглушку генератора мира. Плюс проведена некоторая оптимизация, в результате чего ощутимо вырос фпс.
upd:
Перед тем как уйти на работу немного доработал систему. Теперь вместо одноканальной текстуры используется трехканальная, что в три раза удорожает передачу данных об изменении состояния фрагмента карты на GPU, но позволяет передавать не только ID текстуры, а еще и два байта дополнительных данных. Эти два байта будут использованы для передачи смещения текстурных координат пикселя, что позволит размещать в любой точке карты любой фрагмент любой текстуры, а не строго по сетке, как это было до сих пор.
Использоваться возможность задать сдвиг будет в основном ради свободного размещения различных небольших объектов, имеющих четкие контуры на текстуре. Например, столы, стулья, печки, деревья и канделябры. Правда на счет деревьев не уверен - их бы по хорошему генерировать программно, да и уместить дерево на текстуре 256*256 довольно проблематично. С другой стороны, возможность использовать произвольную развертку по текстуре вместо сквозной позволяет, например, уместить в одной текстуре листья из центра дерева, листья с краев дерева, кору ствола из центра и кору ствола с краев, а потом программно расставить пиксели дерева с разными смещениями текстуры.
В числе недостатков такого решения - увеличение потребляемой памяти, увеличение потенциальных затрат на передачу по сети, увеличение времени передачи информации об изменении фрагмента карты на GPU, усложнение внесения этих самых изменений в фрагмент карты. Возможно, стоит задуматься об использовании одноканальной текстуры для фрагментов карты, в которых нет пикселей со смещением текстурных координат с переключением на трехканальный режим при необходимости.
Новые скриншоты будут уже вечером - работать надо, а не выбирать текстуру и править генератор мира.
upd:
И так, обещанные скриншоты
На скриншоте слева направо представлены следующие ситуации:
  • наложение нового тайла из атласа на тайл камней с травой, без смешивания с тайлом камней чтобы визуально было понятно где границы фрагмента карты
  • попытка сдвинуть новый тайл в пределах своего участка карты на 10 пикселей, при использовании старой системы
  • тот-же самый сдвиг нового тайла, но уже в новой системе
  • наложение двух экземпляров нового тайла в пределах одного фрагмента карты
Хочу заметить, что ни тайлы поверхности, ни изображающий некий объект новый тайл не являются самостоятельными объектами и представлены общим массивом байт.
Если вместо текстуры из атласа подставлять фиксированный цвет, то получим такой психодел:
0
20
10 лет назад
0
А о процедурной генерации, без текстур-пресетов, не думал? Просто у меня был ещё в школе проект - генерация текстур естественных поверхностей.
зы. читал не всё, может это оно и есть)
2
24
10 лет назад
2
Mihahail, посмотри на последние скриншоты, в которых текстуры заменены для наглядности простыми цветами. Ядро игры оперирует массивом байт, в которых лежат id типа пикселя, а текстуры и дополнительные данные вроде смещения нужны уже в процессе отображения.
В принципе, я вполне могу использовать и процедурную генерацию текстур - от этого в самом ядре мало что изменится, но не вижу большой необходимости. Мороки много с процедурной покраской процедурно сгенерированного мира, а визуально результат меня и на запеченных текстурах устраивает. Я лучше добавлю автоматическую сборку отдельных текстур в атлас и поддержку вариаций одной текстуры.

Следующим этапом у меня в планах запилить полноценный чанк-менеджмент, обеспечивающий сквозную нумерацию пикселей карты, независимо от внутренней структуры - карта разбита на фрагменты 128*128 и каждый фрагмент это отдельный массив для удобства пересылки обновлений по сети и упрощения перерисовки, но работать с этими массивами напрямую это жуткая головная боль. После чего можно будет браться за полноценный генератор мира, а не это жалкое его подобие.
Одна из первых фич генератора, которую я планирую запилить - добавление в слой земли мелких объектов вроде камней и корней. Под корни придется выделить отдельный id и, соответственно, отдельную текстуру, а вот камни, возможно, получится реализовать и на общей для камней текстуре, хотя выделение отдельной текстуры под маленькие камешки разных вариаций даст более интересный визуальный результат.
Также в планах с высоким приоритетом уже упомянутые автоматическая сборка атласа "на лету" и поддержка вариаций текстур. На автоматический сборке атласа, думаю, заострять внимание не обязательно, а вот подробнее рассмотреть поддержку вариаций текстур очень даже стоит.
На данный момент покраска текстурами на основе id пикселя ведется с помощью простейшего шейдера, который на входе получает текстуру атласа (одна для всех) и псевдотекстуру, в которой закодированы id каждого пикселя плюс данные о смещении. Таким образом, у каждого фрагмента карты размером 128*128 в наличии своя уникальная псевдотекстура и ссылка на общую текстуру атласа. А теперь представим, что у нас есть два атласа, которые отличаются только вариациями текстур - назначить каждому фрагменту карты свою ссылку на нужный атлас не составит труда. Следующим вполне логичным шагом было бы разделить атлас для поверхностей и атлас для объектов ведь объекты с фиксированными контурами куда менее вероятно будут иметь большое кол-во вариаций. Более того, разделение атласов даст возможность использовать для объектов текстуры не 128*128, а 256*256 при неизменной структуре карты - под информацию о смещении выделено два байта и на практике остается два неиспользуемых бита т.к. смещение нет смысла делать больше, чем размеры текстуры. С другой стороны, такое разделение несомненно усложнит переход от id пикселя к текстуре и добавление новых id.
Таким образом, результат будет выглядеть примерно так: многостраничный атлас, каждая страница которого содержит все текстуры в отличной от других страниц вариации, а каждый фрагмент карты ссылается на выбранную произвольным образом страницу атласа. Плюс для объектов фиксированной формы будет отдельный атлас без страниц вариаций, компенсирующий этот недостаток увеличенным размером текстур.
1
24
10 лет назад
Отредактирован prog
1
Сперва по статусу - пришла пора реализовать нормальный чанк-менеджмент и полноценный генератор мира, оперирующий не отдельными несвязанными массивами байт, а связанными между собой фрагментами карты. Этот процесс не сопровождается какими-то принципиальными изменениями во внешнем виде, так что новых скриншотов какое-то время не будет.
А теперь немного абстрактных рассуждений: немного подумав, я пришел к мысли, что смещение по текстуре можно использовать не только для отображения, но и для упрощения такого незаменимого процесса, как определение принадлежности пикселя тому или иному объекту. Будут некоторые сложности при наложении в одних координатах нескольких разных объектов и для составных объектов, использующих разное смещение по текстуре в разных частях объекта, а для процедурно генерируемых объектов, имеющих произвольную форму, это и вовсе почти невыполнимая задача.
Таким образом, самое быстрое получение объекта по координатам пикселя будет для объектов фиксированной формы, состоящих из одной текстуры, не имеющих вариаций и использующих только линейное смещение по текстуре. Добавление вариаций к объекту, собирание объекта из разных кусков одной текстуры и прочие манипуляции, остающиеся в рамках фиксированной формы и линейности смещения, по крайней мере для каждого отдельно взятого фрагмента объекта, несколько усложняют алгоритм, но теоретически реализуются без потерь производительности.
Чем это чревато для геймплея? В первую очередь тем, что для интерактивных объектов вроде дверей и сундуков будут максимально использоваться одноэлементные объекты с вариациями в пределах одной текстуры - без вариаций было бы проще и быстрее, но тратить целую текстуру и id материала ради каждой вариации, например, сундука это перебор - система поддерживает всего 256 различных материалов и я не хочу без крайней необходимости повышать этот лимит.
Второе последствие для геймплея - генерируемые объекты сложной формы будут частью рельефа, а не отдельными объектами - никаких дополнительных параметров, задаваемых для всего объекта или особой реакции на активацию - только общие свойства материала.
Ну и напоследок небольшой финт ушами: для повышения вариативности можно разделить текстуру объекта и пресет, по которому заполняются пиксели карты для создания объекта. Тогда при использовании одной текстуры можно получить различные вариации объекта, отличающиеся наличием или отсутствием некоторых пикселей в пресете.

upd:
Кажется пора создавать отдельный проект - ведение этого подобия WIP-а в формате блога начинает вызывать у меня дискомфорт своим внешним видом.
0
20
10 лет назад
0
А я вот с удовольствием читаю тут.
0
24
10 лет назад
0
Mihahail, ну так текста меньше не станет, просто хочется немного его структурировать.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.