54 KiB
id
| id |
|---|
| aego/material.Vec4.X |
Хранит первую вещественную компоненту числового vec4 материала; она не становится красным цветовым каналом автоматически.
id: aego/material.Vec4.Y
Хранит вторую вещественную компоненту числового vec4 материала; её смысл определяет параметр шейдера.
id: aego/material.Vec4.Z
Хранит третью вещественную компоненту числового vec4 материала; её смысл определяет параметр шейдера.
id: aego/material.Vec4.W
Хранит четвёртую вещественную компоненту; она не считается альфой, если получатель явно не придаёт ей такой смысл.
id: engine.MaterialParameter
Хранит одно явное типизированное переопределение материала узла. Это запись внутри MaterialOverride, а не добавляемый компонент или ассет материала.
id: engine.MaterialParameter.Name
Указывает объявленный параметр шейдера по точному имени, а не по позиции в раскладке материала.
id: engine.MaterialParameter.Kind
Сохраняет объявленный тип параметра, чтобы удаление или последующая смена типа не переинтерпретировали сохранённое значение молча.
id: engine.MaterialParameter.Value
Хранит вещественные, векторные или цветовые компоненты согласно Kind. Integer и Boolean сохраняют значения отдельно.
id: engine.MaterialParameter.Integer
Хранит целочисленное переопределение как точное знаковое 32-битное значение без преобразования через вещественные компоненты.
id: engine.MaterialParameter.Boolean
Хранит явное значение true/false булева параметра; использование поля определяется типом Kind.
id: render2d/materials title: Материалы и шейдеры
Материалы и шейдеры
Материал — общий ассет. Назначьте его компоненту «Отрисовка спрайта» или Mesh2D, затем добавьте «Переопределение материала» для значений отдельного узла. Итоговое значение выбирается последовательно: значение шейдера по умолчанию, явное значение материала, явное переопределение узла. Режим игры и предпросмотр используют отдельное состояние узлов.
Создание и редактирование
- В палитре Создать с поиском выберите Шейдер, Материал или Материал из шейдера. Редактируемые исходники — .aeshader и .aemat.
- Выберите материал в Ассетах и настройте шейдер, вариант, смешивание, параметры и текстуры. Сохранение общего материала затрагивает всех потребителей этого ассета.
- Назначьте его нужному SpriteRenderer или Mesh2D. Отдельно сохраните исходник материала и сцену с этим назначением.
- Добавьте Переопределение материала, если отличаться должен только этот узел. Измените объявленный параметр экземпляра, сравните второй узел с тем же материалом, затем нажмите Сброс для восстановления наследования.
Исходник материала и его Инспектор используют общую историю отмены. Одно перетаскивание параметра создаёт один шаг истории. Сброс восстанавливает наследование даже при совпадении явного и унаследованного значений; это не присваивание нуля.
Выберите спрайт, назначьте поле материала и добавьте Переопределение материала. Переопределять можно только числовые параметры с аннотацией @instance. Текстуры, варианты и смешивание принадлежат ассету материала. Удалённые поля сохраняются как неизвестные значения, а неразрешённые ссылки сохраняют свой AssetID.
Переносимый шейдер
Пишите GLSL 330 с метаданными Aego. Импортёр подготавливает и проверяет исходники GLSL 330 и GLSL ES 3.00. Он разрешает включения из engine/ и проектные включения из assets/shaders/include/. Общедоступные поля определяются объявлениями: параметр, который драйвер исключил при оптимизации, остаётся в Инспекторе.
#pragma aego abi 1
#pragma domain sprite
#include "engine/sprite.glsl"
#pragma material
uniform float Opacity; // @instance @default(1) @range(0, 1)
#pragma end
void fragment() {
aego_out = aego_sample() * Opacity;
}
aego_sample() уже возвращает линейный цвет с RGB, умноженными на альфу. Дополнительная прозрачность умножает весь полученный vec4 один раз. Обычные значения vec4 остаются числовыми; семантика Color применяется только к параметрам с аннотацией @color. Отдельную текстуру шума считывайте по aego_local, независимо от положения спрайта в атласе. aego_sample_at ограничивает выборку областью этого спрайта и возвращает прозрачный цвет за её пределами.
Sprite и Mesh2D — разные домены шейдеров. Материал должен соответствовать формату вершин своего потребителя. Время кадра принадлежит текущему миру, данные View — текущей камере, значения материала — его принятой ревизии. Пользовательская вершинная стадия отключает отсечение на CPU для использующего её Sprite или Mesh2D. CPU не анализирует GLSL, чтобы угадать границы смещения вершин.
Анимация и перезагрузка
Tween и Animation обращаются к объявленному параметру экземпляра через путь свойства. Последняя часть пути — имя параметра из схемы шейдера, например:
MaterialOverride.Flash
MaterialOverride.Threshold
Привязки обновляются после принятия нового поколения разметки. Целочисленные ключи анимации сохраняют точность знакового целого числа; для дробных значений Tween использует интерполяцию с плавающей точкой.
Сохраните шейдер или включаемый файл, чтобы импортировать новое поколение. Компиляция, линковка, проверка разметки и миграция зависимых материалов должны завершиться успешно до его принятия на границе кадра. При ошибке сохраняются прежние программа, схема и значения. Панель проблем открывает строку исходного шейдера или включаемого файла; номер столбца не показывается, если компилятор его не сообщил.
Ошибка в текущем исходнике блокирует строгий экспорт, даже если сцена продолжает использовать последнюю рабочую версию. Перед экспортом сохраните изменённые буферы шейдеров, материалов и включаемых файлов. Экспорт содержит подготовленные артефакты шейдеров и материалов: игре не требуются импортёр и glslang.
Демонстрация
Проект examples/materials показывает полный сценарий: полупрозрачные спрайты A/B/A с общим атласом, соседние экземпляры с разными переопределениями, Mesh2D, две камеры, Tween для Flash и анимацию Dissolve. В его README приведены шаги редактирования, отмены, перезагрузки и экспорта на desktop и web. Предпросмотр Инспектора использует отдельный материал и прозрачную внеэкранную поверхность; если GPU недоступен, он показывает причину вместо фиктивного успешного изображения.
id: aego/material summary: Находит ссылки на встроенные материалы и шейдеры, назначает материал узлу и представляет числовые четырёхкомпонентные значения.
Используйте material.Builtin("Flash"), а также имена Dissolve, Outline, Additive, PixelSnap, Unlit, Lit и LitMesh2D (Default — псевдоним Unlit). Неизвестное имя вызывает ошибку. Lit и LitMesh2D вычисляют вклад каждого выбранного источника с учётом нормали своей поверхности. material.Assign записывает ссылку в SpriteRenderer или Mesh2D текущего мира. Для пользовательского ассета назначьте экспортируемое поле AssetRef<Material> или установите свойство Material соответствующего компонента.
package demo
import (
"aego/material"
"aego/log"
)
script SharedMaterial {
func Ready() {
ref := material.Builtin("Flash")
sprite := node.Get<SpriteRenderer>()
if sprite != nil {
material.Assign(node, ref)
}
weights := material.Vec4{0.1, 0.2, 0.3, 0.4}
log.Info("Flash reference available; numeric lane X=" + string(weights.X))
}
}
У узла с MaterialOverride доступны SetFloat, SetInt, SetBool, SetVec2, SetVec3, SetVec4, SetColor, соответствующие методы чтения и Reset. Обычный vec4 использует material.Vec4, цветовой параметр — линейный Color. Несоответствие типа вызывает ошибку до изменения узла.
id: engine.MaterialOverride summary: Явные типизированные значения материала отдельного узла, наследующие значения общего ассета.
Используйте компонент, когда два узла разделяют материал, но им нужны разные числовые значения. Инспектор показывает объявленные параметры экземпляра и унаследованные значения. Сохраняйте переопределения режима редактирования со сценой; изменения во время Play затрагивают игровую копию, а не общий исходник .aemat.
Методы записи принимают точное name параметра шейдера, например Flash, а не AssetID или ключ экземпляра постобработки. Тип объявления должен совпадать с методом, а параметр должен разрешать переопределение через @instance. Вещественные компоненты должны быть конечными, целые — помещаться в int32, а узел поддерживает не более восьми активных явных параметров. Диапазон в Инспекторе шейдера не обещает автоматического ограничения значения скриптовым методом.
Методы чтения возвращают итоговое значение с учётом значений шейдера по умолчанию, материала и переопределения узла. Сброс удаляет явное значение вместо сохранения текущего унаследованного. Удалённые параметры шейдера остаются в values для восстановления, но не передаются как активные значения шейдера. У PostProcess другая область действия — экземпляр эффекта.
Пример Flash одного узла
Прикрепите скрипт к узлу SpriteRenderer с MaterialOverride и запустите Play. Он назначает встроенный материал Flash, записывает одно переопределение и сбрасывает его. Журнал показывает унаследованное значение, переопределение, результат удаления через Reset и снова унаследованное значение. Без нужных компонентов скрипт сообщает об ошибке, а не пропускает пример молча.
package demo
import (
"aego/log"
"aego/material"
)
script FlashProbe {
func Ready() {
sprite := node.Get<SpriteRenderer>()
values := node.Get<MaterialOverride>()
if sprite == nil || values == nil {
log.Error("FlashProbe needs SpriteRenderer and MaterialOverride")
return
}
material.Assign(node, material.Builtin("Flash"))
inherited := values.GetFloat("Flash")
values.SetFloat("Flash", 0.65)
log.Info("inherited=" + string(inherited) + ", explicit=" + string(values.GetFloat("Flash")))
removed := values.Reset("Flash")
log.Info("reset=" + string(removed) + ", inherited=" + string(values.GetFloat("Flash")))
}
}
scene version=1 {
node "d3400000000000000000000000000001" name="Flash probe" enabled=true layers=1 {
transform { position=[0, 0] rotation=0 scale=[1, 1] }
component "engine.SpriteRenderer" version=1 {
sprite=asset("ae900000000000000000000000000010") size=[2, 2] tint=#ffffffff
}
component "engine.MaterialOverride" version=1 { values=[] }
component "engine.Script" version=1 { script "game.demo.FlashProbe" enabled=true {} }
}
node "d3400000000000000000000000000002" name="Camera" enabled=true layers=1 {
transform { position=[0, 0] rotation=0 scale=[1, 1] }
component "engine.Camera2D" version=1 { zoom=40 active=true }
}
}
id: engine.MaterialOverride.SetFloat
name выбирает float-параметр с @instance. value должно быть конечным; вызов меняет только переопределение узла и не сохраняет сцену или общий материал.
id: engine.MaterialOverride.SetInt
value должно помещаться в знаковый int32, хотя скриптовый int шире. Ошибка диапазона или типа сохраняет прежнее переопределение.
id: engine.MaterialOverride.SetBool
name выбирает bool-параметр с @instance. Это типизированное булево присваивание, а не преобразование целого или вещественного числа.
id: engine.MaterialOverride.SetVec2
value задаёт две конечные компоненты объявленного параметра экземпляра vec2. Другая размерность вектора вызывает ошибку типа.
id: engine.MaterialOverride.SetVec3
value задаёт три конечные компоненты объявленного параметра экземпляра vec3. Другая размерность вектора вызывает ошибку типа.
id: engine.MaterialOverride.SetVec4
value — числовой material.Vec4. Для параметра шейдера с цветовой семантикой используйте SetColor: эти типы не взаимозаменяемы.
id: engine.MaterialOverride.SetColor
value — линейный Color для vec4-параметра с цветовой подсказкой и @instance. Вызов не интерпретирует числовые Vec4 как цвета.
id: engine.MaterialOverride.GetFloat
name выбирает объявленный float-параметр. При отсутствии явного значения узла результат учитывает наследование; неразрешённый материал или несовместимый тип вызывают ошибку скрипта.
id: engine.MaterialOverride.GetInt
Возвращает итоговое знаковое значение int32 как скриптовый int, без промежуточного вещественного преобразования. Объявленный параметр должен иметь целый тип.
id: engine.MaterialOverride.GetBool
Возвращает итоговое типизированное булево значение. Не трактует нулевой или ненулевой числовой параметр шейдера как bool.
id: engine.MaterialOverride.GetVec2
Возвращает две итоговые компоненты объявленного vec2. Метод не отбрасывает компоненты вектора большей размерности.
id: engine.MaterialOverride.GetVec3
Возвращает три итоговые компоненты объявленного vec3. Метод не отбрасывает компоненты вектора большей размерности.
id: engine.MaterialOverride.GetVec4
Возвращает числовой material.Vec4. Параметр с цветовой подсказкой требует GetColor.
id: engine.MaterialOverride.GetVec4Lane
lane равен 0 для X, 1 для Y, 2 для Z или 3 для W обычного vec4. Индекс вне диапазона или цветовой параметр вызывают ошибку скрипта.
id: engine.MaterialOverride.GetColor
Возвращает итоговый линейный Color параметра с цветовой подсказкой. Это не преобразование обычного vec4 в цвет.
id: engine.MaterialOverride.Reset
Удаляет явное значение name этого узла, в том числе сохранённое для удалённого параметра шейдера. Возвращает false, если явного значения не было; не обнуляет общий материал.
id: engine.Light2D summary: Освещает спрайты и двумерные меши Lit точечным, коническим, направленным или текстурным источником. try: try/Light2D.aescene try_select: engine.Light2D
Light2D влияет на SpriteRenderer с материалом Lit и Mesh2D с LitMesh2D. Материалы Unlit сохраняют исходный цвет. Добавьте источник через палитру создания, настройте интенсивность и радиус в Инспекторе, затем перетащите ручки радиуса и направления в Scene View. Один жест создаёт одну команду отмены.
Point освещает круг. Spot направлен вдоль локальной +X; innerAngle и outerAngle задают полную ширину конуса в радианах: внешний угол π/2 означает 90°. Sprite применяет текстуру cookie как маску с её собственной областью. Directional использует поворот узла для азимута и elevation для направления к поверхности. Тени Directional не поддерживаются; их включение даёт диагностическое сообщение.
height направляет локальный свет к нормали поверхности. Для плоской нормали и света строго в плоскости спрайта диффузный вклад может быть нулевым. Высота меняет освещение, а окклюдеры остаются плоскими. Радиус задаётся в мировых единицах и не зависит от масштаба узла источника.
layers выбирает слои получателей. shadowCasterMask независимо выбирает слои окклюдеров; эти настройки не заменяют маски столкновений. Один набор получателей учитывает до восьми источников. При превышении бюджета выбор определяется приоритетом, оценкой влияния и постоянным ID. Scene View выделяет исключённые источники; Профайлер считает исключения и разделения батчей по свету. Порядок прозрачных Sprite/Mesh2D сохраняется.
В Try it тёплый свет расположен рядом с холодным Spot. Измените интенсивность тёплого источника и сравните его вклад, затем нажмите «Сброс». Источники неподвижны, чтобы результат изменения было легче увидеть.
id: engine.LightOccluder2D summary: Задаёт полигон или открытую цепочку, отбрасывающую тени от локальных источников без обязательного Physics. try: try/LightOccluder2D.aescene try_select: engine.LightOccluder2D
LightOccluder2D задаёт геометрию тени отдельно от видимого спрайта. Polygon использует локальные точки; closed замыкает простой полигон без отверстий. Отключите его для цепочки. Валидатор отклоняет нечисловые координаты, рёбра нулевой длины и самопересечения. Спрайт не становится окклюдером автоматически.
В Scene View перетаскивайте вершину для перемещения, середину ребра для вставки вершины; Alt + щелчок удаляет вершину. Каждый жест использует одну транзакцию History. ShapeProvider копирует локальные контуры поставщика, например Physics, по shapeNode и постоянному ключу формы. Physics необязателен: Try it использует только ручной полигон. Изменение collision mask не меняет layers этого компонента.
Point, Spot и Sprite используют общий алгоритм плоских теней. Перекрывающиеся объёмы объединяются. Свет внутри замкнутого контура блокируется им; получатель не игнорирует собственный контур автоматически. cullMode выбирает направление рёбер независимо от односторонности физической цепочки. Мягкость фильтрует маску в ограниченном радиусе, не моделируя площадной источник.
Окклюдер за экраном участвует, если его тень достигает видимого получателя. Свет и геометрия теней используют presentation transforms, включая интерполированное движение. Движение только камеры не пересчитывает статические маски в пространстве света. Движение света или окклюдера, изменение контура, разрешения или фильтрации инвалидирует нужную маску. Инспектор показывает активные слои и их источники; режим теней Scene View показывает видимость на поверхностях Lit.
id: engine.LightingEnvironment2D summary: Настраивает фоновое освещение, цветовой режим вывода и бюджет теней для выхода камеры. try: try/LightingEnvironment2D.aescene try_select: engine.LightingEnvironment2D
LightingEnvironment2D задаёт ambient, экспозицию, Auto/LDR/HDR, разрешение масок и бюджет локальных теней. Поле camera выбирает Camera2D; пустая ссылка применяет окружение ко всем двумерным выходам мира. Несколько подходящих окружений дают ошибку: порядок регистрации не выбирает победителя. Без окружения белый ambient с интенсивностью один сохраняет совместимые значения Lit.
LDR использует линейную цель RGBA8. HDR использует проверенную RGBA16F и преобразование для вывода. Auto выбирает HDR, когда выходу нужно освещение и устройство его поддерживает. Если framebuffer нельзя использовать, Инспектор показывает причину перехода на LDR. UI и редакторские наложения остаются вне тональной компрессии сцены. Включённый на камере Bloom обрабатывает итоговый цвет мира перед преобразованием для вывода.
Scene View имеет собственный выход и не подставляет ID игровой камеры. Нажмите Предпросмотр в Scene View в Инспекторе окружения, чтобы явно выбрать его. Изменения полей сразу видны в этом виде. Использовать окружение сцены по умолчанию снимает выбор. Он хранится отдельно для каждого документа и не меняет ссылки камер, prefab, Play или историю отмены. Удаление или отключение окружения сохраняет выбранный ID и показывает диагностику до восстановления узла либо сброса выбора.
Панель Scene View позволяет отключить освещение или показать преобразованные нормали и видимость теней. Настройки действуют только в этом виде. Вывод прозрачной HDR-цели сохраняет контракт premultiplied alpha. Аддитивное свечение перед отображением нужно смешать с непрозрачным фоном либо сохранить в линейной промежуточной RGBA16F. Additive суммирует RGB и сохраняет альфу назначения.
id: aego/lighting summary: Меняет освещение и диагностическое отображение presentation view текущего мира.
SetEnabled сравнивает освещённое изображение с исходным альбедо. SetDebug принимает lighting, normals или shadows; неизвестное имя вызывает ошибку до изменения вида. Enabled и Debug читают состояние вида. Эти вызовы не редактируют ассеты материалов, компоненты сцены или игровое состояние.
package demo
import (
"aego/lighting"
"aego/log"
)
script InspectLighting {
func Ready() {
lighting.SetEnabled(true)
lighting.SetDebug("normals")
log.Info("Lighting display: " + lighting.Debug())
}
}
Компоненты света используют обычные типизированные привязки и пути анимации. Например, Light2D.intensity, Light2D.range, Light2D.color и углы конуса доступны Tween и Animation. В дорожке MaterialOverride выберите объявленный параметр Lit по имени: NormalStrength, EmissionIntensity или ReceiveShadows. Ссылки normal map и cookie — ресурсы текстур, а не числовые переопределения экземпляра.
Фонарь в platformer
Откройте examples/platformer: его основной уровень — каноническая демонстрация освещения. Лампы используют emission для собственного вида и отдельные Light2D для соседних поверхностей. Платформы и стены имеют ручные контуры теней. HUD и меню остаются Unlit. В проект включены реальные исходники альбедо, normal и height с .meta и постоянными ID.
Измените цвет, высоту или радиус лампы, проверьте Undo/Redo, Play и зарегистрированные действия отладки освещения. Bloom на основной камере создаёт ореол вокруг ярких пикселей лампы и искр. За освещение соседних поверхностей отвечает Light2D. Экспортируйте проект на native и web обычным строгим экспортом. Демо сайта собирается из этого же platformer без отдельной правки копии уровня.
id: render2d/normal-mapping title: Карта нормалей и движущийся свет
Карта нормалей и движущийся свет
Левый спрайт использует карту нормалей, полученную из карты высот; правый — то же альбедо и плоскую нормаль. Движущийся точечный свет вычисляет освещение каждой поверхности отдельно. Меняйте высоту, интенсивность и радиус в интерактивном инспекторе. Height задаёт высоту над плоскостью спрайта, а тени остаются плоскими.
Полный исходный проект находится в modules/render2d/res/docs/try/lighting/NormalMapping.assets. Откройте его project.aego в редакторе, чтобы менять изображения, материал и скрипт движения вместе. Копия одного .aescene не включает внешние ресурсы. Браузер получает подготовленные артефакты этого проекта через обычный загрузчик ресурсов: импортёр изображений и поиск файлов нормалей во время игры не запускаются.
В surface_height.png.meta указаны semantic=height, generate_normal=true, height_channel=r, height_strength=12 и normal_y=up. Импорт создаёт линейную карту нормалей. Явная ссылка NormalMap материала Lit указывает на её постоянный AssetID. Альбедо имеет цветовую семантику без автоматической связи с нормалью, поэтому правый образец остаётся плоским. Переименование файла вместе с .meta сохраняет связь.
Для готовой карты задайте semantic=normal и normal_y=up либо down согласно направлению зелёного канала в исходнике. Нормали, маски источника и высоты нельзя импортировать как цвет sRGB. Независимо упакованный атлас нормалей сохраняет собственную область, исходный размер и смещение обрезки. Поворот областей атласа по-прежнему не поддерживается. Если нормаль кадра недоступна, ссылка сохраняется, а до исправления используется плоская нормаль.
Если поверхность выглядит плоской, проверьте Lit, пересечение маски света со слоями спрайта, положительный Height, доступность NormalMap и ненулевой NormalStrength. Слишком яркое фоновое освещение скрывает вклад источника. Режим «Нормали поверхности» в окне сцены показывает преобразованную нормаль без экспозиции и тонального преобразования. В examples/platformer этот же путь используется в настоящей игре.
code: LGT001 title: Недопустимые параметры света
Источник исключён из отрисовки из-за недопустимого типа, интенсивности, радиуса, высоты или угла.
Исправление. Выберите поддерживаемый тип, конечные неотрицательные интенсивность и высоту, положительный радиус, полные углы Spot в пределах 0 <= InnerAngle <= OuterAngle <= pi и угол возвышения Directional в интервале (0, pi/2].
code: LGT002 title: Тени направленного света не поддерживаются
Направленный свет освещает поверхность, но не поддерживает тени от локальных масок.
Исправление. Выключите Shadows у Directional или используйте Point, Spot либо Sprite для локальных теней.
code: LGT003 title: Неверные или конфликтующие настройки окружения
Для выхода заданы конфликтующие окружения, неверные параметры либо недоступная камера или цель предпросмотра.
Исправление. Оставьте одно окружение с действующей камерой, неотрицательным ambient, положительной экспозицией, разрешением теней степенью двойки от 64 до 2048 и бюджетом от 0 до 16 либо сбросьте устаревший выбор в Scene View.
code: LGT004 title: Неверный контур окклюдера
У контура тени неподдерживаемая геометрия, недопустимый источник или неизвестный режим отсечения.
Исправление. Выберите поддерживаемый источник и направление обхода, затем задайте простой полигон из 3–256 конечных вершин или открытую цепочку без самопересечений и рёбер нулевой длины.
code: LGT005 title: Недоступны поставщик геометрии или форма
Для сохранённой ссылки окклюдера не найден владелец, поставщик геометрии или ключ формы.
Исправление. Восстановите узел или поставщика, выберите доступную форму либо задайте полигон вручную без Physics.
code: LGT006 title: Недоступная или несовместимая текстура поверхности
Текстура освещения отсутствует либо её назначение несовместимо с использованием в материале или источнике света.
Исправление. Восстановите ресурс с сохранённым AssetID или назначьте совместимую линейную нормаль либо маску и проверьте исходные размеры и обрезку парных кадров.
code: LGT007 title: Неверное преобразование отображения света
Из-за вырожденного базиса или неконечных координат отображаемое преобразование не задаёт нужную ориентацию света либо окклюдера.
Исправление. Проверьте узел и родителей на нулевой масштаб и неконечные координаты как в исходной, так и в интерполированной позе.
code: LGT008 title: Превышен бюджет геометрии или ресурсов освещения
Данные освещения превышают бюджет ресурсов либо целевая текстура не может представить запрошенный результат.
Исправление. Прочтите указанное ограничение и упростите контур, измените бюджет источников либо скомпонуйте аддитивное свечение на непрозрачном фоне до вывода на экран.
id: render2d/image-viewer title: Просмотр и настройка изображений и спрайтов
Просмотр и настройка изображений и спрайтов
Откройте PNG двойным щелчком в Assets, перейдите к кадру из Inspector или нажмите Открыть изображение / спрайт. Каждый исходник открывается обычной вкладкой рабочей области. Кадры используют документ и историю метаданных своего изображения: открытие другого кадра меняет выбор в той же вкладке. PNG — текущий поддерживаемый формат исходников текстур. Сгенерированные страницы атласа и встроенные текстуры доступны только для чтения. Неподдерживаемые бинарные ассеты показывают информацию о ресурсе и не попадают в текстовый редактор.
Пиксели и упаковка в атлас
Исходные пиксели — оригинальный файл или выбранный исходный кадр. Импортированные пиксели — активный runtime-артефакт с его форматом, линейной обработкой и premultiply. Импортированный кадр показывается в исходном логическом холсте, с прозрачными полями обрезки. Открыть атлас отдельно показывает упакованную страницу и выделяет регион. Координаты исходника и идентификаторы кадров не подменяются координатами атласа.
Колесо масштабирует изображение под курсором, средняя или правая кнопка перемещает его. Вписать подбирает масштаб по области просмотра; 1:1 сопоставляет тексель физическому пикселю экрана с учётом масштаба редактора. При достаточном увеличении видна сетка. RGB и отдельные R/G/B/Alpha показывают исходные байты каналов, включая RGB под нулевой альфой, и не меняют настройки импорта. Строка состояния содержит логические координаты пикселя и четыре значения RGBA8 выбранного представления. RGBA показывает прозрачность на шахматном, светлом или тёмном фоне.
Pivot исходника/кадра нормирован в исходном логическом холсте и описывает авторское выравнивание. У превью отдельное начало в центре; существующие узлы сохраняют SpriteRenderer.Origin. Выбор кадров использует постоянные ID: переименование и перестановка не создают новые привязки каналов. Этот просмотрщик не рисует пиксели и не создаёт кадры анимации.
Роли и каналы поверхности
Просмотрщик, Inspector и структурированные CLI/MCP-мутации используют один документ метаданных. Правки остаются несохранёнными до Сохранить настройки. Одно перетаскивание числового поля создаёт один шаг Undo. Чистый документ подхватывает внешние изменения; при несохранённых правках возникает конфликт. Сохранение не перезаписывает неподтверждённую внешнюю версию.
| Роль исходника | Значение при импорте |
|---|---|
color |
Цветовой RGB, заданное кодирование sRGB/linear, линейная альфа, premultiply в линейном пространстве |
normal |
Линейные данные без premultiply; явное направление normal_y=up/down |
height |
Линейные данные; выбранный канал, сила и Y используются для генерации нормали при импорте |
emission-rgb |
Straight RGB с заданным цветовым пространством; альфа текстуры не умножает эмиссию |
emission-mask |
Скаляр из выбранного канала, умножающий цвет и интенсивность эмиссии материала |
cookie-mask / mask |
Линейная скалярная маска из выбранного канала |
data |
Неизменённые линейные каналы данных |
У цветового исходника доступны Нормаль, Источник высот и Эмиссия. Выберите совместимый исходник/кадр или перетащите его из Assets. Проверяются роль, логические размеры и pivot; независимо упакованные карты сохраняют собственные UV и trim. Отключено явно отличается от Наследовать / найти. Неразрешённый AssetID остаётся виден для исправления или удаления и не заменяется другим файлом молча.
Привязка целого листа нужна импортёру для создания постоянных соответствий кадров. Она не растягивает весь лист нормалей на один спрайт. При отсутствии привязки кадра используются плоская нормаль или параметры эмиссии материала. Автопоиск _n, _e и _em превращается в ссылки по ID при импорте; явные привязки приоритетнее.
Параметры генерации принадлежат исходной карте высот и общие для всех её потребителей. Откройте связанный источник, чтобы изменить height_channel, height_strength или normal_y. Явная Нормаль имеет приоритет перед Height. Ссылка на сырую карту высот с отключённой генерацией сохраняет ID и объясняет, почему пока не даёт нормаль.
Превью, сохранение и Undo
Lit-поверхность использует подготовленный встроенный Lit, обычный кэш материалов и настоящий renderer в отдельной сессии. Перетаскивайте свет по поверхности. Высота, цвет, интенсивность, ambient, Lit/Unlit, включение нормали/эмиссии и Flip X/Y действуют только в превью. Они не вызывают игровые скрипты, не меняют сцену или prefab overrides и не сохраняют настройки импорта. Отражение корректно преобразует нормали. Эмиссия меняет собственный выход поверхности, но не освещает соседей и не создаёт Bloom. Без GPU просмотр пикселей и метаданных остаётся доступным, а Lit-превью сообщает об отсутствующем устройстве.
Для карты высот включите Генерировать нормаль при импорте и меняйте параметры. Приватный кандидат строится по снимкам изображения и текущих метаданных. Кандидат карты нормалей показывает его байты; Lit-поверхность использует тот же результат. Одновременно работает одна задача, новые правки заменяют ожидающую. Ошибка импорта или загрузки на GPU оставляет предыдущее рабочее превью. Изменившийся исходник, устаревшая версия метаданных, смена графического контекста или закрытая вкладка не могут опубликовать старый результат.
Сохранить настройки проверяет текущий кандидат карты высот, сохраняет метаданные и применяет обычную транзакцию импорта/reload. Пиксели PNG не меняются. После явного сохранения Undo/Redo также подготавливает и атомарно применяет рабочую версию артефактов в работающей сцене. Буфер метаданных остаётся несохранённым; файл на диске меняется только при следующем явном Save. При ошибке рабочего импорта runtime сохраняет last-good. Закрытие с отбрасыванием правок восстанавливает сохранённые ресурсы. Строгий экспорт редактора блокирует несохранённые метаданные и не экспортирует старую дисковую версию незаметно.
В examples/platformer откройте assets/surfaces/platform.png, перейдите к platform_height.png, измените силу, посмотрите сгенерированную нормаль и Lit-поверхность, затем сохраните и отмените изменение, сравнивая платформу в реальном уровне. В runner.png выберите существующий кадр и включайте Flip X/Y для проверки связанного кадра нормалей. Лампа показывает настоящий ассет маски эмиссии. Эти же ассеты входят в native/web export и платформер на сайте.
Диагностика
| Код | Значение и исправление |
|---|---|
TEX001 |
Некорректная настройка, роль, прямоугольник кадра, размер или pivot канала. Исправьте типизированное значение или выберите соответствующий исходник/кадр. |
TEX002 |
Явный AssetID канала не разрешается. Верните ассет, выберите совместимый ID или отключите/сбросьте привязку. Исходный ID сохраняется. |
TEX003 |
Подготовка кандидата или импорт завершились ошибкой. Исправьте причину из диагностики импортёра; предыдущая рабочая версия остаётся активной. |
Inspector каналов, команды texture.get/schema/set/channel/channel-reset/reset/validate/apply и структурированные операции используют одну схему и одинаковые проверки. Из панели можно перейти к зависимостям и потребителям. Байты импортированного артефакта не становятся редактируемым документом.