Как вершинный шейдер передает информацию о цвете в фрагментарный шейдер?
В простой приветственной программе OpenGL, которая просто рисует статический треугольник в окне,
когда я устанавливаю 3 вершины треугольника на красный, зеленый и синий цвета, треугольник заполняется градиентом.
Но когда я использую шейдеры следующим образом:
Vertex Shader:
attribute vec4 aVertex;
attribute vec4 aColor;
varying vec4 vColor;
void main(void) {
gl_Position = gl_ModelViewMatrix * gl_ProjectionMatrix * aVertex;
vColor = aColor;
}
где атрибуты aVertex
и aColor
поступают из буфера вершин, прошедшего через вызов glVertexAttribPointer
.
Фрагментный шейдер:
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
Треугольник по-прежнему заполнен градиентом, и возникает вопрос:
Если для вершины вычисляется вершинный шейдер, то каждому экземпляру vColor
следует назначить цвет вершины. Цвет вершин должен быть красным, зеленым или синим, как установлено в буфере вершин.
Итак, откуда появился градиент?
Или, другими словами, когда это случилось, что в frag-shader, vColor
оказывается интерполированным цветом вместо вершин?
Ответы
Ответ 1
"переменные" переменные в шейдере фрагмента имеют результат линейной интерполяции между значениями, указанными на этапе вершинного шейдера (на основе относительного положения фрагмента между вершинами).
То есть, когда растеризатор выплескивает фрагмент в пикселе, его положение также задается относительно вершин треугольника в барицентрических координатах. Эти координаты затем используются для интерполяции всех переменных переменных из вершинного шейдера. В большинстве случаев это то, что вы хотите, и скорость, получаемая от не интерполяции, в наши дни невелика.
Использование ключевого слова "flat" отключит интерполяцию и вместо этого будет использовать значение первой вершины (я не уверен на 100% "плоский" работает с изменением, поскольку я переключился на использование ключевых слов ввода/вывода с помощью более новые версии GLSL).
На стороне примечания, я нашел это особенно полезным, если фрагмент нуждается в некоторых значениях из каждой из вершин. В этом случае я использую flat out myVertexValue[3]
в геометрическом шейдере (например здесь).
Ответ 2
Градиент исходит из интерполяции между цветами вершин, которые происходят, когда переменный проход переходит в fragment shader.If вы не хотите интерполировать используйте "плоское" ключевое слово в начале изменения.
Ваше недоразумение, вероятно, связано с недостатком знаний о том, как работают этапы вершин и фрагментов. Они работают по-разному. Вершина шейдера вызывается за вершину, а фрагмент - пиксель. Интерполяция происходит по умолчанию, так как существует необходимость обрезать фрагменты, генерируемые во время растеризации этап в области, определенной примитивной сборкой. И, как я уже сказал, вы можете отключить интерполяцию "плоской". В таком случае цвет первого атрибута вершины определит общий цвет формы.