2014-12-28 32 views
0

我遇到了this article中描述的问题,其中第二个色阶是有效地进行了伽马校正的两次,导致颜色过亮和颜色不清。这部分是我使用sRGB帧缓冲的结果,但这不是问题的真正原因。在iOS上的OpenGL中对纹理进行sRGB校正

我在我的iOS8测试应用程序中测试纹理,尤其是我正在使用PNG图像文件并使用GLKTextureLoader将它作为立方体贴图加载。

默认情况下,纹理被视为不在sRGB空间中(它们总是由用于构建纹理的图像编辑软件保存)。

这样做的后果是,苹果已经取得了GLKTextureLoader做glTexImage2D找你,他们总是与GL_RGB8设置调用它,而对于未来的颜色操作实际的正确性,我们必须uncorrect伽玛为了获得我们的纹理中的线性亮度值可供我们的着色器进行采样。

现在我可以看到,大多数移动应用程序并不需要大量的颜色操作和颜色正确性,这些应用程序适用于涉及颜色混合的高级3D技术。部分问题是,使用珍贵的共享设备RAM以每通道8位以上的任何位深度存储纹理是不现实的,如果我们读取JPG/PNG/TGA/TIFF和gamma-uncorrect其8位sRGB成8位线性,我们将降低质量。

因此,大多数应用程序的过程只是愉快地将线性颜色正确性抛出窗外,而忽略伽玛校正,并在SRGB空间中进行混合。这非常适合愤怒的小鸟,因为它是一款没有阴影或混合的游戏,因此在伽马校正的色彩空间中进行所有操作是非常明智的。

所以这给我带来了我现在的问题。我需要使用EXT_sRGB,并且GLKit可以让我轻松设置sRGB帧缓冲区,这对运行iOS 7或更高版本的最新3代或更多代设备非常有用。在这样做的过程中,我解决了未修正的渲染管线的阴影和不自然的阴影外观。这可以让我的朗伯和blinn-phong的东西看起来很好。它允许我将sRGB存储在渲染缓冲区中,这样我就可以进行后期处理,同时利用通过将缓冲区存储在此颜色空间中而提供的改进的感知颜色分辨率。

但是现在我开始使用纹理的问题是它看起来像我甚至不能像使用GLKTextureLoader那样使用它,因为当我为SRGB设置选项标志时,我只是得到了一个神秘的错误(代码18) (GLKTextureLoaderSRGB)。由于没有源代码可以进行调试,因此无法进行调试。

所以我想我可以用glTexImage2D备份纹理加载管道,并使用GL_SRGB8来指定我在纹理着色器中对它们进行采样之前使用伽玛校正纹理。然而,快速浏览GL ES 2.0文档显示,GL ES 2.0甚至不支持sRGB。

最后我找到EXT_sRGB规范,它说

Add Section 3.7.14, sRGB Texture Color Conversion 

If the currently bound texture's internal format is one of SRGB_EXT or 
SRGB_ALPHA_EXT the red, green, and blue components are converted from an 
sRGB color space to a linear color space as part of filtering described in 
sections 3.7.7 and 3.7.8. Any alpha component is left unchanged. Ideally, 
implementations should perform this color conversion on each sample prior 
to filtering but implementations are allowed to perform this conversion 
after filtering (though this post-filtering approach is inferior to 
converting from sRGB prior to filtering). 

The conversion from an sRGB encoded component, cs, to a linear component, 
cl, is as follows. 

     { cs/12.92,     cs <= 0.04045 
    cl = { 
     { ((cs + 0.055)/1.055)^2.4, cs > 0.04045 

Assume cs is the sRGB component in the range [0,1]." 

自从实施了对桌面硬件的游戏引擎(这是我所期待的颜色必须考虑分辨率基本上是没有实际意义的时候,当我从来没有挖这个深使用每个通道或更高的16位深度的渲染缓冲区)我对这种工作原理的理解还不清楚,但是这段文字确实让我放心,我可以吃掉蛋糕并且在保留所有8位颜色信息如果我要使用SRGB_EXT图像存储格式加载纹理。

这里在OpenGL ES 2.0与此扩展我可以使用SRGB_EXTSRGB_ALPHA_EXT而不是类似SRGBSRGB8_ALPHA从香草GL。

我不愿意提出一个简单的可回答的问题。让它成为这一个:我在这里咆哮错误的树,还是我的假设或多或少是正确的?感觉像我一直在盯着这些规格现在太久了。解决我的问题的另一种方法是,如果您可以了解我在尝试设置sRGB选项时遇到的GLKTextureLoader错误18。

看来我还有更多的阅读需要做,因为我必须决定是否开始分支我的代码以获得一个使用GL ES 2.0与EXT_sRGB的代码路径,另一个使用GL ES 3.0,当然通过比较glTexImage2D与其他GL版本的文档看起来非常有希望,并且看起来比其他GL版本更接近OpenGL 4,所以我非常喜欢ES 3将使移动设备更接近桌面上使用的API。

回答

0

我在这里叫错了树还是我的假设或多或少 是否正确?

您的假设是正确的。如果支持GL_EXT_sRGB OpenGL ES扩展,则sRGB帧缓冲区(自动从线性转换为伽玛校正的sRGB)和sRGB纹理格式(从sRGB采样时自动转换为线性RGB)都可用,所以这是明确的要走的路,如果你想在线性色彩空间工作。

我不能帮助GLKit的问题,不知道。

+0

谢谢!你碰巧知道[texture_sRGB_decode](https://www.opengl.org/registry/specs/EXT/texture_sRGB_decode.txt)扩展提供了什么?似乎它不支持iOS设备,但仍然...它似乎*是各种额外的好东西,如mipmapped sRGB纹理等 –

+0

texture_sRGB_decode的描述似乎只是说它提供了一些灵活性,可以决定是否使用或不使用伽马校正解码来读取数据。这听起来不是很复杂,也不像是任何一个大的举动。 –

+0

@StevenLu:是的。该唯一的优点是,您不必在创建纹理时决定需要什么样的解码,但可以稍后选择您想要的解码。在某些情况下可能有用,但我从未意识到这个功能甚至存在 - 我也没有错过它... – derhass