Компьютерная графика Лабораторная работа № 2 Теоретические сведения. Алгоритм, использующий Z-буфер. Метод сортировки по глубине Метод двоичного разбиения пространства Метод построчного сканирования Алгоритм Робертса Задание на лабораторную работу: Алгоритмы закрашивания трехмерных фигур. Теоретические сведения. Алгоритм, использующий Z-буфер. Это один из простейших алгоритмов удаления невидимых поверхностей. Впервые он был предложен Кэтмулом. Работает этот алгоритм в пространстве изображения. Идея zбуфера является простым обобщением идеи о буфере кадра. Буфер кадра используется для запоминания атрибутов (интенсивности) каждого пиксела в пространстве изображения, zбуфер - это отдельный буфер глубины, используемый для запоминания координаты z или глубины каждого видимого пиксела в пространстве изображения. В процессе работы глубина или значение z каждого нового пиксела, который нужно занести в буфер кадра, сравнивается с глубиной того пиксела, который уже занесен в z-буфер. Если это сравнение показывает, что новый пиксел расположен впереди пиксела, находящегося в буфере кадра, то новый пиксел заносится в этот буфер и, кроме того, производится корректировка z-буфера новым значением z. Если же сравнение дает противоположный результат, то никаких действий не производится. По сути, алгоритм является поиском по х и у наибольшего значения функции z (х, у). Главное преимущество алгоритма - его простота. Кроме того, этот алгоритм решает задачу об удалении невидимых поверхностей и делает тривиальной визуализацию пересечений сложных поверхностей. Сцены могут быть любой сложности. Поскольку габариты пространства изображения фиксированы, оценка вычислительной трудоемкости алгоритма не более чем линейна. Поскольку элементы сцены или картинки можно заносить в буфер кадра или в z-буфер в произвольном порядке, их не нужно предварительно сортировать по приоритету глубины. Поэтому экономится вычислительное время, затрачиваемое на сортировку по глубине. Основной недостаток алгоритма - большой объем требуемой памяти. Если сцена подвергается видовому преобразованию и отсекается до фиксированного диапазона координат z значений, то можно использовать z-буфер с фиксированной точностью. Информацию о глубине нужно обрабатывать с большей точностью, чем координатную информацию на плоскости (х, y); обычно бывает достаточно 20 бит. Буфер кадра размером 512х512х24 бит в комбинации с z-буфером размером 512х512х20 бит требует почти 1.5 мегабайт памяти. Однако снижение цен на память делает экономически оправданным создание специализированных запоминающих устройств для z-буфера и связанной с ним аппаратуры. Альтернативой созданию специальной памяти для z-буфера является использование для этой цели оперативной или массовой памяти. Уменьшение требуемой памяти достигается разбиением пространства изображения на 4, 16 или больше квадратов или полос. В предельном варианте можно использовать г-буфер размером в одну строку развертки. Для последнего случая имеется интересный алгоритм построчного сканирования. Поскольку каждый элемент сцены обрабатывается много раз, то сегментирование z-буфера, вообще говоря, приводит к увеличению времени, необходимого для обработки сцены. Однако сортировка на плоскости, позволяющая не обрабатывать все многоугольники в каждом из квадратов или полос, может значительно сократить этот рост. Другой недостаток алгоритма z-буфера состоит в трудоемкости и высокой стоимости устранения лестничного эффекта, а также реализации эффектов прозрачности и просвечивания. Поскольку алгоритм заносит пикселы в буфер кадра в произвольном порядке, то нелегко получить информацию, необходимую для методов устранения лестничного эффекта, основывающихся на предварительной фильтрации. При реализации эффектов прозрачности и просвечивания, пикселы могут заноситься в буфер кадра в некорректном порядке, что ведет к локальным ошибкам. Хотя реализация методов устранения лестничного эффекта, основывающихся на префильтрации, в принципе возможна, практически это сделать трудно. Однако относительно легко реализуются методы постфильтрации (усреднение подпикселов). Напомним, что в методах устранения лестничного эффекта, основывающихся на постфильтрации, сцена вычисляется в таком пространстве изображения, разрешающая способность которого выше, чем разрешающая способность экрана. Поэтому возможны два подхода к устранению леcтничного эффекта на основе постфильтрации. В первом используется буфер кадра, заданный в пространстве изображения, разрешение которого выше, чем у экрана, и z-буфер, разрешение которого совпадает с разрешением экрана. Глубина изображения вычисляется только в центре той группы подпикселов, которая усредняется. Если для имитации расстояния от наблюдателя используется масштабирование интенсивности, то этот метод может оказаться неадекватным. Во втором методе оба буфера, заданные в пространстве изображения, имеют повышенную разрешающую способность. При визуализации изображения как пикселная информация, так и глубина усредняются. В этом методе требуются очень большие объемы памяти. Например, изображение размером 512х512х24 бита, использующее z-буфер размером 20 бит на пиксел, разрешение которого повышено в 2 раза по осям х и у и на котором устранена ступенчатость методом равномерного усреднения, требует почти 6 мегабайт памяти. Более формальное описание алгоритма z-буфера таково: Заполнить буфер кадра фоновым значением интенсивности или цвета. Заполнить z -буфер минимальным значением z. Преобразовать каждый многоугольник в растровую форму в произвольном порядке. Для каждого Пиксел(x,y) в многоугольнике вычислить его глубину z(x,y). Сравнить глубину z(х,у) со значением Zбуфер(х,у), хранящимся в z-буфере в этой же позиции. Если z(х, у) > Zбуфер (х,у), то записать атрибут этого многоугольника (интенсивность, цвет и т. п.) в буфер кадра и заменить Zбуфер(х,у) на z(х,у). В противном случае никаких действий не производить. В качестве предварительного шага там, где это целесообразно, применяется удаление нелицевых граней . Если известно уравнение плоскости, несушей каждый многоугольник, то вычисление глубины каждого пиксела на сканирующей строке можно проделать пошаговым способом. Напомним, что уравнение плоскости имеет вид aх + by + сz + d = 0 z = - (ах+ by+d)/c<>0 Для сканирующей строки y = const. Поэтому глубина пиксела на этой строке, у которого x1 = х +Dx, равна z1 - z = -(ax1 + d)/c+ (ах + d)/c = а(х - х1)/с или z1 = z - (a/c)Dx Но Dx = 1, поэтому z1 =z - (a/с). Метод сортировки по глубине Наиболее простым подходом к упорядочиванию граней является их сортировка по минимальному расстоянию до картинной плоскости (вдоль направления проектирования) с последующим выводом их в порядке приближения. Этот метод великолепно работает для ряда сцен, включая, например, построение изображения нескольких непересекающихся достаточно простых тел. Однако возможны случаи, когда просто сортировка по расстоянию до картинной плоскости не обеспечивает правильного упорядочения граней; поэтому желательно после такой сортировки проверить порядок, в котором грани будут выводиться. Предлагается следующий алгоритм этой проверки. Для простоты будем считать, что рассматривается параллельное проектирование вдоль оси Oz. Перед выводом грани Р следует убедиться, что никакая другая грань Q, проекция которой на ось Oz пересекается с проекцией грани Р, не может закрываться гранью Р. И если это условие выполнено, то грань Р должна быть выведена раньше. Предлагаются следующие 5 тестов в порядке возрастания сложности проверки: 1. Пересекаются ли проекции этих граней на ось Ох? 2. Пересекаются ли их проекции на ось Оу? 3. Находится ли грань Р по другую сторону от плоскости, проходящей через грань Q, чем начало координат (наблюдатель)? 4. Находится ли грань Q по ту же сторону от плоскости, проходящей через грань Р, что и начало координат (наблюдатель)? 5. Пересекаются ли проекции этих граней на картинной плоскости? 1. Если хотя бы на один из этих вопросов получен отрицательный ответ, то считаем что эти две грани - Р и Q упорядочены верно, и сравниваем Р со следующей гранью. В противном случае считаем, что эти грани необходимо поменять местами, для чего проверяются следующие тесты: 2. Находится ли грань Q по другую сторону от плоскости, проходящей через грань Р, чем начало координат? 3. Находится ли грань Р по ту же сторону от плоскости, проходящей через грань Q, что и начало координат? В случае если ни один из этих тестов не позволяет с уверенностью решить, какую из этих двух граней нужно выводить раньше, то одна из них разбивается плоскостью, проходящей через другую грань. В этом случае вопрос об упорядочении оставшейся грани и частей разбитой грани легко решается. Метод двоичного разбиения пространства Существует другой, крайне элегантный способ упорядочивания граней. Рассмотрим некоторую плоскость в объектном пространстве. Она разбивает множество всех граней на два непересекающихся множества (кластера), в зависимости от того, в каком полупространстве относительно плоскости эти грани лежат (будем считать, что плоскость не пересекает ни одну из этих граней). При этом, очевидно, что ни одна из граней, лежащих в полупространстве, не содержащем наблюдателя, не может закрывать собой ни одну из граней, лежащих в том же полупространстве, что и наблюдатель. Тем самым сначала необходимо вывести грани из дальнего кластера, а затем уже и из ближнего. Применим подобную технику для упорядочения граней внутри каждого кластера. Для этого построим разбиение граней каждого кластера на два множества очередной плоскостью; а затем для вновь полученных граней повторим процесс разбиения, и будем поступать так, до тех пор, пока в каждом получившемся кластере останется не более одной грани. Обычно в качестве разбивающей плоскости рассматривается плоскость, проходящая через одну из граней (на самом деле при этом множество всех граней разбивается на 4 класса - лежащих на плоскости, пересекающих ее, лежащих в положительном полупространстве и лежащие в отрицательном полупространстве относительно этой плоскости). Грани, пересекаемые плоскостью, разобьем вдоль этой плоскости. В результате мы приходим к дереву разбиения пространства (Binary Space Partitioning), узлами которого являются грани. Каждый узел такого дерева можно представить в виде следующей структуры: Struct BSPNode { Facet * facet; // corresponding facet Vector n; // normal to facet double d; // plane parameter BSPNode * Left; // left subtree BSPNode * Right; // right subtree }; При этом Left указывает на вершину поддерева, содержащуюся в положительном полупространстве, a Right - на поддерево содержащееся в отрицательном полупространстве. Процесс построения дерева заключается в выборе грани, проведении через нее плоскости и разбиении множества всех граней. В этом процессе присутствует определенный произвол в выборе очередной грани. Существует два основных критерия для выбора: - получить как можно более сбалансированное дерево; - минимизировать количество разбиений. К сожалению, эти критерии, как правило, являются взаимоисключающими, поэтому выбирается некоторый компромиссный вариант. После того как это дерево построено, осуществляется построение изображения в зависимости от используемого проектирования. Одним из основных преимуществ этого метода является его полная независимость от положения центра проектирования, что делает его крайне удобным для построения серий изображений одной и той же сцены из разных точек наблюдения. Метод построчного сканирования Метод построчного сканирования является еще одним примером метода, работающего в пространстве картинной плоскости. Однако вместо того, чтобы решать задачу удаления невидимых граней для проекций объектов на картинную плоскость, сведем ее к серии простых одномерных задач. Все изображение на картинной плоскости можно представить как ряд горизонтальных (вертикальных) линий пикселей. Рассмотрим сечение сцены плоскостью, проходящей через такую линию пикселей и центр проектирования. Пересечением этой плоскости с объектами сцены будет множество непересекающихся (за исключением концов) отрезков, которые и необходимо спроектировать. Задача удаления невидимых частей для такого набора отрезков решается тривиально. Рассматривая задачу удаления невидимых граней для каждой такой линии, мы тем самым разбиваем исходную задачу на набор гораздо более простых задач. Подобные алгоритмы с успехом используются для создания компьютерных игр типа Wolfenstein 3d и DOOM. Метод построчного сканирования является примером метода, удачно использующего растровые свойства картинной плоскости для упрощения исходной задачи и сведения ее к серии простых задач в пространстве меньшей размерности. Всѐ изображение на картинной плоскости (экране) можно представить как состоящее из горизонтальных (вертикальных) линий пикселов (строк или столбцов). Каждой такой строке пикселов соответствует сечение сцены плоскостью, проходящей через соответствующую строку и наблюдателя (для параллельного проектирования – проходящей через строку и параллельную направлению проектирования) при наших допущениях. Пересечением секущей плоскости со сценой будет множество непересекающихся (за исключением концов) отрезков, высекаемых на гранях секущей плоскостью. В результате мы приходим к задаче удаления невидимых частей для отрезков и секущей плоскости при проектировании на прямую, являющуюся результатом пересечения с ней картинной плоскости. Тем самым получается задача с размерностью на единицу меньше, чем исходная задача, - вместо определения того, какие части отрезков закрывают друг друга при проектировании на прямую. Существуют различные методы решения задачи удаления невидимых частей отрезков. Одним из наиболее простых является использование одномерного z-буфера, совмещающего крайнюю простоту с весьма небольшими затратами памяти даже при высоком разрешении картинной плоскости. К тому же существуют аппаратные реализации этого подхода. С другой стороны, для определения видимых частей можно воспользоваться и аналитическими (непрерывными) методами. Заметим, что изменение видимости отрезков может происходить лишь в их концах. Поэтому достаточно проанализировать взаимное расположение концов отрезка с учетом глубины. Алгоритм решения задачи Алгоритм решения данной задачи можно разбить на такие шаги: 1. находим точки пересечения сканирующей линии со всеми ребрами фигуры. 2. упорядочиваем точки пересечения по возрастанию координаты x. 3. раскрашиваем все пиксели между парами точек пересечения. Для решения поставленной задачи будем использовать специальные таблицы для отслеживания концов отрезков: Таблица ребер (Edge Table), где для каждого негоризонтального ребра (горизонтальные ребра игнорируются) хранятся минимальная и максимальная yкоординаты, x-координата, соответствующая вершине с наименьшей y-координате, шаг изменения x при переходе к следующей строке и ссылка на соответствующую грань; Таблица граней (Facet Table), где для каждой грани помимо информации о плоскости, проходящей через эту грань, и информации, необходимой для ее закрашивания, хранится также специальный флажок, устанавливаемый в нуль при обработке очередной строки; Таблица активных ребер (Active Edge Table), содержащая список всех ребер, пересекаемых текущей сканирующей плоскостью, и проекции точек пересечения (x-координаты при параллельном проектировании). Все ребра в таблице активных ребер сортируются по возрастанию x. Для удобства определения ребер, пересекаемых текущей сканирующей плоскостью, список всех ребер обычно сортируются по меньшей y-координате. Алгоритм Робертса Алгоритм Робертса представляет собой первое известное решение задачи об удалении невидимых линий. Это математически элегантный метод, работающий в объектном пространстве. Алгоритм прежде всего удаляет из каждого тела те ребра или грани, которые экранируются самим телом. Затем каждое из видимых ребер каждого тела сравнивается с каждым из оставшихся тел для определения того, какая его часть или части, если таковые есть, экранируются этими телами. Поэтому вычислительная трудоемкость алгоритма Робертса растет теоретически как квадрат числа объектов. В алгоритме Робертса требуется, чтобы все изображаемые тела или объекты были выпуклыми. Невыпуклые тела должны быть разбиты на выпуклые части. В этом алгоритме выпуклое многогранное тело с плоскими гранями должно представляться набором пересекающихся плоскостей. Уравнение произвольной плоскости в трехмерном пространстве имеет вид aх + by + cz + d = 0 Если любая точка S(xs, ys, zs) лежит на плоскости, то axs + bys + czs + d = 0. Если же S не лежит на плоскости, то знак этого скалярного произведения показывает, по какую сторону от плоскости расположена точка. В алгоритме Робертса предполагается, что точки, лежащие внутри тела, дают положительное скалярное произведение. Пусть F1, F2, ..., Fn - грани многогранника. Рассмотрим одну из граней. Обозначим вершины, инцидентные грани, через V1, V2, ..., Vk. Найдем вектор нормали к грани, вычислив векторное произведение любых двух смежных ребер этой грани V1V2 = [x1,y1,z1] и V2V3 = [x2,y2,z2]: i j k = (y1z2 - y2z1)·i + (z1x2 - z2x1)·j + (x1y2 - x2y1)·k = Ai·i + Bi·j ni = [V1V2,V2V3] = x1 y1 z1 + Ci·k x2 y2 z2 Тогда опорная функция грани имеет вид: Li(x,y,z) = Aiх + Biy + Ciz + D Величина D вычисляется с помощью произвольной точки на плоскости. В частности, если компоненты этой точки на плоскости (х1,y1,z1), то: D = -(ах1 + by1 + cz1) Так как многогранник выпуклый, коэффициенты Ai, Bi, Ci легко выбрать так, чтобы ni(Ai, Bi, Ci) был вектором внешней нормали. Для этого найдем какую-либо внутреннюю точку, например, барицентр многогранника: W = (V1 + V2 + ... + Vk)/k Если скалярное произведение уравнения плоскости и этой точки меньше 0, то необходимо поменять знак уравнения этой плоскости, чтобы отразить правильное направление внешней нормали. Остается только вычислить скалярное произведение уравнения плоскости на точку, в которой находится наблюдатель. Если это скалярное произведение меньше 0, то плоскость невидима и необходимо удалить весь многоугольник, лежащий в этой плоскости. Запись этого алгоритма на псеводокоде приводится ниже. Алгоритм Робертса V1, V2, V3 - вершины многогранника W - барицентр многогранника P - точка наблюдения выделим одну из граней многогранника Vec1.X = V1.X - V2.X; Vec2.X = V3.X - V2.X; Vec1.Y = V1.Y - V2.Y; Vec2.Y = V3.Y - V2.Y; Vec1.Z = V1.Z - V2.Z; Vec2.Z = V3.Z - V2.Z; A = Vec1.Y·Vec2.Z - Vec2.Y·Vec1.Z; B = Vec1.Z·Vec2.X - Vec2.Z·Vec1.X; C = Vec1.X·Vec2.Y - Vec2.X·Vec1.Y; D = -(A·V1.X + B·V1.Y + C·V1.Z); m = -Sign(A·W.X + B·W.Y + C·W.Z + D); / для этой грани найдем координаты двух векторов, которые лежат в плоскости грани / вычислим коэффициенты уравнения плоскости / коэффициент, изменяющий знак плоскости / корректируем направление плоскости A = A·m; B = B·m; C = C·m; D = D·m; if A·P.X + B·P.Y + C·P.Z + D > 0 then грань видима; отобразить грань else (грань невидима) Если задано только одно тело, то, применив этот алгоритм для всех граней тела, поиск невидимых граней завершается. Если в сцене присутствует несколько тел, то следует сформировать приоритетный список этих тел по максимальным значениям координаты z вершин тел. Наибольшим приоритетом будет обладать тело, у которого минимальное значение z. Это тело будет самым удаленным от точки наблюдения, расположенной в бесконечности на оси z. Для каждого тела из приоритетного списка: Проверить экранирование всех лицевых ребер всеми другими телами сцены. Тело, ребра которого проверяются, называется пробным объектом, а тело, относительно которого в настоящий момент производится проверка, называется пробным телом. Естественно, что нужно проверять экранирование пробного объекта только теми пробными телами, у которых ниже приоритеты. Провести проверки экранирования для прямоугольных объемлющих оболочек пробного объекта и пробного тела. Провести предварительные проверки протыкания, чтобы увидеть, не протыкается ли пробное тело пробным объектом и существует ли возможность частичного экранирования первого последним. Задание на лабораторную работу: 1. Изучить теоретические основы изображения трехмерных объектов на плоскости и законы изменения координат в пространстве. 2. На языке высокого уровня (без применения технологий OpenGL и Direct3D) составить программу, изображающую трехмерное изображение первой буквы имени студента. Фигура должна иметь два слоя точек, соединенных между собой соединительными линиями (см. рис. 1). Рис. 1. Пример трехмерного изображения буквы «П». 3. Составить подпрограммы, реализующие вращение изображенной буквы вокруг различных осей координат. 4. Посредством использования алгоритмов закрашивания трехмерных фигур необходимо в процессе движения фигуры по экрану удалять невидимые грани в каждый момент времени. 5. Выполнить электронный отчет по лабораторной работе.