CFA LogoCFA Logo Computer
Новости Статьи Магазин Драйвера Контакты
Новости
RSS канал новостей
В конце марта компания ASRock анонсировала фирменную линейку графических ускорителей Phantom Gaming. ...
Компания Huawei продолжает заниматься расширением фирменной линейки смартфонов Y Series. Очередное ...
Компания Antec в своем очередном пресс-релизе анонсировала поставки фирменной серии блоков питания ...
Компания Thermalright отчиталась о готовности нового высокопроизводительного процессорного кулера ...
Компания Biostar сообщает в официальном пресс-релизе о готовности флагманской материнской платы ...
Самое интересное
Программаторы 25 SPI FLASH Адаптеры Optibay HDD Caddy Драйвера nVidia GeForce Драйвера AMD Radeon HD Игры на DVD Сравнение видеокарт Сравнение процессоров

АРХИВ СТАТЕЙ ЖУРНАЛА «МОЙ КОМПЬЮТЕР» ЗА 2002 ГОД

Алгоритмы текстурирования

Davert davert@ukr.net

Задумывались ли вы, проходя какую-нибудь трехмерную игрушку, про то, как и почему при приближении к стене текстура на ней плавно размывается? Задумывались ли вы, как именно накладывается текстура на тот или иной полигон? Если да, то в этой статье вы найдете ответы на эти и многие другие вопросы, связанные с текстурированием.

Текстура как клочок резины

Для начала рассмотрим, как же осуществляется масштабирование текстуры перед ее наложением на полигон. Как вы уже знаете, этот процесс связан с такими понятиями как билинейная, трилинейная фильтрация и мип-мэппинг (см. статью Валерия Аксака «Трехмерный ликбез», МК №44(215)). Я предлагаю рассмотреть эти технологии на уровне алгоритмов их создания, и может, самим написать что-то подобное. Хоть, впрочем, писать вам и не придется. Чтобы проиллюстрировать материал, я сам написал программку на Delphi, исходный код которой я и буду здесь приводить.

Итак, прежде чем приступить к самим алгоритмам, хотел бы вас познакомить с понятием интерполяции. Что же это такое и зачем оно нам нужно? Интерполяция — это процесс плавного перехода одного значения в другое на некотором участке. Если мое определение звучит несколько невнятно, то попытаюсь объяснить это на примере линейной интерполяции цветов. Что получится, если проинтерполировать два цвета на участке длинной в n пикселей? Получится градиент — плавный переход от одного цвета к другому, причем по краям будут располагаться пиксели заданного цвета, а между ними промежуточные значения. Общая формула для создания градиента имеет такой вид :

Формула 1   Рис. 1

Где Ci — цвет в i-той точке, Cl— цвет в начальной, а Cn — в конечной точке, l же — длина участка, на котором проводится интерполяция (причем i<l). Если что-то непонятно, взгляните на Рис. 1. А если вашим родным языком давно является Паскаль, приведу пример создания градиента на Дельфи.

Вот таким образом мы создали на форме градиент от черного цвета к белому на участке длинной в 100 пикселей. Если с интерполяцией все понятно, поговорим о ее применении в билинейной фильтрации.

Например, есть у нас текстура размером 4x4, ее надо увеличить до размера 5x5, причем сделать это надо с минимальной потерей качества. При таком увеличении будут использоваться точки, имеющие дробные координаты (в нашем случае 1/5, 2/5 и т.д.) Можно, конечно, находить цвета ближайших пикселей, но этот метод весьма неточен; для примера, именно на этом принципе работает GDI`евский StretchDraw, а в Direct3D и OpenGL`е этот метод обозначается как NEAREST и является наименее ресурсоемким. Но его качество нас не устраивает, потому мы обратимся к билинейной фильтрации. Для более точного масштабирования нам необходимы точные значения цвета в этих точках. Как их найти? Применить интерполяцию на ближайших к ним точках с целыми координатами и найти требуемое значение цвета. Учитывая, что текстура — двухмерное изображение, делать нам это придется как по горизонтали, так и по вертикали. То есть использовать две интерполяции на каждый пиксель, иными словами, билинейную интерполяцию. А пример билинейной интерполяции на Дельфи приведен ниже.

Здесь Pic1 содержит исходное изображение, а Pic2 — увеличенное; imWidth и imHeight Рис. 2— размеры новой картинки. Пример изображения, увеличенного с помощью билинейной фильтрации, смотрите на Рис. 2. Но у билинейной фильтрации есть один существенный недостаток: она не может использоваться для уменьшения изображения, ведь тогда при интерполяции координаты точки выйдут за пределы участка, на котором она проводится. Так что для уменьшения изображения используется комбинация мип-мэпинга и билинейной фильтрации. Мип-мэпинг — это набор уменьшенных текстур, созданных на основе заданной. При этом размеры каждой следующей текстуры в 2 раза меньше предыдущей, а так как размер текстуры равен степени двойки, то проблем с делением не возникает. То есть общее количество созданных изображений будет равняться логарифму по основанию 2 меньшего из размеров. Вот так:

Мип-мэп изображения (дальше — мип-мэп уровни) создаются не в режиме реального времени — это отняло бы немало временных ресурсов, — а перед загрузкой сцены. То есть, они непрерывно висят в видеопамяти вместе с самой текстурой. Но мип-мэп уровни занимают только на треть больше памяти, чем сама текстура. Почему? Каждый следующий уровень в 4 раза меньше предыдущего. Следовательно, они образуют убывающую геометрическую прогрессию.

По формуле:

Формула 2

(здесь bl=1, а q=1/4), вычислим ее сумму и получим 4/3.

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

Как выглядят мип-мэп изображения, созданные таким образом, смотрите на Рис. 3. Рис. 3А вот как это будет выглядеть на Дельфи:

Переменные здесь те же, только Levels — массив картинок мип-мэп уровней, Levels[0] содержит начальное изображение. Теперь текстура будет уменьшаться Рис. 4следующим образом: находится меньший из ближайших мип-мэп уровней и с помощью билинейной интерполяции увеличивается до требуемых размеров. Вот теперь уже с помощью билинейной фильтрации мы можем создать изображение любых размеров. Но вот в чем беда: при приближении к полигону текстура (пусть ее размер будет 32x32) на нем растягивается, и при переходе от 31x31 к 32x32 мы заметим резкую смену картинок от сильно размытого 16x16 мип-мэпа до детализированного изображения текстуры.

Чтобы исправить этот неприятный эффект, используется трилинейная фильтрация, как например на рисунке 4. Что же она из себя представляет? Две линии, по которым будет проводиться интерполяция, мы знаем — вертикаль и горизонталь. А какая же третья? Третья линия лежит между ближайшими мип-мэп уровнями. То есть при создании нового изображения будут учитываться оба мип-мэп уровня, а не только меньший, как было в случае с билинейной фильтрацией. Итак, на основе ближайших мип-мэп уровней создаются изображения нужного размера, и в зависимости от удаленности требуемого изображения от этих мип-мэп уровней значения цветов интерполируются. Увеличиваем меньший мип-мэп с помощью билинейной интерполяции, а больший уменьшаем методом ближайшего пиксела (нам здесь качество не важно). Создав оба изображения попиксельно, проинтерполируем значения их цветов.

Здесь Levels[l] — меньший мип-мэп уровень, а Pic1 и Pic2 — созданные нами изображения. Но и трилинейная фильтрация не без недостатков: она требует намного больше вычислительных ресурсов, чем билинейная, но так как она уже полностью поддерживается железом, об этом можно забыть. Добавлю только, что исходники моей программы, демонстрирующей использование этих алгоритмов, вы можете скачать с http://www.mycomp.com.ua/issue/97_218/prgscr.zip.

Аппликация

Берем в руки клей, бумагу… Нет, немного не так. Берем текстуру и пытаемся прилепить ее на требуемый полигон. Мы уже знаем, как ее подогнать под необходимые размеры, но это подходит только для полигона, расположенного параллельно плоскости камеры. Если же он немного наклонен, придется произвести еще несколько вычислений. Текстура в этом случае будет накладываться построчно (строка определяется по ее удалению от камеры), то есть изображения будут создаваться для каждой строки. При учете перспективы эти строки разбиваются на некоторые участки, для которых в зависимости от их удаленности от камеры и рассчитываются их пиксели.

Вот приблизительно так и происходит наложение текстуры в том же Direct3D и OpenGL (см. цикл статей Романа Aka Archivarius Савчука «Прямой Х и открытый GL», MK №45, 47(216, 218)). Надеюсь, моя статья дала вам возможность получше осмыслить этот процесс.

Рекомендуем ещё прочитать:






Данную страницу никто не комментировал. Вы можете стать первым.

Ваше имя:
Ваша почта:

RSS
Комментарий:
Введите символы или вычислите пример: *
captcha
Обновить





Хостинг на серверах в Украине, США и Германии. © sector.biz.ua 2006-2015 design by Vadim Popov