PBR‑выпечка карт: пакетные задания на GPU

Задача страницы. Дать практический рецепт массовой PBR‑выпечки карт (normal/AO/curvature/thickness/bent‑normal/position/ID/height/roughness/metallic) и UV‑лейаута (включая UDIM) на облачных GPU: архитектуры очередей, профили GPU, конвейеры Blender headless, упаковка каналов (RMA/MRA), метрики/алерты, экономика и безопасность.

TL;DR

  • Batch‑подход: оффлайн‑очереди по ассетам/UDIM‑тайлам, Interruptible с чанк‑целью ≤ 120 с и ретраями. См. https://cloudcompute.ru/solutions/interruptible-patterns/
  • UDIM: разрезайте выпечку по тайлам (1001, 1002, …), чтобы держать VRAM и время на задание в пределах SLA.
  • GPU‑профили: 24 ГБ (Compact) — небольшие ассеты/1–2 K; 48 ГБ (Balanced) — основной поток/2–4 K; 80 ГБ (HQ) — 8 K/много карт/много UDIM.
  • Точность: cage/«экструзия луча», match by name, сглаживание нормалей, единая конвенция нормалей (OpenGL vs DirectX, Y‑flip).
  • Хранилище: исходники/ассеты в «тёплом» бакете; выпечка/временные файлы — локальный NVMe; итог → «холодное». См. https://cloudcompute.ru/solutions/storage-data/
  • Наблюдаемость: bake_map_seconds{type}, bake_udim_seconds, gpu_utilization, gpu_memory_used_bytes, p50/p95, job_queue_depth. См. https://cloudcompute.ru/solutions/monitoring-logging/
  • Экономика: Cost_per_asset = Σ_maps (c_gpu * t_map / 3600) / U * r; для библиотек — Cost_per_1K_assets. См. https://cloudcompute.ru/solutions/cost-planner/
  • Интеграция: headless‑Blender (Cycles Bake) как базовый исполнитель; аналогичным образом подключаются другие движки. См. https://cloudcompute.ru/solutions/containers-ci-cd/
  • Качество: достаточный padding (dilation), пост‑проверка швов, согласование цвет‑пространства/битности (EXR 16f для мастер‑карт).

Сценарии: когда это нужно

  • Игровые пайплайны: массовая выпечка Normal/AO/Roughness/Metallic + упаковка RMA/MRA; LOD‑версии.
  • Кино/высокое качество: EXR 16f, большие UDIM‑сеты (4–16 тайлов), curvature/thickness для шейдинга.
  • Скан‑ассеты/фотограмметрия: high→low bake c cage, position/bent‑normal для AO.
  • Каталоги/репозитории: нормализация карт, пере‑UV‑лейаут, проверка соответствия неймингу и структура каталогов. См. https://cloudcompute.ru/solutions/rendering/asset-pipelines/
  • Гибриды: интерактивная подготовка и QC на удалённых станциях, массовая выпечка в очередях. См. https://cloudcompute.ru/solutions/rendering/studio-remote/

Архитектуры/пайплайны A. Массовая выпечка по ассетам и UDIM

[Assets (hi/low/cage, UV, meta)] -> [Validator/Probe] -> [Job Queue] -> [Prefetch -> NVMe cache]
 |
 +----------------+----------------+
 | |
 [GPU Baker #1] [GPU Baker #N]
 (per-UDIM per-map tasks) (per-UDIM per-map tasks)
 | |
 [Maps (EXR/PNG/TIF)] [Maps (EXR/PNG/TIF)]
 /
 +------> [Channel Pack / QA / Catalog] -> [Cold Storage]

Ключи: разбиение по UDIM и по типу карты, идемпотентные задания, ретраи; NVMe как «горячий» кэш.

B. Интерактивный QC + оффлайн‑очередь

[Remote GPU Workstation] --approve--> [Job Queue] --> [GPU Bakers] --> [QA Report]

Художники проверяют превью/швы/паддинг на удалённых станциях. См. https://cloudcompute.ru/solutions/rendering/studio-remote/

C. Multi‑GPU узлы

[Worker Node: GPU0..GPU3]
 • Mode 1: по 1 процессу выпечки на 1 GPU (рекомендуется)
 • Mode 2: монолитные выпечки на одном крупном GPU (редко нужно)

Для 80 ГБ карт возможен шардинг через MIG. См. https://cloudcompute.ru/solutions/mig/ и общие паттерны https://cloudcompute.ru/solutions/multi-gpu/

Профили GPU/VRAM/скоростей (ориентиры)

**Профиль** **VRAM** **Типовые задачи** **Режим** **Отн. throughput (≈)** **Примечания**
**24 ГБ (Compact)** 24 ГБ Ассеты 1–2 K, 1–2 UDIM, базовый набор карт Interruptible / On‑Demand 1.0 Следить за VRAM при EXR 16f и множестве карт
**48 ГБ (Balanced)** 48 ГБ 2–4 K, до 4–8 UDIM, широкий набор карт Interruptible / On‑Demand 1.5–1.8 Базовый профиль для библиотеки ассетов
**80 ГБ (HQ)** 80 ГБ 8 K, много карт, 8–16 UDIM On‑Demand / Interruptible 2.2–2.6 Возможен MIG под параллельные мелкие задания

Индексы относительные; зависят от разрешения карт, количества UDIM и настроек bake.

Конфиги и скелеты

1) YAML‑спека задания выпечки

job:
 name: "pbr_bake_statues_set"
 mode: "interruptible" # on-demand | interruptible
 gpu_profile: "48GB-Balanced" # 24GB-Compact | 48GB-Balanced | 80GB-HQ
 chunk_seconds: 120
 retries: 3
 input:
 low_mesh: "s3://warm/assets/statue_low.fbx"
 high_mesh: "s3://warm/assets/statue_high.fbx"
 cage_mesh: "s3://warm/assets/statue_cage.fbx" # опционально
 udims: [1001, 1002, 1003]
 naming: "{asset}_{map}_{udim}.{ext}"
 maps:
 - {type: "normal", res: 4096, bitdepth: "16f", space: "tangent", y_flip: true}
 - {type: "ao", res: 4096, bitdepth: "16f", samples: 64, distance: 1.0}
 - {type: "curvature", res: 4096, bitdepth: "16f"}
 - {type: "thickness", res: 4096, bitdepth: "16f"}
 - {type: "position", res: 4096, bitdepth: "16f"}
 - {type: "id", res: 4096, bitdepth: "8", source: "material"} # или "vertex"
 bake:
 dilation: 16 # пиксели (padding)
 aa: 2 # либо samples
 ray_extrude: 0.03 # экструзия луча, если без cage
 match_by_name: true
 output:
 dir: "s3://cold/bakes/statue/"
 master_format: "exr" # exr/png/tif
 hooks:
 on_start: ["python /scripts/prefetch_nvme.py"]
 on_udim: ["python /scripts/register_udim.py"]
 on_success: ["python /scripts/pack_channels.py"]
 on_failure: ["python /scripts/requeue.py --backoff"]

2) Headless‑Blender (Cycles Bake) — Python‑скрипт

# bake_pbr.py — упрощённый пример. Запуск через: blender -b -P bake_pbr.py -- 
# --low low.fbx --high high.fbx --cage cage.fbx --udims 1001,1002 --out /out --map normal --res 4096
import bpy, sys, argparse, os
parser = argparse.ArgumentParser()
parser.add_argument("--low"); parser.add_argument("--high"); parser.add_argument("--cage", default="")
parser.add_argument("--udims"); parser.add_argument("--out"); parser.add_argument("--map")
parser.add_argument("--res", type=int, default=4096)
parser.add_argument("--dilation", type=int, default=16)
parser.add_argument("--ray_extrude", type=float, default=0.03)
parser.add_argument("--match_by_name", action="store_true")
args, _ = parser.parse_known_args(sys.argv[sys.argv.index("--")+1:])
bpy.ops.wm.read_factory_settings(use_empty=True)
scene = bpy.context.scene
scene.render.engine = 'CYCLES'
bpy.context.preferences.addons['cycles'].preferences.compute_device_type = 'CUDA'
scene.cycles.device = 'GPU'
scene.cycles.samples = 1
# Импорт
bpy.ops.import_scene.fbx(filepath=args.low); low_objs = [o for o in bpy.context.selected_objects if o.type == 'MESH']
bpy.ops.import_scene.fbx(filepath=args.high); high_objs = [o for o in bpy.context.selected_objects if o.type == 'MESH']
if args.match_by_name:
 pairs = [(lo, next((hi for hi in high_objs if hi.name.split('.')[0]==lo.name.split('.')[0]), None)) for lo in low_objs]
else:
 pairs = list(zip(low_objs, high_objs))
# Настройки bake
b = scene.render.bake
b.use_selected_to_active = True
b.margin = args.dilation
b.cage_extrusion = args.ray_extrude
if args.cage:
 bpy.ops.import_scene.fbx(filepath=args.cage)
 cage = [o for o in bpy.context.selected_objects if o.type=='MESH'][-1]
 b.use_cage = True
 b.cage_object = cage
map_type = args.map.upper()
if map_type == "NORMAL":
 b.use_clear = True; b.use_pass_direct = True; b.use_pass_indirect = False
 b.target = 'IMAGE_TEXTURES'
 b.type = 'NORMAL'
elif map_type == "AO":
 b.type = 'AO'
elif map_type == "CURVATURE":
 b.type = 'NORMAL' # замените на ваш генератор кривизны/узел в материалe
 # для продакшена используйте нодовый граф и выпечку Emission
# ... добавьте другие типы через Emission bake по нодам
# Выпечка по UDIM (создаём тайловое изображение)
udims = [int(u) for u in args.udims.split(',')]
os.makedirs(args.out, exist_ok=True)
for lo, hi in pairs:
 lo.select_set(True); hi.select_set(True)
 bpy.context.view_layer.objects.active = lo
 img = bpy.data.images.new(name=f"BAKE_{lo.name}", width=args.res, height=args.res, alpha=False, float_buffer=True, tiled=True)
 # Привязываем image к слоту материала low-модели
 for ms in lo.material_slots:
 for node in ms.material.node_tree.nodes:
 if getattr(node, "image", None):
 node.image = img
 for udim in udims:
 tile = img.tiles.new(tile_number=udim)
 tile.number = udim
 img.filepath = os.path.join(args.out, f"{lo.name}_{args.map}_{udim}.exr")
 bpy.ops.object.bake(type=b.type)
 bpy.data.images.remove(img)
 lo.select_set(False); hi.select_set(False)

Для нестандартных карт (curvature/thickness/ID) используйте нодовый граф и выпечку Emission (подготавливая соответствующий shader‑узел).

3) Упаковка каналов (RMA/MRA) после выпечки

# pack_rma.py — собираем Roughness/Metallic/AO в один RGB (RMA)
import OpenImageIO as oiio, sys
rough, metal, ao, out = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]
R = oiio.ImageBuf(rough); M = oiio.ImageBuf(metal); A = oiio.ImageBuf(ao)
spec = R.spec(); spec.nchannels = 3; spec.channelnames = ["R","G","B"]
dst = oiio.ImageBuf(spec); dst.zero()
oiio.ImageBufAlgo.setchannel(dst, 0, R)
oiio.ImageBufAlgo.setchannel(dst, 1, M)
oiio.ImageBufAlgo.setchannel(dst, 2, A)
oiio.ImageOutput.create(out).write_image(dst)

4) Docker/Compose — воркер выпечки

services:
 pbr-baker:
 image: registry.local/blender-gpu:latest
 command: ["bash","-lc","blender -b -P /opt/bake_pbr.py -- --low /in/low.fbx --high /in/high.fbx --udims 1001,1002 --out /out --map normal --res 4096 --match_by_name"]
 deploy:
 resources:
 reservations:
 devices: [ { capabilities: ["gpu"] } ]
 volumes:
 - /mnt/warm/in:/in:ro
 - /mnt/cold/out:/out
 - /nvme:/nvme
 environment:
 - TMPDIR=/nvme/tmp

5) SSE‑прогресс для панели

from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import time, json
app = FastAPI()
def stream():
 while True:
 yield "data: " + json.dumps({"map":"normal","udim":1001,"progress":0.73}) + "nn"
 time.sleep(1)
@app.get("/events")
def events():
 return StreamingResponse(stream(), media_type="text/event-stream")
``` **Наблюдаемость/метрики/алерты**

См. базовые страницы:[ https://cloudcompute.ru/solutions/monitoring-logging/](https://cloudcompute.ru/solutions/monitoring-logging/?utm_source=chatgpt.com) и[ https://cloudcompute.ru/solutions/llm-inference/observability/](https://cloudcompute.ru/solutions/llm-inference/observability/?utm_source=chatgpt.com)

**Метрики:**

- bake\_map\_seconds{type="normal|ao|..."} (histogram) — длительность выпечки карты.
- bake\_udim\_seconds{udim=1001} — длительность по тайлу.
- gpu\_utilization, gpu\_memory\_used\_bytes, io\_read\_mb\_s, io\_write\_mb\_s.
- job\_queue\_depth, tasks\_inflight, retry\_total.
- Качество: edge\_bleed\_px (оценка паддинга), seam\_artifacts\_rate (детектор швов по маске).

**Алерты:**

- p95 bake\_map\_seconds растёт > X% к эталону N минут.
- gpu\_utilization < 60% при глубокой очереди → узкое место I/O/CPU/нодовая конкуренция.
- gpu\_memory\_used\_bytes → лимит VRAM → уменьшить размер карт/UDIM‑пакет, перейти на больший профиль.
- retry\_total аномально высок → некорректный cage/экструзия/пересечения.

## **Экономика и формулы**

См.[ https://cloudcompute.ru/solutions/cost-planner/](https://cloudcompute.ru/solutions/cost-planner/?utm_source=chatgpt.com) и <https://cloudcompute.ru/solutions/throughput-vs-latency/>

**Стоимость выпечки ассета:**

Cost\_per\_asset = ( Σ\_maps t\_map + Overhead\_io ) \* c\_gpu / 3600 / U \* r

где t\_map — время выпечки каждой карты (в сек), c\_gpu — цена/час, U — целевая загрузка GPU (0..1), r — retry‑factor (Interruptible).

**UDIM‑разбиение (параллель):**

t\_map ≈ max(T\_udim\_i) + t\_merge

при достаточном количестве воркеров; иначе учитываем расписание по слотам.

**Библиотека из K ассетов:**

Cost\_per\_1K\_assets ≈ 1000 \* Cost\_per\_asset

**Когда выгоден Interruptible:** если Discount\_gain &gt; (r - 1) и каждая единица работы (UDIM/карта) укладывается в чанк ≤ 120 с.

**Безопасность/политики**

См.[ https://cloudcompute.ru/solutions/security/](https://cloudcompute.ru/solutions/security/?utm_source=chatgpt.com)

- **Приватные ассеты/сканы** — доступ по временным токенам, no‑list бакетов, изоляция проектов.
- **Секреты** (ключи DCC/плагины) — через секрет‑хранилище; запрет логирования.
- **Лицензии** — контролируйте seat‑ы, аудит checkout/check‑in.
- **Ретеншн** — сырые и промежуточные карты → «холодное» по регламенту; храните только мастер‑EXR/готовые пакеты.
- **Аудит** — логировать, кто и когда выпекал/утверждал версии карт.

**Траблшутинг (симптом → причина → решение)**

<table><tbody><tr><td>**Симптом**

</td><td>**Причина**

</td><td>**Решение**

</td></tr><tr><td>Швы/просветы по UV

</td><td>Недостаточный padding

</td><td>Увеличить dilation (16–32 px), проверить фильтрацию в DCC

</td></tr><tr><td>Волнистые/ломаные нормали

</td><td>Неправильный smoothing/разный tangent space

</td><td>Единые настройки, Y‑flip (OpenGL vs DirectX), match by name

</td></tr><tr><td>Чёрные пятна на AO/curvature

</td><td>Слишком мала/велика экструзия луча

</td><td>Подобрать ray\_extrude или использовать cage

</td></tr><tr><td>Утечки света между UDIM

</td><td>Перекрытия UV или неверный UDIM диапазон

</td><td>Проверить UV‑оверлапы, корректность списка UDIM

</td></tr><tr><td>Жрёт VRAM/OOM

</td><td>Слишком большой пакет карт/EXR 16f

</td><td>Делить по мапам/UDIM, перейти на 48–80 ГБ, EXR 16f только для мастеров

</td></tr><tr><td>Медленно/низкий util GPU

</td><td>Узкое место I/O/многопоточность

</td><td>NVMe‑кэш, увеличить параллелизм «1 процесс = 1 GPU», профилировать I/O

</td></tr><tr><td>Разные результаты на нодах

</td><td>Версии Blender/плагинов различаются

</td><td>Единый контейнер‑образ, smoke‑бэйк эталона

</td></tr><tr><td>Сдвиги при pack RMA

</td><td>Разные резолюции/гамма

</td><td>Нормализовать размер/формат, линейное пространство, проверка гаммы

</td></tr></tbody></table>

## **Как запустить в cloudcompute.ru**

1. **Шаблон**:[ https://cloudcompute.ru/solutions/templates/](https://cloudcompute.ru/solutions/templates/?utm_source=chatgpt.com)
 - «PBR Bake (Blender headless)» — оффлайн очереди.
 - «Remote GPU workstation» — интерактивный QC.
2. **Профиль GPU**: 24/48/80 ГБ по таблице выше; большие UDIM/8 K — 80 ГБ (HQ).
3. **Режим**: **Interruptible** с UDIM‑/map‑разбиением (чанк ≤ 120 с), критичные мастера — **On‑Demand**. См. <https://cloudcompute.ru/solutions/interruptible-patterns/>
4. **Хранилище/кэш**: «тёплое» для ассетов, NVMe для выпечки/временных файлов, «холодное» для архивов. См.[ https://cloudcompute.ru/solutions/storage-data/](https://cloudcompute.ru/solutions/storage-data/?utm_source=chatgpt.com)
5. **Оркестрация/CI**: YAML‑спеки задач; единый контейнер‑образ; smoke‑бэйк эталонного ассета. См. https://cloudcompute.ru/solutions/containers-ci-cd/
6. **Наблюдаемость**: метрики bake\_map\_seconds, GPU/VRAM/I‑O, alerты p95; отчёт QC по швам/паддингу. См.[ https://cloudcompute.ru/solutions/monitoring-logging/](https://cloudcompute.ru/solutions/monitoring-logging/?utm_source=chatgpt.com)

**Чек‑лист перед продом**

- Единый контейнер (Blender/скрипты), версии зафиксированы; smoke‑бэйк пройден.
- Конвенции: tangent space, Y‑flip, smoothing, match‑by‑name — задокументированы.
- UDIM‑разбиение и dilation протестированы; швов нет.
- Чанк ≤ 120 с на UDIM/карту; ретраи включены.
- NVMe‑кэш и префетч активны; I/O не бутылочное горлышко.
- Метрики/алерты p50/p95 заведены; дашборды доступны команде.
- Экономика: Cost\_per\_asset, Cost\_per\_1K\_assets посчитаны для выбранного профиля.
- Политики безопасности/ретенции применены; логи без секретов.

**Навигация**

- Хаб «Рендеринг»: <https://cloudcompute.ru/solutions/rendering/>
- Пайплайны ассетов:[ https://cloudcompute.ru/solutions/rendering/asset-pipelines/](https://cloudcompute.ru/solutions/rendering/asset-pipelines/)
- Blender/Cycles (headless): <https://cloudcompute.ru/solutions/rendering/blender/>
- Redshift/Octane/V‑Ray: <https://cloudcompute.ru/solutions/rendering/redshift/>
- Houdini Karma XPU: <https://cloudcompute.ru/solutions/rendering/houdini-karma/>
- Unreal Engine: <https://cloudcompute.ru/solutions/rendering/unreal/>
- Удалённые станции: <https://cloudcompute.ru/solutions/rendering/studio-remote/>
- Деноайзинг: <https://cloudcompute.ru/solutions/rendering/de-noising/>
- Транскодирование: <https://cloudcompute.ru/solutions/rendering/video-transcode/>
- Шаблоны запусков:[ https://cloudcompute.ru/solutions/templates/](https://cloudcompute.ru/solutions/templates/?utm_source=chatgpt.com)
- Хранилище/данные:[ https://cloudcompute.ru/solutions/storage-data/](https://cloudcompute.ru/solutions/storage-data/?utm_source=chatgpt.com)
- Multi‑GPU/MIG:[ https://cloudcompute.ru/solutions/multi-gpu/](https://cloudcompute.ru/solutions/multi-gpu/?utm_source=chatgpt.com) • <https://cloudcompute.ru/solutions/mig/>
- Оптимизация:[ https://cloudcompute.ru/solutions/performance-tuning/](https://cloudcompute.ru/solutions/performance-tuning/?utm_source=chatgpt.com)
- Мониторинг/логи:[ https://cloudcompute.ru/solutions/monitoring-logging/](https://cloudcompute.ru/solutions/monitoring-logging/?utm_source=chatgpt.com)
- Throughput vs Latency: <https://cloudcompute.ru/solutions/throughput-vs-latency/>
- Interruptible‑паттерны: <https://cloudcompute.ru/solutions/interruptible-patterns/>
- CI/CD: <https://cloudcompute.ru/solutions/containers-ci-cd>

Готовы запустить?

Запустить GPU-сервер