Matrixcolor
Ren'Py는 matrixcolor 트랜스폼 속성으로 이미지의 색상을 바꿀 수 있습니다. 이 속성은 Matrix 또는 ColorMatrix 객체를 받습니다.
알파를 미리 곱한 색상
이미지를 로드하면 Ren'Py가 압축을 풀고 컴퓨터나 모바일 기기의 GPU로 복사합니다. 복사 과정에서 네 색상 채널(빨강, 초록, 파랑, 불투명도를 나타내는 알파)을 각각 0.0에서 1.0 사이의 값으로 변환합니다. 1.0은 색상이 최대 강도이거나 완전히 불투명함을 뜻하고, 0.0은 색상이 없거나 픽셀이 완전히 투명함을 뜻합니다.
Ren'Py는 이어서 빨강, 초록, 파랑 채널에 알파 채널 값을 곱합니다. 따라서 불투명한 흰색 픽셀은 (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)이 됩니다.
알파를 미리 곱하면 Ren'Py가 이미지를 확대·축소할 때 색상을 직접 표현하는 방식에서 생기는 어두운 렌더링 오류를 피할 수 있습니다. 크기 조절은 두 픽셀의 평균을 구하는 것과 비슷합니다. 알파를 미리 곱하지 않을 때 불투명한 흰색 픽셀 (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% 불투명도의 회색을 뜻합니다.
하지만 완전히 투명한 픽셀에는 실제 색상이 없으므로 결과의 색상에는 영향을 주지 않고 투명도에만 영향을 주어야 합니다. 알파를 미리 곱하는 방식에서도 시작값과 결과는 같지만, (0.5, 0.5, 0.5, 0.5)는 50% 불투명도의 흰색을 뜻하도록 정의되어 있습니다. 이 방식으로 저장하면 Ren'Py가 색상을 올바르게 그리고 크기 조절 시 이상한 오류가 생기지 않습니다.
Matrix로 색상 변경
색상을 바꾸는 Matrix 객체는 4x4 격자로 배열할 수 있는 숫자 16개로 구성할 수 있습니다. 각 숫자에 문자를 붙여 표현하면 다음과 같습니다.
define mymatrix = Matrix([ a, b, c, d,
e, f, g, h,
i, j, k, l,
m, n, o, p, ])
여기서는 문자로 표시했지만 실제로는 직접 지정하거나 계산한 숫자입니다.
이 값들을 원래 색상의 빨강(R), 초록(G), 파랑(B), 알파(A) 채널에 적용하여 새 색상 (R', G', B', A')을 만듭니다. 계산식은 다음과 같습니다.
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
Matrix 객체는 정적인 색상 변경에는 적합하지만 색상 변경에 애니메이션을 적용하는 데는 유용하지 않습니다. 자주 쓰는 행렬을 매개변수로 조절할 수 있는 형태로 묶는 방법도 유용합니다.
ColorMatrix는 행렬을 생성하는 여러 클래스가 확장하는 기반 클래스입니다. Ren'Py가 ColorMatrix 인스턴스를 호출하면 Matrix를 반환합니다. ATL과 긴밀하게 연동되므로 matrixcolor에 애니메이션을 적용할 수 있습니다.
transform red_blue_tint:
matrixcolor TintMatrix("#f00")
linear 3.0 matrixcolor TintMatrix("#00f")
linear 3.0 matrixcolor TintMatrix("#f00")
repeat
ColorMatrix를 상속한 하위 클래스에서 __call__ 메서드를 재정의할 수 있습니다. 이 메서드는 다음을 받습니다.
보간의 시작 기준이 되는 이전 객체. 어느 클래스의 객체든 가능하며 이전 객체가 없으면 None일 수 있습니다.
보간할 시점을 나타내는 0.0에서 1.0 사이의 값. 0.0은 완전히 이전 객체, 1.0은 완전히 새 객체입니다.
Matrix를 반환해야 합니다.
ColorMatrix의 예제로 Ren'Py의 TintMatrix 클래스 구현을 살펴보겠습니다.
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):
# When not using an old color, we can take
# r, g, b, and a from self.color.
r, g, b = self.color.rgb
a = self.color.alpha
else:
# Otherwise, we have to extract from self.color
# and other.color, and interpolate the results.
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
# To properly handle premultiplied alpha, the color channels
# have to be multiplied by the alpha channel.
r *= a
g *= a
b *= a
# Return a Matrix.
return Matrix([ r, 0, 0, 0,
0, g, 0, 0,
0, 0, b, 0,
0, 0, 0, a ])
구조적 유사성
ATL에서 matrixcolor 속성을 보간하려면 구조적으로 유사한 ColorMatrix들을 사용해야 합니다. 같은 종류의 ColorMatrix들이 같은 순서로 곱해져 있어야 한다는 뜻입니다.
예를 들어 다음 코드는 원래 색상에서 채도가 낮은 파란 색조로 보간한 뒤 원래대로 돌아갑니다.
show eileen happy at center:
matrixcolor TintMatrix("#ffffff") * SaturationMatrix(1.0)
linear 2.0 matrixcolor TintMatrix("#ccccff") * SaturationMatrix(0.0)
linear 2.0 matrixcolor TintMatrix("#ffffff") * SaturationMatrix(1.0)
첫 번째 matrixcolor 설정이 불필요해 보일 수 있지만 첫 선형 보간의 기준을 제공하기 위해 필요합니다. 이 설정이 없으면 해당 보간을 건너뜁니다.
내장 ColorMatrix 하위 클래스
다음은 Ren'Py에 내장된 ColorMatrix 하위 클래스 목록입니다.
- class BrightnessMatrix(value=1.0)
matrixcolor와 함께 사용하여 알파 채널은 유지하면서 이미지의 밝기를 바꾸는 ColorMatrix입니다.- value
이미지 밝기의 변경량입니다. -1에서 1 사이의 숫자여야 하며 -1은 가장 어두운 이미지, 1은 가장 밝은 이미지입니다.
- class ColorizeMatrix(black_color, white_color)
matrixcolor와 함께 사용하여 흑백 디스플레이어블에 색을 입히는 ColorMatrix입니다. 흑백 이미지의 각 픽셀 색상을 사용하여 지정한 검정 색상과 흰색 색상 사이를 보간합니다.알파 채널은 바꾸지 않습니다.
흑백 이미지 또는
SaturationMatrix()로 채도를 제거한 이미지에 사용하도록 설계되었습니다. 흑백이 아닌 이미지에 사용하면 이상한 결과가 나옵니다.- black_color, white_color
보간에 사용할 색상입니다.
- class ContrastMatrix(value=1.0)
matrixcolor와 함께 사용하여 알파 채널은 유지하면서 이미지의 대비를 바꾸는 ColorMatrix입니다.- value
대비 값입니다. 0.0에서 1.0 사이의 값은 대비를 줄이고 1.0보다 큰 값은 대비를 높입니다.
- class HueMatrix(value=1.0)
matrixcolor와 함께 사용하여 색조를 value도 회전하는 ColorMatrix입니다. value는 양수와 음수 모두 가능하며 360도는 한 바퀴입니다. 알파 채널은 바꾸지 않습니다.
- class IdentityMatrix
matrixcolor와 함께 사용하며 입력의 색상과 알파를 바꾸지 않는 ColorMatrix입니다.
- class InvertMatrix(value=1.0)
matrixcolor와 함께 사용하여 각 색상 채널을 반전하는 ColorMatrix입니다. 알파 채널은 바꾸지 않습니다.- value
반전 정도입니다. 0.0은 반전하지 않고 1.0은 완전히 반전합니다. 반전에 애니메이션을 적용할 때 사용합니다.
- class OpacityMatrix(value=1.0)
matrixcolor와 함께 사용하여 색상 채널은 유지하면서 이미지의 불투명도를 바꾸는 ColorMatrix입니다.- value
알파 채널에 곱할 값으로, 0.0에서 1.0 사이의 숫자입니다.
- class SaturationMatrix(value, desat=(0.2126, 0.7152, 0.0722))
matrixcolor와 함께 사용하여 알파 채널은 유지하면서 이미지의 채도를 바꾸는 ColorMatrix입니다.- value
결과 이미지의 채도입니다. 1.0은 원본 그대로이며 0.0은 회색조입니다.
- desat
채도를 완전히 제거한 이미지의 세 채널 모두에 원본의 빨강, 초록, 파랑을 얼마나 반영할지 제어하는 3요소 튜플입니다. 기본값은 NTSC 텔레비전 신호의 휘도 채널에 사용하는 상수를 바탕으로 합니다. 사람의 눈은 초록에 가장 민감하므로 다른 두 채널보다 초록을 더 많이 반영합니다.
- SepiaMatrix(tint='#ffeec2', desat=(0.2126, 0.7152, 0.0722))
matrixcolor와 함께 사용하여 디스플레이어블에 세피아 색조를 적용하는 ColorMatrix를 반환하는 함수입니다. 다음과 같습니다.TintMatrix(tint) * SaturationMatrix(0.0, desat)
- class SplineMatrix(matrix, spline)
스플라인으로 두 행렬 사이를 보간하는 Matrix 래퍼입니다. 스플라인은 두 행렬의 반영 비율을 제어합니다.
- matrix
보간 목표가 되는 행렬입니다.
- spline
보간에 사용할 스플라인입니다. 부동 소수점 수가 세 개 이상 들어 있는 리스트여야 합니다. 첫 숫자는 시작 비율(보통 0.0), 마지막 숫자는 끝 비율(보통 1.0)이며 그 사이의 값은 매듭점입니다.
매듭점 하나(숫자 3개인 리스트)에는 이차 곡선을 사용합니다.
매듭점 두 개(숫자 4개인 리스트)에는 베지어 스플라인을 사용합니다.
매듭점 세 개 이상에는 Catmull-Rom 스플라인을 사용합니다. 첫 번째와 마지막 매듭점(두 번째와 끝에서 두 번째 숫자)은 제어점이고 나머지 매듭점은 스플라인이 통과하는 비율입니다.
예를 들어 다음 코드는 이차 곡선으로 시작에서 끝을 향해 보간한 뒤 다시 시작점으로 돌아갑니다.
show eileen happy: center matrixcolor BrightnessMatrix(0.0) linear 2.0 matrixcolor SplineMatrix(BrightnessMatrix(1.0), [ 0.0, 1.0, 0.0 ]) repeat
- class TintMatrix(color)
matrixcolor와 함께 사용하여 알파 채널은 유지하면서 이미지에 색조를 입히는 ColorMatrix입니다.- color
행렬이 대상에 입힐 색조입니다.
Color()에 전달하므로 Color가 첫 인수로 지원하는 모든 값을 사용할 수 있습니다.