【问题标题】:sRGB on iOS OpenGL ES 2.0iOS OpenGL ES 2.0 上的 sRGB
【发布时间】:2013-12-25 06:12:06
【问题描述】:

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

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

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 设置为RenderbufferStorageinternalformat 参数,但没有说明如何让正常的最终帧缓冲区免费为我们应用sRGB。

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

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 渲染缓冲区,但如果没有我该怎么办一?我是索尔吗?

如果是这样的话,pow 调用会占用太多时间,以至于我几乎可以通过构建一维纹理来采样并用作伽玛查找表来从中挤出更多性能。然后可以使用此纹理以自定义方式调整输出颜色强度(与仅原始取幂相比,获得更好的 sRGB 近似值)。但这似乎有点不对劲,因为据说 sRGB 是免费的。

同样令人担忧的是,在 GL ES 2.0 规范中的任何地方都没有提到字符串 srgbAccording to the makers of glmGL ES 完全忽略了 sRGB。

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

【问题讨论】:

  • 这并不完全正确。 GLES 确实支持 sRGB 默认帧缓冲区,但您需要另一个扩展(EGL 扩展)才能获得它。 EGL_KHR_gl_colorspace。这是一个非常新的扩展,所以我并不奇怪 G-Truc 不知道或没有写任何关于它的东西。
  • 好的,这很有趣。正如你所说,它很新。令我惊讶的是,目前关于 iOS 上的伽马校正/sRGB 的文献很少。这让我猜测EGL_KHR_gl_colorspace 不是当前支持的 GL ES 2.0 扩展。 (GL 3.0 确实带来了 sRGB 支持,所以如果我的应用请求并获得 3.0 上下文,我应该为此做好准备。)

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


【解决方案1】:

iOS 7.0 添加了新的颜色格式kEAGLColorFormatSRGBA8,您可以为CAEAGLLayerdrawableProperties 字典中的kEAGLDrawablePropertyColorFormat 键设置kEAGLColorFormatRGBA8(默认值)。如果您使用 GLKit 为您管理主帧缓冲区,您可以通过将 drawableColorFormat 属性设置为 GLKViewDrawableColorFormatSRGBA8888 来让 GLKView 创建一个 sRGB 渲染缓冲区。

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

【讨论】:

  • 您知道这是否仅适用于实际运行 iOS 7 的设备,并且我仍需要为所有 iOS 6 设备执行片段着色器解决方案吗?或者,如果我使用 iOS7 SDK(我用来构建与 iOS 5.1 兼容的应用程序)并且也可以在 iOS 5/6 设备上工作(免费的 sRGB 帧缓冲区),这是提供给我的选项吗? (当我开始实际测试这些东西时,我会更新我的发现。)在我看来,最合理的路线是使用实际的 EXT_sRGB 扩展的功能,只要设备支持扩展,就应该保证这一点.
  • 该扩展仅在 iOS7 设备上实现,如果您要部署的内容少于此,则必须在着色器中执行 gamma 校正。
【解决方案2】:

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

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

【讨论】:

  • 好吧,我正在创建一个 3D 模型渲染应用程序,它实际上在任何时候都没有使用纹理。我是否仍然可以将 main 帧缓冲区指定为 sRGB,以便在屏幕上显示之前将我的(线性)片段输出并更正为 sRGB?我可以说,由于缺乏伽马校正,我在“黑暗”区域丢失了大量细节。
  • 是的。渲染到帧缓冲区的所有片段都假定在线性色彩空间中,并将进行伽马校正。如果启用了混合,则帧缓冲区的内容将在与片段混合之前转换回线性空间,然后再次转换回 sRGB。
  • 似乎不是这样,除非我在片段着色器中手动应用 1.8 伽马曲线,否则我的照明看起来不正确。我的意思是,我显然需要“打开某些东西”以启用主帧缓冲区的 sRGB 写入(由 EXT_sRGB 提供,它并没有真正提到它......),因为如果我不启用某些东西,我会和 应该获得假装 sRGB 不存在的标准 OpenGL ES 2.0 行为。
  • 那么你将不得不展示你的设置代码,我在一个使用 GLKit 的项目中可以很好地工作,并且不需要“打开”。
  • 如果您的应用程序是从 OpenGL 应用程序模板派生的,那么 -[ViewController viewDidLoad:] 中应该有一些代码将您的 GLKView 的 drawableDepthFormat 设置为 GLKViewDrawableDepthFormat24。尝试添加一行将 drawableColorFormat 更改为 GLKViewDrawableColorFormatSRGBA8888。
【解决方案3】:

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

就性能而言,使用GLKViewDrawableColorFormatSRGBA8888 确实似乎是免费的或接近免费的。我没有合适的时间演示风格基准设置,所以我只是在测试“类似”的场景,并删除了 pow 大约 2 毫秒的帧时间(例如,需要 43 毫秒到 41 毫秒,22 fps 到 24 fps)。然后,设置 sRGB 帧缓冲区颜色格式并没有像调试器报告的那样显着增加帧时间,但这不是很科学,它肯定会减慢半毫秒左右的速度。如果不先构建更多的基准测试软件,我实际上无法判断它是否完全免费(即完全利用硬件路径来执行最终的 sRGB 转换),但我已经解决了问题,因此需要等待更严格的测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多