- Дмитрий СЫТНИК
-
(Продолжение, начало в IZone
98 )
Кривые
Кривые впервые появились
в Quake III (32-разрядную демо-версию Arena
для Windows 9x можно скачать по адресу http://download1.activision.com/activision/
quake3/demo/Q3ADemo.exe, 46.6 Мб). Это и "язык"
на первом уровне, и кривые арки, которые
тоже состоят из множества
треугольников. Они создаются не в
процессе моделирования уровня, а на
этапе его загрузки. Их количество и
гладкость могут варьироваться -
естественно, это напрямую влияет на
скорость построения изображения.
Данные кривые тоже генерируются с
помощью интерполяции, но не линейной, а
гораздо более сложной квадратичной.
Здесь используются начальная, конечная
и промежуточная контрольные точки;
расположение последней определяет
изогнутость кривой. Из них в Quake III
строятся кривые различной гладкости.
Освещенность
Но даже подобных изысков недостаточно
для получения качественного
изображения. Дело в том, что на каждый
полигон сверху накладывается еще и так
называемая карта освещенности. Зачем?
Посмотрите вокруг. Ни один предмет, ни
одна поверхность не кажется нам
равномерно залитой каким-либо одним
цветом. Везде лежат тени, играют блики
или рефлексы. Именно это и придает
реалистичность изображению.
Современные компьютеры еще
недостаточно быстры, чтобы уметь во
время игры рассчитывать все
многообразие световых нюансов, имеющих
место в реальной жизни. Для того чтобы
придать изображению реалистичность,
используются карты освещенности.
Это обычные текстуры, которые
рассчитываются в момент проектирования
уровня. Представьте себе: дизайнер при
создании уровня разместил где-то
статические источники света и с помощью
определенных утилит рассчитал эти карты
освещенности. Чем ярче пиксель на карте
освещенности, тем ярче в этой точке свет.
При изображении сверху на пиксель
текстуры накладывается еще и пиксель
карты освещенности. Получается, что
пиксели текстуры уже зависят от
пикселей карты освещенности. Это опять-таки
достигается с помощью интерполяции.
Карты освещенности применялись еще со
времен Quake I. С помощью анимации этих карт
освещенности достигаются интересные
эффекты - например, мерцающие тени от
факелов. Или блики солнца, играющие на
поверхности воды.
Смешивание цвета может быть
произведено различными формулами. В
зависимости от этих формул также
достигаются различные графические
эффекты. Например, у нас есть
определенный цвет текстуры (назовем его
A) и определенный цвет карты
освещенности (B). Чем ярче пиксель в карте
освещенности(имеет большее число), тем
резче, к примеру, должны быть тени. И
наоборот, чем меньше индекс карты
освещенности, тем ярче должно быть
изображение текстуры в том месте. Тогда
результирующий цвет будет REZ=A/B. Все
достаточно тривиально. Конечно, точные
карты освещенности отнимают очень много
памяти. Ведь это не текстуры, которые
могут повторятся для каждой одинаковой
поверхности (например, текстура металла
для каждой металлической стены). Вернее,
карты освещенности могут повторятся, но
значительно реже, чем текстуры. Для
этого карты освещенности немножечко
упрощают. Берут не каждый пиксель карты
освещенности, а каждый n-ный пиксель.
Причем n должно быть четным числом .
Это упрощает
вычисления. Например, каждый 16-й или 8-й
пиксель. Получается карта освещенности
в 16 или 8 раз меньше - зато и менее точная.
Вспомните, что в современных игрушках
нет или очень редки четко очерченные
тени. Значения, как вы, наверное, уже
догадались, просто интерполируются
между полученными значениями, и
получается гладкая картинка. Конечно,
интерполяция производится во время
процесса построения изображения, ведь
если мы произведем предварительный
расчет, то потеряется весь смысл
уменьшения размера карты освещенности -
она все равно будут занимать в памяти
столько же места, сколько и не
уменьшенная.
То есть мы попросту экономим место на
диске. Самым простым методом для карт
освещенности является vertex lighting. Это
простейший вариант (и самый быстрый):
цвета карты освещенности берутся только
в вершинах полигона, а затем
интерполируются на все ее поверхности. В
данном случае нам достаточно лишь для
каждой вершины определить кроме
пространственных координат и двумерных
координат текстуры еще и цвет,
соответствующий цвету карты
освещенности в этой точке. Конечно, при
использовании карты освещенности не
удастся получить точную тень от
предмета, но это значительно лучше, чем
рисовать каждую тень отдельно во всех
проекциях. Тут стоит заметить, что при
использовании обычных карт
освещенности для каждой вершины надо
еще указать и координаты карты
освещенности, ведь в конце концов это
обычные текстуры. В современных
ускорителях все это делается аппаратно,
благодаря чему достигается приемлемая
скорость. Например, в Riva TNT за один такт
производится наложение двух текстур -
благодаря двум конвейерам. Так
получается так называемое "бесплатное"
мультитекстурирование - в смысле
скорости, конечно. Скорость изображения
обычной текстуры и скорость изображения
двух наложенных текстур теоретически
должны быть равны. На деле это не совсем
так - при наложении двух текстур более
часты обращения к памяти. Все
динамические эффекты делаются другими
способами.
Зеркала и туманы
Например, в Quake III для изображения
динамического освещения и теней от
выстрелов не используются возможности
библиотеки OpenGL. Кроме карт освещенности,
для придания реалистичности к
изображению может добавляться и туман (fog).
Часто туман применяется не только для
придания реалистичности изображению, но
и для ограничения области видимости
игрока, что, естественно, должно
увеличить скорость вывода. Так, иногда
применяют туман, чтобы упростить движок
и не использовать PVS. Честно говоря, этот
"ограничивающий" туман всех только
раздражает и уж никак не может считаться
признаком качественной графики в игре.
Туман создается все тем же методом
смешения цветов - он имеет определенный
цвет, который смешивается с текстурами
полигонов в зависимости от расстояния.
Чем дальше расстояние, тем большее
значение имеет туман. Зависимость цвета
тумана от расстояния может быть не
только линейной, а задаваться
различными формулами. Например,
экспоненциальными.
Хотелось бы рассказать и еще об одном
интересном эффекте, появившемся впервые
в Quake III - о зеркалах. Зеркала
изображаются в два прохода. Для этого
используется stencil buffer - специальный
буфер, предназначенный специально для
создания прозрачных областей в
изображении. Перед тем как изображается
сцена, stencil buffer обнуляется. Stencil buffer как и depth
buffer имеет размер экрана и является,
естественно, внеэкранным буфером. Если
рисуется обычный, не зеркальный полигон,
то в соответствующем месте записывается
"1". Если же рисуется полигон,
который должен быть зеркалом, то тогда в
stencil buffer ничего не записывается (предполагается,
что при обнулении в stencil buffer
записываются "0" а не какие-либо
другие значения). Получается так
называемая "вырезка" на месте
зеркального полигона. На этом первый
этап создания изображения закончен.
Далее вычисляется положение камеры
относительно зеркала. То есть все, что вы
видите в зеркале, вы видите глазами
своего отражения. Соответственно, и
уровень изображается глазами отражения.
Производится тест: если stencil buffer на месте
пикселя равен "1", то туда ничего не
записывается. А если "0", то тогда в
экранный буфер записывается значение
пикселя. Полученное изображение из
экранного буфера копируется на экран.
Построение сцены с зеркалами требует в
два раза больше ресурсов, чем обычной,
поэтому при изображении зеркал и
частота кадров падает в два раза. Stencil
buffer как раз и предназначен для создания
вот таких различных эффектов с
наложением двух изображений и вырезками
(только не путать с blending - наложением
двух изображений (прозрачные зеркала,
например)). Stencil buffer тоже поддерживается
на аппаратном уровне.
Качество
Качество графики в игрушке
определяется не только наличием
различных спецэффектов и количеством
полигонов, но также и качеством текстур?.
Качество текстур - один из важнейших
моментов: если для карт освещенности еще
можно сделать скидку и применить
размытые тени, то подобные махинации с
текстурами неубедительны. Качество
текстур определяется их размером и
глубиной цвета (16, 24 или 32 бит ). Кроме
того, не последнюю роль играет и работа
дизайнера-художника. Чем больший размер
текстуры, тем четче будут видны
различные изменения в фактуре материала,
а это значительно улучшает изображение
в игре. Например, в Quake III изначально
используются различные текстуры
размером от 64х64 до 512х512. Стоит отметить,
что текстуры должны иметь степень
двойки. Это значительно упрощает
процесс их изображения в плане
оптимизации и скорости. Если данное
условие не выполняется, то движок при
загрузке принудительно изменит их
размер к размеру, кратному степени
двойки, или просто откажется загружать
такую текстуру. Мне не известно ни
одного исключения. Но размер текстуры не
может быть бесконечно большим, иначе
происходит и перерасход памяти, и
перерасход текстур. Ведь каждое
обращение к памяти значительно тормозит
процесс построения изображения. Чтобы
решить эту проблему, разработчики из S3
предложили использовать их новый API для
использования сжатых текстур. Впервые
этот API появился в Savage4, теперь же он
поддерживается и со стороны nVidia в ее GeForce.
В Quake III тоже есть возможность
использования этого расширения. Что же
оно собой представляет? Здесь
предлагается использование в памяти
сжатых текстур. Текстуры состоят из
пикселей. Каждый имеет определенное
значение - цвет. Предположим, что у нас в
текстуре есть полоска одинакового цвета.
Например, такая: 0000000000 - десять черных
пикселей. Тогда мы можем записать эту
строчку в виде !,0,10, где "!" -
некий управляющий символ,
сигнализирующий, что следующие два
байта будут компрессированными данными,
"0" - символ, который помторяется 10
раз (знаки запятых я расставил для
разделения байтов).
Вот мы и сжали строчку
символов, причем весьма прилично.
Процесс распаковки производится
обратным путем. Когда встречаются
неповторяющиеся данные, они остаются в
нормальном виде. Этот алгоритм
применяется в PCX-файлах для хранения
информации и имеет название RLE-кодирования
(Run Length Encoding). В API от S3 используется как
этот, так и другие, более сложные
алгоритмы. Учитывая, что данные хранятся
в сжатом виде, уменьшается нагрузка на
пересылку данных и уменьшается размер
используемой памяти. Распаковка данных
ведется непосредственно во время
процесса построения изображения. Это,
конечно, дополнительная нагрузка на
видеокарту, но качество и количество
графики того стоят. К тому же и скорость
современных GPU (Graphics Processing Unit ) постоянно
увеличивается. 3dfx настаивает на своем API
для сжатия изображений в памяти - правда,
кажется, она одна ею и используется. Для
улучшения качества графики
используется и MIP mapping. Что это такое?
Очень просто: в памяти компьютера
хранятся заранее отмасштабированные (с
заранее вычисленным размером или просто
специально рассчитанные изображения)
изображения. Например, если исходная
текстура имеет размер 256х256, то в памяти
хранятся, предположим, три ее
уменьшенные копии размерами 128х128, 64х64, 32х32.
Зачем это нужно? Может быть, для
увеличения скорости? А вот и не угадали.
Скорость-то, как и размер используемой
памяти, наоборот, уменьшаются. Ведь для
того, чтобы отобразить текстуру нужного
размера на полигоне, нужно сначала
вычислить приблизительный размер
полигона, а затем уже, основываясь на
полученной информации, мы выбираем
текстуру нужного размера. Причем это так
называемое увеличение
производительности не происходит при
переходе к меньшим текстурам из-за их
относительного мизерного изменения
размера. Во всяком случае, если
производительность и возрастает, то она
лишь компенсирует затраты на вычисление
площади полигона на экране. На самом же
деле это нужно для того, чтобы более
точно создать уменьшенные текстуры, а
также для удаления всевозможных мелких
артефактов, которые могут появится при
масштабировании текстуры во время
наложения на экран.
Источник: http://www.mycomp.com.ua/
|