2014-10-08 17 views
5

Das SzenarioAlpha-Blending Ausgabe mit mehreren Iterationen Rendering in die gleiche Textur (OpenGL)

Ich bin ein Frame-Puffer-Objekt erstellt und die Bindung eine Textur Farb Befestigung 0. Ich bin nicht einen Tiefenpuffer . Nachdem ich es erstellt habe, entbinde ich es.

Zu einem späteren Zeitpunkt wird der Frame-Buffer gebunden, ein dreieckiger Streifen wird gerendert (einige Teile sind teilweise transparent) und dann wieder ungebunden. Dies wird mehrmals mit verschiedenen Dreiecksstreifen wiederholt.

Am Ende ist der Hauptframe-Puffer ein texturierter Quad mit der Textur, die an das von mir erstellte Bildpufferobjekt angehängt ist.

Das Problem

Ich finde, dass die teilweise transparenten Teile der Dreiecksstreifen in die Textur gezeichnet, die mit anderen Dreiecksstreifen überlappt nicht richtig gemischt werden. Sie scheinen eher mit Weiß gemischt zu sein als mit der Farbe, die bereits in der Textur ist. Selbst wenn ich die Textur beispielsweise mit einem durchgehenden Grün ausfülle, ist die Farbe, die während des Mischens aufgenommen wird, immer noch weiß.

Hier ein paar Schnipsel des Codes verwende ich all dies zu tun:

Initialisierung

glGenTextures(1, &texture_id); 
glBindTexture(GL_TEXTURE_2D, texture_id); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
glGenFramebuffers(1, &framebuffer_id); 
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0); 
glBindTexture(GL_TEXTURE_2D, 0); 
glBindFramebuffer(GL_FRAMEBUFFER, 0); 

In Textur rendern (iteriert auf)

glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id); 
glDisable(GL_DEPTH_TEST); 
glEnable(GL_BLEND); 
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

// On the first render iteration, do_clear is true 
if (do_clear) 
{ 
    glClearColor(r, g, b, a); 
    glClear(GL_COLOR_BUFFER_BIT); 
} 

// ... render the current triangle strip ... 

glBindFramebuffer(GL_FRAMEBUFFER, 0); 

Render Textur zum Haupt Framebuffer

// Set up the texture (making no assumptions about current state) 
glEnable(GL_TEXTURE_2D); 
glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, texture_id); 
glDisable(GL_DEPTH_TEST); 
glEnable(GL_BLEND); 
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

// Set up the vertex buffer (quad made up of triangle strip) 
glBindBuffer(GL_ARRAY_BUFFER, vertices_id); 
glVertexAttribPointer(VERTEX_ATTRIB_POSITION_TAG, 3, GL_FLOAT, GL_FALSE, sizeof(MyRenderVertex), BUFFER_OFFSET(0)); 
glEnableVertexAttribArray(VERTEX_ATTRIB_POSITION_TAG); 
glVertexAttribPointer(VERTEX_ATTRIB_TEXCOORD_TAG, 2, GL_FLOAT, GL_FALSE, sizeof(MyRenderVertex), BUFFER_OFFSET(3 * sizeof(GLfloat))); 
glEnableVertexAttribArray(VERTEX_ATTRIB_TEXCOORD_TAG); 
glVertexAttribPointer(VERTEX_ATTRIB_COLOR_TAG, 4, GL_FLOAT, GL_FALSE, sizeof(MyRenderVertex), BUFFER_OFFSET(5 * sizeof(GLfloat))); 
glEnableVertexAttribArray(VERTEX_ATTRIB_COLOR_TAG); 
glVertexAttribPointer(VERTEX_ATTRIB_NORMAL_TAG, 3, GL_FLOAT, GL_FALSE, sizeof(MyRenderVertex), BUFFER_OFFSET(9 * sizeof(GLfloat))); 
glEnableVertexAttribArray(VERTEX_ATTRIB_NORMAL_TAG); 

// Draw the textured geometry 
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

// Reset everything 
glDisableVertexAttribArray(VERTEX_ATTRIB_POSITION_TAG); 
glDisableVertexAttribArray(VERTEX_ATTRIB_TEXCOORD_TAG); 
glDisableVertexAttribArray(VERTEX_ATTRIB_COLOR_TAG); 
glDisableVertexAttribArray(VERTEX_ATTRIB_NORMAL_TAG); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 
glBindTexture(target, 0); 
glActiveTexture(0); 

Ein Beispiel, was ich sehe

Die Teile, wo Sie die weißen Linien zu sehen sind, wo die Dreiecksstreifen überlappen. Sie sollten teilweise transparent und mit dem zuvor gezeichneten Schwarz gemischt sein.

Bad Blending

aktualisieren

ich einige Entdeckungen gemacht habe, seit ich gepostet:

  • Die "weißen" Teil tatsächlich vollständig transparent ist, so wird es nur zeigen, die Farbe von allem, was hinter der Textur gerendert wird
  • Ich ersetzte die komplexeren Dreiecksnetze durch zufällig platzierte Quadrate, die aus ve bestehen Die Bilder, die von der einen Seite des Quadrats völlig durchsichtig sind und auf der anderen Seite völlig undurchsichtig sind, und ich sehe nicht das gleiche Mischproblem. Hier ist ein Bild der Quadrate:

Good Blending

So scheint es ein Problem mit dem Dreieck Maschen Ich verwende und nicht die Vermischung.

Eigentlich, sehr genau auf das "Gute Blending" Bild, kann ich sehen, dass die völlig undurchsichtigen Teile eines Quadrats tatsächlich aufgehellt werden, wenn ein anderes Quadrat darüber gerendert wird. Das Problem ist also da, es ist nicht ganz so extrem.

+0

ich die „weißen“ Teil nicht ganz erklären kann. Ich denke, Sie könnten das beste Ergebnis erzielen, wenn Sie den FBO auf Schwarz setzen. Benutzt du Shader? Produziert der Fragment-Shader den richtigen Alpha-Wert? Auf jeden Fall sieht das ziemlich ähnlich zu einer früheren Frage, die ich ausführlich beantwortete (Kopfgeld!), Vielleicht wird es hilfreich sein: http://stackoverflow.com/questions/24346585/opengl-render-to-texture-with- Teiltransparenz-Transluzenz und dann Rende. –

+0

Ich habe versucht, den FBO zu allen Arten von Farben ohne Erfolg zu löschen. Und ja, ich verwende Vertex- und Fragment-Shader (sehr ähnlich denen in Kapitel 8 des OpenGL ES 2.0 Programmierhandbuchs). Ich habe diese andere Frage gesehen, und ich habe eine Reihe von verschiedenen Mischfunktionen ausprobiert, ohne Erfolg. Siehe mein Update oben - ich glaube, es ist das Problem mit den Dreiecksnetzen. – codely

Antwort

6

Wenn Sie Textur machen, versuchen

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); 

statt:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

Der Fall in das heißt, wenn Sie die Alpha-Kanal wird auch gemischt Textur machen zu.

Um das klarzustellen, betrachten wir eine halbtransparente Kante über einem undurchsichtigen Dreieck, die zuvor gerendert wurde. Lassen Sie uns den Alpha-Wert der Kante 0,5 (Quell-Alpha) und das Alpha im Render-Puffer 1,0 (Zielwert) sein. So würde der resultierende Wert sein:

r = SrcAlpha * SrcAlpha + DstAlpha * (1.0 - SrcAlpha) = 0.5 * 0.5 + 0.5 * 0.5 = 0.5 

Wie Sie sehen, ist der Wert von alpha in Puffer machen nicht gleich 1,0 ist, wie Sie erwartet hatten. Als Ergebnis würde die Quellfarbe mit der Zielfarbe im Hauptrahmenpuffer gemischt werden.

Sie müssen also Alpha-Kanal nicht mischen. Sie können zum Beispiel einfach den Quell-Alpha-Wert zum Ziel-Alpha-Wert hinzufügen. Dies kann erreicht werden, indem Sie eine andere Mischfunktion für den Alphakanal unter Verwendung von glBlendFuncSeparate angeben.

Weitere Einzelheiten finden Sie unter this und this.

Vergewissern Sie sich auch, dass Sie eine richtige Mischungsgleichung gesetzt haben:

glBlendEquation(GL_FUNC_ADD); 

Siehe this für weitere Details

+0

Ausgezeichnete Vorschläge (Ich würde diese Antwort auffrischen, wenn ich könnte)! Ich habe vorher mit glBlendFuncSeparate() experimentiert, aber nicht mit diesen speziellen Parametern. Ich habe beide Vorschläge ausprobiert, aber immer noch kein Glück. Es scheint mit den Scheitelpunkten verwandt zu sein, die in den Dreiecksgittern verwendet werden, die irgendwie "Löcher" in meine Textur schlagen. – codely

+0

Ignorieren Sie diesen letzten Kommentar. Ich habe vergessen, dass das Dreiecksgitter-Rendering stapelweise verwendet wird und dass der Batch-Renderer seine eigene Mischfunktion verwendet. Sobald ich Ihre Mischungsgleichung in den Batch-Renderer eingefügt habe, wurde das Problem behoben! – codely