4.8 KiB
OpenGLRenderTargetView
命名空间: XCEngine::RHI
类型: class
头文件: XCEngine/RHI/OpenGL/OpenGLRenderTargetView.h
描述: OpenGL 后端的轻量级颜色渲染目标视图封装,为单个纹理子资源创建并管理一个专用 framebuffer。
概览
在商业级图形引擎里,render target view 的核心价值通常不是“拥有一张纹理”,而是“定义这张纹理在本次渲染里以什么子资源视角、什么附件槽位被使用”。这样资源分配、生命周期管理、渲染图编排和具体渲染阶段可以解耦。
OpenGL 没有独立的 RTV 对象,所以 OpenGLRenderTargetView 走的是常见的适配做法: 为每个颜色视图生成一个单独 FBO,再把纹理的某个 mip、数组层或 cubemap face 附着到 GL_COLOR_ATTACHMENT0。这让上层仍然可以保留“创建 view -> 绑定 view -> 清除 / 绘制”的使用方式。
设计定位
这个类更像旧路径兼容层或工具层封装,而不是完整、长期的 framebuffer 抽象。
- 它的优点是调用直接、很适合单测和小型渲染样例。
- 它的优点是把 2D、数组、3D、cubemap、cubemap array 这些常见纹理形态都统一进了一个入口。
- 它的缺点是能力边界明显: 当前只附着到
GL_COLOR_ATTACHMENT0,没有真正表达多颜色附件组合,也没有和更完整的 framebuffer 描述体系完全融合。
如果目标是更接近商业引擎的现代组织方式,OpenGLFramebuffer 与 OpenGLResourceView 那条路径更适合承载复杂 render pass、MRT、缓存复用和严格状态校验。OpenGLRenderTargetView 适合保持旧接口稳定,或者作为“快速把一张纹理当作单附件颜色目标使用”的轻量层。
相关声明
RenderTargetType
当前支持五种视图类型:
Texture2DTexture2DArrayTexture3DTextureCubeTextureCubeArray
它们决定初始化时使用 glFramebufferTexture2D() 还是 glFramebufferTextureLayer()。
OpenGLRenderTargetViewDesc
描述结构包含:
type: 视图类型。mipLevel: 目标 mip。baseArraySlice: 数组层索引,或 cubemap / cubemap array 的 face / slice 偏移。arraySize: 当前实现未使用。layer: 仅Texture3D路径会真正使用。format: 当前实现未使用。
可以看出,接口已经朝“更通用的 subresource view 描述”靠拢,但落地实现仍然只消费了其中的一部分字段。
生命周期
- OpenGLRenderTargetView() 构造空对象。
- Initialize 或 InitializeCubemap 生成 FBO 并附着颜色纹理子资源。
- Bind / Unbind 切换 framebuffer。
- Clear 在当前 view 对应的 FBO 上执行清除。
- Shutdown 删除内部 FBO。
当前实现的真实行为
- 所有初始化路径都只把纹理附着到
GL_COLOR_ATTACHMENT0。 Initialize()里虽然计算了unsigned int target = ToOpenGL(desc.type);,但这个局部变量最终没有被使用。- 初始化失败时函数返回
false,但不会立即删除刚生成的 FBO,也不会回滚成员状态。 - Bind 的
slot参数当前被完全忽略。 - 多 FBO 重载
Bind(count, framebuffers, drawBuffers)并不是真正的 MRT 抽象。它只是逐个绑定传入 framebuffer,并分别调用一次glDrawBuffers(1, ...),最终留下最后一个 FBO 处于绑定状态。 - GetWidth / GetHeight 始终返回
0,因为实现没有维护尺寸。 m_framebuffers在 Shutdown 中会被尝试统一删除,但当前实现里没有任何地方向这个数组写入内容。- 单测
tests/RHI/OpenGL/unit/test_render_target_view.cpp只验证了初始化、绑定/解绑和基础 getter,不能把它看成复杂 attachment 行为的严格证明。
使用建议
- 当你需要快速把单张纹理的某个子资源作为颜色渲染目标使用时,这个类非常直接。
- 当前不要把
slot、arraySize、format、GetWidth、GetHeight 当作可靠能力。 - 如果需求已经涉及 MRT、统一 render pass 描述、framebuffer 复用或更严格的后端一致性,应优先转向更完整的 framebuffer / resource view 路径。
Initialize()失败后,建议立即调用 Shutdown 清理半初始化状态。