Gli shader (e in che modo) possono dipingere i pixel dello schermo oltre a quelli occupati dalla mesh ombreggiata?


8

Ho una certa esperienza nella programmazione della geometria e nel calcolo degli shader, ma non mi sono mai avventurato a giocare davvero con gli shader di frammenti. Attualmente, sto cercando di capire meglio come funzionano e il loro potenziale. Una delle cose che ho letto in più punti è che un frammento (cioè un pixel dello schermo) non può estendersi oltre se stesso all'interno dello shader di frammenti. Il che significa che un dato frammento che viene ripetuto può influenzare solo se stesso.

Pertanto, e per motivi di apprendimento, vorrei sapere se è possibile quanto segue (e se lo è, come, in linea generale, può essere raggiunto). Supponiamo di avere, per semplicità, una maglia a punti costituita da solo due vertici (situati nello spazio del Mondo 3D). Possiamo programmare uno shader in modo tale che ciascuno di questi due vertici venga dipinto sullo schermo nella posizione esatta di WorldToViewport, ma anche che un cerchio attorno a ciascuno di essi di raggio = R sia anche dipinto nei pixel circostanti anche se si estendono oltre la mesh originale a cui è collegato lo shader? Come nella figura in basso (dove il quadrato rosso al centro dei cerchi rappresenta i vertici dipinti sullo schermo):

inserisci qui la descrizione dell'immagine

Se ciò è possibile, uno shader può anche essere programmato in modo tale che questi cerchi che si estendono oltre i vertici influenzano il colore (RGBA) l'uno dell'altro? Come nella figura seguente:

inserisci qui la descrizione dell'immagine

Come ho detto, se queste sono cose possibili, mi piacerebbe sapere un po 'di come realizzare una cosa del genere - in termini concettuali o pratici. Viene eseguito nello shader di frammento o deve essere calcolato prima nel vertice o nello shader di geometria? Come calcolare e passare "frammenti aggiuntivi" che si estendono oltre quei frammenti occupati dal corpo della mesh?


Uno shader di geometria può aggiungere più primitivi di quelli presenti nella mesh originale. Questo lo fa per te?
Andreas,

Risposte:


6

Quando si utilizza la larghezza di linea o l'antialiasing della linea o la larghezza del punto o pointsprite, OpenGL crea per te un piccolo rettangolo anziché la linea o il punto, con coordinate di trama. Oggi puoi persino programmarlo tu stesso usando shader di geometria o persino il tassellatore.

Un approccio completamente diverso consiste nell'utilizzare l'ombreggiatura differita, utilizzando un passaggio geometrico solo per memorizzare le informazioni nel buffer RGBAZ, quindi un secondo passaggio rispetto a quello eseguito su tutti i pixel dello schermo per eseguire un processo. (per agire su tutti i pixel, basta disegnare un rettangolo a schermo intero). Al giorno d'oggi puoi persino eseguire il primo passaggio come uno o più "rendering su texture", quindi MIPmap queste trame, in modo che il passaggio finale possa facilmente accedere a valori locali inferiori.


Grazie! Ho fatto quello che hai detto all'inizio, usando shader di geometria per creare geometria attorno ai punti e quindi abilitare a disegnare pixel attorno al punto. Funziona, ovviamente, ma è una soluzione più ingombrante. Mi sono particolarmente interessato alle ultime parti di ciò che hai detto: se ti capissi correttamente, ciò che dici è che potresti renderizzare l'intera scena e quindi utilizzare uno screen shader mirato all'area di interesse e quindi fare un passaggio sul frame renderizzato per lavorare su quanti pixel si vogliono intorno ai punti al centro?
AndrewSteer,

È possibile eseguire il rendering del primo passaggio in una trama. Quindi nel secondo passaggio a schermo intero, in ogni pixel è possibile ispezionare il contenuto della trama in un disco attorno al pixel e fare ciò che si desidera (ad es. Colore in base al pixel riempito più vicino o dipingere bianco solo se la distanza è inferiore a una soglia) . Naturalmente per disegnare solo dischi, questo è ben lungi dall'essere il modo più efficiente ;-)
Fabrice NEYRET,

Certo, ho appena dato l'esempio semplice che mi viene in mente. Ma sì, penso che quello che dici sia in linea con quello che stavo pensando, ovvero renderizzare una trama in un passaggio e poi in seguito abbiamo le informazioni per, in altri passaggi, modificare i pixel in relazione a ciò che si trova nei pixel circostanti . Grazie molto.
AndrewSteer,

3

Un buon modo per organizzare un cerchio (o altra forma) per ogni vertice di una mesh consiste nell'utilizzare l' istanziazione della geometria . Questa è una funzione GPU che consente di disegnare più istanze (copie) di una mesh contemporaneamente, con i vertici / indici della mesh forniti da un set di buffer e un altro buffer vertici che può fornire dati aggiuntivi per istanza. Lo shader di vertice può essere utilizzato per combinare i dati di entrambi i buffer nel modo che preferisci.

Per essere concreti, nel tuo caso potresti creare una mesh che rappresenta un cerchio del raggio desiderato, con i suoi vertici specificati direttamente nelle coordinate dello spazio dello schermo e centrati sull'origine. Quindi useresti instancing per rendere la GPU render una nuova copia della mesh circolare per ogni vertice della tua mesh puntiforme originale. Nello shader di vertice, calcoleresti la posizione dello spazio dello schermo del punto (usando le trasformazioni di proiezione della visione del mondo come al solito), quindi traduresti la mesh del cerchio da centrare in quella posizione.

Per quanto riguarda la seconda parte della tua domanda, su come i cerchi si influenzano a vicenda il colore: dipende da cosa vuoi fare, in particolare. La fusione hardware può essere utilizzata per gestire casi semplici, come l'aggiunta o la moltiplicazione dei colori o la fusione alfa. Se vuoi qualcosa di più complicato di così, allora potrebbe essere possibile farlo con un algoritmo multi-pass o (sulle ultime GPU) miscelazione programmabile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.