Search
Write a publication
Pull to refresh

3dfx в браузере (Glide -> WebGL)

Level of difficultyEasy
Reading time7 min
Views3K
Лого 3dfx
Лого 3dfx

Технологии 3dfx Interactive навсегда остались в истории как символ золотой эпохи компьютерных игр. Их графические ускорители Voodoo открыли эру аппаратного ускорения 3D-графики, а API Glide стал неотъемлемой частью многих культовых игр конца 90-х. 

Сегодня, спустя более трех десятилетий, я попытался вернуть это наследие прямо в браузер — без плагинов и нативных компонентов.

В России часто люди не могли позволить себе такую роскошь, как видеокарты Voodoo. Мне удалось купить Voodoo 3 уже в тот момент, когда компания доживала свои последние дни и была куплена Nvidia. Естественно, Glide уже нигде не использовался, а Direct3D стал стандартом. Но я всегда знал, что существовала такая технология как Glide, и что она делала графику в таких крутых играх, как NFS 3 невероятной. В своё время я не мог этим насладиться. И вот, спустя много лет, я добился того, чтобы Glide работал в браузере, и наконец-то могу посмотреть, что же это за Glide такой.

3dfx в js-dos

Я — автор проекта js-dos  и занимаюсь развитием сообщества DOS Zone, где мы запускаем классические игры прямо в браузере. За последние годы нам удалось запустить множество культовых игр. Мы давно умеем запускать Windows 9x игры с 3D-ускорением. Но, многие 3D-игры, особенно конца 90-х, тормозят в браузере из-за высокой нагрузки на CPU и программного рендеринга (тоже на CPU). DOSBox-X из коробки позволяет эмулировать Glide, но и эта эмуляция в браузере выполняется в режиме программного рендеринга, что медленно, и как оказывается — ещё и отличается качеством картинки в худшую сторону.

У меня была надежда, что если получится прикрутить WebGL к Glide то производительность таких игр значительно улучшится. Так оно и вышло. Некоторые игры не просто стали работать быстрее, но и выглядеть лучше.

Теперь, спустя годы, я могу не только увидеть, как выглядела графика с Glide, но и запустить её прямо в браузере — без плагинов, установок и сложной настройки.

Как работает эмуляция 3dfx Voodoo

3dfx Voodoo — это не просто видеокарта. Это был отдельный 3D-ускоритель, который подключался к основной 2D-карте и перехватывал видеосигнал при запуске 3D-приложения. Он имел свой собственный набор команд и буферов, работал с фиксированной глубиной цвета (обычно 16 бит), и предлагал крайне ограниченный, но зато очень быстрый набор 3D-функций: трансформация, растеризация, билинейная фильтрация, Z-буфер, альфа-блендинг.

Низкоуровневая эмуляция Glide в DOSBox-X (режим по умолчанию)

Этот режим эмуляции поддерживается в DOSBox-X уже давно. Он эмулирует оригинальный чипсет 3dfx Voodoo 1 и, таким образом, совместим с официальными драйверами 3dfx для DOS и Windows 9x. Это самый простой в использовании режим, он включён по умолчанию. В зависимости от игры, может не потребоваться никакой настройки — достаточно выбрать 3dfx Voodoo в программе установки.

Основной недостаток этого режима в том, что рендеринг осуществляется средствами процессора. Это чистая программная реализация, в которой Glide-команды обрабатываются внутренним программным 3D-рендерером, без использования GPU. Эта модель полностью кроссплатформенная и работает даже в средах без аппаратного ускорения, но обладает самым низким качеством и производительностью.

Именно этот тип эмуляций использовался в браузере. По факту в этом режиме игры не играбельны и качество картинки отстает от желаемого.

Высокоуровневая эмуляция

Этот режим работает только для DOS-игр, использующих библиотеку GLIDE2X.OVL, или для Windows 9x-игр, использующих GLIDE2X.DLL. Суть метода заключается в том, что мы заменяем оригинальные драйверы 3dfx специальными обёртками, которые ретранслируют вызовы API Glide на хост (например, в браузер). На хосте устанавливается специальная Glide-библиотека (например, OpenGlide), которая обрабатывает эти вызовы и транслирует их в нативное API системы.

Этот метод эмуляции очень эффективен, но сложен в реализации, особенно в браузере, поскольку его реализация использует динамическую загрузку библиотек. Кроме того, в браузер необходимо портировать одну из библиотек, реализующих API Glide.

Низкоуровневая эмуляция Glide в DOSBox-X (OpenGL)

Для низкоуровневой эмуляции существует оптимизация, которая использует для рендеринга не CPU, а GPU (OpenGL). Она работает по тому же принципу, что и обычный режим — полностью эмулируется видеокарта Voodoo с её регистрами, буферами и т.д., но на этапе растеризации используется API OpenGL вместо CPU.

Низкоуровневая эмуляция является лучшим решением, потому что она полностью воспроизводит поведение Voodoo, и с ней работают стандартные драйверы, включая драйверы MiniGL (OpenGL-обёртки через Glide). Использование OpenGL решает основные проблемы с производительностью, а также упрощает реализацию на стороне браузера.

Тем не менее, потенциально реализация высокоуровневого режима может быть ещё быстрее, поскольку ей не требуется пересобирать рендеринг из низкоуровневых команд — она сразу работает с высокоуровневым API. Однако стоит учитывать мощность современных GPU: для нашей задачи — эмуляции игр 90-х — некоторая потеря производительности не критична.

Поэтому, в js-dos реализовано аппаратное ускорение для низкоуровневого режима эмуляции Glide.

Как работает ускорение Glide в браузере

Как уже говорилось, Voodoo — это не полноценная видеокарта. Она вступает в работу только при активации API Glide, а до этого момента вывод на экран осуществляется штатной видеокартой.

DOSBox-X строго следует этой логике в процессе эмуляции: до тех пор, пока 3dfx не используется, рендеринг осуществляется через встроенную карту (обычно эмулируется видеокарта S3). В момент инициализации 3dfx, DOSBox-X создаёт новое окно с OpenGL-контекстом и использует его для рендеринга изображения — до тех пор, пока активен 3dfx.

Иными словами, DOSBox-X «жонглирует» графическими контекстами во время эмуляции.

Но как добиться такого же эффекта в браузере? Напомним, js-dos — уникальное решение в области DOS-эмуляции: он работает внутри Web Worker и вообще не создаёт окон. Рендеринг в обычном режиме выполняется в буфер, который затем используется клиентским кодом для отображения.

Однако, для аппаратного ускорения Voodoo необходим контекст WebGL. К счастью, благодаря современным стандартам HTML, стало возможно передавать элемент <canvas> в Worker. Именно этот механизм используется в js-dos: в режиме аппаратного ускорения клиентский canvas передаётся в Worker, где на его основе создаётся WebGL-контекст и производится рендеринг.

OpenGL -> WebGL

DOSBox-X использует OpenGL 2.0 с ARB-расширениями (шейдерами) для реализации аппаратного ускорения Glide. Стоит ли говорить, что OpenGL 2.0 уже давно устарел и не поддерживается в WebGL 1/2. WebGL примерно соответствует стандартам OpenGL ES 2.0 / 3.0.

Первая задача на пути к ускоренному Glide в браузере — научить DOSBox-X рендерить через GLES 2/3. Самый надёжный способ добиться этого — вручную переписать весь рендеринг под GLES. Однако мне очень хотелось как можно скорее увидеть рабочий результат, поэтому я решил использовать библиотеку GL4ES, которая реализует OpenGL 1.x/2.x поверх GLES.

Мне удалось достаточно быстро интегрировать эту библиотеку в DOSBox-X, и аппаратное ускорение Glide заработало через GLES 2.

Однако в браузере всё оказалось не так просто:

Мелькающее изображение

В отличие от нативного рендеринга, рендеринг в браузере не имеет прямых аналогов функций вроде SwapBuffers, glFlush или glCommit. Обычная эмуляция предполагает, что фрагменты изображения рисуются последовательно, и когда кадр полностью готов — вызывается SwapBuffers, после чего изображение отображается на экране.

Однако в браузере всё устроено иначе: он ожидает, что весь рендеринг будет завершён в пределах одного JavaScript-кадра (одного вызова requestAnimationFrame). В случае Glide-эмуляции рендеринг одного кадра занимает несколько JS-кадров, из-за чего на экране мы видим "распадающееся" изображение — фрагменты промежуточных состояний кадра.

Решить эту проблему удалось с помощью Frame Buffer Object (FBO). Glide в браузере рендерит изображение во внутренний виртуальный буфер, и только когда в нативном коде вызывается SwapBuffers, этот буфер копируется на экран.

Отсутствие текстур

При первых запусках игры через 3dfx запускались, но полностью отсутствовали текстуры. Я долго разбирался в проблеме и в итоге выяснил, что причина кроется в библиотеке GL4ES.

В старом OpenGL текстуры можно было использовать без явного вызова glEnable(GL_TEXTURE_2D), если предварительно использовался glActiveTexture. Однако GL4ES требует явного включения текстур. Поэтому пришлось вручную вызывать glEnable(GL_TEXTURE_2D) перед каждым glBegin.

Подробнее об этом — в этом issue.

glVertexAttrib не работает для каждой вершины

Ещё одна проблема GL4ES — это поведение glVertexAttrib. В эмуляторе этот вызов используется для назначения каждому вершинному элементу определённого атрибута (например, плотности тумана или силы блендинга). Однако из-за упрощённой реализации, GL4ES использует одно значение glVertexAttrib для всех вершин, вместо индивидуального для каждой (см. issue #486).

Из-за этого в некоторых играх туман отображается некорректно.

Погрешности работы тумана
Погрешности работы тумана

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

Мне удалось решить эту проблему в нативной сборке DOSBox-X + GL4ES, но моё решение пока не заработало в браузере — вероятно, из-за особенностей эмуляции в Emscripten. Думаю, эта проблема будет решена в ближайшее время.

Медленный UI

Тормоза в UI — это как раз тот случай, где высокоуровневая эмуляция должна дать заметный прирост производительности. Суть проблемы в том, что при рендеринге меню (2D) эмуляция Voodoo выводит каждый пиксель изображения отдельным вызовом glPoint(). То есть даже для изображения размером 640×400 пикселей вызывается 256 000 команд glPoint. Даже для современных GPU это чрезмерно — никто всерьёз не рассчитывает на такой сценарий использования.

Так что не удивляйтесь, если у вас меню Carmageddon тормозит, а сама игра работает плавно — причина именно в этом. Это одна из нерешённых проблем, которую можно будет устранить в будущем.

Визуальные артефакты

В некоторых играх часто возникают мерцающие треугольники и другие графические артефакты. Хотя они не влияют на стабильность эмуляции, они могут мешать комфортной игре. Это проблема именно эмуляции в DOSBox-X, так как артефакты присутствуют и в оригинальной версии эмулятора. Было бы здорово, если бы кто-то их исправил.

Итог

Самое главное — мне удалось реализовать полноценную поддержку Glide в браузере:

DOSBox-X → GL4ES → Emscripten (FULL_ES) → WebGL.

Тестирование показало, что производительность с Glide в WebGL оказалась выше, чем в режиме программного рендеринга без Glide. Кроме того, повышение разрешения больше не влияет на производительность.

Многие игры, которые раньше были не играбельны, теперь работают в браузере. Конечно, не все — узким местом по-прежнему остаётся CPU. Но если у вас достаточно мощный компьютер, вы уже сегодня можете играть в 3D-игры с поддержкой Glide прямо в браузере.

Мы активно работаем над созданием библиотеки Glide-игр на DOS Zone.

Вот список игр уже готовых к публикации игр:

  1. Recoil

  2. Grand Theft Auto

  3. Grand Theft Auto London

  4. Grand Theft Auto 2

  5. Turok

  6. Sub Culture

  7. Carmageddon 3Dfx

  8. Hard Truck (Дальнобойщики)

  9. Future Cop LAPD

  10. NFS 2

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

Спасибо за внимание.

Tags:
Hubs:
+24
Comments0

Articles