• Advertisement
Sign in to follow this  

Problem with shaded triangle

This topic is 1930 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

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 Edited by arnsa

Share this post


Link to post
Share on other sites
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. Edited by Ignifex

Share this post


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

  • Advertisement