Спрайтовое кэширование
Спрайты не умерли! Они живее всех живых!
Для начала, попытайтесь найти
принципиальную разницу между этими скриншотами (сделаны в Doomsday с разным 3d model visibility limit):
..не можете?.. Правильно, потому что её нет! Разница только в качестве картинки.
Что и требовалось доказать: если главная цель графики - не "eye-candy"
или "wow-factor", то совершенно не важно, какими средствами мы изображаем.
Важно,
что мы изображаем.
Прокрустово ложе 3d графики
Допустим, нам надо изобразить 30 человек. Принимая современные требования
к качеству моделей, это выйдет от тысячи полигонов на модель, и выше. Окей,
для любой современной видеокарты это пустяк..
Едем дальше: нам надо отрисовать толпу из 300 человек. Hi-end видеокарты
кряхтят, но справляются, Low-end тихо выпадают в осадок. Игра получается
только для буржуев...
Но и это не предел!.. Допустим, мы обрабатываем "живой" мир реалистичных
размеров, заботливо скрыли дали туманом... А все три тысячи неписей вдруг
возьми, да и соберись на одной рыночной площади (осетрину там, допустим,
завезли)... И всё умерло. Никакое железо не выдержит, даже если модели сделать
квадратноголовыми, как в Q2.
Вывод: стремление к фотореалистичности, конечно, хорошо, но оно жесточайшим
образом ограничивает свободу выражения тех, кто творит игровой мир. И главной
задачей дизайнеров становится сокрытие этих ограничений. Нельзя сказать,
что люди не справляются - иногда выходят такие красоты, что збудешь обо
всём, и залюбуешься... Но потом всё равно выплывает факт, что "величайший
город мира" состоит из дюжины домиков, между которыми бродят два-три десятка
неписей...
Грустно.
Что я понимаю под "спрайтовым кэшированием"
Очень просто. Периодически рендерим объект в текстуру, и используем
полученный спрайт вместо модели. Согласитесь: если это - дерево, оно далеко,
и камера двигается медленно, то лучше ничего и придумать нельзя.
С людьми сложнее - анимированные, заразы. Но их мы рассмотрим ниже.
Теперь кратко о динамическом освещении. При помощи dot3 bump mapping, который
поддерживается ещё со времён первой GeForce, можно реализовать освещение
спрайта, которое ничем не будет отличаться от освещения истинно трёхмерного
объекта (правда "стоимость" создания спрайта получится вдвое выше, так как
надо будет отрисовывать ещё и bump map)
Теоретические блуждания
Попытка первая, неудачная:
Тупо рисуем и храним в памяти все потребные фазы движения...
неписей
|
Размер спрайта
|
Требуемый на одну фазу объём видеопамяти (оно
же - минимальный объём видеопамяти под спрайты. В худшем случае, полностью
перекачивается каждый кадр), Мбайт
|
Полный объём,
3 фазы движения,
4 фазы поворота, Мбайт
(ужатой до 8 бит)
|
То же,
10 фаз движения,
8 фаз поворота, (как в Doom'е)
(ужатой до 8 бит)
|
То же,
16 фаз движения,
8 фаз поворота
(ужатой до 8 бит)
|
1000
|
16х32
(г-но)
|
2
|
24
(6)
|
160
(40)
|
256
(64)
|
1000
|
32х64
(Doom)
|
8
|
96
(24)
|
640
(160)
|
1 Гбайт
(256)
|
1000
|
64х128
(Blood)
|
32
|
384
(96)
|
2,5 Гбайт
(640)
|
4 Гбайт
(1 Гбайт)
|
...Да уж. Выглядит устрашающе. Даже если спрайты маленькие, и анимация
отвратная, и спрайты жестоко упакованы при хранении в системной памяти -
всё равно как-то нехорошо получается.
Может, тогда, раз уж приличной анимации добиться невозможно (спрайты болеют
этим с детства, это у них врождённое), то надо уж идти до конца, и оставить
в спрайтовой анимации всего три кадра: два для ходьбы (чтобы было видно,
что непись ногами перебирает, а не едет на колёсиках), и один для стояния?..
(причём, для одного направления движения).
Это позволило бы строить спрайты на лету, в момент попадания непися в
зону видимости. Правда, возникает проблема внезапной смены направления движения
огромным количеством неписей (взрыв их, допустим, отпугнул) - но тут уж
вечный компромисс между качеством картинки и FPS'ами. И пусть неписи бегут
задом наперёд, пока у программы не хватает ресурсов на их перерисовку?..
Попытка вторая, тоже неудачная:
Рисуем все спрайты на лету, меняя их когда меняется состояние непися
(скин, скорость движения, угол обзора, и пр.)
Принимаем, что <вертексов на модель> = 1000.
Неписей
|
Предел видеокарты, вертексов/кадр
|
Предел видеокарты, моделей/кадр
|
Предел видеокарты,
спрайтов/кадр (рисуется по три фазы сразу)
|
Средний период перерисовки спрайтов одного непися,
кадров (с предположением, что перерисовка спрайтов занимает треть всего
времени рендеринга)
|
Оно же, секунд (при FPS=30)
|
1000
|
100 000 (GF2)
|
100
|
33
|
100
|
3,33
|
3000
|
500 000
|
500
|
166
|
18
|
0,6
|
Хм... Следующая мысль, которая возникает: "а на кой тогда рендерить
по три фазы, и всё равно получать уродскую анимацию?.." Не лучше ли просто
держаться принципа "Один объект - один спрайт. Когда дойдут руки - перерисуем,
а пока пусть едет на одной ноге" ?..
Попытка третья
Рисуем на лету один спрайт на каждый объект, независимо от того, стоячее
ли это дерево или анимированный непись. Приоритеты и очерёдность расчитываем
за счёт "накопления изменений" - фазы, угла обзора, расстояния, и т.д...,
по которой бегущий на игрока неандерталец с дубиной будет перерисовываться
чаще, чем куст у горизонта.
Неписей
|
Предел видеокарты, моделей/кадр
|
Средний период перерисовки спрайтов одного непися,
кадров (с предположением, что перерисовка спрайтов занимает треть всего
времени рендеринга)
|
Оно же, секунд (при FPS=30)
|
Средний FPS одного непися
(при общем FPS=30)
|
1000
|
100
|
33
|
1
|
1
|
1000
|
500
|
6
|
0,2
|
6
|
3000
|
500
|
18
|
0,6
|
1,6
|
Что ж... Один кадр в секунду для чудовищной толпы персонажей на GeForce2
- не такой уж плохой результат, тем более, если перемещаться и они и игрок
будут на честных 30FPS. Тем более, что на hi-end получатся терпимые 6 FPS
(это на полном экране они выглядят гадостью, а для анимации далёкого объекта
- вполне даже ничего)
К тому же, этот алгоритм - простейший из всех возможных.
Обсуждение
идеи на форуме GameDev.ru