Direct3D9 中的Gamma矫正

纹理内容常常是存在sRGB格式中的。关于这个格式的细节是可以被找到的。通常,像素管线假定颜色是线性的以便融合(blending)操作可以在线性空间中进行。因为sRGB中的内容是Gamma较正,所以融合操作在线性空间中处理会导致错误的结果。显卡在读到有关sRGB内容的时候便会取消Gamma较正以避免错误的发生。然后当输出像素的时候再将像素信息写回sRGB格式中。在这种情况下,所有像素管线中的操作就可以都在心线性空间中进行。

Gamma校正
在D3D9中。
     可以指明一张纹理是不是Gamma 2.2(sRGB) 较正.驱动程序将会在SetTexture的时候将其转换到线性的Gamma以进行融合操作。或者采样器将会在查询的时候将其变为线性数据。
     可以指明像素管线在输出到渲染目标的时候是否将Gamma校正变换回sRGB空间。

所有其它颜色(clear color, material color, vertex color, etc)都被假定为线性空间中。应用程序可以用像素着色器指令对写入到帧缓存中的颜色进行Gamma校正。线性化操作只对RGB通道有效,忽略ALPHA通道。

不是所有的表面格式都可以线性化。只有通过 IDirect3D9::CheckDeviceFormat检测(参数为D3DUSAGE_QUERY_SRGBREAD )的格式才可以被线性化。除此之外,采样状态D3DSAMP_SRGBTEXTURE 也会被忽略。只有无符号纹理格式支持这种变换。无符号纹理格式是指仅包含有R G B 和 L成分的纹理格式。如果包含ALPHA通道,那它将被忽略。如果混合的格式支持sRGB线性化,那么只有无符号通道有效。理想情况是硬件在纹理过滤前实现线性化。但在D3D9中,硬件只有在纹理过滤后才允许线性化。

不是所有的表面都可以被写进sRGB空间,只有通过用D3DUSAGE_QUERY_SRGBWRITE进行IDirect3D9::CheckDeviceFormat 测试的表面格式才能进行线性化。另外,渲染状态中的D3DRS_SRGBWRITEENABLE标志将会被忽略。每个通道8位的无符号RGB格式是比较适合的格式。
理想地,硬件将会在线性空间上进行帧缓存融合操作。但实际上硬件只能在像素管线处理后,帧缓存融合前进行。这意味着在sRGB中进行帧缓存融合操作会导致错误的结果。当清除渲染目标时。D3DRS_SRGBWRITEENABLE 标志 is Honored.对于硬件支持多渲染目标或多元素纹理的情况,只有第一个渲染目标和第一个元素会被写入缓存。

API变化

API Changes

// New sampler state (DWORD) 新的采样器状态// If this is nonzero, the texture is linearized on lookup.
如果它非0,纹理在查询是线性化。D3DSAMP_SRGBTEXTURE       // Default FALSE   默认为假// New render state (DWORD)
新的渲染状态D3DRS_SRGBWRITEENABLE     // Default FALSE 默认为假// New usage flags
新的使用标志D3DUSAGE_QUERY_SRGBWRITED3DUSAGE_QUERY_SRGBREAD
 
窗口下的交换链
为了进行正确的融合操作,应用程序保存他们的交换链在线性空间中的后台缓冲区是非常必要的。因为桌面通常情况下是不在线性空间的。所以需要在后台缓冲区内容显示前进行Gamma校正。
应用程序可以通过新增额外的缓冲区来自我校正,并把他自已正确的结果从线性空间复制到后台缓冲区。当驱动将Gamma校正作为部分显示的时候,是可以避免使用额外的缓冲区的。
posted @ 2010-04-24 12:12  麒麟子MrKylin  阅读(419)  评论(0编辑  收藏  举报