iOS OpenGL ES 2.0上的sRGB

时间:2013-12-25 06:12:07

标签: ios opengl-es opengl-es-2.0

根据非常few related topics that I could find我正在收集的是,获取正确照明计算的取幂步骤可能必须在iOS应用程序的最终片段着色器中完成。

我一直在使用最新最好的Xcode 5 OpenGL调试器进行分析,并且片段的取幂占了大量的计算量。在整个着色器中花费时间最长的线(其余的性能被点光源所需的各种norm调用所吸引)。

遗憾的是,{p> glEnable(GL_FRAMEBUFFER_SRGB);无效,因为GL_FRAMEBUFFER_SRGB未声明。

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

根据Apple

  

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

     

EXT_color_buffer_half_float
  EXT_occlusion_query_boolean
  EXT_pvrtc_sRGB
  EXT_shadow_samplers
  EXT_sRGB
  EXT_texture_rg
  OES_texture_half_float_linear

嗯,这很好,没有543或554的最新设备是iPhone 4。

the extension's text file看起来我可以将SRGB8_ALPHA8_EXT设置为internalformat的{​​{1}}参数,但没有说明如何让正常的最终帧缓冲区应用sRGB对我们来说是免费的。

现在,sRGB修正似乎是获得正确颜色的缺失步骤。我在我的应用程序中处理可怕的“曝光不足”颜色的方法是在片段着色器中手动应用像这样的伽马校正:

RenderbufferStorage

现在我认识到典型的渲染管道涉及一个或多个渲染纹理,然后是FS四边形绘制,这将使我有机会使用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()` 渲染缓冲区,但我应该怎么做没有一个吗?我是SOL吗?

如果是这种情况,那么SRGB8_ALPHA_EXT调用就会耗费太多时间,以至于我几乎可以通过构建一维纹理进行采样并将其用作伽玛查找表来挤出更多的信息。 。然后可以使用此纹理以自定义方式调整输出颜色强度(与仅原始取幂相比,获得更好的sRGB近似值)。但这一切似乎都是错误的,因为据说sRGB是免费的。

另外有些令人担忧的是在GL ES 2.0规范中没有提到字符串powAccording to the makers of glm GL ES完全忽略了sRGB。

我知道我已经使用我的代码来渲染纹理(我制作了一个基本的OpenGL驱动的图像查看器,渲染PVRTC纹理)并且它们没有“变暗”。我认为那里发生的事情是由于GL ES 2缺乏sRGB意识,纹理被加载到线性空间中并以相同的方式写回。在那种情况下,由于没有应用光照(所有颜色都乘以srgb),结果没有发生任何不良。

3 个答案:

答案 0 :(得分:8)

iOS 7.0添加了新的颜色格式kEAGLColorFormatSRGBA8,您可以为kEAGLColorFormatRGBA8词典中的kEAGLDrawablePropertyColorFormat键设置而不是drawableProperties(默认值) CAEAGLLayer。如果您正在使用GLKit来管理主帧缓冲区,则可以通过将GLKView属性设置为drawableColorFormatGLKViewDrawableColorFormatSRGBA8888创建sRGB渲染缓冲区。

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

答案 1 :(得分:7)

我认为你在EXT_sRGB和ARB_framebuffer_sRGB扩展之间感到困惑。 EXT_sRGB是最近的扩展,是iOS设备支持的扩展。这与ARB_framebuffer_sRGB的一个重要方面不同,没有必要在帧缓冲区上调用glEnable(GL_FRAMEBUFFER_SRGB)来启用伽马校正,它始终处于启用状态。您需要做的就是使用sRGB内部格式创建帧缓冲区并渲染线性纹理。

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

答案 2 :(得分:2)

以下是我的测试结果。我唯一的iOS7设备是A7驱动的iPad5,为了测试填充率,我必须稍微调整我的测试应用程序以启用混合。在iOS 6.1上,这足以防止对不透明几何体进行片段丢弃优化,但对于iOS 7,我还需要在着色器中编写gl_FragColor.w!= 1.0。不是问题。

在性能方面,使用GLKViewDrawableColorFormatSRGBA8888确实似乎是免费的或接近免费的。我没有适当的timedemo风格基准设置,所以我只是测试“相似”的场景,移除pow在帧时间约2ms处被削减(例如需要43ms到41ms,22 fps到24 fps )。然后,设置sRGB帧缓冲区颜色格式没有引入调试器报告的帧时间的显着增加,但这不是非常科学的,它肯定可以将它减慢大约半毫秒左右。我无法确定它是否完全免费(即完全利用硬件路径来执行最终的sRGB转换),而无需先构建更多的软件,但我已经解决了问题,因此需要等待更严格的测试。