Files
SergObsidian/PERSONAL PROJECTS/PS1 DOCS/PS1 Ordering table.md
2025-04-18 23:10:56 +05:00

137 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### **Сортировка полигонов на PlayStation 1 (PS1)**
PS1 не имеет аппаратной поддержки **Z-буфера** (depth buffer), поэтому правильный порядок отрисовки полигонов (сортировка) критически важен для корректного отображения 3D-сцен. Вот как это реализовано:
---
## **1. Основные методы сортировки**
### **1.1. Ordering Table (OT)**
**Ordering Table** — это главный механизм сортировки на PS1.
Работает по принципу **связного списка** в VRAM, где полигоны группируются по расстоянию.
#### **Как это работает?**
1. **Инициализация OT**:
- Создаётся массив указателей (например, на 256 или 1024 элемента).
- Каждый элемент соответствует диапазону глубин (Z-значений).
2. **Добавление примитивов**:
- Для каждого полигона вычисляется **Z-координата** (например, средняя точка).
- По Z-значению выбирается **ячейка OT** (чем дальше объект, тем меньше индекс).
- Полигон добавляется в список для этой ячейки.
3. **Рендеринг**:
- OT обрабатывается **от дальних к ближним** ячейкам (от 0 до N).
- Все примитивы в одной ячейке рисуются в порядке добавления.
#### **Пример кода (PsyQ SDK)**
```c
#include <libgpu.h>
#define OT_LEN 256 // Размер Ordering Table
uint32_t ot[OT_LEN]; // Сама таблица
void init_ot() {
ClearOTagR(ot, OT_LEN); // Очистка OT
}
void add_polygon(POLY_F4 *poly, int z) {
// Вычисляем индекс в OT (0 = дальний, OT_LEN-1 = ближний)
int ot_entry = (z >> 8) & (OT_LEN - 1); // Простейшее масштабирование Z
// Добавляем полигон в OT
addPrim(ot + ot_entry, poly);
}
void render_frame() {
DrawOTag(ot + (OT_LEN - 1)); // Рендеринг OT (от ближних к дальним)
}
```
---
### **1.2. Сортировка по Bounding Box**
Для сложных объектов (например, моделей) используется **сортировка по ограничивающему объёму**:
1. Вычисляется **сфера или AABB** (коробка), охватывающая объект.
2. Сортируются **центры сфер** по Z-координате.
#### **Псевдокод**
```c
struct Object {
int center_z;
POLY_F4 *polys;
};
void sort_objects(Object *objs, int count) {
qsort(objs, count, sizeof(Object), compare_by_z);
}
int compare_by_z(const void *a, const void *b) {
return ((Object*)a)->center_z - ((Object*)b)->center_z;
}
```
---
### **1.3. Priority Groups**
Некоторые игры (например, *Crash Bandicoot*) используют **приоритетные группы**:
- Полигоны делятся на **статические** (уровень) и **динамические** (персонажи).
- Статические рисуются через OT, динамические — поверх них.
---
## **2. Оптимизации**
### **2.1. Z-Сортировка только для прозрачных объектов**
- Непрозрачные полигоны рисуются **без сортировки** (через алгоритм художника).
- Прозрачные (с полупрозрачностью) сортируются **строго от дальних к ближним**.
### **2.2. Двойная OT**
- **Одна OT для непрозрачных**, вторая — **для прозрачных** полигонов.
- Позволяет уменьшить накладные расходы.
### **2.3. Субпиксельная корректировка**
- Для борьбы с **Z-файтингом** (мерцание полигонов) используется:
- Случайное смещение Z (`z += rand() % 4`).
- Принудительный порядок для мелких объектов.
---
## **3. Пример для игры**
Допустим, у нас есть:
- **10 коробок** на разных расстояниях.
- **1 полупрозрачный полигон** (вода).
#### **Код рендеринга**
```c
// 1. Инициализация
init_ot();
// 2. Добавление непрозрачных полигонов (коробки)
for (int i = 0; i < 10; i++) {
add_polygon(&boxes[i], boxes[i].z);
}
// 3. Добавление прозрачного полигона (вода)
add_polygon(&water_poly, water_z);
// 4. Рендеринг
render_frame();
```
---
## **4. Проблемы и решения**
| Проблема | Решение |
|------------------------|----------------------------------|
| **Мерцание полигонов** | Субпиксельная корректировка Z. |
| **Низкая производительность** | Уменьшение размера OT. |
| **Неправильный порядок** | Ручная настройка приоритетов. |
---
## **5. Итог**
- **Ordering Table** — основа сортировки на PS1.
- **Для сложных сцен** комбинируют OT, Bounding Box и приоритетные группы.
- **Оптимизации** нужны для борьбы с артефактами.
Этот подход использовался в играх типа *Tekken 3* и *Resident Evil*. Для глубокого понимания изучите [документацию PsyQ](http://psx.arthus.net/sdk/PsyQ/DOCS/).