iOS - Как нарисовать изображение YUV с помощью openGL

В настоящее время я пытаюсь нарисовать изображение с помощью openGL (изображение обновляется очень часто, и поэтому его необходимо перерисовать). Ранее я конвертировал свое изображение из YUV в RGB, а затем использовал это новое изображение для рисования с openGL. Все работало нормально, но процесс конвертации был не особенно быстрым.

Сейчас я пытаюсь изменить код, чтобы преобразование осуществлялось в шейдерах openGL. Осмотревшись вокруг, ямы нашли пару фрагментов кода (особенно шейдеры и основную часть моей функции renderImage), которые помогли мне получить базовый уровень, но я могуПохоже, что на самом деле изображение правильно нарисовано - все, что я вижу, - это черное изображение.

Это'вполне вероятно, что яМне не хватает чего-то чрезвычайно простого и важного - мой опыт работы с openGL довольно ограничен. Если кто-нибудь может взглянуть и увидеть, если они что-то не так, пожалуйста, дайте мне знать.

Я должен указать, яя пытаюсь поддерживать iOS 4.x, поэтому CVOpenGLESTextureCacheCreateTextureFromImage не долженне пригодный для использования (а яЯ не очень уверен, как настроить, чтобы использовать его, даже если я хотел).

Любая помощь будет оценена. Код ниже -

Мой Вершинный шейдер:

attribute vec4 position;
attribute vec4 inputTextureCoordinate;

varying vec2 textureCoordinate;

void main()
{
    gl_Position = position;
    textureCoordinate = inputTextureCoordinate.xy;
}

Фрагмент шейдера:

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 textureCoordinate;

uniform sampler2D videoFrame;
uniform sampler2D videoFrameUV;

const mat3 yuv2rgb = mat3(
                          1, 0, 1.2802,
                          1, -0.214821, -0.380589,
                          1, 2.127982, 0
                          );

void main() {
    vec3 yuv = vec3(
                    1.1643 * (texture2D(videoFrame, textureCoordinate).r - 0.0625),
                    texture2D(videoFrameUV, textureCoordinate).r - 0.5,
                    texture2D(videoFrameUV, textureCoordinate).a - 0.5
                    );
    vec3 rgb = yuv * yuv2rgb;

    gl_FragColor = vec4(rgb, 1.0);
}

Функция renderImage:

-(void)renderImage:(ImageBuffer *)image
{
    if (image)
    {        
        int bufferHeight = image->GetHeight();
        int bufferWidth = image->GetWidth();

        if(!imageTexture){
            // Dealing with the Y portion of the YCbCr
            glActiveTexture(GL_TEXTURE0);
            glGenTextures(1, &imageTexture);
            //Bind Y texture
            glBindTexture(GL_TEXTURE_2D, imageTexture);
            glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);
            // For fitting
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            // This is necessary for non-power-of-two textures
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

            glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, bufferWidth, bufferHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, image->GetPlanePointer(0));

            // Dealing with the CbCr potion of the YCbCr
            glActiveTexture(GL_TEXTURE1);
            glGenTextures(1, &imageTextureUV);
            //Bind CbCr texture
            glBindTexture(GL_TEXTURE_2D, imageTextureUV);
            glUniform1i(uniforms[UNIFORM_VIDEOFRAMEUV], 1);
            // For fitting
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            // This is necessary for non-power-of-two textures
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

            glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, bufferWidth/2, bufferHeight/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, image->GetPlanePointer(1));

        }

        [self drawFrame];
    }
}

И, наконец, функция drawFrame:

- (void)drawFrame
{
    [self setFramebuffer];

    // Replace the implementation of this method to do your own custom drawing.
    static const GLfloat squareVertices[] = {
        -1.0f, -1.0f,
        1.0f, -1.0f,
        -1.0f, 1.0f,
        1.0f, 1.0f
    };

    static const GLfloat textureVertices[] = {
//        1.0f, 1.0f,
//        1.0f, 0.0f,
//        0.0f,  1.0f,
//        0.0f,  0.0f,
        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f
//        0.0f, 0.8f,
//        1.0f, 0.8f,
//        0.0f, 0.2f,
//        1.0f, 0.2f
    };

    static float transY = 0.0f;


    if ([context API] == kEAGLRenderingAPIOpenGLES2) {
        // Use shader program.
        glUseProgram(program);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, imageTexture);

        // Update attribute values.
        glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
        glEnableVertexAttribArray(ATTRIB_VERTEX);
        glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
        glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);

        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, imageTextureUV);

        // Update attribute values.
        glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
        glEnableVertexAttribArray(ATTRIB_VERTEX);
        glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
        glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);

        // Validate program before drawing. This is a good check, but only really necessary in a debug build.
        // DEBUG macro must be defined in your debug configurations if that's not already the case.
#if defined(DEBUG)
        if (![self validateProgram:program]) {
            NSLog(@"Failed to validate program: %d", program);
            return;
        }
#endif
    } else {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0f, (GLfloat)(sinf(transY)/2.0f), 0.0f);
        transY += 0.075f;

        glVertexPointer(2, GL_FLOAT, 0, squareVertices);
        glEnableClientState(GL_VERTEX_ARRAY);
    } 

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    [self presentFramebuffer];
}

Ответы на вопрос(1)

Ваш ответ на вопрос