#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 для восстановления текстурных данных обратно в память. Это не было жизненно важным для того, что я делал, поэтому я могу просто обойти это.