Самоучитель по 3dsmax 7

         

Методы расположены в порядке уменьшения скорости и увеличения качества уменьшенной текстуры


Методы расположены в порядке уменьшения скорости и увеличения качества уменьшенной текстуры.

Метод 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));

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



Содержание раздела