• Advertisement
Sign in to follow this  

LERP colour line (gourand shading - algorith)

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

If you intended to correct an error in the post then please contact us.

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: tempo.jpg 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: tempo2.jpg

Share this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
Share on other sites
Quote:
Original post by Doggan
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.
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]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement