Чтобы нарисовать один кадр, или, скажем, задан массив вершин, пока этот массив передается и проходит этапы программы закраски, существует ли строгое соответствие между предыдущим и следующим этапами?
Например . Учитывая 3 вершины (0,1,0), (1,1,0), (1,0,0), вершинный шейдер будет выполняться 3 раза, если это макет (location = 0) в vec3 aPos; написано в верхней части шейдера. Поскольку вершинный шейдер будет выполняться для каждой вершины (именно атрибут вершины определяет, сколько вершин имеется, поэтому даже если в начале у нас есть 6 переменных типа вектор3, VS все равно будет выполняться 3 раза, если половина переменных считается нормальной одной вершины)
Я понятия не имею, сколько раз будет выполняться GS, поскольку после GS может быть сгенерировано больше вершин, чем на входе. А что насчет ФС?
Я знаю, что перед FS есть растеризация. Он проецирует аналоговый сигнал (εR. Точность ограничена только размером с плавающей запятой) в цифровой сигнал (наш экран, ограниченный количеством пикселей). Есть ли соответствие между треугольником и тем, сколько раз FS будет выполняться для этого треугольника, например, для треугольника (3 вектора), программа растрирует его, и FS будет выполняться количество раз, равное количеству пикселей в покрытой области )?
Или FS выполняется общее количество раз, равное количеству пикселей размера экрана, например, покрытие стены валиком?
редактировать: Я думаю, GS выполняется для каждого примитива. Поскольку у вас есть массив структур, представляющих несколько вершин в одном примитиве.





Вершинный шейдер запускается столько раз, сколько вы укажете в качестве последнего параметра glDrawArrays (параметр под названием count).
Геометрический шейдер запускается столько раз, сколько у вас имеется примитивов (точек, линий, треугольников). Однако имейте в виду, что шейдеры тесселяции (если они у вас есть) обычно увеличивают количество примитивов.
Теоретически фрагментный шейдер выполняется примерно столько раз, сколько пикселей покрывается вашими примитивами. Однако это немного сложнее, поскольку на это может повлиять множество факторов. Если вы включите тест глубины или тест трафарета, графический процессор (скорее всего) не будет запускать фрагментный шейдер на пикселях, где он не прошел тесты. Очевидно, что графический процессор не будет растрировать пиксели за пределами области просмотра, которую вы установили с помощью glViewport. При использовании мультисэмплинга или консервативной растеризации фрагментный шейдер может запускаться большее количество раз. И еще одна важная вещь: графический процессор не может растеризовать один пиксель, он растеризует в единицах 2х2, так что можно использовать производные.
Допустим, у вас есть буфер вершин с 6 вершинами. Если вы вызовете glDrawArrays со значением count, равным 6, вершинный шейдер запустится 6 раз, независимо от того, какой примитивный режим вы используете. Если вы вызовете его с помощью GL_POINTS, шейдер геометрии запустится 6 раз, поскольку вы рисуете все вершины индивидуально. Если вы вызовете его с помощью GL_LINES, шейдер геометрии запустится 3 раза, поскольку каждая линия состоит из двух вершин. Если вы вызовете его с помощью GL_TRIANGLES, шейдер геометрии запустится 2 раза, поскольку каждый треугольник состоит из 3 вершин. От фрагментного шейдера зависит. Например, если у вас экран с более высоким разрешением, он будет запускаться больше раз, потому что один и тот же примитив охватывает больше пикселей, но опять же, это зависит от многих настроек, о которых я упоминал ранее.
Так что определить количество вызовов фрагментного шейдера непросто, особенно для сложной сцены. К счастью, вы можете создать объект запроса в OpenGL с параметром GL_SAMPLES_PASSED и заставить OpenGL подсчитывать количество пикселей, прошедших в тесте глубины.
Поскольку фрагментный шейдер обычно является наиболее требовательным к производительности этапом шейдера (и обычно он выполняется наибольшее количество раз), важно запускать его как можно меньше раз. Например, некоторые игровые движки упорядочивают сетки по расстоянию от камеры и сначала визуализируют более близкие сетки, поскольку сетки, расположенные ближе к камере, могут перекрывать сетки, расположенные дальше. Но существует множество других методов уменьшения количества вызовов фрагментных шейдеров, таких как отсечение окклюзии, масштабирование динамического разрешения, рендеринг шахматной доски, масштабирование изображения (например, DLSS, FSR или XeSS) и т. д.
@Shahashahaha: Это трубопровод. Программа GL отправляет в конвейер поток примитивов, каждый из которых будет разбит на вершины и отправлен в VS, затем снова собран в примитивы и отправлен в GS, а затем растрирован и каждый фрагмент отправлен в FS. Результат ФС будет записан или смешан с результирующим пикселем в буфере кадра. Это происходит параллельно, поэтому первый примитив будет записывать пиксели, а последующие примитивы находятся на более ранних стадиях.
Если вам интересно, как работает конвейер и этапы, прочтите эти статьи. Они немного устарели и устарели, но все еще являются довольно хорошими ресурсами.
Может ли графический процессор одновременно работать с VS GS FS? Я бы сказал, что это как покрасить стену. Сначала у вас должны быть базовые примитивы (как сгенерированные GS, так и подразумеваемые буфером), затем вам разрешено рисовать на нем второй слой (передавать все эти примитивы в FS). Графический процессор не запустит FS до тех пор, пока стена не будет полностью окрашена первым цветом, что завершает все процедуры GS и не имеет полного количества примитивов. Или он распределен на несколько подразделений, каждое из которых работает на определенном количестве вершин, будучи независимыми друг от друга и способными рассинхронизироваться на этапах?