2014-10-08 14 views
5

Lo scenarioAlpha blending problema con più iterazioni di rendering nella stessa trama (OpenGL)

Sto creando un oggetto frame buffer e vincolante una consistenza all'attaccamento colore 0. Non sto usando un buffer di profondità . Dopo averlo creato, lo smeriglio.

A un certo punto nel tempo, il frame buffer è vincolato, una striscia triangolare viene visualizzata su di esso (alcune parti parzialmente trasparenti), quindi non è più rilegato. Questo viene ripetuto un numero di volte con diverse strisce triangolari.

In definitiva, ciò che viene disegnato sul frame buffer principale è un quad strutturato con la texture che è collegata all'oggetto del frame buffer che ho creato.

Il problema

Ho constatato che le parti parzialmente trasparenti delle strisce di triangoli disegnati nella trama che si sovrappongono con altre strisce triangolo non vengono miscelati correttamente. Sembrano essere miscelati con il bianco piuttosto che con il colore già presente nella trama. Anche se riempio la trama con il verde fisso (ad esempio), il colore che viene raccolto mentre si fonde è ancora bianco.

Ecco alcuni frammenti di codice che sto usando per fare tutto questo:

inizializzazione

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); 

rendere a Texture (iterati su)

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 texture al framebuffer principale

// 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); 

un esempio di quello che sto vedendo

Le parti in cui si vedono le linee bianche sono dove le strisce di triangoli si sovrappongono. Dovrebbero essere parzialmente trasparenti e miscelati con il nero disegnato in precedenza.

Bad Blending

Aggiornamento

Ho fatto un paio di scoperte da quando ho postato questo:

  • La parte "bianca" è in realtà completamente trasparente, in modo che sarà solo mostrare il colore di tutto ciò che viene reso dietro la trama
  • Ho sostituito le maglie triangolari più complesse con quadrati disposti casualmente che sono costituiti da ve ritorni che vanno da completamente trasparente su un lato del quadrato a completamente opaco dall'altro lato, e non vedo lo stesso problema di fusione. Ecco una foto delle piazze:

Good Blending

Così sembra essere un problema con il triangolo maglie sto usando e non la fusione.

In realtà, guardando molto attentamente l'immagine "Buona fusione", posso vedere che le parti completamente opache di un quadrato vengono effettivamente alleggerite quando un altro quadrato viene reso sopra di esso. Quindi il problema è lì, non è proprio così estremo.

+0

Non riesco a spiegare la parte "bianca". Penso che potresti ottenere il miglior risultato cancellando l'FBO in nero. Stai usando gli shader? Lo shader di frammenti genera il giusto valore alfa? In ogni caso, sembra abbastanza simile a una domanda precedente che ho risposto in dettaglio (bounty!), Forse sarà di aiuto: http://stackoverflow.com/questions/24346585/opengl-render-to-texture-with- parziale trasparenza-traslucenza-e-poi-Rende. –

+0

Ho provato a cancellare l'FBO a tutti i tipi di colori senza successo. E sì, sto usando vertex e framment shaders (molto simili a quelli del capitolo 8 della guida alla programmazione di OpenGL ES 2.0). Ho visto quell'altra domanda, e ho provato un sacco di diverse funzioni di fusione senza successo. Vedi il mio aggiornamento sopra - Credo che sia il problema con le mesh triangolari. – codely

risposta

6

Quando si esegue il rendering di tessitura, provare

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); 

invece di:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

La cassa è in che, quando si esegue il rendering per la grana canale alfa è anche miscelato.

Per chiarire le cose, prendiamo in considerazione il rendering di un bordo semitrasparente su una striscia triangolare opaca precedentemente renderizzata. Diamo il valore alfa del bordo sia 0,5 (origine alfa) e l'alfa nel buffer di rendering sia 1.0 (valore di destinazione). Quindi il valore risultante sarebbe:

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

Come si vede, il valore di alfa a rendere buffer non è uguale a 1.0, come ti aspettavi. Di conseguenza, il colore di origine verrebbe unito al colore di destinazione nel buffer del frame principale.

Quindi non è necessario unire il canale alfa. Ad esempio, è possibile semplicemente aggiungere il valore alfa di origine al valore alfa di destinazione, questo può essere ottenuto specificando una diversa funzione di fusione per il canale alfa usando glBlendFuncSeparate.

Vedere this e this per ulteriori dettagli.

Inoltre assicurarsi, che è stata impostata un'equazione miscelazione corretta:

glBlendEquation(GL_FUNC_ADD); 

Vedere this per maggiori dettagli

+0

Ottimi suggerimenti (avrei alzato questa risposta se potessi)! Ho già fatto esperimenti con glBlendFuncSeparate(), ma non con quei particolari parametri. Ho provato entrambi i tuoi suggerimenti, ma ancora senza fortuna. Sembra che sia correlato ai vertici utilizzati nel triangolo, maglie in qualche modo perforando "buchi" nella mia trama. – codely

+0

Ignora l'ultimo commento. Ho dimenticato che il rendering della mesh triangolare è in batch e che il renderer in batch applica la propria funzione di fusione. Una volta che ho inserito la tua equazione di fusione nel renderizzatore di lotti, ha risolto il problema! – codely

Problemi correlati