Reputation: 765
I'm trying to write an 'apply gradient' function, which takes a bunch of points and a linear gradient and calculates the colour for each point. I have something like this (given an array of points
and a gradient defined by two points start
and end
):
struct Colour {
float red; float green; float blue;
};
struct Point {
int x; int y;
Colour colour;
};
Point points[total_points] = { ... };
Point start = { ... };
Point end = { ... };
for (int i=0; i<total_points; i++) {
// Get normalised position along x and y
float scale_x = end.x-start.x;
float pos_x = (scale_x == 0) ? 0 : (points[i].x-start.x) / scale_x;
float scale_y = end.y-start.y;
float pos_y = (scale_y == 0) ? 0 : (points[i].y-start.y) / scale_y;
// Average the positions
float pos = .5 * (pos_x + pos_y);
// Blend colours
points[i].colour = blend_colour(start.colour, end.colour, pos);
}
My colour blending function is something simple like this:
static Colour blend_colour(Colour start, Colour end, float position) {
Colour blend;
blend.red = (start.red * (1-position)) + (end.red * position);
blend.green = (start.green * (1-position)) + (end.green * position);
blend.blue = (start.blue * (1-position)) + (end.blue * position);
return blend;
}
My maths in the for loop is definitely not quite right — do I need to calculate the colour using trigonometry?
Upvotes: 0
Views: 160
Reputation: 16406
Instead of
// Average the positions
float pos = .5 * (pos_x + pos_y);
Try
// Get scaled distance to point by calculating hypotenuse
float dist = sqrt(pos_x*pos_x + pos_y*pos_y);
Also, while the compiler will do it for you, you ought to hoist your scale factors out of the loop. In fact, it might be better to calculate the scale factor for the distance:
Point start = { ... };
Point end = { ... };
float xdelta = end.x - start.x;
float ydelta = end.y - start.y;
float hypot = sqrt(xdelta*xdelta + ydelta*ydelta);
for (int i=0; i<total_points; i++) {
// Get normalised distance to points[i]
xdelta = points[i].x - start.x;
ydelta = points[i].y - start.y;
float dist = sqrt(xdelta*xdelta + ydelta*ydelta);
if (hypot) dist /= hypot;
// Blend colours
points[i].colour = blend_colour(start.colour, end.colour, dist);
}
Upvotes: 2