Алгоритм сканирования — это то, что люди делали в программном обеспечении еще в 1990-х годах, до появления современных графических процессоров. Разработчики графических процессоров довольно быстро поняли, что алгоритмы, которые вы используете для программного рендеринга, сильно отличаются от алгоритмов, которые вы бы реализовали в реализации СБИС с миллиардами транзисторов. Алгоритмы, оптимизированные для аппаратной реализации, имеют тенденцию выглядеть довольно чуждыми любому, кто так или иначе имеет опыт работы с программным обеспечением.
Еще одна вещь, которую я хотел бы прояснить, это то, что OpenGL ничего не говорит о том, «как» вы визуализируете, это просто «что» вы визуализируете. Реализации OpenGL могут делать это так, как им заблагорассудится. Мы можем узнать «что», прочитав стандарт OpenGL, но «как» скрыто в секретах, хранимых производителями графических процессоров.
Наконец, прежде чем мы начнем, статьи, на которые вы ссылаетесь, не связаны между собой. Они о том, как работает ультразвуковое сканирование.
Что мы знаем о преобразовании сканирования?
Преобразование сканирования имеет в качестве входных данных ряд примитивов. Для наших целей предположим, что все они треугольники (что в наши дни становится все более верным).
Каждый треугольник должен быть обрезан секущими плоскостями. Это может добавить к треугольнику до трех дополнительных сторон, в худшем случае (превратив его в шестиугольник). Это должно произойти перед перспективной проекцией.
Каждый примитив должен пройти перспективную проекцию. Этот процесс берет каждую вершину с однородными координатами (X, Y, Z, W) и преобразует ее в (X/W, Y/W, Z/W).
Фреймбуфер обычно организован иерархически в плитки, а не линейно, как это делается в программном обеспечении. Кроме того, обработка может выполняться более чем на одном иерархическом уровне. Причина, по которой мы используем линейную организацию в программном обеспечении, заключается в том, что для вычисления адресов памяти в иерархической структуре требуются дополнительные циклы. Однако реализации СБИС не страдают от этой проблемы, они могут просто подключить биты в регистре так, как они хотят сделать из него адрес.
Таким образом, вы можете видеть, что в программном обеспечении плитки «сложны и медленны», но в аппаратном обеспечении они «просты и быстры».
Некоторые примечания к руководству R5xx:
Серия R5xx определенно старая (2005 г.), но документация доступна в Интернете (ищите «R5xx_Acceleration_v1.5.pdf»). В нем упоминаются два преобразователя сканирования, поэтому конвейер выглядит примерно так:
primitive output -> coarse scan converter -> quad scan converter -> fragment shader
Преобразователь грубой развертки, по-видимому, работает с более крупными плитками настраиваемого размера (от 8x8 до 32x32) и имеет несколько выбираемых режимов, режим «на основе перехвата» и «на основе ограничивающей рамки».
Затем четырехканальный преобразователь берет выходные данные преобразователя грубой развертки и выводит отдельные четверки, которые представляют собой группы из четырех отсчетов. Значения глубины для каждого квадроцикла могут быть представлены в виде четырех дискретных значений или уравнения плоскости. Уравнение плоскости позволяет быстро отбросить весь четырехугольник, если соответствующий четырехугольник в буфере глубины также указан как уравнение плоскости. Это называется «ранняя Z» и является обычной оптимизацией.
Затем фрагментный шейдер работает с одним четырехугольником за раз. Квадрат может содержать сэмплы за пределами треугольника, которые затем будут отброшены.
Стоит еще раз отметить, что это старая видеокарта. Современные видеокарты сложнее. Например, R5xx не позволяет даже сэмплировать текстуры из вершинных шейдеров.
Если вам нужна еще более радикально другая картина, поищите реализации графического процессора PowerVR, в которых используется так называемый «отложенный рендеринг на основе тайлов». Эти современные и мощные графические процессоры оптимизированы для низкой стоимости и низкого энергопотребления, и они бросают вызов многим вашим предположениям о том, как работают средства визуализации.
person
Dietrich Epp
schedule
12.04.2016
bool inside(ivec2 a, ivec2 b, ivec2 c, ivec2 p) {return cross(p-a,b-a)>0 && cross(p-b,c-b)>0 && cross(p-c,a-c);}
. - person HolyBlackCat   schedule 12.04.2016