Updated
While debugging I looked at the lerp and it was calculating into a negative number at the start. So I added in checks for to low or high a value, and that seems to have fixed it. I'll answer the question myself unless someone can find a way to fix the formula that calculates the lerp, since that seems to be the culprit. My fix was this:
double lerp = (start - here) / (start - end);
if (lerp < 0d)
lerp = 0d;
if (lerp > 1d)
lerp = 1d;
Original Question
I'm applying a gradient to a texture per the answer in this topic: Code to generate a color gradient within a texture using a diagonal line
My code is referenced below. The code was seeming to work fine. I was using a two-color gradient: green to purple. However, when I changed it to two colors that blended well into a 3rd color, I could instantly see that something was wrong.
For example, blue to purple was producing a red element outside of the gradient area. If you also look closely, the blue itself is also enhanced on the outer edges. It's almost as if the two colors are mixing outside of the gradient area, when they should be the original colors.
Calling Code
This is applying to the center of an area 80x25.
Color[] colors = new Color[] { Color.Blue, Color.Purple };
float[] colorStops = new float[] { 0f, 1f };
Algorithms.GradientFill(new Point(40, 12), 3, 33, new Rectangle(0, 0, CellData.Width, CellData.Height), colors, colorStops);
Gradient Calculation Code
public static void GradientFill(Point position, int strength, int angle, Rectangle area, Color[] colors, float[] colorStops)
{
double radians = angle * Math.PI / 180; // = Math.Atan2(x1 - x2, y1 - y2);
Vector2 angleVector = new Vector2((float)(Math.Sin(radians) * strength), (float)(Math.Cos(radians) * strength)) / 2;
Vector2 location = new Vector2(position.X, position.Y);
Vector2 endingPoint = location + angleVector;
Vector2 startingPoint = location - angleVector;
double x1 = (startingPoint.X / (double)area.Width) * 2.0f - 1.0f;
double y1 = (startingPoint.Y / (double)area.Height) * 2.0f - 1.0f;
double x2 = (endingPoint.X / (double)area.Width) * 2.0f - 1.0f;
double y2 = (endingPoint.Y / (double)area.Height) * 2.0f - 1.0f;
double start = x1 * angleVector.X + y1 * angleVector.Y;
double end = x2 * angleVector.X + y2 * angleVector.Y;
for (int x = area.X; x < area.Width; x++)
{
for (int y = area.Y; y < area.Height; y++)
{
// but we need vectors from (-1, -1) to (1, 1)
// instead of pixels from (0, 0) to (width, height)
double u = (x / (double)area.Width) * 2.0f - 1.0f;
double v = (y / (double)area.Height) * 2.0f - 1.0f;
double here = u * angleVector.X + v * angleVector.Y;
double lerp = (start - here) / (start - end);
float newLerp;
int counter;
for (counter = 0; counter < colorStops.Length && colorStops[counter] < (float)lerp; counter++) ;
counter--;
counter = Math.Max(counter, 0);
counter = Math.Min(counter, colorStops.Length - 2);
newLerp = (colorStops[counter] - (float)lerp) / (colorStops[counter] - colorStops[counter + 1]);
SetPixel(x, y, color);
}
}
}
Answer
The answer is that the amount to use during the lerp method was going below 0 or above 1. This will fix it:
lerp = MathHelper.Clamp((float)lerp, 0f, 1.0f);
No comments:
Post a Comment