Программирование 3D-графики на Glide для 3dfx Voodoo: текстуры и практические сложности

Это вторая часть масштабного цикла статей, посвященного легендарной видеокарте 3dfx Voodoo. Из-за ограничений платформы на длину поста материал пришлось разделить. Настоятельно рекомендую начать знакомство с темой с первой части.

На скриншоте виден промежуточный результат: текстура нанесена, но с искажениями из-за некорректных настроек сэмплера. Также заметны артефакты, вызванные отсутствием сортировки по глубине (Z-сортировки).

Пока результат выглядит скромно, не правда ли? Где же детализированные текстуры? Об этом мы подробно поговорим в следующем разделе!

❯ Работа с текстурами в Glide


Модели без текстур, даже с подсветкой, выглядят плоско и невыразительно. Современные графические API сильно упрощают жизнь разработчика: драйвер сам управляет видеопамятью, а программист просто создает объект текстуры, указывает параметры, и система сама заботится о загрузке и даже генерации мип-уровней.

Glide, API для 3dfx Voodoo, предлагал совершенно иной, более низкоуровневый подход. Здесь не было абстракции «текстура как объект». Вместо этого программист получал прямой доступ к адресному пространству памяти текстурного модуля (TMU) и мог размещать данные текстур где угодно в этих пределах. После загрузки в видеопамять сохранялся указатель на текстуру, который затем передавался в комбайнер (блок смешивания) для использования при рендеринге. Интересно, что сам TMU не знал характеристик текстуры — всю необходимую информацию (размер, формат) ему сообщал программист.

TMU поддерживал несколько форматов пикселей: 8-битный RGB332, 16-битный RGB565, палитровый режим и собственный формат сжатия NCC. Важно отметить, что для корректной работы с форматом RGB565 в 3dfx требовался специальный порядок байт, иначе текстуры превращались в «кашу». К счастью, Glide предоставлял вспомогательные функции, такие как gu3dfGetInfo и gu3dfLoad, для удобной загрузки текстур с диска, а также утилиту texUS для их подготовки и создания полного набора мип-уровней.

Кстати: В музеях Москвы протестируют приложение для посетителей.

Для планирования использования памяти существовала функция grTexCalcMemRequired, которая рассчитывала необходимый объем с учетом мип-уровней, формата и требований к выравниванию.

В рамках демонстрационного проекта я не стал реализовывать сложный аллокатор видеопамяти. Поскольку игра загружает все ресурсы уровня единовременно, можно просто выделить и освободить всю необходимую память при переходе между сценами.

Пример кода для расчета размера текстуры: https://pastecode.io/s/ruf14177

Следующий шаг — загрузка подготовленных данных текстуры в видеопамять с помощью функции grTexDownloadMipMap.

Пример кода для загрузки текстуры: https://pastecode.io/s/260k0nrr

В отличие от современного OpenGL с его glBindTexture, в Glide для указания, какую текстуру использовать, применялась функция grTexSource. Она принимала адрес в видеопамяти, где начинается самый детальный мип-уровень, а также структуру с параметрами текстуры, которая хранилась в оперативной памяти CPU.

Пример кода для настройки источника текстуры: https://pastecode.io/s/6ouq99eo

Однако если запустить программу на этом этапе, текстуры мы не увидим. Необходимо дополнительно настроить сэмплер (блок выборки текселей) и комбайнер. Для простейшего случая мы настроим комбайнеры на вывод текстуры «как есть», без умножения на цвет вершины. Альфа-канал мы игнорируем, так как в нашей конфигурации отсутствует альфа-буфер.

Запускаем исправленную программу и получаем результат:


Вот она — первая полностью текстурированная 3D-модель! Фактически мы вручную реализовали половину функционала видеодрайвера, и конечный результат, несмотря на всю сложность пройденного пути, выглядит отлично! Конечно, это еще не игра — создание полноценного геймплея потребовало бы отдельного, не менее объемного материала.

❯ Проблемы с практической реализацией



К сожалению, в этой части не будет демонстрации работы на реальном железе. Изначально я планировал использовать для тестов материнскую плату с разъемом AGP на процессоре Intel 478. Однако я упустил из виду важный нюанс: существовало несколько физических и электрических стандартов AGP, и платформа 478 использовала поздние версии с напряжением 1,5 В/0,8 В, которые могли быть несовместимы со старыми видеокартами.

Поскольку материал нужно было подготовить к определенному сроку, а заказ комплектующих почтой затянулся бы из-за новогодних праздников, я начал искать локальных поставщиков в надежде найти материнскую плату с более старым сокетом PGA370 в любом состоянии.

Поиски увенчались успехом! Нашлась материнская плата ECS P6IPAT на чипсете Intel 815 с «универсальным» разъемом AGP, поддерживающим все основные стандарты. Продавец отдал ее всего за 100 рублей, вместе с процессором и кулером. Однако затем начались трудности: плата потребовала замены всех электролитических конденсаторов (пришлось импровизировать с номиналами), и она заработала только с третьей попытки. Добавила проблем и установка Windows — отказал старый IDE-диск. Из-за этих непредвиденных сложностей практическая часть тестирования серьезно затянулась.


❯ Итоги и выводы


Подводя итог, можно сказать, что для создания 3D-игры в 90-е годы программисту требовалось как минимум:

  1. Понимание математики: Знание основ преобразования геометрии, работы с матрицами (хотя теоретически можно обойтись и без них, но это крайне непрактично).

  2. Понимание аппаратной части: Четкое представление о конвейере видеокарты, состояниях, комбайнерах, управлении видеопамятью, организации кадрового буфера и буфера глубины (Z-буфера).

  3. Знание алгоритмов рендеринга: Понимание ключевых методов: перспективно-корректного интерполяции (perspective-correct interpolation), Z-буферизации, форматов вершин, фильтрации текстур, мипмэппинга, затенения по Гуро, методов анимации и многого другого.


Материал получился очень объемным и информативным. Я постарался собрать и структурировать все знания об архитектуре 3dfx Voodoo, которые изучал, и поделиться не только ими, но и общими принципами низкоуровневого программирования графики, объясняя, как изображение строится «под капотом» видеокарты.

Что касается личных историй о 3dfx в странах СНГ: я родился в 2001 году, поэтому могу судить лишь по рассказам и архивным материалам. А каким был ваш опыт знакомства с 3dfx Voodoo? Делитесь воспоминаниями в комментариях!
Надеюсь, статья была вам интересна. Она готовилась в авральном режиме, за несколько бессонных ночей, чтобы успеть к Новому году! Больше технических подробностей, размышлений и проектов — в моем Telegram-канале.

Статья подготовлена при поддержке TimeWeb Cloud. Подписывайтесь на меня и на @Timeweb.Cloud, чтобы не пропускать новые публикации каждую неделю!

[my]ГаджетыКупить 3D-графикуГрафикаПрограммированиеC++3dfxVoodooВидеокарты90-е ЖелезоСтарое железоРетро игрыИгрыРетроYouTube Ответить на постДлинный постTelegram (ссылка) 29

Больше интересных статей здесь: Гаджеты.

Источник статьи: Продолжение поста «Игровая легенда из 90-х: Как работала 3dfx Voodoo "под капотом"? Пишем 3D-приложение нуля на Glide (1/2)».