¿Pueden (y cómo) los sombreadores pintar píxeles de la pantalla más allá de los que ocupan la malla sombreada?

8

Tengo algo de experiencia en la programación de geometría y cálculo de sombreadores, pero nunca me aventuré a jugar realmente con los sombreadores de fragmentos. Actualmente, estoy tratando de entender mejor cómo funcionan y su potencial. Una de las cosas que he leído en varios lugares es que un fragmento (es decir, un píxel de la pantalla) no puede extenderse más allá de sí mismo dentro del sombreador de fragmentos. Lo que significa que un fragmento dado que se está iterando solo puede afectarse a sí mismo.

Por lo tanto, y por el bien del aprendizaje, me gustaría saber si es posible lo siguiente (y si es así, cómo, en líneas generales, se puede lograr). Supongamos que tenemos, por simplicidad, una malla de puntos que consta de solo dos vértices (ubicados en el espacio 3D World). ¿Podemos programar un sombreador de tal manera que cada uno de estos dos vértices se pinten en la pantalla en su posición exacta de WorldToViewport, pero también que un círculo alrededor de cada uno de ellos con radio = R también se pinte en los píxeles circundantes incluso si se extienden más allá de la malla original a la que está unido el sombreador? Como en la figura a continuación (donde el cuadrado rojo en el centro de los círculos representa los vértices pintados en la pantalla):

ingrese la descripción de la imagen aquí

Si eso es posible, ¿se puede programar un sombreador de tal manera que estos círculos que se extienden más allá de los vértices influyan en el color (RGBA) entre sí? Como en la figura a continuación:

ingrese la descripción de la imagen aquí

Como dije, si estas son cosas posibles, me encantaría escuchar un poco de cómo lograrlo, ya sea en términos conceptuales o prácticos. ¿Se hace en el sombreador de fragmentos o debe calcularse antes en los sombreadores de vértice o geometría? ¿Cómo calcular y pasar "fragmentos adicionales" que se extienden más allá de los fragmentos ocupados por el cuerpo de malla?

AndrewSteer
fuente
Un sombreador de geometría puede agregar más primitivas que las que se encuentran en la malla original. ¿Esto lo hace por ti?
Andreas

Respuestas:

6

Cuando usa ancho de línea o antialiasing de línea o ancho de puntero o puntos, OpenGL crea para usted un pequeño rectángulo en lugar de la línea o punto, con coordenadas de textura. Hoy en día, incluso puede programarlo usted mismo utilizando sombreadores de geometría o incluso el tesselator.

Un enfoque totalmente diferente es usar sombreado defendido, usando una pasada geométrica solo para almacenar información en el búfer RGBAZ, luego una segunda pasada de la que ejecuta en todos los píxeles de la pantalla para realizar algún proceso. (para actuar en todos los píxeles, simplemente dibuje un rectángulo de pantalla completa). Hoy en día, incluso puede hacer el primer pase como uno o varios "renderizar a textura", luego MIPmap estas texturas, para que el pase final pueda acceder fácilmente a valores menos locales.

Fabrice NEYRET
fuente
¡Gracias! He estado haciendo lo que dijiste al principio, usando sombreadores de geometría para crear geometría alrededor de los puntos y así poder dibujar píxeles alrededor del punto. Funciona, por supuesto, pero es una solución más engorrosa. Me interesé particularmente en los últimos fragmentos de lo que has dicho: si te entendí correctamente, lo que mencionas es que se podría representar toda la escena y luego usar un sombreador de pantalla dirigido al área de interés y luego pasar por alto el marco renderizado para trabajar en cuántos píxeles se desean alrededor de los puntos en el centro?
AndrewSteer
Podrías renderizar la primera pasada en una textura. Luego, en la segunda pasada en pantalla completa, en cada píxel puede inspeccionar el contenido de textura en un disco alrededor del píxel y hacer lo que desee (por ejemplo, color según el píxel lleno más cercano o pintar de blanco solo si la distancia está por debajo de algún umbral) . Por supuesto, solo para dibujar discos, esto está lejos de ser la forma más eficiente ;-)
Fabrice NEYRET
Claro, acabo de dar el ejemplo más simple que se me ocurrió. Pero sí, creo que lo que dices está en línea con lo que he estado pensando, es decir, renderizar una textura en una pasada y luego tenemos la información para, en otras pasadas, alterar píxeles en relación con lo que se encuentra en los píxeles circundantes. . Muchas gracias.
AndrewSteer
3

Una buena manera de organizar un círculo (u otra forma) para dibujar cada vértice en una malla es usar instancias de geometría . Esta es una función de GPU que permite dibujar múltiples instancias (copias) de una malla a la vez, con los vértices / índices de la malla dados por un conjunto de búferes y otro búfer de vértices que pueden proporcionar datos adicionales por instancia. El sombreador de vértices se puede usar para combinar los datos de ambos búferes de la forma que elija.

Para ser concreto, en su caso, podría crear una malla que represente un círculo del radio deseado, con sus vértices especificados directamente en las coordenadas del espacio de la pantalla y centrados en el origen. Luego usaría la creación de instancias para hacer que la GPU renderice una nueva copia de la malla circular para cada vértice de su malla de puntos original. En el sombreador de vértices, calcularía la posición en el espacio de la pantalla del punto (utilizando las transformaciones de proyección de vista del mundo como de costumbre), luego traduciría la malla circular para centrarla en esa posición.

En cuanto a la segunda parte de tu pregunta, sobre cómo hacer que los círculos influyan en el color del otro: depende de lo que quieras hacer, específicamente. La combinación de hardware se puede utilizar para manejar casos simples, como agregar o multiplicar los colores, o la combinación alfa. Si desea algo más complicado que eso, entonces podría ser posible hacerlo con un algoritmo de múltiples pasadas o (en las últimas GPU) mezclas programables.

Nathan Reed
fuente