2012-05-18 12 views
9

Ho creato una classe che esegue il rendering di videoframes (su Mac) su un oggetto framebuffer personalizzato. Come input ho una texture YUV, e ho creato con successo uno shader di frammenti, che prende come input 3 trame rettangolari (uno per Y, U e V piani ciascuno, i dati per i quali è caricato da glTexSubImage2D utilizzando GL_TEXTURE_RECTANGLE_ARB, GL_LUMINANCE e GL_UNSIGNED_BYTE) prima di eseguire il rendering, ho impostato le trame attive su tre diverse unità di texture (0, 1 e 2) e ho associato una texture per ciascuna, e per motivi di prestazioni ho utilizzato GL_APPLE_client_storage e GL_APPLE_texture_range. Poi l'ho reso usando glUseProgram (mioProg), glBegin (GL_QUADS) ... glEnd().Texture rettangolo di rendering con GLSL

Questo ha funzionato bene e ho ottenuto il risultato previsto (a parte un effetto sfarfallio, che suppongo abbia a che fare con il fatto che ho usato due diversi contesti GL su due thread diversi, e suppongo che entrino l'uno nell'altro a un certo punto [è argomento per un'altra domanda più tardi]). Ad ogni modo, ho deciso di migliorare ulteriormente il mio codice aggiungendo anche un vertex shader, in modo da poter saltare glBegin/glEnd - che ho letto è obsoleto e dovrebbe essere comunque evitato.

Così come un passo successivo ho creato due oggetti di buffer, uno per i vertici e uno per la texture coordinate

 const GLsizeiptr posSize = 4 * 4 * sizeof(GLfloat); 
     const GLfloat posData[] = 
     { 
      -1.0f, -1.0f, -1.0f, 1.0f, 
      1.0f, -1.0f, -1.0f, 1.0f, 
      1.0f, 1.0f, -1.0f, 1.0f, 
      -1.0f, 1.0f, -1.0f, 1.0f 
     }; 

     const GLsizeiptr texCoordSize = 4 * 2 * sizeof(GLfloat); 
     const GLfloat texCoordData[] = 
     { 
      0.0, 0.0, 
      1.0, 0.0, 
      1.0, 1.0, 
      0.0, 1.0 
     }; 

    glGenBuffers(1, &m_vertexBuffer); 
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer); 
    glBufferData(GL_ARRAY_BUFFER, posSize, posData, GL_STATIC_DRAW); 

    glGenBuffers(1, &m_texCoordBuffer); 
    glBindBuffer(GL_ARRAY_BUFFER, m_texCoordBuffer); 
    glBufferData(GL_ARRAY_BUFFER, texCoordSize, texCoordData, GL_STATIC_DRAW); 

Poi dopo aver caricato gli shaders cerco di recuperare le posizioni dei attributi nel vertice shader:

 m_attributeTexCoord = glGetAttribLocation(m_shaderProgram, "texCoord"); 
     m_attributePos = glGetAttribLocation(m_shaderProgram, "position"); 

che mi dà 0 per texCoord e 1 per posizione, il che sembra soddisfacente.

Dopo aver ottenuto gli attributi anche io chiamo

 glEnableVertexAttribArray(m_attributePos); 
     glEnableVertexAttribArray(m_attributeTexCoord); 

(che sto facendo che solo una volta, o ha di essere fatto prima di ogni glVertexAttribPointer e glDrawArrays? Ha bisogno di essere fatto per unità di tessitura? O ? mentre il mio shader è attivato con glProgram o posso farlo solo da nessuna parte)

Dopo che ho cambiato il codice di rendering per sostituire il glBegin/glEnd:?

 glActiveTexture(GL_TEXTURE0); 
     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texID_Y); 

     glActiveTexture(GL_TEXTURE1); 
     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texID_U); 

     glActiveTexture(GL_TEXTURE2); 
     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texID_V); 

     glUseProgram(myShaderProgID); 

     // new method with shaders and buffers 
     glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer); 
     glVertexAttribPointer(m_attributePos, 4, GL_FLOAT, GL_FALSE, 0, NULL); 
     glBindBuffer(GL_ARRAY_BUFFER, m_texCoordBuffer); 
     glVertexAttribPointer(m_attributeTexCoord, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
     glDrawArrays(GL_QUADS, 0, 4); 

     glUseProgram(0); 

Ma da quando ho cambiato il codice, ho sempre avuto sempre uno schermo nero come risultato. Quindi suppongo che mi mancano alcuni semplici passaggi, forse alcuni glEnable/glDisable o l'impostazione di alcune cose correttamente - ma, come ho detto, sono nuovo per questo, quindi non ho davvero avuto un'idea. Per il vostro riferimento, ecco la vertex shader:

#version 110 
attribute vec2 texCoord; 
attribute vec4 position; 

// the tex coords for the fragment shader 
varying vec2 texCoordY; 
varying vec2 texCoordUV; 

//the shader entry point is the main method 
void main() 
{ 
    texCoordY = texCoord; 
    texCoordUV = texCoordY * 0.5; // U and V are only half the size of Y texture 
    gl_Position = gl_ModelViewProjectionMatrix * position; 
} 

La mia ipotesi è che mi manca qualcosa di ovvio qui, o semplicemente non ho un abbastanza profonda comprensione dei processi in corso qui ancora. Ho provato a usare anche OpenGLShaderBuilder, il che mi ha aiutato a ottenere il codice originale per il frammento shader a destra (questo è il motivo per cui non l'ho postato qui), ma da quando ho aggiunto il vertex shader non mi ha dato alcun output (mi chiedevo come potrebbe sapere come produrre l'output, se non conosce la posizione/attributi di texCoord comunque?)

+1

Per i rettangoli di texture, le coordinate non dovrebbero essere normalizzate, ma sembra che si stiano passando in coordinate normalizzate. – harold

+0

Oh so per il texCoordData [] invece di 0.0, 1.0 ecc. Passo per esempio 1920.0, 1080.0 (cioè la dimensione effettiva del frame video)? – Bjoern

+0

Lo schermo nero della morte è così comune nella grafica.Immagino che tu abbia provato a cambiare il colore chiaro solo per assicurarti di disegnare qualcosa? Se * sei *, allora si tratta di un problema con lo shader, in caso contrario, problema con array di vertici. – imallett

risposta

2

Non ho studiato da vicino ogni riga, ma penso che la tua logica sia per lo più corretta. Quello che mi manca è glEnableVertexAttribArray. È necessario abilitare entrambi gli attributi di vertice prima della chiamata a glDrawArray.

+0

Grazie per la tua risposta rapida, e mi dispiace, ma lo sto già facendo ma ho dimenticato di menzionarlo nel post precedente (lo modificherò ora), e no, quello non mi ha aiutato in realtà – Bjoern

+0

Ok, come si trasforma ho chiamato glEnableVertexAttribArray nel posto sbagliato. Prima che lo chiamassi dopo aver ottenuto le posizioni degli attributi, così ora l'ho cambiato per essere chiamato su ogni frame, e finalmente funziona. Ma non capisco perché ho bisogno di chiamare ogni fotogramma, ho pensato che avrebbe ricordato di essere abilitato? – Bjoern

+0

@Bjoern dovrebbe ricordarlo senza dover essere chiamato ogni frame, stavi forse disabilitandolo da qualche parte? – Tim