Методы расположены в порядке уменьшения скорости и увеличения качества уменьшенной текстуры.
Метод 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 проще всего, по-моему, посчитать по формуле Герона для площади треугольника:
Этот метод практически не требует вычислительных затрат, так как все операции проделываются один раз на грань.