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

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

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






Этот метод основан на приближении 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; просмотров: 357. Нарушение авторских прав; Мы поможем в написании вашей работы!



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

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

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

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

Огоньки» в основной период В основной период смены могут проводиться три вида «огоньков»: «огонек-анализ», тематический «огонек» и «конфликтный» огонек...

Упражнение Джеффа. Это список вопросов или утверждений, отвечая на которые участник может раскрыть свой внутренний мир перед другими участниками и узнать о других участниках больше...

Влияние первой русской революции 1905-1907 гг. на Казахстан. Революция в России (1905-1907 гг.), дала первый толчок политическому пробуждению трудящихся Казахстана, развитию национально-освободительного рабочего движения против гнета. В Казахстане, находившемся далеко от политических центров Российской империи...

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

Закон Гука при растяжении и сжатии   Напряжения и деформации при растяжении и сжатии связаны между собой зависимостью, которая называется законом Гука, по имени установившего этот закон английского физика Роберта Гука в 1678 году...

Характерные черты официально-делового стиля Наиболее характерными чертами официально-делового стиля являются: • лаконичность...

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