Linear Gradient on a QUAD from 2 colors

Hi,

i have to render a quad with a linear gradient but i have colors for only 2 vertices like this scheme:

Ideally, i would let OpenGL to find which colors to interpolate for 2 others vertices but i’m suspect it is impossible. it’s right ?

So, how do interpolate theses yourself ?

My intuition say me that it’s corresponds to translate the diagonal (respecting //) until they reach another vertex.
In theses cases both other vertices would touch the diagonal at it’s center ! (it’s right ?) (it’s right only if the gradient line fit a square)

If it’s the case, i’m would compute the color at 50% of the gradient so that would being :

 
  red    = ( ( redB - redA ) / 2 ) + redA
  green = ( ( greenB - greenA ) / 2 ) + greenA
  blue   = ( ( blueB - bleuA ) / 2 ) + blueA

Best regards,
Sébastien.

So i answer to myself (because maybe it will help a day someone else)

My intuition saying that we should use for 2 other vertices, the color at the center of the gradient line is a false assumption.
Or at least, it was true only for a gradient line that fit a perfect [b]square[/b].

So, it’s more complicate with a quad.

Let’s go with this example (full size of image : http://i.imgur.com/RCb1fGc.png)

Principle
It’s a linear gradient, that mean all points on an orhogonal line of the gradient line has the same color !
That mean, for computing the color for 2 others vertices, we must find the orthogonal line of the gradient line that pass by the vertex and check where is the intersection with the gradient line.
After what, we can compute the distance of this intersection point and the start point (x0,y0).
This distance (in a range of [0 ~ 1] relative to the length of the gradient line) give us the interpolation factor to apply for finding the color at this intersection point.
This color is the same for our vertex. That’s all.

We must compute theses distances:

 
 dU that give the factor of interpolation to apply from color A to colorB for the vertex (x0,y1)
 dV that give the factor of interpolation to apply from color A to colorB for the vertex (x1,y0)

Compute the equation of our gradient line:
The slope is the change in height divided by the change in horizontal distance : m = (y0 - y1) / (x0 - x1)
The slope-intercept formula is y = mx + b that give b = y - mx

 
  float m = (y0 - y1) / (x0 - x1);
  float b = y0 - (m * x0);

Compute the equation of the orthogonal line of the gradient line that pass by (x0,y1)
The slope of a line perpendicular to a line is the negative reciprocal of its slope : 1 / -m


  float mo = 1f / -m;
  float bo = y1 - ( m * x0 );

Compute the intersection point of the gradient line and the orthogonal line
At the intersection point, both equation lines are equals, that give y == mx + b == mox + bo
That provide theses equations for computing the intersection :
x = (bo - b) / (m - mo)
y = mx + b


  float xU = (bo - b) / (m - mo);
  float yU = (m * xU) + b;

Computing the distance of the point (x0,y0) to the intersection point (that provide dU)
I use the simple pythagor theorem:


  float d1 = xU - x0;
  float d2 = yU - y0;
				
  dU = (float)Math.sqrt( (d1*d1) + (d2*d2) );
  dU = dU / length;                                          // Length is the distance of the gradient line from (x0,y0) to (x1,y1). That allow to convert dU in a [0 ~ 1] range.

Compute dV from dU
dV can be computed by symetric from dU.


  dV = 1 - dU;

Interpolate colors at (x0,y1) and (x1,y0)

  • Considering cA[] giving color’s component of color A at (x0,y0)
  • Considering cB[] giving color’s component of color B at (x1,y1)

We can obtain cU[] giving color’s component at (x0,y1)


  float[] cU = new float[4];
  cU[0] = ( (cB[0] - cA[0]) * dU ) + cA[0];
  cU[1] = ( (cB[1] - cA[1]) * dU ) + cA[1];
  cU[2] = ( (cB[2] - cA[2]) * dU ) + cA[2];
  cU[3] = ( (cB[3] - cA[3]) * dU ) + cA[3];

And the same for cV[] giving color’s component at (x1,y0)


  cV = new float[4];
  cV[0] = ( (cB[0] - cA[0]) * dV ) + cA[0];
  cV[1] = ( (cB[1] - cA[1]) * dV ) + cA[1];
  cV[2] = ( (cB[2] - cA[2]) * dV ) + cA[2];
  cV[3] = ( (cB[3] - cA[3]) * dV ) + cA[3];

I tested, i obtain the same result than LinearGradientPaint from awt/swing
Maybe it exist a simpler method but this one seems to work !