为何OpenGL ES中多数3通道存储类型不可着色渲染?
我难以理解为何部分int和unsigned int内部存储类型具备“可着色渲染”属性,而其他类型却没有。以下是示例:
四通道
| internal storage type | color renderable |
|---|---|
| GL_RGBA8 | Y |
| GL_RGBA8I | Y |
| GL_RGB32UI | Y |
三通道
| internal storage type | color renderable |
|---|---|
| GL_RGB8 | Y |
| GL_RGB8I | |
| GL_RGB32UI | |
| GL_RGB565 | Y |
单通道与双通道
| internal storage type | color renderable |
|---|---|
| GL_RG8 | Y |
| GL_RG8UI | Y |
| GL_R8 | Y |
| GL_R8UI | Y |
我大致理解sRGB和浮点型内部存储类型不可着色渲染的原因,但为何非归一化的3通道int和unsigned int存储类型不可着色渲染?而单通道、双通道的同类型却可以?我查阅了OpenGL ES 3规范的相关部分,仅看到表格中标记为不可着色渲染,似乎遗漏了基础原理。
解答
这个限制本质上源于GPU硬件渲染管线的设计历史与实现约束,核心原因可归纳为两点:
硬件通道对齐与兼容性限制
早期GPU的颜色输出管线围绕RGBA四通道设计,即使是RGB三通道的归一化格式,硬件底层也会按四通道结构处理(比如自动填充固定Alpha值)。但对于非归一化整数类型(I/UI后缀),其存储的是原始整数数值,没有归一化到[0,1]范围,硬件无法像处理归一化RGB那样自动补全Alpha通道且保证数据语义完整。专门为三通道整数设计单独渲染路径的性价比极低,因此OpenGL ES规范直接禁用了这类格式的着色渲染性。渲染管线的输出格式约定
OpenGL ES的片元着色器输出需要与帧缓冲内部格式严格匹配。单/双/四通道整数格式有明确的对应输出路径:单通道对应着色器输出的单个分量,双通道对应前两个分量,四通道对应全部四个分量。但三通道整数格式没有原生的着色器输出变量匹配,强行适配会增加管线复杂度,且实际应用场景极少,因此规范选择不支持这类格式的着色渲染。
另外需要注意,GL_RGB8和GL_RGB565这类归一化RGB格式能被支持,是因为它们属于传统颜色格式,硬件可通过将RGB数据打包到四通道存储结构(忽略或固定Alpha值)兼容渲染管线,而归一化的数值特性也允许这种无损转换。
内容的提问来源于stack exchange,提问作者Andrew

