RGB 値をコンポーネントごとに線形結合して、グラデーション効果を作成できます。(r1, g1, b1)
colorから別の color に渡したいとします(r2, g2, b2)
。RGB グラデーションのすべての中間色は、0 から 1 まで変化する((1-a)*r1 + a*r2, (1-a)*g1 + a*g2, (1-a)*b1 + a*b2)
になります。a
ポイントからポイントへp=(x,y)
の線形グラデーションに沿って各ポイントの色を計算するには、との内積を計算し、 のノルムとのノルムで割り、値を間隔 にクランプします。p1=(x1,y1)
p2=(x2,y2)
p1 p
p1 p2
p1 p2
p1 p
[0,1]
c
中心と半径の円の放射状グラデーションのrad
場合、 を計算a = distance(p, c) / r
し、 にクランプし[0, 1]
ます。
どの中間色が表示されるかは、使用される色空間 (RGB、HSV、HSL など) によって異なります (コンポーネントごとに補間されます) http://howaboutanorange.com/blog/2011/08/10/color_interpolation/を参照してください。
コード例 (疑似コード、未テスト):
struct rgb_color {
float r, g, b;
};
struct vec {
float x, y;
};
// Color at point p, for a linear RGB gradient from point a (with color a_col) to b (with color b_col)
rgb_color linear_gradient(vec p, vec a, rgb_color a_col, vec b, rgb_color b_col) {
vec ab = { b.x - a.x, b.y - a.y };
vec ap = { p.x - a.x, p.y - a.y };
float ab_norm = sqrt(ab.x*ab.x + ab.y*ab.y);
float ap_norm = sqrt(ap.x*ap.x + ap.y*ap.y);
float dot = ab.x*ap.x + ab.y*ap.y;
k = dot / (ab_norm * ap_norm);
if(k < 0.0) k = 0.0;
else if(k > 1.0) k = 1.0;
float r = (1.0-k)*a_col.r + k*b_col.r;
float g = (1.0-k)*a_col.g + k*b_col.g;
float b = (1.0-k)*a_col.b + k*b_col.b;
return { r, g, b };
}
// Color at point p, for a radial RGB gradient from for circle with center c (with color c_col), radius, and color outer_col outside the circle.
rgb_color radial_gradient(vec p, rgb_color c_col, vec c, float radius, rgb_color outer_col) {
vec pc = { c.x - p.x, c.y - p.y };
float pc_norm = sqrt(pc.x*pc.x + pc.y*pc.y);
float k = pc_norm / radius;
if(k < 0.0) k = 0.0;
else if(k > 1.0) k = 1.0;
float r = (1.0-k)*c_col.r + k*outer_col.r;
float g = (1.0-k)*c_col.g + k*outer_col.g;
float b = (1.0-k)*c_col.b + k*outer_col.b;
return { r, g, b };
}