Почему я не могу прикрепить эту форму текстуры к своему фрагментному шейдеру GLSL? - PullRequest
3 голосов
/ 13 ноября 2010

В моем приложении Mac я определяю прямоугольную текстуру на основе данных YUV 4: 2: 2 с подключенной камеры. Используя стандартные координаты вершин и текстур, я могу без проблем нарисовать это в прямоугольной области на экране.

Однако я хотел бы использовать фрагментный шейдер GLSL для обработки этих кадров изображения на графическом процессоре, и у меня возникли проблемы с передачей прямоугольной видео-текстуры как унифицированной фрагментному шейдеру. Когда я пытаюсь это сделать, текстура просто выглядит как черная.

Шейдерная программа компилирует, связывает и проходит валидацию. Я получаю правильный адрес для униформы из шейдерной программы. Другие формы, такие как значения с плавающей запятой, передаются корректно, и фрагментный шейдер реагирует на изменения этих значений. Фрагмент шейдера получает правильные координаты текстуры. Я также обильно посыпал свой код функцией glGetError () и нигде не видел ошибок.

Вершинный шейдер выглядит следующим образом:

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

    gl_FrontColor = gl_Color;
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
}

и фрагмент шейдера выглядит следующим образом:

uniform sampler2D videoFrame;

void main()
{
    gl_FragColor = texture2D(videoFrame, gl_TexCoord[0].st);
}

Это должно просто отобразить текстуру на моей прямоугольной геометрии.

Соответствующий код чертежа выглядит следующим образом:

static const GLfloat squareVertices[] = {
    -1.0f, -1.0f,
    1.0f, -1.0f,
    -1.0f,  1.0f,
    1.0f,  1.0f,
};

const GLfloat textureVertices[] = {
    0.0, videoImageSize.height,
    videoImageSize.width, videoImageSize.height,
    0.0, 0.0,
    videoImageSize.width, 0.0
};

CGLSetCurrentContext(glContext);

if(!readyToDraw)
{
    [self initGL];
    readyToDraw = YES;
}


glViewport(0, 0, (GLfloat)self.bounds.size.width, (GLfloat)self.bounds.size.height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); 

glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glEnable(GL_TEXTURE_2D);

glGenTextures(1, &textureName);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, textureName);

glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, videoImageSize.width, videoImageSize.height, 0, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, videoTexture);  

glUseProgram(filterProgram);    

glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);   

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, squareVertices);
glTexCoordPointer(2, GL_FLOAT, 0, textureVertices);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

[super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:interval displayTime:timeStamp];

glDeleteTextures(1, &textureName);

Этот код находится в CAOpenGLLayer, где суперкласс -drawInCGLContext:pixelFormat:forLayerTime: displayTime: просто запускает glFlush().

Унифицированный адрес читается с использованием кода, подобного следующему:

uniforms[UNIFORM_VIDEOFRAME] = glGetUniformLocation(filterProgram, "videoFrame");

Как я уже сказал, если я закомментирую линии glUseProgram() и glUniform1i(), этот текстурированный прямоугольник будет отображаться правильно. Оставив их, можно нарисовать черный прямоугольник.

Что может помешать передаче моей текстурной униформы в мой фрагментный шейдер?

1 Ответ

7 голосов
/ 13 ноября 2010

Не уверен насчет используемой вами версии GLSL, но начиная с версии 1.40 и выше есть тип sampler2DRect, специально предназначенный для доступа к текстурам, отличным от двух. Может быть тем, что вы ищете, однако я не знаю, как обрабатывались прямоугольные текстуры до glsl 1.40.

...