Как восстановить GL_RENDERBUFFER?

Я работаю над сохранением и восстановлением состояния моего приложения на основе OpenGL ES.

У меня есть функция для сохранения GL_RENDERBUFFER для вывода данных со следующим кодом:

glBindFramebuffer(GL_FRAMEBUFFER, fboTextureBufferData.framebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, fboTextureBufferData.colorbuffer);

GLint x = 0, y = 0, width2 = backingWidth, height2 = backingHeight;
NSInteger dataLength = width * height * 4;
GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte));

// Read pixel data from the framebuffer
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);

Я не вижу функцию glWritePixels. Каков наилучший способ повторно заполнить GL_RENDERBUFFER данными GLubyte, указанными выше? Пример был бы очень признателен.

РЕДАКТИРОВАТЬ 3:

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

Я пробовал различные комбинации (например, также использовал GL_COLOR_ATTACHMENT1 для параметра glFramebufferRenderbuffer), но затем при попытке рендеринга я получаю сообщение об ошибке недопустимого буфера кадра. Кажется, я так близок, но не могу понять, как заставить их восстанавливать и рендерить вместе.

- (bool)configureRenderTextureBuffer {

    [EAGLContext setCurrentContext:context];

    glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];

    glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];

    glGenFramebuffers(1, &fboTextureBufferData.framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, fboTextureBufferData.framebuffer);

    glGenRenderbuffers(1, &fboTextureBufferData.colorbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, fboTextureBufferData.colorbuffer);

    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, backingWidth, backingHeight);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboTextureBufferData.colorbuffer);

    // Generate texture name, stores in .textureID
    glGenTextures(1, &fboTextureBufferData.textureID);

    glBindTexture(GL_TEXTURE_2D, fboTextureBufferData.textureID);

    ////////////////// Read Existing texture data //////////////////
    NSString *dataPath = [TDTDeviceUtilitesLegacy documentDirectory]; //This just returns the app's document directory
    NSData *data = [NSData dataWithContentsOfFile:[NSString stringWithFormat:@"%@/buffer.data", dataPath]];
    GLubyte *pixelData = (GLubyte*)[data bytes];

    // If I use GL_COLOR_ATTACHMENT1 here, my existing pixel data is restored
    // but no drawing occurs. If I use GL_COLOR_ATTACHMENT0, then data isn't
    // restored but drawing updates work
    glFramebufferTexture2D ( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, fboTextureBufferData.textureID, 0 );

    // Populate with existing data
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, backingWidth, backingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixelData[0]); //&image[0]

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ;
    if(status != GL_FRAMEBUFFER_COMPLETE) {
        NSLog(@"failed to make complete render texture framebuffer object %x", status);
        return false;
    }

    return true;
}

Вот код для рендеринга. ViewFramebuffer присоединен к GL_COLOR_ATTACHMENT0 и используется, чтобы буфер кадра текстуры можно было масштабировать и позиционировать внутри представления.

- (void)renderTextureBuffer {

    //Bind the texture frame buffer, if I don't use this, I can't get it to draw
    //glBindFramebuffer(GL_FRAMEBUFFER, fboTextureBufferData.framebuffer);

    //If I use this instead of binding the framebuffer above, I get no drawing and black background
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTextureBufferData.textureID, 0);

    renderParticlesToTextureBuffer();

    //Bind the view frame buffer.
    glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);

    drawFboTexture();

    [context presentRenderbuffer:GL_RENDERBUFFER];
}

person Jeshua Lacock    schedule 11.09.2016    source источник
comment
Вероятно, проще использовать текстуру вместо рендербуфера. Затем вы можете использовать glTexImage2D(), чтобы заполнить его данными.   -  person Reto Koradi    schedule 11.09.2016
comment
Проблема с таким подходом в том, что я думаю, что потребуется гораздо больше памяти. Это будет довольно большая текстура - около 67 МБ (4096x4096x4), тогда как буфер рендеринга уже выделен.   -  person Jeshua Lacock    schedule 11.09.2016
comment
Я предлагаю использовать текстуру вместо буфера рендеринга. Поэтому никогда не выделяйте буфер рендеринга в первую очередь и не используйте вместо него текстуру.   -  person Reto Koradi    schedule 11.09.2016
comment
Но мне нужен буфер рендеринга.   -  person Jeshua Lacock    schedule 11.09.2016
comment
Чтобы уточнить, это приложение для рисования, поэтому мне нужен буфер рендеринга для накопления мазков кисти за кадр.   -  person Jeshua Lacock    schedule 11.09.2016
comment
Вы можете использовать текстуру в качестве вложения FBO и выполнять рендеринг в нее так же, как вы рендерите в буфер рендеринга.   -  person Reto Koradi    schedule 11.09.2016
comment
Интересно. Не могли бы вы указать мне пример?   -  person Jeshua Lacock    schedule 11.09.2016


Ответы (1)


Если вам нужно записать данные непосредственно в цель рендеринга, использование буфера рендеринга не является хорошим вариантом. В этом случае гораздо лучше использовать текстуру.

Использование текстуры в качестве вложения FBO очень похоже на использование буфера рендеринга. Там, где вы в настоящее время используете glRenderbufferStorage() для выделения буфера рендеринга необходимых размеров, вместо этого вы создаете текстуру и выделяете ее хранилище с помощью:

GLuint texId = 0;
glGenTextures(1, &texId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
    GL_RGBA, GL_UNSIGNED_SHORTglTexSubImage2D()6_5, 0);

Затем вы прикрепляете его к фреймбуферу с помощью:

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

Теперь, если вы позже захотите заполнить рендер-цель данными, вы можете просто снова вызвать glTexImage2D() или, что еще лучше, glTexSubImage2D(), если размер не изменился, чтобы сделать это.

person Reto Koradi    schedule 11.09.2016
comment
Спасибо - сейчас пытаюсь реализовать. В настоящее время перед рисованием в буфер кадра я связываю его с: glBindFramebuffer(GL_FRAMEBUFFER, fboTextureBufferData.framebuffer); Поскольку буфер кадра не создается, указатель для fboTextureBufferData.framebuffer не существует. Итак, как мне привязать текстуру для рендеринга? Обратите внимание, что у меня есть второй буфер кадра, поэтому требуется привязка во время выполнения. - person Jeshua Lacock; 12.09.2016
comment
Просто используйте glFramebufferTexture2d вместо glFramebufferRenderbuffer. - person solidpixel; 12.09.2016
comment
У меня ничего не получается этим нарисовать. Не могли бы вы взглянуть на мое редактирование выше и посмотреть, как я инициализирую и рисую? - person Jeshua Lacock; 13.09.2016
comment
Как восстановить текстуру пока не понятно. Предоставлять ли заполненную переменную данных (из приведенного выше примера кода) для аргумента glTexSubImage2D пикселей? Также обратите внимание, согласно документам Apple вызовы glTexImage2D и glFramebufferTexture2D необходимы в дополнение для создания GL_FRAMEBUFFER, так что часть моего кода может быть правильной. - person Jeshua Lacock; 13.09.2016
comment
@Reto Koradi, не могли бы вы увидеть правку 3 выше? Я могу заставить его рисовать восстановленные пиксели или свежие визуализированные пиксели, но не то и другое вместе. Я действительно в тупике! - person Jeshua Lacock; 15.09.2016