aboutsummaryrefslogtreecommitdiff
path: root/docs/specs/render.md
blob: 06feaef1ff272dccfc55d1ece75534196e60c978 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# Render pipeline

Документ описывает полный процесс рендера кадра в движке Parkan: Iron Strategy, без привязки к внутренним адресам/именам дизассемблера.

Связанные страницы:

- [MSH core](msh-core.md)
- [MSH animation](msh-animation.md)
- [Material (`MAT0`)](material.md)
- [Wear table (`WEAR`)](wear.md)
- [Texture (`Texm`)](texture.md)
- [FXID](fxid.md)

## 1. Инициализация рендера

На старте движок:

1. Выбирает видеодрайвер (software или аппаратный).
2. Создаёт render backend.
3. Подключает библиотеки ресурсов:
   - `Material.lib`
   - `Textures.lib`
   - `LightMap.lib`
   - `palettes.lib`
4. Инициализирует менеджеры:
   - material manager
   - texture/lightmap cache
   - effect manager
5. Загружает базовые world-ресурсы (включая наборы объектов сцены).

## 2. Структура кадра

Кадр выполняется как последовательность:

1. `Simulation update`
2. `Animation sampling`
3. `Visibility / culling`
4. `Material + texture resolve`
5. `Mesh draw`
6. `FX update + draw`
7. `UI/overlay draw`
8. `Present`

## 3. Geometry path

### 3.1. Подготовка инстансов

Для каждого видимого объекта:

1. Вычисляется `world transform`.
2. Выбирается `LOD`.
3. Для каждого узла выбирается slot через `Res1`.

### 3.2. Culling

Сначала отсекаются узлы/слоты по bounds (`AABB/sphere`) из `Res2`.

### 3.3. Батчи

Для каждого прошедшего slot:

1. Берутся батчи из диапазона `Res13`.
2. По `materialIndex` выбирается активный материал.
3. По фазе материала выбирается текстура/lightmap.
4. Выполняется `DrawIndexedPrimitive`:
   - индексный диапазон: `indexStart/indexCount`
   - базовая вершина: `baseVertex`
   - индексы читаются из `Res6`
   - вершины/атрибуты читаются из `Res3/Res4/Res5` (+ optional streams)

## 4. Animation path

Для анимированных моделей:

1. Для узла выбирается ключ через `Res19` и fallback-логику.
2. Декодируются `pos + quat` из `Res8`.
3. При необходимости выполняется blending двух сэмплов.
4. Узловая матрица передаётся в geometry path.

## 5. Material path

Material pipeline на кадре:

1. По material handle выбирается запись `MAT0`.
2. По игровому времени выбирается текущая фаза.
3. Применяются коэффициенты фазы (цвет/альфа/параметры).
4. Резолвятся ссылки на texture/lightmap.
5. Невалидные ссылки обрабатываются fallback-стратегией.

Практическая цепочка привязки для большинства `*.msh` ассетов из `*.rlb`:

1. Для модели выбирается одноимённый `WEAR` (`<model_stem>.wea`).
2. Из `WEAR` берётся material-слот (по имени, `legacyId` не участвует в выборе).
3. В `Material.lib` ищется `MAT0` по имени (`DEFAULT`, затем индекс `0` как fallback).
4. Из выбранной material-фазы берётся `textureName`.
5. `Texm` ищется в `Textures.lib` (и/или lightmap-архиве для lightmap-ветки).

## 6. Texture path

При резолве текстуры:

1. Ищется `Texm` entry по имени.
2. Проверяется и декодируется заголовок.
3. При необходимости применяется `mipSkip`.
4. Для indexed-формата подключается палитра.
5. Optional `Page` chunk интерпретируется как atlas-таблица.
6. Объект текстуры кладётся/берётся из cache.

## 7. FX path

Эффекты выполняются параллельно mesh-рендеру:

1. Для активных инстансов FX вычисляется runtime-коэффициент (`time_mode + flags`).
2. Команды FX обновляют внутреннее состояние.
3. Команды emit-этапа формируют примитивы/батчи эффектов.
4. Эффекты рисуются в 3D-кадре с собственным счётчиком батчей.

## 8. Псевдокод кадра

```c
void RenderFrame(Scene* scene, Camera* cam, float dt) {
    UpdateGame(scene, dt);

    for (Object* obj : scene->objects) {
        if (!obj->visible) continue;

        UpdateObjectAnimation(obj, scene->time);
        BuildObjectNodeTransforms(obj);
    }

    BeginFrame(cam);

    for (Object* obj : scene->objects) {
        if (!obj->visible) continue;
        RenderObjectMeshes(obj, cam);
    }

    UpdateAndRenderFx(scene, dt, cam);
    RenderUI(scene);
    Present();
}
```

## 9. Критичные условия для 1:1

1. Та же политика округления/FP для анимации и FX.
2. Та же логика fallback по материалам и текстурам.
3. Та же очередность стадий кадра.
4. Тот же контракт интерпретации `Res1/Res2/Res13/Res6`.
5. Тот же контракт `FXID` командного потока.

## 10. Статус валидации

- Порядок кадра и подключение `Material.lib / Textures.lib / LightMap.lib` подтверждены текущей runtime-валидацией проекта.
- Детальные инварианты форматов зафиксированы в `tools/msh_doc_validator.py` и `tools/fxid_abs100_audit.py`.

## 11. Статус покрытия и что осталось до 100%

Закрыто:

1. Высокоуровневый кадр: simulation -> animation -> culling -> material/texture resolve -> mesh draw -> fx -> ui -> present.
2. Связка MSH/MAT0/WEAR/Texm/FXID в едином runtime-процессе.
3. Форматная валидация входных данных на полном retail-корпусе.

Осталось:

1. Полный pixel-parity контур с эталонными кадрами оригинального рендера по набору моделей/сцен.
2. Формализация всех render-state деталей (точные blend/depth/cull/state transitions) для гарантии 1:1 в каждом draw-pass.
3. Полный coverage-пакет по динамическим веткам (FX-heavy кадры, сложные material-режимы, lightmap-комбинации).