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.
Таким образом, результат будет выглядеть примерно так: многостраничный атлас, каждая страница которого содержит все текстуры в отличной от других страниц вариации, а каждый фрагмент карты ссылается на выбранную произвольным образом страницу атласа. Плюс для объектов фиксированной формы будет отдельный атлас без страниц вариаций, компенсирующий этот недостаток увеличенным размером текстур.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.