# LERP colour line (gourand shading - algorith)

This topic is 4609 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi I am having trouble making a line function that renders a fade from one colour to another. Here is my output at the moment: Here is the relevant code
struct CColor4f
{
float r,g,b,a;
CColor4f() {r=g=b=a=1.0f;};
CColor4f(float rr,float gg,float bb,float aa = 1.0f) {r=rr;g=gg;b=bb;a=aa;};

unsigned int GetColor()
{
if (a < 0.0f) a = 0.0f;
if (r < 0.0f) r = 0.0f;
if (g < 0.0f) g = 0.0f;
if (b < 0.0f) b = 0.0f;
if (a > 1.0f) a = 1.0f;
if (r > 1.0f) r = 1.0f;
if (g > 1.0f) g = 1.0f;
if (b > 1.0f) b = 1.0f;
return ((unsigned int(255.0f*a)) << 24) + ((unsigned int(255.0f*r))<< 16) + ((unsigned int(255.0f*g))<< 8) +(unsigned int(255.0f*b));
};
CColor4f operator-(CColor4f n)
{
return CColor4f(r-n.r,g-n.g,b-n.b,a-n.a);
};
CColor4f operator+(CColor4f n)
{
return CColor4f(r+n.r,g+n.g,b+n.b,a+n.a);
};
CColor4f operator*(float m)
{
return CColor4f(r*m,g*m,b*m,a*m);
};
CColor4f operator/(float m)
{
return CColor4f(r/m,g/m,b/m,a/m);
};
};

// Render a double colour line
void putLine(int x1,int y1,CColor4f *c1,int x2,int y2,CColor4f *c2)
{
CColor4f *tempColor;
int t;
// Make sure x1 is smaller than x2
if (x1 > x2)
{	// Swap input
t = y1;
y1 = y2;
y2 = t;
t=x1;
x1 = x2;
x2 = t;
tempColor=c1;
c1=c2;
c2=tempColor;
};

// Cancel absurd case
if (x1 >= g_iWidth) return;
if (x2 < 0) return;

bool divideByZero = false;

// Find the gradient of the slope
float deltaX = float(x2-x1);
float slope1 = float(y2-y1)/deltaX;
float c = float(y1) - float(x1)*slope1;

// check if the intersection of the line and the y axis has a larger and smaller x respectively
//y = mx+c,x = y-c/m
/*float temp = (y1 - c) / slope1;
if (*/

if (x1 == x2)
{
divideByZero = true;
slope1 = 10.0f;
}

if (fabs(slope1)  < 1.0f)
{
int sx,ex;

// Clip our drawing range
if (x1 < 0) sx = 0;
else sx = x1;
if (x2 >= g_iWidth) ex = g_iWidth-1;
else ex = x2;

// Okay now we need to find the slope of each colour!
CColor4f deltaC = (*c2-*c1)/deltaX;

unsigned int *start = (g_puiScreen) + (y2 * g_iScreenMultiple);
for (int x=sx;x < ex;x++)
{
int lineoffset = int(float(x)*slope1+c) * (g_iScreenMultiple);
g_puiScreen[lineoffset + x] = (*c1 + deltaC * float(x)).GetColor(); // Colour = Colour1 + (Colour2-Colour1) * x/deltaX
// Colour = Colour1 + (Colour2-Colour1)/deltaX * x
//	putPixel(x,float(x)*slope1+c,color);
}
}
else
{
int sy,ey;
// Make sure y1 is smaller than y2
if (y1 > y2)
{
t = y1;
y1 = y2;
y2 = t;
t=x1;
x1 = x2;
x2 = t;
tempColor=c1;
c1=c2;
c2=tempColor;
};
float deltaY = float(y2-y1);
// Clip our drawing range
if (y1 < 0) sy = 0;
else sy = y1;
if (y2 >= g_iHeight) ey = g_iHeight-1;
else ey = y2;
if (divideByZero) slope1 = 0;
else slope1 = 1.0f / slope1;	// Inverse slope

// Okay now we need to find the slope of each colour!
CColor4f deltaC = (*c2-*c1)/deltaY;

for (int y=sy;y < ey;y++)
{
int lineoffset = y * (g_iScreenMultiple);
g_puiScreen[lineoffset + int((float(y)-c)*slope1)] = (*c1 + deltaC * float(y)).GetColor(); // Colour = Colour1 + (Colour2-Colour1) * y/deltaY
// Colour = Colour1 + (Colour2-Colour1)/deltaY * y
}
}

};


As you can see I have tried to patch the error a bit by adding
		if (a < 0.0f) a = 0.0f;
if (r < 0.0f) r = 0.0f;
if (g < 0.0f) g = 0.0f;
if (b < 0.0f) b = 0.0f;
if (a > 1.0f) a = 1.0f;
if (r > 1.0f) r = 1.0f;
if (g > 1.0f) g = 1.0f;
if (b > 1.0f) b = 1.0f;

Without it this is how the render looks:

##### Share on other sites
1). After a quick look, I don't like this line:

return ((unsigned int(255.0f*a)) << 24) + ((unsigned int(255.0f*r))<< 16) + ((unsigned int(255.0f*g))<< 8) +(unsigned int(255.0f*b));

Casting a float to an int is going to lose you some precision. I'm not sure if this is your problem, but it can't be good.

I think you're making it more difficult than it actually is. To fade from one color to the other, you can just use a LERP equation:

newColor = (1 - currentLinePercent)startColor + (currentLinePercent * endColor)

- newColor (r,g,b) is the color of your line.
- currentLinePercent is the line number you're on divided by the total lines in the quarter circle (as based on your pictures).
- startColor and endColor are obvious. Both are (r,g,b) triplets.

2). Capping the alpha/r/g/b values to the 0-1 range is a good idea.

3). Use [ source ] [ /source ] tags instead of [ code ] [ /code ] tags. It makes it easier to read :)

##### Share on other sites
Quote:
 Original post by Doggan1). After a quick look, I don't like this line:return ((unsigned int(255.0f*a)) << 24) + ((unsigned int(255.0f*r))<< 16) + ((unsigned int(255.0f*g))<< 8) +(unsigned int(255.0f*b));Casting a float to an int is going to lose you some precision. I'm not sure if this is your problem, but it can't be good.3). Use [ source ] [ /source ] tags instead of [ code ] [ /code ] tags. It makes it easier to read :)

How do I get rid of the type casting?

// Here is my improved version, It still type casts but now handles the wrapping correctly
		unsigned int ret;		char mr,mg,ma,mb;		mr =  char(twopower8f*r);		mg =  char(twopower8f*g);		mb =  char(twopower8f*b);		ma =  char(twopower8f*a);		__asm		{			//mov edi,[ret]	// Get the memory address of ret			mov ah,ma			mov al,mr			shl eax,16			mov ah,mg			mov al,mb			// Okay so my colour is now stored in eax			mov ret,eax		}		return ret;

Okay but I am seriously considering changing from using floats to bytes for the storage of the colours

PS Thanks your percentage thing works...

[Edited by - dawidjoubert on April 5, 2006 9:52:55 AM]

1. 1
Rutin
37
2. 2
3. 3
4. 4
5. 5

• 11
• 14
• 12
• 14
• 9
• ### Forum Statistics

• Total Topics
633352
• Total Posts
3011482
• ### Who's Online (See full list)

There are no registered users currently online

×