Могут ли (и как так) шейдеры рисовать пиксели экрана за пределами тех, которые заняты закрашенной сеткой?

8

У меня есть некоторый опыт программирования геометрии и вычисления шейдеров - но я никогда не испытывал особого желания играть с фрагментными шейдерами. В настоящее время я пытаюсь лучше понять, как они работают и каков их потенциал. Одна из вещей, которые я прочитал в нескольких местах, заключается в том, что фрагмент (то есть пиксель экрана) не может выходить за пределы самого себя внутри шейдерного фрагмента. Это означает, что данный повторяющийся фрагмент может влиять только на себя.

Поэтому и ради обучения я хотел бы знать, возможно ли следующее (и если да, то как вообще можно этого достичь). Предположим, что для простоты у нас есть точечная сетка, состоящая только из двух вершин (расположенных в пространстве трехмерного мира). Можем ли мы запрограммировать шейдер таким образом, чтобы каждая из этих двух вершин была нарисована на экране в их точном положении WorldToViewport, а также чтобы окружность вокруг каждого из них радиусом = R также рисовалась в окружающих пикселях, даже если они расширяются за исходную сетку, к которой прикреплен шейдер? Как на рисунке ниже (где красный квадрат в центре кругов представляет нарисованные на экране вершины):

введите описание изображения здесь

Если это возможно, можно ли запрограммировать шейдер так, чтобы эти круги, выходящие за пределы вершин, влияли на цвет (RGBA) друг друга? Как на рисунке ниже:

введите описание изображения здесь

Как я уже сказал, если это возможные вещи, я бы хотел услышать немного о том, как этого добиться - либо в концептуальном, либо в практическом плане. Это делается в фрагментном шейдере, или его нужно вычислять раньше в вершинных или геометрических шейдерах? Как рассчитать и передать «дополнительные фрагменты», которые выходят за пределы тех фрагментов, которые заняты телом сетки?

AndrewSteer
источник
Геометрический шейдер может добавить больше примитивов, чем в исходной сетке. Это делает это для вас?
Андреас

Ответы:

6

Когда вы используете сглаживание линий или сглаживание линий, или ширину точек, или точки, OpenGL создает для вас небольшой прямоугольник вместо линии или точки с координатами текстуры. В настоящее время вы можете даже программировать это самостоятельно, используя геометрические шейдеры или даже тесселятор.

Совершенно другой подход состоит в том, чтобы использовать защищенное затенение, используя один геометрический проход, чтобы просто сохранить информацию в буфере RGBAZ, затем второй проход, чем вы выполняете на всех пикселях экрана, чтобы выполнить какой-то процесс. (чтобы действовать на все пиксели, просто нарисуйте один полноэкранный прямоугольник). В настоящее время вы можете даже сделать первый проход как один или несколько «рендеринг в текстуру», а затем MIP-карту этих текстур, так что последний проход может легко получить доступ к менее локальным значениям.

Fabrice NEYRET
источник
Спасибо! Я делал то, что вы сказали в начале, используя геометрические шейдеры для создания геометрии вокруг точек и, таким образом, позволяя рисовать пиксели вокруг точки. Это работает, конечно, но это более громоздкое решение. Меня особенно заинтересовали последние фрагменты того, что вы сказали: если я правильно вас понял, то вы упомянули, что можно визуализировать всю сцену, а затем использовать экранный шейдер, нацеленный на интересующую область, а затем выполнить переход через Рендеринг кадра, чтобы работать на сколько пикселей нужно вокруг точек в центре?
AndrewSteer
Вы можете сделать первый проход в текстуре. Затем, во втором проходе на весь экран, в каждом пикселе вы можете проверять содержимое текстуры на диске вокруг пикселя и делать то, что вы хотите (например, цвет в соответствии с ближайшим заполненным пикселем, или рисовать белым только, если расстояние ниже некоторого порога) , Конечно, только для рисования дисков, это далеко не самый эффективный способ ;-)
Fabrice NEYRET
Конечно, я привел самый простой пример, который мог придумать. Но да, я думаю, что то, что вы говорите, соответствует тому, о чем я думал, то есть рендеринг в текстуру за один проход, а затем у нас есть информация для других проходов, чтобы изменить пиксели относительно того, что лежит в окружающих пикселях. , Большое спасибо.
AndrewSteer
3

Один хороший способ сделать так, чтобы круг (или другая фигура) рисовался для каждой вершины в сетке, - это использование геометрии . Это особенность графического процессора, которая позволяет одновременно рисовать несколько экземпляров (копий) сетки, причем вершины / индексы сетки задаются одним набором буферов, а другой буфер вершин может давать дополнительные данные для каждого экземпляра. Вершинный шейдер можно использовать для объединения данных из обоих буферов любым способом, который вы выберете.

Чтобы быть конкретным, в вашем случае вы могли бы создать сетку, представляющую круг желаемого радиуса, с его вершинами, указанными непосредственно в координатах экранного пространства и центрированными в начале координат. Затем вы будете использовать создание экземпляров, чтобы графический процессор отображал новую копию круговой сетки для каждой вершины вашей исходной точечной сетки. В вершинном шейдере вы вычисляете положение точки на экране (используя обычные преобразования проекции мировоззрения), а затем переводите круговую сетку для центрирования в этой позиции.

Что касается второй части вашего вопроса, о том, как круги влияют на цвет друг друга: это зависит от того, что вы хотите сделать, в частности. Аппаратное смешивание может использоваться для обработки простых случаев, таких как добавление или умножение цветов или альфа-смешивание. Если вы хотите что-то более сложное, чем это, то может быть возможно сделать это с помощью многопроходного алгоритма или (на последних графических процессорах) программируемого смешивания.

Натан Рид
источник