2012-05-18 57 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