Визуализация текстуры прямоугольника с помощью 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.

Другие вопросы по тегам