Infinity World (Дневники разработчицы)
440 subscribers
52 photos
24 videos
37 links
Канал-дневник разработчицы на Unity, рассказываю о всяком интересном и не очень, что встречается на пути разработки.

Тех стэк:
- Unity
- DOTS
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
Суббота прошла не зря (кря-кря): я вернула шейдинг, который ранее поломала, а также перенесла смешивание биомов на GPU сторону. 🥔

Интересный эффект "висюлек" получился на границе двух биомов + пещер. 😧

Теперь надо подумать, как генерировать карту биомов, чтобы переходы были плавными, а не такими резкими 🔍

#generation
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥126👍2
Media is too big
VIEW IN TELEGRAM
Путешествие в гору

Долго же я возилась со смешиванием биомов 😔: попробовала множество вариантов, механик, функций. Четыре дня непрерывных поисков.

Пока пришла к весовым функциям для каждого биома + карта высоты, которая является входным параметром для весовых функций. В дальнейшем добавится карта температуры и влажности. Но сейчас всего лишь три тестовых биома, и усложнять не очень хочется.

Каждый биом сам является функцией, которая определяет как SDF, так и воксели. Но некоторым биомам, оказалось, нужна и та самая базовая высота, по которой считается вес, иначе выглядит фу 🫣

На самом деле тут еще экспериментировать и экспериментировать. Но как стартовая точка вполне подходит. Можно добавить побольше типов вокселей и деталей, чтобы разнообразить вид.

Note: текстуры сейчас используются максимально простые, чтобы видеть как смешивается, в дальнейшем их заменю на более подходящие.

#generation
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥117
Видео в прошлом посте конечно длинное 🤪 Но я хотела показать масштабы мира и на сколько все далеко генерируется, причем в режиме realtime ☺️

Размер видимого мира - 4 кубических километра, то есть 4096x4096x4096 units, где каждый 1x1x1 unit - воксель. А это почти 69 млрд вокселей-кубиков! Ну, почти, есть же уровни детализации 🔍

Для тестирования я добавила 3 биома с одноцветными текстурами (спасибо Paint за это 🤭).

Почему одноцветные? Потому что другие надо готовить, плюс я нашла ошибку в шейдере в части смешивания текстур по высоте 🤷

Почему всего три? Потому что два - показалось мало, а четыре - слишком много 🤭 Биомы добавлять не сложно, но вот сделать их интересными - задача не из простых.

Что дальше?
Надо починить шейдер для ландшафта и вернуть инстансинг объектов на карте.

Ах, совсем забыла, пока возилась с биомами, я починила еще один краш: иногда лучше не трогать Pack в StructLayout под Burst 🤦 Даже если очень, очень надо.

А еще вернула под новый генератор мира поиск стартовой точки, чтобы не оказываться в воздухе ☺️

#generation
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18🥰5
Типы вокселей

Я уже не раз рассказывала, что мир у мня воксельный, и вся генерация основана на вокселях. Что это означает? А то, что инстансинг окружения, выбор материала, текстур и прочее, все это основано на вокселе. То есть сам воксель определяет что как именно у нас выглядит.

Снег в горах - это не отдельный биом, и не просто градиент, это именно другие воксели. Каждый биом ведь предоставляет не только SDF, но и информацию о типах вокселей в конкретной точке пространства и их веса.

Для проверки своей идеи я добавила парочку масок для снега. Чтобы это была не просто "шапка" на верхушке горы, а что-то более реалистичное. Одна маска базируется на высоте поверхности (я ее знаю из SDF), вторая же - на нормали, которая вычисляется из SDF с помощью метода численного дифференцирования.

Жаль только, что с повышением уровня детализации (LOD), эффект становится слишком уж приближенным. У меня есть идеи как для высоких уровней детализации дополнять детали, с этим как раз поможет GPU. Надеюсь когда-нибудь дойду до этого ☺️

#generation #shading
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥118🥰2👍1🤯1
StructLayout.Pack и Burst

Когда мы работаем со структурами, нам часто бывает важно как именно расположены члены этой структуры в памяти. Это может быть по причинам работы с P/Invoke, или может мы захотели оптимизировать использование памяти.

Для того, чтобы управлять тем, как члены структуры расположены в памяти, мы можем обратиться к атрибуту StructLayout, который имеет несколько параметров.

Note: атрибут StructLayout может применяться также и к классам!

1️⃣ Первый параметр - LayoutKind - тип макета, который бывает:
1. Sequential: все поля располагаются в памяти последовательно в порядке объявления.
2. Explicit: поля располагаются в памяти по заданным смещениям. Эти смещения указываются через атрибут FieldOffset.
3. Auto: автоматическое расположение полей в зависимости от компилятора. Совсем не обязательно, что поля будут располагаться в порядке объявления, так что с этим поосторожнее.

Note: по умолчанию всегда стоит Sequential, то есть получаем поведение из пункта 1.

2️⃣ Второй параметр, который тоже частенько используется - Size. Он отвечает за абсолютный размер структуры. Используется, когда мы хотим выделять конкретное количество байт на структуру. Причем, мы можем выделить больше, чем поля в сумме занимают на самом деле. Таким образом можно, например, выделить кусочек памяти на header структуры и там хранить какую-то информацию.

Note: размер структуры без каких-либо полей равен одному байту. Так что не обязательно указывать Size = 1 у "пустой" структуры.

3️⃣ Третий параметр - CharSet - задает кодировку для строк. Но в рамках Burst это мало интересует. Но может понадобиться, если работа ведется с неуправляемыми библиотеками.

4️⃣ И четвертый параметр - Pack - задает выравнивание полей. Тоже может использоваться частенько, но надо быть очень осторожным с ним. Полезен, если мы хотим, чтобы структура не занимала лишнее место в памяти, если используем поля с разным размером.

Давайте придумаем пример:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ExampleStruct
{
public byte ByteValue;
public int IntValue;
public short ShortValue;
}


Какой размер у такой структуры? Ответ - 7 байт. Почему? Потому что мы указали выравнивание 1 байт, тогда: поле ByteValue занимает 1 байт, поле IntValue занимает 4 байта и поле ShortValue - 2 байта. Если указать Pack = 4, то размер структуры будет уже 12 байт, по 4 байта на каждое поле.

Вроде бы все логично, но не для Burst: до версии 1.8.16 включительно было замечено такое поведение, что Burst пытается вставить свое выравнивание. Возможно это связано с векторизацией 🤷, но это приводит к тому, что в коде без Burst, структура занимает N памяти, например, те же 7 байт, а в коде с Burst, это структура будет занимать уже 16 байт.

К чему приводит такое поведение? А то, что если выделить память по размеру структуры без Burst, а потом попытаться читать/писать под Burst, то приходим к крашу, так как получаем сдвиг элементов и выходим за границы выделенной памяти.

Как с этим справляться? Я пока не придумала лучше того, чтобы совсем не использовать Pack. Но иногда так хочется, хочется сэкономить пару байт (да-да, я часто использую поля с размером 1 байт). А потом вспоминаю, как я искала неделю причину краша. 🤦

Когда-то Burst поддерживал только частично параметр Pack, сейчас в документации написано, что полностью поддерживает. Но все равно будьте осторожны!

P.S.: возможно кто-то сталкивался с подобным, поделитесь в комментариях!

#programming
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍7🔥4🥰1
This media is not supported in your browser
VIEW IN TELEGRAM
Редакторы тоже важны

Возвращала инстансинг объектов, и столкнулась с тем, что совсем не помню, что и как указывать в LOD. Я просто не могла настроить свои же лоды! 😔

Причина в том, что там надо указывать процентное отношение объекта к размеру камеры, а не какие-то понятные единицы. Это отношение еще надо посчитать, ох, лучше я редактор напишу ☺️

Взяла за основу редактор от UnityEngine.LODGroup - он понятен и привычен. Переписала его под свои нужды: в моей реализации LOD многое упрощено, да и работаю я напрямую с Mesh и Material, так как моя реализация под BRG.

Что ж, часа 4, и вот, PropertyDrawer, который почти повторяет функционал LODGroup. Рисуется в MonoBehaviour, ScriptableObject, везде, где указано сериализованное поле моего типа. Удобненько. 🥔

#programming
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1410👍2
Возвращение заблудших фич

Наконец-то я вернула весь функционал, который у меня был до начала переделки генератора и его оптимизации. 💃

Почему так долго? Потому что это десятки тысяч строк кода и много математики (ну и не всегда я работаю полный день, признаю 🤷). Плюс я не раз натыкалась на свои же старые баги (все еще задаюсь вопросом, зачем я их наделала? 🤦), а также добавила новые и снова наткнулась на них 🤭

По результатам оптимизации я писала пост вот туть.

Просто пост радости, теперь можно продолжить работать над ГД, добавлять новые возможности и идти к новым горизонтам, даже если из этого проекта ничего не получится.

#generation
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
27
Когда ты инди-разработчица, то приходится делать абсолютно все: продумывать геймдизайн, разрабатывать геймплейные фичи, инструменты, оптимизировать свой же код и графику, рисовать текстуры и моделировать объекты. Направлений просто куча! 😧

Каждое из этих направлений интересно по своему: где-то можно прокачаться в сохранении байтиков и получении более маленьких циферок в Profiler, а где-то можно почувствовать себя художником (может даже не от слова "худо" 🤭) и воплотить свои идеи в реальность в виде различных красивостей.

Последнюю неделю я изучала Adobe Substance 3D Designer: очень мощный инструмент для создания разнообразных текстур. Правда оказался достаточно сложным для меня: после тысячи часов за кодом снова вернуться к арту - задачка та еще)

Зато этот инструмент довольно близок ко мне по духу: шум, много шума, очень много шума и различные операции над ним. Тяп-ляп, и текстура готова 😄 Процесс почти такой же, что и у меня в генераторе мира)

#texturing
Please open Telegram to view this post
VIEW IN TELEGRAM
16🔥5😱2🥰1
Нас уже 300 человек! Удивительно Спасибо вам всем за поддержку! ❤️

Я немного отдыхала в последнее время и не работала над проектом, поэтому пока нового не покажу. Но, я скоро вернусь за работу и там будет очень много интересного по графике, по сетевой части, по геймплею и многому другому!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥287💋7🎉21
Написала статью по новому этапу разработки 👏 Будет серия постов и статей.

К сожалению, telegraph больше не поддерживается telegram, поэтому пришлось переехать на teletype 🧂 Надеюсь вам будет удобно читать! 🥰

Русская версия: вот тут.
English: here.

#game_design #demo_scene
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14💋52😍2
Entities (DOTS) и Wireframe режимы

Когда я только начала использовать DOTS и использовать BatchRendererGroup (BRG), то столкнулась с тем, что посмотреть сетку мешей в окне сцены невозможно. Переключалка в Scene View работает только для GameObject и MeshRenderer, а для сущностей, которых на сцене фактически то и нет, уже не работает. 😭

Учитывая, что вся геометрия у меня процедурно генерируется, посмотреть получившуюся сетку было жизненно необходимо. Я спасалась тем, что был отдельный debug MonoBehaviour, который умел генерировать отдельные чанки и запихивать их в MeshRenderer. Неудобно, скажите вы, и будете абсолютно правы. 😔

Что же делать? Использовать Rendering Debugger! Подробное описание можно найти вот тут. В Unity его можно найти в меню Window -> Analysis -> Rendering Debugger. Там на самом деле множество полезных инструментов для дебага графики, но что меня порадовало в свое время - есть wireframe режимы, которые работают и с сущностями!

Чтобы переключить wireframe режим, надо найти выпадающий список по пути Rendering -> Rendering Debug -> Additional Wireframe Modes в окошке Rendering Debugger. Вдруг кому-нибудь полезно будет ☺️

#dots
🔥194👀4💋2
Демо-сцена. Форма ландшафта.

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

Русская версия: вот тут.
English: here.

Приятного чтения! 🥰

#generation #demo_scene
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥104🥰2💋1
Custom properties в DOTS Instancing

Как и в GPU Instancing, в DOTS Instancing есть определенные правила работы с полями, которые должны быть per instance. 🧐

Если рассматривать как в DOTS Instancing устроено хранение данных для каждого инстанса, то стоит обратиться к Batch Renderer Group. А там, фактически, один буфер, где под каждое поле (будь то матрица или просто цвет) выделяется определенный кусок памяти. Дальше, с помощью оффсетов, которые можно вычислить, зная размер данных поля и количество интансов, можно получить доступ к конкретному значению конкретного поля для конкретного инстанса.

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

Определение поля:
#ifdef UNITY_DOTS_INSTANCING_ENABLED
UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
UNITY_DOTS_INSTANCED_PROP(float4, _ChunkDebugColor)
UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)
#else
int _ChunkDebugColor;
#endif


И получение значения:
float4 debug_color = (float4)0;
#ifdef UNITY_DOTS_INSTANCING_ENABLED
debug_color = UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, _ChunkDebugColor);
#else
debug_color = _ChunkDebugColor;
#endif


Но как же указать значение для инстансов? 🤔
Когда мы работаем с GPU Instancing, то необходимо передать буфер per property, который мы можем как-то заполнить на стороне CPU. В случае же с DOTS Instancing, мы должны работать с буфером BRG и заполнять его. Это немного сложновато, но у меня есть небольшая реализация, которая упрощает этот процесс.

Но также есть и другой способ, если используется пакет Entities. Там мы можем указывать значения через компоненты!
Для этого необходимо создать небольшой компонент и повесить его на сущность, все остальное за нас сделает Unity:

[Serializable]
[MaterialProperty("_ChunkDebugColor")]
public struct DebugChunkColorProperty : IComponentData
{
public float4 Value;

public static implicit operator DebugChunkColorProperty(float4 value)
{
return new DebugChunkColorProperty
{
Value = value
};
}
}


#dots
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥124👏3👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Что такое Biome?

Биом - это правила генерации ландшафта, правила выбора вокселей, правила генерации окружения и многое другое.

Так как воксели генерируются у меня на стороне GPU (использую вычислительные шейдеры), то правила генерации ландшафта и выбор типов вокселей описываются на языке HLSL.

Фактически, это просто математическое уравнение. Довольно большое и сложное, но все же уравнение: на входе позиция в world space и зерно (seed) мира, а на выходе - дистанция для Signed Distance Field и вектор типов вокселей, которые могут быть в указанной точке пространства. Вот и все 👏

#generation
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🥰3😍21💋1
Демо-сцена. Базовые цвета ландшафта. Часть 1.

На этот раз затрагиваю тему материалов вокселей и базовых цветов ландшафта для демо сцены.

Это первая часть статьи, так как для продолжения необходимо вначале настроить освещение 👏

Русская версия: вот тут.
English: here.

Приятного чтения! 🥰

#generation #demo_scene
Please open Telegram to view this post
VIEW IN TELEGRAM
10💋4🔥1😢1