Files
XCEngine/docs/api/XCEngine/RHI/OpenGL/OpenGLScreenshot/Capture.md

2.5 KiB

OpenGLScreenshot::Capture

bool Capture(RHIDevice* device, RHISwapChain* swapChain, const char* filename) override;
static bool Capture(OpenGLDevice& device,
                    OpenGLSwapChain& swapChain,
                    const char* filename);
static bool Capture(OpenGLDevice& device,
                    OpenGLSwapChain& swapChain,
                    const char* filename,
                    int width,
                    int height);

作用

从 OpenGL 当前呈现目标读取像素并写成 PPM 文件。

核心流程

三个公开重载最终都汇合到同一套同步读回流程:

  1. 切换当前上下文 device.MakeContextCurrent()
  2. 分配 RGB 像素缓冲
  3. 调用 glFinish()
  4. 配置 GL_PACK_* 像素打包状态
  5. 根据当前 back buffer 情况选择读取路径
  6. 调用 glReadPixels(...)
  7. P6 PPM 格式写盘,并在写盘时做上下翻转

重载 1: RHI 入口

bool Capture(RHIDevice* device, RHISwapChain* swapChain, const char* filename) override;

当前实现行为

  • 直接把 device 转成 OpenGLDevice*
  • 直接把 swapChain 转成 OpenGLSwapChain*
  • 然后转发到 OpenGL 包装对象重载

注意事项

  • 没有运行时类型检查
  • 没有空指针保护

重载 2: 使用 swap chain 尺寸

static bool Capture(OpenGLDevice& device,
                    OpenGLSwapChain& swapChain,
                    const char* filename);

当前实现行为

  • 直接使用 swapChain.GetWidth()swapChain.GetHeight()
  • 然后调用完整尺寸重载

重载 3: 显式尺寸

static bool Capture(OpenGLDevice& device,
                    OpenGLSwapChain& swapChain,
                    const char* filename,
                    int width,
                    int height);

当前实现行为

  • 分配 width * height * 3 字节的 RGB 缓冲
  • 如果内存分配失败,记录错误日志并返回 false
  • 判断当前 back buffer 是否可以走纹理读取路径:
    • backBufferTexture != nullptr
    • backBufferTexture->GetID() != 0
    • backBufferTexture->GetState() != ResourceStates::Common
  • 纹理路径下会创建临时 GL_READ_FRAMEBUFFER,把纹理挂到 GL_COLOR_ATTACHMENT0 后读取
  • 否则直接 glReadBuffer(GL_BACK) 读取默认后备缓冲
  • 打开输出文件失败时返回 false
  • 写文件时从最后一行开始写,实现图像垂直翻转

输出格式

  • 固定输出 P6 PPM
  • 只写 RGB
  • 不写 alpha
  • 不压缩

相关文档