Material
Как выглядит 3D-поверхность. Встроенные виды — статические фабрики: Material.lit (PBR),
Material.unlit (плоский), Material.video, Material.shadow — и кастомные скомпилированные шейдеры
тоже грузятся как материалы. Юниформы задаются через .set() / прокси uniforms, который приводит
каждое JS-значение к нужному нативному вызову юниформа. Присваивай мешу через mesh.material — см.
Mesh.
Обзор
const tex = await Texture.load(asset('./crate.jpg'))
const crate = Mesh.box({ material: Material.lit({ color: '#ffffff', map: tex }) })
const marker = Mesh.sphere({ material: Material.unlit({ color: '#0f0' }) })
scene.add(crate, marker)
crate.material.set('roughness', 0.3).set('metallic', 1)Фабрики
Material.lit(options?: { color?: ColorInput, map?: Texture | Canvas | null,
roughness?: number, metallic?: number }): Material // PBR с освещением
Material.unlit(options?: { color?: ColorInput, map?: Texture | Canvas | null }): Material // плоский, игнорирует свет
Material.video(map?: Texture): Material // сэмплит текстуру VideoPlayer
Material.shadow(color = '#000000aa'): Material // ловец теней: невидим, кроме мест, куда падают тени
Material.particles(options?: { map?: Texture | null, sheet?: number | [cols, rows],
emissive?: number, blend?: 'alpha' | 'add', soft?: boolean,
render?: 'point' | 'quad' | 'stretch' | 'ribbon', stretch?: number }): Material
// спрайты/квады/ленты для Particles + Trail (их дефолт)
Material.load(url: string): Promise<Material> // кастомный скомпилированный шейдер (.mat / filamat)litтребует света, чтобы быть видимым — IBL и/илиLight.sun(). Его PBR-скаляры в 0–1:roughness0 = зеркало, 1 = матовый;metallic0 = диэлектрик, 1 = металл (оба — обычные юниформы: не задан — действует дефолт шейдера, а.set('roughness', v)меняет их позже).videoберёт текстуру изVideoPlayer.texture.shadow— AR-классика: плоскость земли, показывающая только падающие на неё тени.particles— то, чем рисует системаParticles(иTrail), когда ты не передаёшь кастомный материал — сам ты его конструируешь редко: опцииParticles/Trailпробрасываются в него. Тинт/размер/поворот/непрозрачность/кадр каждой частицы приходят из кривых частиц; юниформы (sheetSize,emissive,additive,softness, плюсmode/stretchу quad-варианта) задают вид системы в целом, и опции фабрики ложатся на них.render: 'point'используетparticles.filamat; остальные режимы делятparticles-quad.filamat.
Цвет и карта
material.color = '#ff8800' // любой ColorInput
material.map = tex // Texture или Canvas (запекается в текстуру при присвоении)
material.map = null // убрать картуcolor и map — удобства поверх нижележащих юниформов (baseColor / baseColorMap у lit/unlit,
color у shadow). У lit/unlit шейдер их перемножает — baseColor × baseColorMap, оба по умолчанию
белые (незаданную карту подменяет 1×1 белая текстура) — поэтому цвет сам по себе или карта сама по
себе проходят без изменений, цвет, заданный вместе с картой, тонирует карту, а map = null
сбрасывает текстуру обратно в белую. На кастомном материале они не знают имён юниформов —
color тихий no-op, а map пишет baseColorMap; задавай свои юниформы напрямую.
Кастомные шейдеры и юниформы
const material = await Material.load(asset('./hologram.mat'))
// или из ответа, который у тебя уже есть:
const material = new Material(await fetch(asset('./hologram.mat'), { useOnce: true }))
material.set(key: string, value): this // чейнится
material.uniforms[key] = value // то же, в стиле свойства
material.uniforms.speed // чтение возвращает последнее ТВОЁ значение (нативного чтения нет)Каждый тип значения приводится к конкретному вызову юниформа:
| JS-значение | Приводится к |
|---|---|
строка '#rrggbb' |
RGB-цвет |
строка '#rrggbbaa' |
RGBA-цвет |
number |
float |
boolean |
bool |
Texture |
сэмплер (учитывает wrapS/wrapT текстуры) |
number[] / Float32Array |
массив float / вектор |
null |
очищает юниформ (текстура сбрасывается в 1×1 белую) |
строки цвета здесь должны быть #-hex — более широкие формы ColorInput (rgba(…), упакованные
int) понимает только сеттер color, не set(). И обёртка Vec3/Quat не приводится —
разверни её в обычный массив: material.set('dir', [...v]).
Окклюзионный материал сцены
scene.occlusionMaterial отдаёт окклюзионный материал сцены как обычный Material, чтобы ты задавал
на нём юниформы — см. Scene (гейтится хостом: недоступен в веб-вьювере).
Подводные камни
// ✗ ждать, что material.color сработает на кастомном шейдере
customMat.color = '#f00' // no-op: SDK не знает имя твоего юниформа
// ✓ адресуй юниформ напрямую
customMat.set('baseColor', '#ff0000')
// ✗ передавать Vec3 как значение юниформа
mat.set('lightDir', dir) // не Array — приводится к NULL, не к vec3
// ✓
mat.set('lightDir', [...dir])