# OpenGLTexture **命名空间**: `XCEngine::RHI` **类型**: `class` **头文件**: `XCEngine/RHI/OpenGL/OpenGLTexture.h` **描述**: OpenGL 后端的纹理资源封装,负责创建原生 texture 对象、缓存资源维度元数据,并提供最基础的绑定与采样参数配置入口。 ## 概览 `OpenGLTexture` 承担的是“纹理资源本体”职责,而不是完整的 view 系统。它主要负责: - 创建 1D / 2D / 2DArray / 3D / Cube / CubeArray 纹理对象 - 上传基础像素数据 - 维护宽高深、mip 数量、OpenGL 纹理类型等缓存字段 - 提供绑定、image bind、mipmap 生成和采样参数设置接口 在商业引擎里,这一层通常只关心“资源如何存在于 GPU 上”;至于它在本次渲染里被当作 SRV、UAV、RTV 还是 DSV 使用,则会交给 resource view 或 framebuffer 层表达。当前 OpenGL 后端也遵循了类似分层思路。 ## 设计背景 OpenGL 的纹理对象天然把“资源本体”和“一部分采样状态”绑在一起,这和 D3D12/Vulkan 那种显式分离资源、view、sampler 的风格不同。`OpenGLTexture` 的设计采用了一个实用主义折中: - 资源分配、上传和基础采样参数由 `OpenGLTexture` 直接负责。 - 更细的资源视图语义交给 `OpenGLResourceView`、`OpenGLRenderTargetView`、`OpenGLDepthStencilView` 等类型处理。 这样做的好处是易于落地和调试;代价是某些字段看起来像完整抽象,但实际上只是缓存元数据,必须通过文档把边界讲清楚。 ## 相关枚举 ### `OpenGLTextureType` 当前支持: - `Texture1D` - `Texture2D` - `Texture2DArray` - `Texture3D` - `TextureCube` - `TextureCubeArray` 它决定了 [Initialize](Initialize.md) 内部选用 `glTexImage1D`、`glTexImage2D` 还是 `glTexImage3D`,以及默认 wrap 参数如何设置。 ### `OpenGLFormat` 头文件中声明了: - `R8` - `RG8` - `RG32F` - `RGBA8` - `RGBA16F` - `RGBA32F` - `Depth24Stencil8` - `Depth32F` - `CompressedDXT1` - `CompressedDXT5` 但当前 `ToOpenGLFormat()` 实际只处理到 `Depth32F`。`CompressedDXT1` 和 `CompressedDXT5` 在现有实现里不会走压缩纹理上传路径,而会落入默认分支,退化为 `GL_RGBA8` 的普通纹理格式映射。 ### `OpenGLInternalFormat` 头文件还声明了 `OpenGLInternalFormat` 数值枚举,但当前 `OpenGLTexture` 的实现并不直接消费它,而是通过 `OpenGLFormat + ToOpenGLFormat()` 获取真正的 OpenGL internal format / format / type 组合。 ## 生命周期 - [OpenGLTexture()](Constructor.md) 构造空对象。 - [Initialize](Initialize.md)、[Initialize2D](Initialize2D.md)、[InitializeCubeMap](InitializeCubeMap.md) 负责创建纹理资源。 - [LoadFromFile](LoadFromFile.md) 通过 stb_image 加载文件后转调 [Initialize2D](Initialize2D.md)。 - [Bind](Bind.md)、[BindImage](BindImage.md)、[GenerateMipmap](GenerateMipmap.md)、[SetFiltering](SetFiltering.md)、[SetWrapping](SetWrapping.md) 在使用阶段配置和绑定纹理。 - [Shutdown](Shutdown.md) 删除原生纹理对象。 ## 当前实现的真实行为 - 通用 [Initialize](Initialize.md) 只上传或分配 level 0,不会按 `mipLevels` 循环创建所有 mip 级别。 - [Initialize2D](Initialize2D.md) 在 `generateMipmap = true` 时会实际调用 `glGenerateMipmap()`,但把 `m_mipLevels` 记成 `0`,而不是真实 mip 数。 - [InitializeCubeMap](InitializeCubeMap.md) 会把同一个 `data` 指针上传到六个 cubemap face,且不会自动生成额外 mip 级别。 - [LoadFromFile](LoadFromFile.md) 当前总是以 `STBI_rgb_alpha` 方式读取,并关闭自动 mipmap 生成。 - [BindImage](BindImage.md) 固定绑定 `level 0`、`layered = GL_FALSE`、`layer = 0`、`format = GL_RGBA8`,不是通用 image view 封装。 - [Unbind](Unbind.md) 不接收 slot 参数,只会在“当前 active texture unit”上解绑当前 target。 - [GetFormat](GetFormat.md) 默认返回 `Format::Unknown`,除非外部显式调用 [SetFormat](SetFormat.md)。例如 `OpenGLDevice::CreateTexture()` 会在初始化后补一次 `SetFormat()`。 - 单测 `tests/RHI/OpenGL/unit/test_texture.cpp` 只覆盖基本初始化、绑定、mipmap 生成和采样参数调用,不验证复杂格式与 image 绑定语义。 ## 使用建议 - 如果纹理是通过 `OpenGLDevice::CreateTexture()` 创建的,`Format` 和初始 `ResourceStates` 元数据会更完整;如果直接调用 `OpenGLTexture::Initialize*()`,这些值需要你自行补齐。 - 不要把 [GetMipLevels](GetMipLevels.md) 在 `Initialize2D(generateMipmap = true)` 后的返回值当作真实 mip 层数。 - 若需要更一般化的 UAV / subresource image 语义,优先查看 `OpenGLResourceView`,不要直接依赖 [BindImage](BindImage.md)。 ## 关键方法 - [Initialize](Initialize.md) - [Initialize2D](Initialize2D.md) - [InitializeCubeMap](InitializeCubeMap.md) - [Bind](Bind.md) - [BindImage](BindImage.md) - [GenerateMipmap](GenerateMipmap.md) ## 相关文档 - [OpenGL](../OpenGL.md) - [OpenGLEnums](../OpenGLEnums/OpenGLEnums.md) - [OpenGLResourceView](../OpenGLResourceView/OpenGLResourceView.md) - [OpenGLRenderTargetView](../OpenGLRenderTargetView/OpenGLRenderTargetView.md) - [OpenGLDepthStencilView](../OpenGLDepthStencilView/OpenGLDepthStencilView.md)