2012-05-18 150 views
9

我創建了一個類,可以將視頻幀(在Mac上)渲染爲自定義幀緩衝區對象。作爲輸入,我有一個YUV紋理,併成功創建了一個片段着色器,該着色器將輸入3個矩形紋理(每個Y,U和V平面分別用glTexSubImage2D使用GL_TEXTURE_RECTANGLE_ARB,GL_LUMINANCE和GL_UNSIGNED_BYTE上傳數據) ,在渲染之前,我將活動紋理設置爲三個不同的紋理單元(0,1和2)併爲每個紋理單元綁定紋理,出於性能原因,我使用了GL_APPLE_client_storage和GL_APPLE_texture_range。然後我使用glUseProgram(myProg),glBegin(GL_QUADS)... glEnd()來渲染它。使用GLSL渲染矩形紋理

工作正常,我得到了預期的結果(除了閃爍的效果,我認爲這與我在兩個不同的線程上使用兩個不同的GL上下文這一事實有關,並且我認爲它們會進入對方的某種程度上[這是後面另一個問題的主題])。無論如何,我決定通過添加一個頂點着色器來進一步改進我的代碼,這樣我就可以跳過glBegin/glEnd - 我讀的過時了,應該避免。

所以作爲下一步我創建了兩個緩衝區對象,一個頂點,一個用於紋理座標:

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

然後加載着色器後,我嘗試檢索屬性的頂點位置着色器:

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

它給我0爲texCoord和1爲位置,這似乎很好。

獲得的屬性後,我也呼籲

 glEnableVertexAttribArray(m_attributePos); 
     glEnableVertexAttribArray(m_attributeTexCoord); 

(我做的只有一次,還是有每glVertexAttribPointer和調用glDrawArrays之前完成?是否需要每個紋理單元做?或者?而我的着色器與glProgram激活,也可以我這樣做只是任何地方)

之後,我改變了渲染代碼替換在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); 

但是,由於將代碼更改爲此,我總是隻會得到一個黑屏。所以我想我錯過了一些簡單的步驟,可能是一些glEnable/glDisable或者正確設置了一些東西 - 但是就像我說的我是新手一樣,所以我沒有真正的想法。供您參考,這裏是頂點着色器:

#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; 
} 

我的猜測是,我失去了一些東西很明顯這裏,或根本沒有正在進行的過程的瞭解不夠深刻這裏呢。我也嘗試過使用OpenGLShaderBuilder,它幫助我得到了片段着色器的原始代碼(這就是爲什麼我沒有在這裏發佈它),但是由於添加了頂點着色器,它也不給我任何輸出(想知道如果它不知道位置/ texCoord屬性怎麼知道如何生成輸出?)

+1

對於紋理矩形,座標不應被標準化,但您似乎正在傳遞標準化座標。 – harold

+0

哦,所以對於texCoordData []而不是0.0,1.0等我通過例如1920.0,1080.0(即視頻幀的實際大小)? – Bjoern

+0

死亡的黑屏在圖形中非常常見。我認爲你試圖改變清晰的顏色,以確保你實際上繪製任何東西?如果你是*,那麼它是一個着色器問題,如果不是的話,頂點數組問題。 – imallett

回答

2

我還沒有仔細研究過每一行,但我認爲你的邏輯大部分是正確的。我看到缺少的是glEnableVertexAttribArray。您需要在調用glDrawArrays之前啓用兩個頂點屬性。

+0

感謝您的快速回復,並對此表示歉意,但我已經這麼做了,但忘了在上面的帖子中提到它(現在將編輯該文件),並且沒有,這實際上並沒有幫助我 – Bjoern

+0

好吧,我在錯誤的地方調用了glEnableVertexAttribArray。在我獲得屬性位置之前,我調用它之前,所以現在我改變它在每一幀被調用,並且它終於起作用。但我不明白爲什麼我需要調用每一幀,我認爲它會記住它被啓用? – Bjoern

+0

@Bjoern它應該記住它,而不必被稱爲每一幀,你是否可能禁用它的某個地方? – Tim