2

我一直在阅读 Frank D. Luna 的书“DirectX 10 3D 编程简介”,其中一个问题是从使用

D3DXCOLOR 颜色(128 位)
到 UINT 颜色(32 位)

大概要使用的格式代码是:DXGI_FORMAT_R8G8B8A8_UNORM。

在我看来,这意味着您有一个变量,该变量在字节级别以确切顺序包含有关通道的信息:RGBA(这是正确的解释吗?--问是因为我确定当您需要 RGBA 时我已经读过真的需要这样的代码:A#R#G#B#首先指定 alpha 通道。

无论如何,我选择(可能有更好的方法)这样做:

UINT color = (UINT)WHITE; 

其中 WHITE 被定义:const D3DXCOLOR WHITE(1.0f, 1.0f, 1.0f, 1.0f); 此转换在 D3DXCOLOR 的扩展中定义。

但是,当 DXGI_FORMAT_R8G8B8A8_UNORM 与 UINT 颜色变量一起使用时,您会得到错误的结果。Luna 将此归因于字节序。

这是因为来自 D3DXCOLOR 的转换产生了 RGBA 形式的 UINT,但是因为 intel x86 使用 little endiann 那么在字节级别你真的得到'ABGR'?那么当这个变量实际被解释时,着色器看到的是 ABGR 而不是 RGBA?它不应该在解释字节时知道高位在较小的地址吗?还有最后一个问题:既然代码被指定为DXGI_FORMAT_R8G8B8A8_UNORM,这是否意味着R应该是最小的地址而A应该是最大的?我确信我有很多误解,所以请随时消除它们。

4

1 回答 1

5

当您使用语句“UINT color = (UINT)WHITE”时,它正在调用 D3DXCOLOR 运算符 DWORD () 转换。由于旧版 D3DX9Math 是为 Direct3D 9 设计的,因此这是一种 BGRA 颜色(相当于 DXGI 的 DXGI_FORMAT_B8G8R8A8_UNORM)。来自 d3dx9math.inl:

D3DXINLINE
D3DXCOLOR::D3DXCOLOR( DWORD dw )

{
    CONST FLOAT f = 1.0f / 255.0f;
    r = f * (FLOAT) (unsigned char) (dw >> 16);
    g = f * (FLOAT) (unsigned char) (dw >>  8);
    b = f * (FLOAT) (unsigned char) (dw >>  0);
    a = f * (FLOAT) (unsigned char) (dw >> 24);
}

由于原始 Direct3D 10 版本的 DXGI (v1.0) 没有定义 DXGI_FORMAT_B8G8R8A8_UNORM(它是随 DXGI 1.1 添加的),用于 Direct3D 10+ 的“默认”颜色是 RGBA。

所有 DXGI 格式都是 Little-Endian,因为所有 Direct3D 10+ Microsoft 平台都是如此。对于 Xbox 360,引入了 Direct3D 9 D3DFORMAT 的一些特殊 Big-Endian 版本,但这并不是真正起作用的。问题更基本:BGRA 和 RGBA 都是有效选项,但 Direct3D 9 首选 BGRA,Direct3D 10+ 首选 RGBA。

为了让事情更混乱,Direct3D 9 D3DFMT 颜色的命名约定在 DXGI 中是相反的。“D3DFMT_A8R8G8B8”与“DXGI_FORMAT_B8G8R8A8_UNORM”相同。请参阅MSDN上的此主题。从历史上看,Windows 图形将其称为“32 位 ARGB”格式,但更自然的描述方式是“BGRA”。

于 2014-07-08T19:46:38.020 回答