部分重绘到 FBO OpenGL

Partial redraw to FBO OpenGL

我的场景被组织成由浮点纹理(16 位带 alpha)支持的 FBO 组成的元素组。然后将这些 FBO 从上到下混合在一起以生成最终场景。所有的 FBO 都是屏幕大小。当屏幕尺寸变大时(在 Intel HD Graphics 630 上 > 2048),帧率直线下降。这是由于填充率问题(我已经尝试使用无操作叶节点和较小的纹理格式来验证这一点)。有没有办法将一个 FBO 的一部分 blit 到另一个 FBO 的一部分?在绘制带纹理的四边形之前可能是这样的:

void FrameBufferManager::SetViewportFromClipBox(const Geometry::BoundingBox& clipBox)
{
    const auto& lowerLeft = clipBox.GetLowerLeft();
    const auto lx = static_cast<GLsizei>(lowerLeft.x);
    const auto ly = static_cast<GLsizei>(lowerLeft.y);
    const auto width = static_cast<GLsizei>(clipBox.GetWidth());
    const auto height = static_cast<GLsizei>(clipBox.GetHeight());
    glViewport(lx, ly, width, height);
    glScissor(lx, ly, width, height);
}

在顶点着色器中,几何体被转换,使得 clipBox 之外的点将落在 ((-1, -1) (1, 1)) 之外。以上是否会确保 clipBox 之外的像素不会浪费 GPU 内存带宽/填充率?如果没有,有没有什么方法可以做到这一点,而无需创建一堆小型 FBO 并根据对象位置在这些 FBO 之间拆分对象渲染?

Is there a way to blit part of an FBO to part of another FBO?

从 OpenGL ES 3.0 开始,您可以使用 glBlitFramebuffer:

glBlitFramebuffer — copy a block of pixels from the read framebuffer to the draw framebuffer

void glBlitFramebuffer(
    GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
    GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
    GLbitfield mask, GLenum filter);

此功能也由扩展程序 NV_framebuffer_blit 提供,它是针对 OpenGL ES 2.0 编写的。