RGB 值可以按分量线性组合以创建渐变效果。假设您想从一种颜色传递(r1, g1, b1)
到另一种颜色(r2, g2, b2)
。RGB 渐变中的所有中间颜色都是((1-a)*r1 + a*r2, (1-a)*g1 + a*g2, (1-a)*b1 + a*b2)
,a
从 0 到 1 不等。
要计算沿从点到点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 };
}