Трехмерный рендер - финал (надеюсь)

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

Меня давно, практически с самого начала работы, беспокоила мысль о том, что игра жрет слишком много памяти под текстуры.
Было устроено все просто — все текстуры хранятся в одном большом атласе 2048*4096 в ARGB формате (просто большой вектор, который получается путем вызова bitmapdata.getVector()).
Текстуры хранились уже с наложенными лайтмапами, что заставляло копировать текстуры по нескольку раз (если у меня 10 ящиков с одинаковой текстурой, но разным освещением, хранилось 10 копий текстуры).
Зачитал инт из текстуры. Записал на экран. Молодец, свободен.
Все это изначально было сделано для скорости рендера, поэтому собирался с этим смириться.

Вот посмотрел я на текущую демку и подумал «А почему это уровень висит в пустоте? Непорядок, надо добавить стенки.»
Начал добавлять стенки и понял, что с трудом влезаю в атлас, а делать 2 атласа совсем не хотелось.
Что тут началось!!1 Истерика! Молодые годы потрачены впустую! Как жить дальше?!?!

Немного успокоившись (порубался несколько дней в QuakeII и Fallout:New Vegas) начал искать выход из ситуации.
Решение, собственно, простое. Разделить текстуры и лайтмапы в разные картинки и смешивать их при рендере.
Текстуры повторяются, а лайтмапы можно хранить в меньшем разрешении.
Раньше я такую штуку тоже пробовал, но смешивать для каждого пикселя три компоненты оказалось слишком медленно.

Возвратился к Кваке.
Чем дольше играл, а играю я в нее исключительно с софтверным рендером, тем больше мне казалось, что 8-битный цвет не так уж и плохо выглядит :)

Итак, возникло решение проблемы.

Все текстуры уровня переводятся в индексированный 8-битный цвет и хранятся в тайлах 64*64 пиксела.
Все лайтмапы рендерятся в маленькое разрешение, тоже переводятся в 8-битный цвет, но со своей палитрой.
По двум палитрам считаем табличку 256*256 и рендер сокращается до 3 вычиток на пиксел (код цвета, код лайтмапа, значение из таблицы).
Лайтмапы еще дизерятся, чтобы хоть как-то сгладить низкое разрешение и маленькое количество цветов.

Попутно пришлось написать свой экспортер для статической геометрии тоже.
Потому что .obj не позволяет сохранять 2 текстурных канала, а .3ds (насколько я помню) экспортирует геометрию только в виде треугольников, что сильно ударило бы по производительности (если не писать свою объединялку треугольников во многоугольники).

Добавил стенки, оказалось, что камера постоянно в них упирается, пришлось добавить отступы и, чтобы было интересней, отступы заполнил «водой».
С водой тоже получилось интересно.
Тут долго рассказывать, но смысл в том, что воды нет :) Ложки нет, Нео.
Я имею ввиду, что она не рисуется отдельным проходом или чем-то подобным. Просто некоторые (подводные) полигоны рендерятся особо хитрым образом, так что наличие воды практически не повлияло на общую производительность.

После того, как определился со статикой, начал думать, как бы освещать пацанов.
Проблема в том, что если марин скрыт от лампочки за стенкой, на него не должен падать свет от этой самой лампочки.
Еще хотелось каким-то образом ускорить вычисление освещения, которое хоть и считается повершинно, но все же может подтормаживать, если лампочек много. 200 вершин на объект и 10 источников освещения дадут о себе знать.
Вот тут, кстати, камрады сетуют в комментах, что мои ковыряния после выхода молехилла окажутся ненужными. Совершенно согласен по части рендера, но если вы думаете, что молехилл будет решать за вас, когда и какие источники света включать/выключать, то вы заблуждаетесь. Все это придется делать самим :)

Надо считать Lighting Grid для уровня.

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

Поэтому для каждой клетки уровня я считаю просто коэффициент освещенности для каждого источника света с учетом удаленности и затененности.

Что такое удаленность понятно, а затененность как раз и зависит от загороженности стенками.

Чтобы все было гладко и мягко, для каждой клетки (уровень 18*18 клеток) для каждого источника света (их 15 штук) считается 3375 лучей.

Считается все просто:
0. Цикл по всем источникам света.
1. Цикл по всем клеткам (cx, cz).
2. Запускаем 3 вложенных цикла по 15 повторений (dz, dy, dx).
3. Получаем точку внутри клетки (x = cx*64+32+(dx*4), y=...) и так далее.
4. Проверяем дальность от точки до источника света.
5. Если далеко — выходим, иначе бросаем луч от точки до источника через геометрию уровня.
6. Если не было пересечений — добавляем вклад с учетом освещенности от этого источника в текущую клетку.
7. Усредняем.

Сначала сделал все это на AS3, но когда за полчаса посчиталось только ~10% от общего объема, начал искать другие решения.

Вспомнил, что haxe может компилироваться в нативный бинарник.
Полгода назад смотрел эту фичу, показалось прикольной, но ненужной. Сейчас вот пригодилось.
Быстренько переписал все на haxe.
Пришлось поковыряться с настройкой ( blog.touchmypixel.com/2009/04/our-possible-haxe-c-plans/ ), попутно нашел глюк в АПИ (отписал багрепорт) и снова поупражнялся в написании кода без отладчика (кажется я уже привык к этому).
В итоге за 15 минут все просчитывается, причем с тупым брутфорсным перебором.
Надо будет, конечно, добавить дерево, чтобы не проверять лишние треугольники, но это потом.

Дальше все просто.
По координатам объекта определяем клетку. Делаем билинейную интерполяцию коэффициентов (чтобы при переходе из клетки в клетку освещение изменялось мягко), если коэффициент больше нуля, добавляем в список источников, которые действуют на данный объект.
В среднем на объект действуют 2-3 источника, так что расчет происходит довольно быстро.

Ну, вроде все.
Надеюсь я полностью определился с рендером и больше добавлять ничего не буду.
Тени и окклюдеры убрал. Тени может еще сделаю просто кружочками, но ничего больше добавлять не намерен.

Демка тут: megaswf.com/serve/102077/, наверное, получилась слишком темная, но это поправимо.
Может глючить, если вылететь за стенки или сильно задрать камеру.
Кстати, отпишитесь про fps, пожалуйста. У меня ~38-45.
  • +7

Комментарии (50)

0
Здорово) Круто, что еще сказать (:
Фпс 15-20.
2гига оперативы, интегрированная видеокарта на 1гиг, проц 1.66
  • z3lf
  • z3lf
0
Блин, что-то медленно совсем.
У меня 1.9, 2 гига, правда видео помощнее, но это не должно влиять.
0
  • Rigo
  • Rigo
0
О, это круто :)
Только памяти что-то много отожрал, должно быть 50 метров.
0
0
Гм, я думал больше будет.
Плеер релизный? И памяти тоже много.
0
сейчас обновил до 10.1.102.64
0
в среднем где то на 45 фпс, при близком приближении к объектам падает до 30, редко 25
0
Хорошо, спасибо.
Близко приближаться камера не будет :)
0
fps: 60
mem: 55

cpu: i3-2.93, 2gb
0
Ага, спасибо.
0

Атлон х2 4200+(2.20 х 2.20) ОЗУ 2Гб
0
Не, ну это же не квака, чтобы в упор смотреть :)
Хотя даже в упор, ~30фпс нормально, по моему.
Спасибо.
0
Крутяк, даже кое что понял из статьи....:)

fps 50-60
mem 82

Ноут мощный, 4Гб, плеер дебажный вроде
0
Круто, спасибо.
0
fps: 20 в основном, 18-26
памяти: 91 Мб
плейер: релиз
проц: атлон 2600+
0
Упс, это как-то совсем плохо.
Ок, спасибо.
0
вобще вполне играбельно.
марины выделяются, ходят.
по опыту 20 фпс еще норм для восприятия с норм рендером (двойной буфер, практически мгновенная отрисовка подготовленного кадра, у тебя похоже так поскольку кривые рендеры и на 30+ видно), вот 15 уже будет заметно.
Ну и вроде как 25 рекомендуемый минимум.
Вот управление клавой — плохое, надо на на опустить-поднять реагировать, а у тебя похоже на кейпресс реакция.
0
Камера будет к потолку прибита. Даже вращаться запрещу.
0
По-моему зря. Теряется прелесть 3D. А у кого проц помощнее, могут даже от первого лица смотреть :) Было бы круто!
0
Оно вблизи страшно выглядит, так что лучше не надо.
0
Не нужно скромничать, выглядит вполне )
0


Респект!
0
Отлично, спасибо.
0
fps: 60
mem: 60

cpu: i7-1.6, 6gb
0
Круто, спасибо.
0

i5 4гб. летает,

крутая будет игрушка!
0
Летает, это хорошо. Надеюсь будет крутая.
Спасибо.
0
На P4 2.0Ггц и 1Гб памяти 22-24 agc в среднем, памяти 59.
Но играть можно без проблем.

На мощном ноуте 50 fps 80 памяти.
0
Спасибо за инфу.
0
C2D 3.16, 8G, GTX260, linux
flash player 64bit (10,3,162,29)
память: 58-59
fps упирается в плеер: 60 fps
0
Ого, крутая конфигурация :)
Спасибо.
0
Проделанная работа конечно поражает! Я бы просто взял готовый 3D движок и занимался бы разработкой игры, а не изобретением велосипедов. Понятно конечно, что тут чисто гиковский фан и все такое :) С нетерпением жду игрового процесса.

fps: 60
ms: 17
mem: 60

MacOS 10.6.6
2.4ghz Intel Core 2 Duo, RAM 4Gb
0
Движка с нужными мне возможностями на флэше нет, а под юнити делать не хочу.
Ну и фан, конечно.
За инфу спасибо.
0
Отличная работа! На C2D 3.33 4Gb: 60 fps и 55Mb.
Каменты про molehill умиляют. Все почему-то ждут его как волшебной палочки )
А что до написания собственного движка или использования готового… это не объяснить и не понять. Просто надо чтобы каждый делал как ему по сердцу (если эта опция доступна) и/или по нужде.
0
Да, свой движок писать это куча специфического удовольствия :)
Спасибо за инфу.
0
очень странно — 175 Мб. 53 фпс если приблизиться к моделе.
C2D e8400 3GHz, GeForce 9800 GTX+, 4GB RAM
Уж очень много памяти жрет
0
Не должен жрать, специально до ~60 уменьшал.
Буду смотреть, спасибо.
0
Возможно, что этот график считает общее потребление флеша? У меня было 70мб, но когда закрыл соседнюю игрушку, то упало до 60.

P.S. А как такой график нарисовать? :)
0
Не знаю, не проверял. Он выводит system.totalmemory или что-то такое.
В соседней теме уже смотрел?
0
да, уже установил :)
+4
Хочу высказать огромный респект автору за проделанную работу!
С удовольствием прочитал все посты об этой разработке.
Исследовательский дух с элементами доброго олдскула — это сейчас редкость.

Если появится желание работать в Альтернативе — с удовольствием обсудим! :)
  • wolf
  • wolf
0
Спасибо за высокую оценку проекта, очень лестно слышать такое именно от вас.
0
0
Спасибо за инфу, у меня также примерно.
0
fps 39
mem 60
0
Ага, спасибо, хорошо.
0
ух как то я проскипать успел это всё… заработался. Вооо — цветное освещение решает, согласись. Красота прямо. Я помню первый раз обнаружил его в SiN (или там динамическое было), но вобщем эффект потрясающий. Тени вообще не нужны, молехил выйдет — там сделаешь. Рендер выглядит очень вкусно, левел реально напоминает инкубейшен. Теперь дело за геймплеем. Но хочется думать если такая работа уже проделана, реализация геймплейной части точно будет на высоте. Успехов!
0
30-45 fps. Офигительно :)
Правда, раздражает, что когда жмешь на кнопки камера дергается.
0
Ниже 60 не опускался ниразу!

ryzed render
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.