Wie schreibt man Pass-Through-Vertex- und Fragment-Shader für einen Framebuffer mit angehängter Textur?

8

Ich versuche, Shader zu verwenden, um eine Textur zu ändern, die an einen Framebuffer gebunden ist, aber ich bin verwirrt, wie die Shader die "ursprünglichen" Eingabewerte erhalten.

Ich mache folgendes:

%Vor%

Wie würden leere Vertex- und Fragment-Shader aussehen? Da ich keine Primes zeichne, wie setze ich gl_Position im Vertex-Shader? Was ist mit dem Passieren der Eingabefarbe als Ausgabefarbe des Fragment-Shaders?

Leerer Vertex-Shader:

%Vor%

Leeres Fragment Shader:

%Vor%     
Mark Ingram 12.06.2013, 11:04
quelle

1 Antwort

13
  

Ich hatte den Eindruck, dass Sie auf einem Offscreen rendern könnten   Framebuffer, mit einer angehängten Textur, dann benutze Shader, um die   Textur, verwenden Sie dann glReadPixels, um die geänderten Daten zurück zu erhalten. Das ist   was ich versuche zu tun.

Ah, ok, also möchtest du eine Textur durch einen Fragment-Shader füttern, um eine neue Textur zu erhalten. Zuallererst müssen Sie daran denken, dass Sie eine Textur nicht direkt ändern können, da Sie nicht von der Textur lesen können, in die Sie gerade rendern. Sie müssen die zu modifizierende Textur als normale Textur in den Fragment-Shader einspeisen und das Ergebnis wie gewohnt in den Framebuffer ausgeben. Dies könnte ein FBO mit einer anderen Textur sein, ein renderbuffer ( wenn Sie es zurück zur CPU sowieso lesen möchten), oder der Standard Framebuffer. Sie benötigen kein FBO, wenn Sie nur ein Bild in ein anderes Bild umwandeln möchten, nur wenn das Ergebnis in einen Offscreen-Puffer oder eine Textur geschrieben werden soll.

Außerdem müssen Sie noch etwas zeichnen, damit der Rasterizer tatsächliche Fragmente erzeugt, um den Fragment-Shader für aufzurufen. Der übliche Weg, dies zu tun, besteht darin, einfach ein bildschirmgroßes Quadrat parallel zur Betrachtungsebene zu zeichnen, um das komplette Ansichtsfenster mit Fragmenten zu füllen:

%Vor%

Als Vertex-Shader genügt ein einfacher Pass-Thru-Shader, da sich die Vertex-Positionen bereits im Clip-Space befinden:

%Vor%

Im Fragment Shader nehmen wir die Textur als Eingabe. Die Texturkoordinate ist bereits durch die Position des Fragments auf dem Bildschirm gegeben, wir müssen sie nur normalisieren, indem wir durch die Texturgröße dividieren (oder verwenden Sie GL_TEXTURE_RECTANGLE und corresponsing samplerRect , um die Fragmentkoordinate direkt zu verwenden):

%Vor%

Das ist alles, die geänderte Textur wird in den Framebuffer geschrieben, egal wohin die Weiterleitung oder was Sie mit den Framebuffer-Daten danach machen.

BEARBEITEN: Mit OpenGL 4.3 und seinen Compute-Shadern gibt es nun einen direkteren Weg für solche reinen Nicht-Rasterisierungs-GPGPU-Aufgaben wie Bildverarbeitung. Sie können einfach einen Compute-Shader aufrufen (der anderen GPU-Computing-Frameworks wie CUDA oder OpenCL ähnlicher ist als die anderen OpenGL-Shader) in einer regulären 2D-Domäne und einem 2D-Prozess eine Textur (unter Verwendung der Bildlade- / Speicherfunktionalität von OpenGL 4.2) direkt an Ort und Stelle. In diesem Fall benötigen Sie nur den entsprechenden Compute Shader:

%Vor%

Dann müssen Sie lediglich die Textur an die entsprechende Bildeinheit (0, wie im Shader eingestellt) binden und einen Compute-Shader über die zweidimensionale Bilddomäne aufrufen:

%Vor%

Und das ist alles, Sie brauchen keinen FBO, Sie brauchen keine anderen Shader, Sie müssen nichts zeichnen, nur rohe Berechnungen. Es muss jedoch bewertet werden, ob dieser direktere Ansatz auch zu einer besseren Leistung führt. Und ebenso müssen Sie möglicherweise auf die richtige Speichersynchronisierung der zu ändernden Textur achten, besonders wenn Sie danach versuchen, davon zu lesen. Konsultieren Sie tiefer gehende Materialien zum Laden / Speichern von Bildern für weitere Informationen.

    
Christian Rau 12.06.2013, 11:40
quelle