vault backup: 2025-04-18 23:10:56

This commit is contained in:
sShemet
2025-04-18 23:10:56 +05:00
parent 8f4ceebaf3
commit 491d7fc92a
15 changed files with 421 additions and 17 deletions

View File

@@ -0,0 +1,137 @@
### **Сортировка полигонов на 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/).