Friday, November 27, 2015

xna - Code to generate a color gradient within a texture using a diagonal line


I want to generate a color gradient between two colors from x1,y1 to x2,y2. I'm unsure how to do this though. I can use Color.Lerp to get all of the color steps, but the problem is that I don't understand how to then apply that to a plane (the texture pixels) when the line would be at an angle.


If it was a horizontal/vertical line, that would be easy, because it's just plotting the same color along the appropriate axis. But if it's a diagonal line of any degree, that seems way more complicated and I'm unsure how to do calculate it.


As an example, here is a gradient from a picture editor program. It goes from green-to-red. The actual start and end positions are the circles. Therefore, the solid start/end colors continue solid outside of the gradient area.


gradient example



Answer




Here is one way to do it, the idea behind this method is rotating the whole image to make the line straight while working on it. I am only using half of the matrix because the line is flattened horizontally and so the Y coordinate doesn't matter to us then.


0. Convert your startPoint and endPoint into vectors:


float x1 = (startPoint.X / (float)width)  * 2.0f - 1.0f;
float y1 = (startPoint.Y / (float)height) * 2.0f - 1.0f;
float x2 = (endPoint.X / (float)width) * 2.0f - 1.0f;
float y2 = (endPoint.Y / (float)height) * 2.0f - 1.0f;

1. Find the angle between (x1,y1) and (x2,y2):


float angle = atan2(x1 - x2, y1 - y2);


2. Create half of a rotation matrix (We only need half for this)


float rx = cos(angle);
float ry = sin(angle);

3. Calculate start and end points in rotated space:


float start = x1 * rx + y1 * ry;
float end = x2 * rx + y2 * ry;

4.-. For each pixel:


for(int x=0;x
for(int y=0;y

4.1. Rotate the pixel so the line is horizontal


        // but we need vectors from (-1, -1) to (1, 1)
// instead of pixels from (0, 0) to (width, height)
float u = (x / (float)width) * 2.0f - 1.0f;
float v = (y / (float)height) * 2.0f - 1.0f;

float here = u * rx + v * ry;


4.2. Find the ratio between start and end


        float lerp = (start - here) / (start - end);

4.3. Interpolate between your colors and finish the pixel


        SetPixel(x,y, Color.Lerp(color1, color2, lerp));
}
}

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...