Визуализация текстуры прямоугольника с помощью GLSL
Я создал класс, который отображает видеокадры (на 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");
что дает мне 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, что помогло мне правильно понять оригинальный код для фрагментного шейдера (вот почему я не разместил его здесь), но с момента добавления вершинного шейдера он также не дает никакого вывода (мне было интересно как он мог знать, как произвести вывод, если он все равно не знает атрибуты position/texCoord?)
1 ответ
Я не внимательно изучил каждую строчку, но думаю, что ваша логика в основном верна. То, что я вижу, отсутствует glEnableVertexAttribArray
, Вам нужно включить оба атрибута вершины перед вызовом glDrawArrays.