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

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

Перспективно-корректное





Этот метод основан на приближении u, v кусочно-линейными функциями. Кратко говоря, при рисовании каждая строка разбивается на куски (обычно несколько кусков длиной 8/16/32 пикселов и один оставшийся произвольной длины), в начале и конце каждого куска считаются точные значения u, v, а на куске они интерполируется линейно.

Точные значения u и v, в принципе, можно считать по формулам из 4.1, но обычно используют более простой путь. Он основан на том факте, что значения 1/Z, u/Z и v/Z зависят от sx, sy ЛИНЕЙНО. Доказательство этого факта пока опущено. Таким образом, достаточно для каждой вершины посчитать 1/Z, u/Z, v/Z и линейно их интерполировать - точно так же, как интерполируются u и v в 4.2. Причем, так как эти значения зависят от sx, sy строго линейно, то интерполяция дает не сильно приближенные результаты, а абсолютно точные!

Сами же точные значения u, v считаются как

u = (u/Z) / (1/Z),

v = (v/Z) / (1/Z).

Дальше все становится совсем просто. При рисовании треугольника, на ребрах интерполируем не u и v, как в 4.2, а 1/Z, u/Z, v/Z. Кроме того, заранее считаем d(u/Z)/dsx, d(v/Z)/dsx, d(1/Z)/dsx (то есть, изменений этих самых u/Z, v/Z, 1/Z соотвествующих шагу по dsx на 1) так, как считали du/dsx – это будет нужно для быстрого вычисления точных значений u, v. Каждую линию рисуем кусками по 8/16/32 пикселов (на самом деле, кусками любой длины; просто если длина - степень двойки, то при вычислении du/dx и dv/dx для текущего куска можно деление на длину куска заменить сдвигом вправо) и, если надо, рисуем оставшийся хвостик. Для расчета точных значений u, v в конце каждого куска пользуемся посчитанными (ага!) значениями d(u/Z)/dsx, d(v/Z)/dsx, d(1/Z)/dsx; раз значения u/Z, v/Z, 1/Z в начале куска известны, меняются они линейно и длина куска известна (либо 16 пикселов, либо длина остатка), то в конце куска они считаются все это до боли просто:

uZ_b = uZ_a + length * duZ_dsx; // расчет u/Z, v/Z, 1/Z в конце куска

vZ_b = vZ_a + length * dvZ_dsx;

Z1_b = Z1_a + length * dZ1_dsx;

Все вместе выглядеть это будет примерно так:

//...

current_sx = x_start;

length = x_end - x_start;

// расчет u/Z, v/Z, 1/Z, u, v в начале самого первого куска

uZ_a = uZ_start;

vZ_a = vZ_start;

Z1_a = Z1_start; // это 1/Z

u_a = uZ_a / Z1_a;

v_a = vZ_a / Z1_a;

// рисуем куски по 16 пикселов

while (length >= 16) {

uZ_b = uZ_a + 16 * duZ_dsx; // расчет u/Z, v/Z, 1/Z, u, v в конце куска

vZ_b = vZ_a + 16 * dvZ_dsx;

Z1_b = Z1_a + 16 * dZ1_dsx;

u_b = uZ_b / Z1_b;

v_b = vZ_b / Z1_b;

u = u_a; // начинаем текстурирование с начала куска

v = v_a;

du = (u_b - u_a) / 16; // можно сделать >> 4, используя fixedpoint

dv = (v_b - v_a) / 16; // можно сделать >> 4, используя fixedpoint

// рисуем 16 пикселов старым добрым "аффинным" методом

len = 16;

while (len--) {

putpixel(current_sx, current_sy, texture[(int)v][(int)u]);

u += du;

v += dv;

current_sx++;

}

length -= 16;

// конец куска становится началом следующего куска

uZ_a = uZ_b;

vZ_a = vZ_b;

Z1_a = Z1_b;

u_a = u_b;

v_a = v_b;

}

// дорисовываем "хвост" линии, если он непуст

if (length!= 0) {

uZ_b = uZ_a + length * duZ_dsx;

vZ_b = vZ_a + length * dvZ_dsx;

Z1_b = Z1_a + length * dZ1_dsx;

u_b = uZ_b / Z1_b;

v_b = vZ_b / Z1_b;

u = u_a; // начинаем текстурирование с начала куска

v = v_a;

du = (u_b - u_a) / length;

dv = (v_b - v_a) / length;

// рисуем остаток пикселов старым добрым "аффинным" методом

while (length--) {

putpixel(current_sx, current_sy, texture[v][u]);

u += du;

v += dv;

current_sx++;

}

}

//...

Как и в 4.2, пройдемся подобным куском кода по всем строкам грани, не забыв вместо "//..." вставить интерполяцию всяких там [u/v/1]Z_start, содранную с интерполяции u_start.. и - о чудо, текстурированная с учетом перспективы грань!

Осталось сказать еще пару слов о кое-какой оптимизации.

Во-первых, два деления при расчете u и v в цикле прорисовки можно (и нужно) заменить на одно - посчитать tmp = 1/Z, дальше u = uZ * tmp, v = vZ * tmp.

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

В-третьих, деление на length при дорисовке хвостика длиной от 1 до 15 пикселов можно заменить на умножение на 1/length, заранее посчитав табличку для значений 1/length.

И наконец, мелкие треугольники можно текстурировать аффинным методом, а большие - методом с коррекцией. Размер треугольника можно определять хотя бы по длине самой длинной горизонтальной линии:

x_start = A.sx+(B.sy-A.sy)*(C.sx-A.sx)/(C.sy-A.sy),

x_end = B.sx,

longest_length = x_end - x_start,

все равно мы ее считаем для расчета du_dsx или duZ_dsx и иже с ними.







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




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


Кардиналистский и ординалистский подходы Кардиналистский (количественный подход) к анализу полезности основан на представлении о возможности измерения различных благ в условных единицах полезности...


Обзор компонентов Multisim Компоненты – это основа любой схемы, это все элементы, из которых она состоит. Multisim оперирует с двумя категориями...


Композиция из абстрактных геометрических фигур Данная композиция состоит из линий, штриховки, абстрактных геометрических форм...

Потенциометрия. Потенциометрическое определение рН растворов Потенциометрия - это электрохимический метод иссле­дования и анализа веществ, основанный на зависимости равновесного электродного потенциала Е от активности (концентрации) определяемого вещества в исследуемом рас­творе...

Гальванического элемента При контакте двух любых фаз на границе их раздела возникает двойной электрический слой (ДЭС), состоящий из равных по величине, но противоположных по знаку электрических зарядов...

Сущность, виды и функции маркетинга персонала Перснал-маркетинг является новым понятием. В мировой практике маркетинга и управления персоналом он выделился в отдельное направление лишь в начале 90-х гг.XX века...

Кран машиниста усл. № 394 – назначение и устройство Кран машиниста условный номер 394 предназначен для управления тормозами поезда...

Приложение Г: Особенности заполнение справки формы ву-45   После выполнения полного опробования тормозов, а так же после сокращенного, если предварительно на станции было произведено полное опробование тормозов состава от стационарной установки с автоматической регистрацией параметров или без...

Измерение следующих дефектов: ползун, выщербина, неравномерный прокат, равномерный прокат, кольцевая выработка, откол обода колеса, тонкий гребень, протёртость средней части оси Величину проката определяют с помощью вертикального движка 2 сухаря 3 шаблона 1 по кругу катания...

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