Problem with shaded triangle

Started by
0 comments, last by Ignifex 11 years, 6 months ago
Hello, I was trying to draw a shaded triangle, but I get wrong colors. Here's the example of what I get, if I call a function with red, green and blue colors:

Capture.jpg

Code's here:


unsigned RGB(unsigned char R, unsigned char G, unsigned B){
return (R << 16) | (G << 8) | B;
}
void put_pixel(SDL_Surface * s, unsigned x, unsigned y, unsigned color){
unsigned long * pixels = (unsigned long *)s->pixels;
if(x >= s->w || y >= s->h)
return;
pixels[x+y*s->w] = color;
}
void draw_line(SDL_Surface * s, int x0, int y0, int x1, int y1, unsigned color){
int x, y;
int xproj = x1-x0, yproj = y1-y0, pm;
if(!xproj && !yproj)
return;

if(abs(xproj) > abs(yproj)){
pm = xproj >= 0 ? 1 : -1;
for(x = 0; x != xproj; x += pm){
y = rint(x* yproj/(double)xproj);
put_pixel(s, x0 + x, y0 + y, color);
}
}else{
pm = yproj >= 0 ? 1 : -1;
for(y = 0; y != yproj; y += pm){
x = rint(y* xproj/(double)yproj);
put_pixel(s, x0+x, y0+y, color);
}
}
}
float sign(int x0, int y0, int x1, int y1, int x2, int y2){
return (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2);
}
int ptintr(int sx, int sy, int x0, int y0, int x1, int y1, int x2, int y2){
int b1, b2, b3;

b1 = sign(sx, sy, x0, y0, x1, y1) < 0.0f ? 1 : 0;
b2 = sign(sx, sy, x1, y1, x2, y2) < 0.0f ? 1 : 0;
b3 = sign(sx, sy, x2, y2, x0, y0) < 0.0f ? 1 : 0;
if((b1 == b2) && (b2 == b3))
return 1;
return 0;
}
float get_dist(int x1, int y1, int x2, int y2){
int xproj = x2-x1;
int yproj = y2-y1;
float dist = sqrt(pow(xproj, 2) + pow(yproj, 2));
return dist;
}
unsigned char getR(unsigned c){
return (c >> 16) & 0xFF;
}
unsigned char getG(unsigned c){
return (c >> 8) & 0xFF;
}
unsigned char getB(unsigned c){
return c & 0xFF;
}
void draw_ftriangle(SDL_Surface * s, int x0, int y0, unsigned c0, int x1, int y1, unsigned c1, int x2, int y2, unsigned c2){
int x;
signed d0, d1, d2;
unsigned R, G, B, color;
int ymin = min(y0, min(y1, y2));
int xmin = min(x0, min(x1, x2));
int ymax = max(y0, max(y1, y2));
int xmax = max(x0, max(x1, x2));
draw_line(s, x0, y0, x1, y1, color);
draw_line(s, x1, y1, x2, y2, color);
draw_line(s, x0, y0, x2, y2, color);
for(; ymin < ymax; ymin++)
for(x=xmin; x < xmax; x++)
if(ptintr(x, ymin, x0, y0, x1, y1, x2, y2)){
d0 = get_dist(x, ymin, x0, y0);
d1 = get_dist(x, ymin, x1, y1);
d2 = get_dist(x, ymin, x2, y2);
R = d0+d1+d2 == 1 ? getR(c0)*d0 + getR(c1)*d1 + getR(c2)*d2 :
(getR(c0)*d0 + getR(c1)*d1 + getR(c2)*d2)/(d0+d1+d2);
G = d0+d1+d2 == 1 ? getG(c0)*d0 + getG(c1)*d1 + getG(c2)*d2 :
(getG(c0)*d0 + getG(c1)*d1 + getG(c2)*d2)/(d0+d1+d2);
B = d0+d1+d2 == 1 ? getB(c0)*d0 + getB(c1)*d1 + getB(c2)*d2 :
(getB(c0)*d0 + getB(c1)*d1 + getB(c2)*d2)/(d0+d1+d2);
color = RGB(R, G, B);
put_pixel(s, x, ymin, color);
}
}


And I call function draw_ftriangle like this:


draw_ftriangle(surface, 100, 100, RGB(255, 0, 0),
235, 150, RGB(0, 255, 0),
64, 254, RGB(0, 0, 255));


I'm not sure, but I think the problem is here:


R = d0+d1+d2 == 1 ? getR(c0)*d0 + getR(c1)*d1 + getR(c2)*d2 :
(getR(c0)*d0 + getR(c1)*d1 + getR(c2)*d2)/(d0+d1+d2);
G = d0+d1+d2 == 1 ? getG(c0)*d0 + getG(c1)*d1 + getG(c2)*d2 :
(getG(c0)*d0 + getG(c1)*d1 + getG(c2)*d2)/(d0+d1+d2);
B = d0+d1+d2 == 1 ? getB(c0)*d0 + getB(c1)*d1 + getB(c2)*d2 :
(getB(c0)*d0 + getB(c1)*d1 + getB(c2)*d2)/(d0+d1+d2);


Please help me to find a problem! smile.png
Advertisement
I first noticed that your triangle is not interpolating between red, green and blue, but between cyan, magenta en yellow. So somewhere your colors are being "reversed".

Your problem is indeed in the code fragment you have shown below. The interpolation between corner points does not depend linearly on the distance, but the inverse of it. If the distance to your red point (d0) is very small, your "red weight" should be high.

You can have a look at Barycentric coordinates, which seem to most closely match what you are doing.

This topic is closed to new replies.

Advertisement