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

Билинейная фильтрация текстур

Читайте также:
  1. Инфильтрация порошковой формовки – заполнение пор порошковой формовки расплавленным металлом или сплавом.
  2. Основы работы в MS Excel. Сортировка и фильтрация данных.
  3. Относительная фильтрация 3
  4. Реферативное чтение или фильтрация
  5. Фильтрация списков

Да-да, это именно тот метод, с помощью которого смазывают текстуры всякие ускорители типа 3Dfx. Итак, пусть у нас есть какая-то текстура. Текстура у нас - это 2D картинка, а 2D картинка в свою очередь - набор замеров цвета через какие-то промежутки. В реальной же жизни цвет не меняется скачком через каждый, например, миллиметр, а является какой-то непрерывной функцией от положения, причем меняется довольно плавно. При обычном текстурировании мы получаем координаты в текстуре, округляем их до ближайшего целого числа и выбираем нужный цвет из текстуры. То есть мы как бы берем значение цвета в самой близкой к рисуемой точке сетки замеров цвета, поэтому у нас цвет резко меняется, оставаясь непрерывным между узлами сетки, поэтому возникает эффект больших квадратов.

 

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

 

1------------2

| |

a * b

| |

| |

| |

3------------4

 

Здесь 1, 2, 3, 4 - "окружающие" точку пикселы текстуры (они же узлы сетки замера цвета). Пусть iu, iv - целые части координат текстуры точки u, v; fu,fv - дробные части. Тогда 1, 2, 3, 4 имеют координаты в текстуре (iu,iv),(iu+1,iv), (iu,iv+1), (iu+1,iv+1). Проинтерполируем какую-то компоненту цвета (R, G или B) по прямым 1-3 и 2-4:

 

a.c = 1.c + (3.c - 1.c) * fv,

b.c = 2.c + (4.c - 2.c) * fv,

 

то есть

 

a.c = c[iu][iv] + (c[iu][iv+1] - c[iu][iv]) * fv,

b.c = c[iu+1][iv] + (c[iu+1][iv+1] - c[iu+1][iv]) * fv,

 

Теперь проинтерполируем цвет по прямой ab в нашей точке:

 

c = a.c + b.c * fu,

 

Проинтерполировав по этой формуле каждую компоненту цвета, получим наконец готовый результат - цвет точки, но уже с учетом билинейной фильтрации. Здесь у нас получилось по три умножения на компоненту. То есть в сумме девять умножений на пиксел. Можно, конечно, честно считать по этим формулам, делая девять умножений для каждого пиксела. Но можно заменить все умножения на выборки по таблице. u, v обычно - это fixedpoint; fu, fv - тоже (кстати, в случае с fixedpoint целые и дробные части вычисляются ровно одним and'ом). Пусть мы используем 24-битный цвет и 16:16 fixedpoint; тогда одна компонента цвета занимает 8 бит, а дробную часть можно одним сдвигом перевести в 24:8 fixedpoint. Получаем 256 возможных значений для любой компоненты цвета и 256 возможных значений для дробной части, то есть - табличка 256x256. Если цвет 15/16-битный, или используется более грубое (скажем, до пяти бит) округление дробной части, то табличка становится еще меньше. Памяти, конечно, не жалко, но кэш-память пока не резиновая, так что чем меньше lookup-таблица, тем оно лучше для скорости. Вот и все.

 

Осталось только упомянуть, что лучше занести в табличку не байты, а слова, для данного примера это будет 8:8 fixedpoint, и складывать все результаты тоже как слова, а потом сдвигом переводить обратно в целые числа. Иначе (особенно в случае 15/16-битных режимов) будет заметен небольшой шум на текстуре, появляющийся из-за ошибок округления.

 

 

38. Расчет нормали к объекту, Освещение по Ламберту

Во всех формулах для освещенности у нас так или иначе будет фигурировать вектор N - нормаль к объекту в точке P. Сразу возникает вопрос, а как жеэтот вектор считать.

 

Обычно придерживаются такой логики. Модель у нас состоит из плоских граней,

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

 

Нормаль в вершине рассчитываются как сумма приведенных к длине 1 нормалей ко всем граням, к которым принадлежит эта вершина. То есть. Сначала считаем нормали ко всем граням и приводим их к длине 1. Далее, для каждой вершины надо перебрать все грани, и если очередная грань содержит эту вершину, то к нормали в вершине прибавляется нормаль к этой грани. Первоначально все нормали к вершинам полагаются равными нулю. Для больших моделей этот процесс может быть довольно долгим, но достаточно провести его заранее один раз и сохранить все посчитанные нормали к вершинам.

 

Для вящей понятности приведу кусок кода:

 

//...

for (i = 0; i < numberOfVertics; i++) {

vertexNormal[i].x = 0;

vertexNormal[i].y = 0;

vertexNormal[i].z = 0;

}

for (i = 0; i < numberOfVertics; i++) {

for (j = 0; j < numberOfFaces; j++) {

if (face[j].vertex0 == i ||

face[j].vertex1 == i ||

face[j].vertex2 == i)

{

vertexNormal[i].x += faceNormal[j].x;

vertexNormal[i].y += faceNormal[j].y;

vertexNormal[i].z += faceNormal[j].z;

}

}

}

//...

 

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

Соответствующий кусочек кода:

 

//...

for (i = 0; i < numberOfVertics; i++) {

vertexNormal[i].x = 0;

vertexNormal[i].y = 0;

vertexNormal[i].z = 0;

}

for (i = 0; i < numberOfFaces; i++) {

vertexNormal[face[i].vertex0].x += faceNormal[j].x;

vertexNormal[face[i].vertex1].y += faceNormal[j].y;

vertexNormal[face[i].vertex2].z += faceNormal[j].z;

}

//...

 


Дата добавления: 2015-11-26; просмотров: 102 | Нарушение авторских прав



mybiblioteka.su - 2015-2024 год. (0.009 сек.)