Чтобы понять это, вам нужно рассмотреть весь конвейер рендеринга. Выходные данные вершинного шейдера (помимо специального выхода gl_Position
) передаются как «связанные данные» вершины на следующие этапы конвейера.
Хотя вершинный шейдер работает с одной вершиной за раз, совершенно не заботясь о примитивах, на следующих этапах конвейера все же учитывается тип примитива (и информация о связности вершин). Это то, что обычно называют «примитивной сборкой». Теперь у нас все еще есть отдельные вершины со связанными данными, созданными VS, но мы также знаем, какие вершины сгруппированы вместе, чтобы определить базовый примитив, такой как точка (1 вершина), линия (2 вершины) или треугольник (3 вершины).
Во время растеризации фрагменты генерируются для каждого местоположения пикселя в выходном растре пикселей, которое принадлежит примитиву. При этом связанные данные вершин, определяющих примитив, могут быть интерполированы по всему примитиву. В строке это довольно просто: выполняется линейная интерполяция. Назовем конечные точки A и B каждым связанным выходным вектором v, так что у нас есть v_A и v_B. Через строку мы получаем интерполированное значение для v как v (x) = (1-x) * v_A + x * v_B в каждой конечной точке, где x находится в диапазоне от 0 (в точке A) до 1 (в точке Б). Для треугольника используется барицентрическая интерполяция между данными всех трех вершин. Таким образом, хотя между вершинами и фрагментами не существует сопоставления 1: 1, выходные данные VS по-прежнему определяют значения соответствующих входных данных FS, но не напрямую, а косвенно путем интерполяции по используемому типу примитива.
![поток концептуального шейдера данных в GL](https://i.stack.imgur.com/a9cKR.png)
Формула, которую я привел до сих пор, немного упрощена. Фактически, по умолчанию применяется коррекция перспективы, эффективно изменяя формулу таким образом, чтобы учитывались эффекты искажения перспективы. Это просто означает, что интерполяция должна действовать так, как она применяется линейно в пространстве объекта (до того, как было применено искажение проекцией). Например, если у вас есть перспективная проекция и какой-то примитив, который не параллелен плоскости изображения, перемещение на 1 пиксель вправо в пространстве экрана действительно означает перемещение на переменное расстояние от реального объекта, в зависимости от расстояния от фактической точки до самолет камеры.
Вы можете отключить коррекцию перспективы, используя квалификатор noperspective
для переменных _3 _ / _ 4_ в GLSL. Затем используется линейная / барицентрическая интерполяция, как я ее описал.
Вы также можете использовать квалификатор flat
, который полностью отключит интерполяцию. В этом случае значение только одной вершины (так называемая «провоцирующая вершина») используется для всех фрагментов всего примитива. Целочисленные данные никогда не могут быть автоматически интерполированы GL и должны быть квалифицированы как flat
при отправке во фрагментный шейдер.
person
derhass
schedule
04.02.2015