Ren’Py可以使用變換特性 matrixcolor
對圖像染色。該特性使用一個 Matrix
類或者 ColorMatrix對象作為參數。
Ren’Py載入圖片後,會先解壓,然後將圖片複製到電腦或移動設備的圖形處理單元(GPU)中。 複製過程中,4種色彩通道(紅、綠、藍和alpha即不透明度)的值都會進行歸一化處理,使之介於0.0與1.0之間。 在GPU系統中,1.0表示最大色彩值或完全不透明,0.0表示最小色彩值或完全透明。
Ren’Py處理的工作不僅限於此。色彩通道數值歸一化完成後,紅綠藍通道的數值會分別與alpha通道的數值相乘。 也就是說,一個純白像素的數值會是(1.0, 1.0, 1.0, 1.0),一個50%不透明度紅色像素的數值會是(0.5, 0.0, 0.0, 0.5),一個透明的像質數值會是(0.0, 0.0, 0.0, 0.0)。
alpha預乘系統,使Ren’Py在縮放圖片時不會出現亮度降低的問題。 因為縮放圖片常常類似於計算兩個像素色彩平均值。 假設不使用alpha預乘,我們需要處理兩個像素,一個純白像素和一個透明純黑像素——即(1.0, 1.0, 1.0, 1.0)和(0.0, 0.0, 0.0, 0.0)。 兩個像素的彩色平均值為(0.5, 0.5, 0.5, 0.5)。但這不是我們需要的,純白像素和透明純黑像素之間應該插入一個50透明度的白色,而不是50%透明度的灰色。
以這種方式存儲色彩訊息後,Ren’Py就可以在螢幕上繪製正確的結果,而不會在縮放圖像時產生問題。
用於修改色彩的 Matrix
對象由16個數字組成,可以寫成一個4×4的陣列形式。
這裡我們將每個數字使用一個字母代替:
define mymatrix = Matrix([ a, b, c, d,
e, f, g, h,
i, j, k, l,
m, n, o, p, ])
注意這裡的字母只是代替數值,實際使用時這些都必須是真實的數值,可以直接寫死或者通過計算獲得。
這些數值將分別作用於原圖像色彩的RGBA通道,並生成新的色彩,具體算法如下:
R' = R * a + G * b + B * c + A * d
G' = R * e + G * f + B * g + A * h
B' = R * i + G * j + B * k + A * l
A' = R * m + G * n + B * o + A * p
看起來有些複雜吧。還有一個十分簡單的解析方式——第一行數值用於生成新的紅色通道,第二行用於生成新的綠色通道,以此類推。 如果我們想要一個交換紅色與綠色的矩陣,可以這樣實現:
transform swap_red_and green:
matrixcolor Matrix([ 0.0, 1.0, 0.0, 0.0,
1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0, ])
這只是一個簡單的樣例,此外有一大堆色彩理論可以使用這種方式進行表示。 矩陣可以組合使用,使用時符合矩陣乘法法則,各矩陣從右往左依次相乘。
因為矩陣對象只是用於靜態色彩修改,對動畫無能為力。 所以能夠同時具有矩陣的功能並能接受參數輸入將會非常實用。
ColorMatrix類是一個基類,可以擴展為很多用於創建色彩矩陣的衍生類。 Ren’Py會調用ColorMatrix類的實例,並返回色彩矩陣。ColorMatrix對象已很好地集成在ATL中,可以直接實現動畫。
transform red_blue_tint:
matrixcolor TintMatrix("#f00")
linear 3.0 matrixcolor TintMatrix("#00f")
linear 3.0 matrixcolor TintMatrix("#f00")
repeat
ColorMatrix類可以被子類繼承,需要重寫 __call__
方法。
該方法有以下要求:
該方法返回值必須是一個 Matrix
。
下面是Ren’Py中TintMatrix類的實現,它是一個典型的ColorMatrix派生類:
class TintMatrix(ColorMatrix):
def __init__(self, color):
# Store the color given as a parameter.
self.color = Color(color)
def __call__(self, other, done):
if type(other) is not type(self):
# 沒有原來的顏色,我們從self.color獲取自身rgba數值
r, g, b = self.color.rgb
a = self.color.alpha
else:
# 否則,我們從self.color和other.color分別獲取rgba並進行計算結果
oldr, oldg, oldb = other.color.rgb
olda = other.color.alpha
r, g, b = self.color.rgb
a = self.color.alpha
r = oldr + (r - oldr) * done
g = oldg + (g - oldg) * done
b = oldb + (b - oldb) * done
a = olda + (a - olda) * done
# alpha預乘
r *= a
g *= a
b *= a
# 返回一個矩陣對象
return Matrix([ r, 0, 0, 0,
0, g, 0, 0,
0, 0, b, 0,
0, 0, 0, a ])
下面列出了Ren’Py內建的ColorMatrix派生類。
BrightnessMatrix
(value=1.0) link在 matrixcolor
特性中使用,用於提高圖像亮度的ColorMatrix派生類,不修改alpha通道數值。
ColorizeMatrix
(black_color, white_color) link在 matrixcolor
特性中使用,對黑白色可視組件染色的ColorMatrix派生類。它會根據像素彩色中的黑色或白色數值用作插值比例進行插值計算。
不對alpha通道進行操作。
使用該類時最好使用黑白圖片(或者使用 SaturationMatrix()
將飽和度降為0後的圖像),不然可能會產生奇怪的結果。
分別對應黑色和白色重映射後的兩種顏色。
(譯者註:colorize又稱“形色化”,本質上是一種色彩RGB值的重映射算法。比如入參 black_color 設置為紅色#ff0000,white_color 設置為藍色#0000ff,黑白圖片染色之後原來純黑的部分將變成紅色,原來純白的部分將變成藍色,原來灰色的部分將變為紅藍混合。原文件中這段的描述過於糾結插值算法,沒有直譯。)
HueMatrix
(value=1.0) link在 matrixcolor
特性中使用,旋轉 value 度色相值的ColorMatrix派生類。value 可以是任意數值,可正可負。360度表示色相正好旋轉一圈。
不對alpha通道進行操作。
IdentityMatrix
link在 matrixcolor
特性中使用,使圖像恢復原色彩和alpha值。
InvertMatrix
(value=1.0) link在 matrixcolor
特性中使用,反轉各色彩通道值的ColorMatrix派生類。不對alpha通道進行操作。
OpacityMatrix
(value=1.0) link在 matrixcolor
特性中使用,修改圖像透明度,而不修改顏色通道值的ColorMatrix派生類。
SaturationMatrix
(value, desat=(0.2126, 0.7152, 0.0722)) link在 matrixcolor
特性中使用,修改圖像飽和度,而不修改alpha通道值的ColorMatrix派生類。
SepiaMatrix
(tint=u'#ffeec2', desat=(0.2126, 0.7152, 0.0722)) link在 matrixcolor
特性中使用,將某個可視組件改為老照片(sepia-tone)風格的ColorMatrix派生類。等效於:
TintMatrix(tint) * SaturationMatrix(0.0, desat)
TintMatrix
(color) link在 matrixcolor
特性中使用,添加圖像色調而不修改alpha通道值的ColorMatrix派生類。
Color()
,可以是Color函數支持的任意類型。