Сбой glFramebufferTexture2D на iPhone из-за определенных размеров текстуры

#iphone #opengl-es #framebuffer #render-to-texture

#iPhone #opengl-es #фреймбуфер #рендеринг в текстуру

Вопрос:

Когда я пытаюсь прикрепить текстуру к фреймбуферу, glCheckFramebufferStatus сообщает, что GL_FRAMEBUFFER_UNSUPPORTED для определенных размеров текстуры. Я тестировал как на iPod Touch 2-го, так и на iPod Touch 4-го поколения. Размеры текстур, которые выходят из строя, не идентичны для двух моделей.

Вот несколько интересных результатов:

2-е поколение — сбой 8×8, сбой 16×8, но сбой 8×16 удался!

4-е поколение — 8×8 успешно, 8×16 успешно, но 16×8 не удалось!

Вот некоторый код, который я использовал для тестирования прикрепления текстур разных размеров:

 void TestFBOTextureSize(int width, int height)
{
    GLuint framebuffer, texture;

    // Create framebuffer
    glGenFramebuffersOES(1, amp;framebuffer);
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);

    // Create texture
    glGenTextures(1,amp;texture);
    glBindTexture(GL_TEXTURE_2D,texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glBindTexture(GL_TEXTURE_2D,0);

    // Attach texture to framebuffer
    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture, 0);
    GLenum error = glGetError();
    GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
    if (status==GL_FRAMEBUFFER_COMPLETE_OES)
        NSLog(@"%dx%d Succeeded!",width,height,status);
    else
        NSLog(@"%dx%d Failed: %x %x %d %d",width,height,status,error,texture,framebuffer);

    // Cleanup
    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, 0, 0);
    glDeleteTextures(1, amp;texture);
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
    glDeleteFramebuffersOES(1, amp;framebuffer);   
}

void TestFBOTextureSizes()
{
    int width,height;
    for (width=1; width<=1024; width<<=1)
    {
        for (height=1; height<=1024; height<<=1)
            TestFBOTextureSize(width,height);
    }
}
  

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

Ответ №1:

Я столкнулся с аналогичной проблемой, когда пытался отобразить текстуру размером 480×320 (полноэкранный режим без масштаба разрешения) на iPod touch 4. Когда я вызываю, glCheckFramebufferStatus() он возвращается GL_FRAMEBUFFER_UNSUPPORTED . Мой код:

 glGenTextures(1, amp;texture);    
glBindTexture(GL_TEXTURE_2D, texture);        
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 480, 320, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
glBindTexture(GL_TEXTURE_2D, 0);

glGenFramebuffers(1, amp;frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
    // report error
}
  

Исследуя эту проблему, я обнаружил, что GL_TEXTURE_2D должен быть допустимый объект OpenGL ES, если мы хотим использовать его в механизме преобразования текстуры. Это означает, что текстура должна быть готова к привязке и использованию. Поэтому, чтобы исправить ошибку, я должен установить некоторые параметры текстуры. Поскольку я использую текстуру, отличную от POT, я должен установить GL_TEXTURE_WRAP_ на GL_CLAMP_TO_EDGE (значение по умолчанию — GL_REPEAT ) и GL_TEXTURE_MIN_FILTER на GL_NEAREST или GL_LINEAR (значение по умолчанию — GL_NEAREST_MIPMAP_LINEAR ), чтобы использовать эту текстуру.

Я не смог найти, в чем проблема с 16×8, но 16×9 и 17×8 работают нормально, если установлены эти параметры. Я надеюсь, что эта информация будет для вас полезной.

Комментарии:

1. Я все еще получаю ошибки, даже если я установил режим переноса на GL_CLAMP_TO_EDGE и минимальный фильтр на ближайший. Когда вы говорите, что у вас нет проблем с текстурой 16×8, вы имеете в виду, что мой пример кода работает на вашем устройстве для текстуры 16×8? Или вы имеете в виду, что это работает в вашем собственном коде? Может быть, вы могли бы опубликовать небольшой образец, подобный моему образцу, который работает для текстуры размером 16×8. Спасибо!

2. У меня также проблема с текстурой 16×8. У меня это тоже не работает. Но 16×9 и 17×8 просто работают! Это очень странно. Я только что заметил, что объект текстуры должен иметь допустимые параметры, если вы хотите прикрепить его к фреймбуферу.

3. Очень странно! Я думаю, что моим решением будет не пытаться считывать данные из моих текстур. Я использовал текстуру, прикрепленную к фреймбуферу, в сочетании с glReadPixels для восстановления текстурных данных обратно в память. Это не было жизненно важным для того, что я делал, поэтому я могу просто обойти это.