2

UPDATE:

Thank you all very much for your answers. As Jesse Hall suggested, it looks like it is a driver (or hardware) problem. I tried the same app on other configurations and it worked as expected.

I tested the app on other computers which share the same GPU (ATI 4800 HD) but different versions of the driver and they all showed the same erroneous behavior (what seems to be a double gamma correction on write). On these computers, if have to set D3DRS_SRGBWRITEENABLE to false to fix the display. Anyone knows if this is a known bug on this hardware?

Even more strange is that I get the same end results with these two configurations:

  • D3DRS_SRGBWRITEENABLE = FALSE and D3DSAMP_SRGBTEXTURE to TRUE
  • D3DRS_SRGBWRITEENABLE = FALSE and D3DSAMP_SRGBTEXTURE to FALSE

In the pixel debugger, I see that linearization is applied properly in case 1 but (automatic) correction on write gives the same output as case 2 (which performs no conversion at all)...

// -- END OF UPDATE

I'm having some trouble fixing the gamma correction of a DirectX9 application.

When I enable texture linearization in the samplers (D3DSAMP_SRGBTEXTURE) and sRGB write for output (D3DRS_SRGBWRITEENABLE), it looks like gamma correction is applied twice.

Here is my setup. I used the following texture (from here) to draw a fullscreen quad: enter image description here

The results were visually too bright on the right side of the picture. I used PIX to debug one of those grey pixels and, if everything was set up properly, I would have expected an output value of 0.73 (=0.5^(1.0/2.2)). Unfortunately, the output of the pixel shader was 0.871 (which looks like it could be a gamma correction applied twice ?). I stepped inside the pixel shader with the debugger and the texture fetch returned a value of (0.491, 0.491, 0.491), which should mean linearization on read worked properly.

enter image description here

When I disable D3DRS_SRGBWRITEENABLE, the output of the pixel shader is 0.729 which looks much more correct to me.

enter image description here enter image description here

Any idea where does this conversion come from (in the debugger the pixel shader output was 0.491)? What other flags/render states should I check?

Thank you very much for your help!

4

2 回答 2

3

一种可能性是您两次应用线性到伽马变换。使用 D3DRS_SRGBWRITEENABLE 写入渲染目标时一次。然后在其他时候使用 D3DPRESENT_LINEAR_CONTENT 呈现帧缓冲区(如果您已指定该标志)。您不需要 D3DPRESENT_LINEAR_CONTENT,因为您已经使用 D3DRS_SRGBWRITEENABLE 转换回 rgb 空间。

另一种可能性是您的图形硬件在转换为像素着色器的线性空间之前会过滤纹理。您可以通过禁用 D3DSAMP_SRGBTEXTURE 和过滤来对此进行测试,然后转换为线性空间并在像素着色器中进行过滤。或者只是将纹理绘制得足够大,以至于过滤不是问题。一篇关于 gamma 校正的好文章还提到 GeForce 8 和更高版本的显卡在过滤之前正确转换为线性空间,可以在这里找到:

线性的重要性

如果您没有使用 D3DPRESENT_LINEAR_CONTENT,那么我的下一个猜测是您的显卡不支持您正在执行的 gamma 转换。以编程方式或使用 DirectX Caps Viewer Tool 等工具检查设备功能:

DirectX Caps 查看器工具

于 2011-07-01T00:08:57.073 回答
2

这与问题有关,但不完全是,但值得了解!

我在 Vista/Win7 上的 D3D9 运行时中遇到了一个错误。此运行时是在 D3D10 之上编写的各种模拟层。在 D3D10 中,SRGB 状态是纹理格式的属性,在 D3D9 中,它是基于采样器的渲染状态。设置 D3D9 纹理时,SRGB 状态始终设置为“关闭”丢失,因为可能正在使用纹理格式,并且 D3D9 没有 SRGB 纹理格式。这意味着需要在绑定纹理后设置 D3DSAMP_SRGBTEXTURE 状态才能正确显示。

于 2011-07-06T08:21:54.090 回答