Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Мипмэппинг





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

Поэтому для удаления артефактов используется значительно более простая вещь, а именно мипмэппинг. Идея, как обычно, проста. Для каждой текстуры заранее создается несколько ее копий уменьшенного размера (1/2, 1/4, и так далее), а далее при текстурировании используется либо сама текстура, либо подходящая уменьшенная копия. Памяти при этом расходуется на 25-33% больше, чем без мипмэппинга, но зато, вроде бы, увеличивается качество изображения.

Как создать уменьшенную в два раза копию текстуры? Здесь мы опишем три метода, два из них очевидны, третий позаимствован у Crystal Space. Методы расположены в порядке уменьшения скорости и увеличения качества уменьшенной текстуры.

Метод 1. Выкинуть все пикселы текстуры с нечетными координатами. Самый простой, самый быстрый, но дает не очень хорошо выглядящие результаты.

Метод 2. Оставить точки с четными координатами, в каждой точке усреднить значения цвета в этой точке и ее трех соседях (справа, снизу и справа-снизу).

Метод 3. Оставить точки с четными координатами, использовав в каждой точке фильтр, заданный вот такой матрицей:

[ 1 2 1 ]

1/16 * [ 2 4 2 ]

[ 1 2 1 ]

В виде формул для каждой из компонент цвета точки уменьшенной в два раза копии текстуры эти методы запишутся, соответственно, так:

mip1[x][y] = tex[2*x][2*y]; // метод 1

mip2[x][y] = (// метод 2

tex[2*x ][2*y ] +

tex[2*x+1][2*y ] +

tex[2*x ][2*y+1] +

tex[2*x+1][2*y+1]) / 4;

mip3[x][y] = (// метод 3

1 * tex[2*x-1][2*y-1] +

2 * tex[2*x ][2*y-1] +

1 * tex[2*x+1][2*y-1] +

2 * tex[2*x-1][2*y ] +

4 * tex[2*x ][2*y ] +

2 * tex[2*x+1][2*y ] +

1 * tex[2*x-1][2*y+1] +

2 * tex[2*x ][2*y+1] +

1 * tex[2*x+1][2*y+1]) / 16;

Последовательно применяя любой из описанных методов, мы можем построить набор уменьшенных текстур. Остается выяснить, какую именно из них надо выбрать при текстурировании. Здесь опять будет описано два достаточно простых метода; а вообще, конечно, их можно придумать значительно больше.

Метод 1: полигональный мипмэппинг. В этом случае мы считаем площадь полигона на экране в пикселах и его же площадь в текстуре в текселах (последнюю обычно можно посчитать заранее), определяем по ним примерное количество пикселов, соотвествующих одному пикселу и выбираем нужный уровень уменьшения текстуры по следующей формуле:

miplevel = floor(log2(screenArea / textureArea) / 2);

здесь

screenArea - площадь грани на экране (в пикселах)

textureArea - площадь грани в текстуре (в текселах)

log2() - функция двоичного логарифма (для Watcom C стандартная)

miplevel - уровень уменьшения; выбираемая текстура должна быть сжата

по обеим осям в (2^miplevel) раз

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

miplevel = floor(log2(screenArea / textureArea) / 2);

if (miplevel < 0) miplevel = 0;

if (miplevel > MAXMIPLEVEL) miplevel = MAXMIPLEVEL;

screenArea и textureArea проще всего, по-моему, посчитать по формуле Герона для площади треугольника:

// a, b, c - стороны треугольника; p - периметр

a = sqrt((v2.sx-v1.sx)*(v2.sx-v1.sx) + (v2.sy-v1.sy)*(v2.sy-v1.sy));

b = sqrt((v3.sx-v1.sx)*(v3.sx-v1.sx) + (v3.sy-v1.sy)*(v3.sy-v1.sy));

c = sqrt((v3.sx-v2.sx)*(v3.sx-v2.sx) + (v3.sy-v2.sy)*(v3.sy-v2.sy));

p = (a + b + c);

screenArea = sqrt(p * (p-a) * (p-b) * (p-c));

a = sqrt((v2.u-v1.u)*(v2.u-v1.u) + (v2.v-v1.v)*(v2.v-v1.v));

b = sqrt((v3.u-v1.u)*(v3.u-v1.u) + (v3.v-v1.v)*(v3.v-v1.v));

c = sqrt((v3.u-v2.u)*(v3.u-v2.u) + (v3.v-v2.v)*(v3.v-v2.v));

p = (a + b + c);

textureArea = sqrt(p * (p-a) * (p-b) * (p-c));

Этот метод практически не требует вычислительных затрат, так как все операции проделываются один раз на грань. С другой стороны, здесь использутся один и тот же уровень уменьшения (он же уровень детализации, LOD, level of detail) для всего полигона, а разным пикселам может соответствовать разное количество текселов. Есть и более неприятное следствие - уровни уменьшения для двух соседних полигонов меняются скачком, а это не очень хорошо выглядит.

Метод 2: попиксельный мипмэппинг. В этом случае нужный уровень уменьшения считается для каждого пиксела и выбирается на основе максимального шага в текстуре из соответствующих переходу к соседнему пикселу:

textureStep = max(

sqrt(dudx * dudx + dvdx * dvdx),

sqrt(dudy * dudy + dvdy * dvdy));

miplevel = floor(log2(textureStep));

Подобную операцию для каждого пиксела проводить, конечно, накладно. Но при аффинном текстурировании dudx, dvdx, dudy и dvdy постоянны для всех пикселов, так что попиксельный мэппинг становится полигонным, только с другой методикой расчета уровня уменьшения. Для перспективно-корректного же текстурирования dudx, dvdx, dudy и dvdy постоянны для всех пикселов одного кусочка (span'а), так что уровень уменьшения считается раз в несколько пикселов.

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

textureStep = sqrt(dudx * dudx + dvdx * dvdx);

Далее, заметим, что log2(sqrt(x)) = log2(x) / 2, откуда

miplevel = floor(log2(dudx * dudx + dvdx * dvdx) / 2);

Осталась, практически, одна трудоемкая операция - взятие логарифма. Но и ее можно убрать. Дело в том, что числа с плавающей запятой (float'ы) как раз и хранятся в логарифмической форме, и floor(log2(x)) можно посчитать вот так:

float x;

int floor_log2_x;

x = 123456;

floor_log2_x = ((*((int*)&x)) - (127 << 23)) >> 23; // чистый C

floor_log2_x = (((int&)x) - (127 << 23)) >> 23; // C++

Соответственно, floor(log2(sqrt(x))) = floor(log2(x) / 2) считаем как

miplevel = ((*((int*)&x)) - (127 << 23)) >> 24; // чистый C

miplevel = (((int&)x) - (127 << 23)) >> 24; // C++

Естественно, что этот трюк можно применить и в случае полигонного мипмэпинга для полного устранения всяческих медленых операций типа sqrt(), log2(). Вот, в общем-то, и все.







Дата добавления: 2015-10-02; просмотров: 402. Нарушение авторских прав; Мы поможем в написании вашей работы!




Функция спроса населения на данный товар Функция спроса населения на данный товар: Qd=7-Р. Функция предложения: Qs= -5+2Р,где...


Аальтернативная стоимость. Кривая производственных возможностей В экономике Буридании есть 100 ед. труда с производительностью 4 м ткани или 2 кг мяса...


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


Расчетные и графические задания Равновесный объем - это объем, определяемый равенством спроса и предложения...

Растягивание костей и хрящей. Данные способы применимы в случае закрытых зон роста. Врачи-хирурги выяснили...

ФАКТОРЫ, ВЛИЯЮЩИЕ НА ИЗНОС ДЕТАЛЕЙ, И МЕТОДЫ СНИЖЕНИИ СКОРОСТИ ИЗНАШИВАНИЯ Кроме названных причин разрушений и износов, знание которых можно использовать в системе технического обслуживания и ремонта машин для повышения их долговечности, немаловажное значение имеют знания о причинах разрушения деталей в результате старения...

Различие эмпиризма и рационализма Родоначальником эмпиризма стал английский философ Ф. Бэкон. Основной тезис эмпиризма гласит: в разуме нет ничего такого...

Типовые ситуационные задачи. Задача 1.У больного А., 20 лет, с детства отмечается повышенное АД, уровень которого в настоящее время составляет 180-200/110-120 мм рт Задача 1.У больного А., 20 лет, с детства отмечается повышенное АД, уровень которого в настоящее время составляет 180-200/110-120 мм рт. ст. Влияние психоэмоциональных факторов отсутствует. Колебаний АД практически нет. Головной боли нет. Нормализовать...

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

Признаки классификации безопасности Можно выделить следующие признаки классификации безопасности. 1. По признаку масштабности принято различать следующие относительно самостоятельные геополитические уровни и виды безопасности. 1.1. Международная безопасность (глобальная и...

Studopedia.info - Студопедия - 2014-2024 год . (0.092 сек.) русская версия | украинская версия