我创建了一个类,可以将视频帧(在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()渲染它。
工作正常,我得到了预期的结果(除了闪烁效果,我猜这与我在两个不同的线程上使用两个不同的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");
这给了我texCoord的0和位置的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属性呢?)
答案 0 :(得分:2)
我没有仔细研究过每一行,但我认为你的逻辑大多是正确的。我看到的缺失是glEnableVertexAttribArray
。您需要在glDrawArrays调用之前启用两个顶点属性。