PDA

View Full Version : how are colors interpolated ?



HamsterofDeath
01-13-2004, 12:51 PM
the situation : i want to create a big blurry texture for my whole outdoor map. therefore, i calculate for every pixel the position where its corresponding landscape point is.
now i end up on a triangle. i know it's textures, and the density of each texture at each vertex, which is stored in its color.
maybe you know the method : http://www.delphi3d.net/articles/viewarticle.php?article=terraintex.htm

well, for the blurry texture, i need to calculate a specific pixels color. in others words : i got 3 vertices, 3 colors. how to calclate a color on a specific point somewhere on this triangle ?

ZbuffeR
01-13-2004, 01:26 PM
OpenGl already interpolates vertices color.
Or I did not understood what you want to achieve ?

HamsterofDeath
01-13-2004, 02:03 PM
i need to interpolate it manually

Overmind
01-14-2004, 04:53 AM
If I understand you correctly, you want to reproduce the color interpolation of OpenGL. But this is not possible, because it is not exactly specified how the graphics hardware has to do it...

If it is not necessary to get exactly the same result as OpenGL would produce, you can use the following algorithm:
Linearely interpolate between the vertices to get the colors at the edges of the polygon and the interpolate along the scanlines to get the inside pixels. I think this is what most graphic cards will do, but don't quote me on that...

cass
01-14-2004, 08:12 AM
Originally posted by HamsterofDeath:
i need to interpolate it manually

There are lots of ways to do this.

One simple way would be to compute barycentric weights, and do a weighted
average.

Another would be to compute screen-space plane equations for each component independently.

I'll leave the how-to for these approaches as an exercise for other posters. (Unless nobody knows how. http://www.opengl.org/discussion_boards/ubb/smile.gif )

Cass

pleopard
01-14-2004, 05:45 PM
Bi-linear interpolation ...




/** Interpolate the dependent axis value of a point.
@param xSw X coordinate of south-western point.
@param ySw Y coordinate of south-western point.
@param zSw Z coordinate of south-western point.
@param xSe X coordinate of south-eastern point.
@param ySe Y coordinate of south-eastern point.
@param zSe Z coordinate of south-eastern point.
@param xNw X coordinate of north-western point.
@param yNw Y coordinate of north-western point.
@param zNw Z coordinate of north-western point.
@param xNe X coordinate of north-eastern point.
@param yNe Y coordinate of north-eastern point.
@param zNe Z coordinate of north-eastern point.
@param x X coordinate of point in question.
@param y Y coordinate of point in question.
receptor.
*/
double interpolate(
double xSw, double ySw, double zSw,
double xSe, double ySe, double zSe,
double xNw, double yNw, double zNw,
double xNe, double yNe, double zNe,
double x, double y
) const;




// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
// Interpolate the dependent axis value of a point.

double MgBilinearInterpolator3D::
interpolate(
double xSw, double ySw, double zSw,
double xSe, double ySe, double zSe,
double xNw, double yNw, double zNw,
double xNe, double yNe, double zNe,
double x, double y
) const
{
double delX = (x - xSw) / (xSe - xSw);
double delY = (y - ySw) / (ySe - ySw);

double delX1 = 1.0 - delX;
double delY1 = 1.0 - delY;
return
delY1*delX1*zSw + delY*delX1*zSe +
delY* delX *zNe + delY1* delX*zNw;
}

HamsterofDeath
01-15-2004, 03:06 AM
well, thanks for the code.

but : does it matter if i switch the points ? there is no "north" and "south" in my triangle.
and more important : i have a triangle, not a quad.

and what exactly does this function do ?

i get a value back...but what do to with it ?

HamsterofDeath
01-15-2004, 03:23 AM
Linearely interpolate between the vertices to get the colors at the edges of the polygon and the interpolate along the scanlines to get the inside pixels. I think this is what most graphic cards will do, but don't quote me on that...

getting the colors of the outer lines is no problem, since it's an interpolation between 2 points. but how to go on ?

xtwombly
01-15-2004, 03:36 PM
Just to restate the problem: You have three vertices (v1, v2, v3), each with an associated color (c1,c2,c3), and you want to generate a color c4 at vertex v4 using a weighted average of colors from v1, v2 and v3. One such solution is given below.

General solution: Calculate the absolute distance between each vertex and v4, denoted d1, d2, d3. Let the total distance between all vectors and v4 be D = d1+d2+d3. Then the weighting factor associated with each vertex is associated with the absolute distance the vertex is from v4 relative to the total distance to v4 of all the points:

w1 = (1 - d1/D)/(N-1)
w2 = (1 - d2/D)/(N-1)
w3 = (1 - d3/D)/(N-1)

N = 3, the number of vertices used to calculate D.

The color at v4 is then c4 = w1*c1 + w2*c2 + w3*c3

Note that this technique easily expands to any number of vertices describing your polygon, and in fact is not restricted to a planar surface. Hope it helps.

cass
01-16-2004, 08:46 AM
The distance-based weighting approach is an interesting one, though I think it'd have a somewhat strange effect when a triangle was scaled between skinny and fat.

Since nobody else has posted, I'll briefly state how to do plane equations and barycentrics.

Plane equations:

Each component of color is a plane equation of the form



f = Ax + By + C


We know that



f1 = A(v1.x) + B(v1.y) + C(v1.z)
f2 = A(v2.x) + B(v2.y) + C(v2.z)
f3 = A(v3.x) + B(v3.y) + C(v3.z)

or



|f1| | v1.x v1.y v1.z | | A |
|f2| = | v2.x v2.y v2.z | | B |
|f3| | v3.x v3.y v3.z | | C |


So if we rewrite this as




| v1.x v1.y v1.z |
M = | v2.x v2.y v2.z |
| v3.x v3.y v3.z |


Then the plane equation is




| A | | f1 |
| B | = (M^1) | f2 |
| C | | f3 |


This and numerous other interesting observations are noted in http://www.cs.unc.edu/~olano/papers/2dh-tri/ .


Barycentric equations:

Barycentric is just a weighted average, so



f = A*f1 + B*f2 + C*f3.



But the weights are based on distance from each edge. A vertex v on edge(v2,v3) has an A weight of 0. And the general formula is




A = dist( v, edge(v2,v3) ) / dist( v1, edge(v2,v3) )
B = dist( v, edge(v3,v1) ) / dist( v2, edge(v3,v1) )
C = dist( v, edge(v1,v2) ) / dist( v3, edge(v1,v2) )


For points inside a triangle, it's true that A+B+C==1, which can be useful.

The interesting thing about Barycentric weights is that they're independent of the attribute being interpolated, so once you've computed them they work for all attributes.

But, you have to compute new barycentric weights for each point in the triangle.

Anyway, I hope this helps.

Thanks -
Cass

HamsterofDeath
01-16-2004, 12:57 PM
thx