iOS OpenGL ES 2.0上的sRGB

iOS OpenGL ES 2.0上的sRGB,ios,opengl-es,opengl-es-2.0,Ios,Opengl Es,Opengl Es 2.0,据我所知,获取适当照明计算的求幂步骤可能必须在iOS应用程序的最终片段着色器中完成 我一直在使用最新和最伟大的Xcode 5 OpenGL调试器进行评测,片段的指数运算占用了大量的计算量。这是在整个着色器中花费时间最长的一行(其余性能被点光源所需的各种norm调用所消耗) glEnable(GL\u帧缓冲区\u SRGB)不起作用,因为未声明GL\u FRAMEBUFFER\u SRGB 当然,我应该用于GL ES的实际枚举可能不同 根据: SGX 543和554支持以下扩展 仅限处理器: 外部

据我所知,获取适当照明计算的求幂步骤可能必须在iOS应用程序的最终片段着色器中完成

我一直在使用最新和最伟大的Xcode 5 OpenGL调试器进行评测,片段的指数运算占用了大量的计算量。这是在整个着色器中花费时间最长的一行(其余性能被点光源所需的各种
norm
调用所消耗)

glEnable(GL\u帧缓冲区\u SRGB)不起作用,因为未声明
GL\u FRAMEBUFFER\u SRGB

当然,我应该用于GL ES的实际枚举可能不同

根据:

SGX 543和554支持以下扩展 仅限处理器:

外部颜色缓冲区半浮点数
外部遮挡查询布尔值
外部pvrtc\U sRGB
外部阴影采样器
外部sRGB
外部纹理\u rg
纹理、半浮体、线性

很好,最新的没有543或554的设备是iPhone4

从它看来,我可以将
SRGB8_ALPHA8_EXT
设置为
RenderbufferStorage
internalformat
参数,但没有提到如何让正常的最终帧缓冲区为我们免费应用sRGB

现在,sRGB校正似乎是获得正确颜色的缺失步骤。我在应用程序中处理可怕的“曝光不足”颜色所做的是在片段着色器中手动应用gamma校正,如下所示:

mediump float gammaf = 1.0/1.8; // this line declared outside of `main()`
// it specifies a constant 1.8 gamma
mediump vec4 gamma = vec4(gammaf, gammaf, gammaf, 1.0);
gl_FragColor = pow(color, gamma); // last line of `main()`
现在我认识到,典型的渲染管道包括一个或多个对纹理的渲染,然后是FS四元图,这将使我有机会使用
SRGB8_ALPHA_EXT
renderbuffer,但是没有它我该怎么办?我是索尔吗

如果是这样的话,
pow
调用占用了太多的时间,似乎我可以通过构建一个1D纹理进行采样并用作gamma查找表来从中挤出更多的性能。然后,可以使用该纹理以自定义方式调整输出颜色强度(并获得比原始指数化更好的sRGB近似值)。但这一切似乎都有点错误,因为据说sRGB是免费的

还有一点令人担忧的是,在GL ES 2.0规范的任何地方都没有提到字符串
srgb
。GL ES只是完全忽略了srgb


我知道我用我的代码来渲染纹理(我制作了一个基本的OpenGL支持的图像查看器来渲染PVRTC纹理),但它们并没有变暗。我认为那里发生的事情是,由于GL ES 2缺乏sRGB意识,纹理以线性空间的形式加载,并以相同的方式写回。在这种情况下,由于没有应用任何照明(所有颜色都乘以
1.0
),因此结果没有出现任何不好的情况。

我认为您会混淆EXT\u sRGB和ARB\u framebuffer\u sRGB扩展。EXT_sRGB是最新的扩展,是iOS设备支持的扩展。这与ARB_framebuffer_sRGB的一个重要区别在于,不必在帧缓冲区上调用glEnable(GL_framebuffer_sRGB)来启用gamma校正,它始终处于启用状态。您只需使用sRGB内部格式创建帧缓冲区,并向其渲染线性纹理


这本身并没有多大用处,因为纹理很少出现在线性颜色空间中。幸运的是,该扩展还包括将sRGB纹理转换为线性空间的功能。通过上传内部格式为sRGB8_ALPHA8_EXT的纹理,在着色器中免费采样时,它们将转换为线性空间。这允许您使用具有更好perception编码颜色范围的sRGB纹理,在更高精度的线性空间中混合,然后在渲染缓冲区中将结果编码回sRGB,而无需任何着色器成本和精确的gamma校正。

iOS 7.0添加了新的颜色格式
kEAGLColorFormatSRGBA8
,您可以为
CaeAglayer
drawableProperties
字典中的
kEAGLDrawablePropertyColorFormat
键设置它,而不是
kEAGLColorFormatRGBA8
(默认值)。如果使用GLKit为您管理主帧缓冲区,则可以通过将其
drawableColorFormat
属性设置为
GlkViewDrawableColorFormatsRgb8888
来获取
GLKView
以创建sRGB renderbuffer


请注意,OpenGL ES版本的
EXT\u sRGB
的行为就像始终启用
GL\u FRAMEBUFFER\u sRGB
一样。如果要在不与目标帧缓冲区进行sRGB转换的情况下进行渲染,则需要使用具有非sRGB内部格式的其他附件。

以下是我的测试结果。我唯一的iOS7设备是A7供电的iPad5,为了测试填充率,我不得不稍微调整我的测试应用程序以启用混合。这在iOS 6.1上足以防止对不透明几何体进行碎片丢弃优化,但对于iOS 7,我还需要编写
gl\u FragColor.w
!=<着色器中的代码>1.0
。没问题

使用
GLKViewDrawableColorFormatSRGBA8888
确实在性能方面看起来是免费的或接近免费的。我没有一个合适的timedemo风格的基准设置,所以我只是测试“类似”的场景,删除
pow
将帧时间缩短了约2ms(例如,需要43ms到41ms,22fps到24fps)。然后,设置sRGB帧缓冲区颜色格式并没有像调试器所报告的那样显著增加帧时间,但这不是很科学,它肯定会将其速度降低半毫秒左右。如果不首先构建mor,我实际上无法判断它是否完全免费(即完全利用硬件路径来执行最终的sRGB转换)