Tag DirectX下的博客主要用于記錄DirectX的學習程序,主要參考《DirectX 12 3D 游戲實戰開發》,
計算機色彩基礎
顏色的表示
人眼對紅、綠、藍三色光最為敏感,而絕大多數顏色都可以通過這三種顏色按不同比例混合產生,同時,絕大多數單色光也可以分解為紅、綠、藍三色光,這就是色度學中光的三原色原理(為了與色彩三原色作區分,通常把紅、綠、藍稱為三基色),
色彩的全息顯示,即在顯示幕中顯示色彩,就是基于三基色原理,基于這個原理,可以得出:
- 自然界的任何光色都可以由3中基色按比例混合(blending)而成,
- 三基色是相互獨立的,任一基色都無法用其余兩種光色表示,
- 混合所得的光色的飽和度(saturation)由3中光色的比例決定,混合色的亮度(brightness)為參與混合的光色的亮度之和,
既然光可以表示為三基色的混合,那么光就可以由一個三維向量(r,g,b)量化,其中r、g、b分別為紅綠藍三種光色的強度,為了便于描述光的強度,我們通常把光量化為區間[0,1]中的值,0為無強度,1為最大強度,以此為基礎的色彩表示法也稱為顏色的RGB模式,
光色的基本混合
光色的混合即兩種光色通過混合得到新的光色,(下圖為最大強度三基色等比混合所得的混合圖)

在光的混合理論中:
- 紅色+綠色=黃色;紅色+藍色=品紅;綠色+藍色=青色;紅色+綠色+藍色=白色
- 在色環中,過色環圓心的直線與色環相交得到的兩種顏色為互補色
光色的混合在現實中是直觀的,但在計算機中由于經過了量化,我們就必須對量化的資料定義混合的表示方法,光色的混合可以通過向量運算實作,在顏色運算程序中可能會超出區間,通常在可能產生風險的時候我們需要進行鉗制(clamp)操作,所謂的鉗制即把值大于1.0分量置為1.0,把值小于0.0的分量置為0.0,
相加混合
\[(0.0,0.5,0.0)+(0.0,0.0,0.25)=(0.0,0.5,0.25) \]
上式的含義是:把中等強度的綠色和低強度的藍色混合會得到深綠色,相加混合通常用于RGB模式中,
相級訓合
\[(1.0,1.0,1.0)-(1.0,1.0,0.0)=(0.0,0.0,1.0) \]
上式的含義是:從白色中減去紅色和綠色的部分會得到藍色,相級訓合通常用于CMYK模式中,
標量運算
\[0.5\times (1.0,1.0,1.0)=(0.5,0.5,0.5) \]
上式的含義是:把白色的各個分量都取一半會得到中等強度的灰色,
分量式(modulation)
分量式是顏色向量專屬的向量運演算法則,定義為:
\[(r_1,g_1,b_1)\bigotimes(r_2,g_2,b_2)=(r_1r_2,g_1g_2,b_1b_2) \]
分量式主要用于光照計算中,上式可以這樣理解:假設有顏色為\((r_1,g_1,b_1)\)的入射光線,照射到一個反射\(r_2\times 100\%\)紅色光、\(g_2\times 100\%\)綠色光、\(b_2\times 100\%\)藍色光且吸收剩余光的表面上,那么計算的結果為反射光線的顏色,
透明度
事實上,我們通常所使用的顏色向量多為四維向量,這并不是單純為了發揮SIMD加速,而是因為顏色的第四維分量是用來表示一個在混合計算中非常重要的值:不透明度(opacity),這個分量通常稱為alpha分量,它的值也是位于區間[0,1]內,
DirectX中的顏色及相關函式
由于顏色也是一個四維向量,所以在DirectX中也可以使用DirectXMath庫提供的XMVECTOR型別表示顏色,
分量式運算
XMVECTOR XM_CALLCONV XMColorModulate(FXMVECTOR C1, FXMVECTOR C2);
32位色
在DirectX中,顏色的資料型別通常有兩種大小:32位色和128位色,其中,32位色的定義如下:
namespace DirectX {
namespace PackedVector {
struct XMCOLOR {
union {
struct {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
};
uint32_t c;
};
XMCOLOR() {}
XMCOLOR(uint32_t Color) : c(Color) {}
XMCOLOR(float _r, float _g, float _b, float _a);
explicit XMCOLOR(_In_reads_(4) const float *pArray);
operator uint32_t () const { return c; }
XMCOLOR& operator=(const XMCOLOR& Color) { c = Color.c; return *this; }
XMCOLOR& operator=(const uint32_t Color) { c = Color; return *this; }
};
}
}
可以看到,DirectXMath庫把32位色存放到一個unsigned int中,位按由高到低分別表示顏色的a、r、g、b分量,每個分量都用一個8位的無符號數表示,即強度區間為整數區間[0,255],
128位色
128位色是最直觀的色彩記錄方式,即每個分量都用一個float表示,
位色轉換
通過把整數區間[0,255]映射到實數區間[0,1]就可以把32位色轉換為128位色,具體做法很簡單:把每個分量都除以255即可,
由于128位色的顏色精度非常高,高精度的優勢在于減少計算誤差,因此其通常用于像素著色器中進行像素顏色的計算,但目前的顯示設備還不足以體現高精度色彩的優勢,因此在計算完成后,存盤的計算結果往往是32位色,即:顏色的加載和存盤實際上是存盤結構和位色的轉換,為此,庫提供了相應的加載/存盤(或稱位色轉換)函式:
XMVECTOR XM_CALLCONV PackedVector::XMLoadColor(const XMCOLOR* pSource);
void XM_CALLCONV PackedVector::XMStoreColor(XMCOLOR* pDestination, FXMVECTOR V);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/3814.html
標籤:其他
上一篇:Shadow Map(單方向)
