Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5] how to draw a rectangle filled with a gradient?

Credits go to Don Freeman, Elias, Neil Walker, SiegeLord, and Thomas Fjellstrom for helping out!
This thread is locked; no one can reply to it. rss feed Print
[A5] how to draw a rectangle filled with a gradient?
axilmar
Member #1,204
April 2001

How can I draw a rectangle filled with a horizontal or vertical gradient with Allegro 5?

With Allegro 4, I could draw a rectangular gradient using the polygon drawing routines.

Thomas Fjellstrom
Member #476
June 2000
avatar

I'm not sure if its the only way, but try using the primitive addon. particularly al_draw_prim.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Elias
Member #358
May 2000

There is no specific function for it, but al_draw_prim should be able to do it (untested):

void draw_vertical_gradient_rect(float x, y, w, h, ALLEGRO_COLOR top, bottom) {
    ALLEGRO_VERTEX v[] = {
        {.x = x, .y = y, .z = 0, .color = top},
        {.x = x + w, .y = y, .z = 0, .color = top},
        {.x = x, .y = y + h, .z = 0, .color = bottom},
        {.x = x + w, .y = y + h, .z = 0, .color = bottom}};
    al_draw_prim(v, NULL, NULL, 0, 4, ALLEGRO_PRIM_TRIANGLE_STRIP);
}

Some of the examples also demonstrate it I think.

--
"Either help out or stop whining" - Evert

Don Freeman
Member #5,110
October 2004
avatar

This is how I've been doing it, but I think that Elias' idea is more elegant. ;)

#SelectExpand
1/////////////////////////////////////////////////////////////////////////////// 2void DrawRoundedGradientRect( float x1, float y1, float x2, float y2, 3 ALLEGRO_COLOR c1, ALLEGRO_COLOR c2 ) 4{ 5 /////////////////////////////////////////////////////////////////////////// 6 // w and h should be AT LEAST a 4 to display correctly. 7 /////////////////////////////////////////////////////////////////////////// 8 int i; 9 float h2; 10 h2 = (y2 - y1); 11 x1+=0.5; 12 y1+=0.5; 13 x2-=0.5; 14 y2-=0.5; 15 UChar r[2], g[2], b[2]; 16 al_unmap_rgb(c1,&r[0],&g[0],&b[0]); 17 al_unmap_rgb(c2,&r[1],&g[1],&b[1]); 18 float dr = ((r[1] - r[0])%255)/h2; 19 float dg = ((g[1] - g[0])%255)/h2; 20 float db = ((b[1] - b[0])%255)/h2; 21 int xOffset = 0; 22 for (i=y1; i<y2; i+=1) 23 { 24 if ( i == y1 || i == y2 ) 25 xOffset = 2; 26 if ( i == (y1+1) || i == (y2-1) ) 27 xOffset = 1; 28 al_draw_line(x1+xOffset,i,x2-xOffset,i,al_map_rgb(r[0]+=dr, 29 g[0]+=dg,b[0]+=db),1); 30 } 31} 32///////////////////////////////////////////////////////////////////////////////

Needs to be fixed up, and strange colors can happen still if the color range is less than the height of the rect. But, I leave that up to you to fix if you wish to use it...

Changed it to use Elias' code...

void DrawRoundedGradientRect( float x1, float y1, float x2, float y2,
                ALLEGRO_COLOR c1, ALLEGRO_COLOR c2)
{
    ALLEGRO_VERTEX v[] =
  {
        { x1, y1, 0, 0, 0, c1},
        { x2, y1, 0, 0, 0, c1},
        { x1, y2, 0, 0, 0, c2},
        { x2, y2, 0, 0, 0, c2}
  };
    al_draw_prim(v, NULL, NULL, 0, 4, ALLEGRO_PRIM_TRIANGLE_STRIP);
}
///////////////////////////////////////////////////////////////////////////////

Same results. I like it much better though. ;D

--
"Everyone tells me I should forget about you, you don’t deserve me. They’re right, you don’t deserve me, but I deserve you."
"It’s so simple to be wise. Just think of something stupid to say and then don’t say it."

axilmar
Member #1,204
April 2001

I have coded this function:

#SelectExpand
1void algui_fill_rect_gradient( 2 int left, int top, int right, int bottom, 3 ALLEGRO_COLOR top_left, ALLEGRO_COLOR top_right, ALLEGRO_COLOR bottom_right, ALLEGRO_COLOR bottom_left) 4{ 5 ALLEGRO_VERTEX v[4]; 6 7 /* setup the top-left vertex */ 8 v[0].x = left; 9 v[0].y = top; 10 v[0].z = 0; 11 v[0].color = top_left; 12 13 /* setup the top-right vertex */ 14 v[1].x = left; 15 v[1].y = right + 0.6f; 16 v[1].z = 0; 17 v[1].color = top_right; 18 19 /* setup the bottom-left vertex */ 20 v[2].x = left; 21 v[2].y = bottom + 0.6f; 22 v[2].z = 0; 23 v[2].color = bottom_left; 24 25 /* setup the bottom-right vertex */ 26 v[3].x = right + 0.6f; 27 v[3].y = bottom + 0.6f; 28 v[3].z = 0; 29 v[3].color = bottom_right; 30 31 /* draw the shape */ 32 al_draw_prim(v, NULL, NULL, 0, 4, ALLEGRO_PRIM_TRIANGLE_STRIP);

I am using the above function like this:

    algui_fill_rect_gradient(20, 10, 59, 49, 
        al_map_rgb(255, 255, 255), al_map_rgb(255, 255, 255), al_map_rgb(255, 255, 255), al_map_rgb(255, 255, 255));

However, the result is not a rectangle, it is a triangle:

{"name":"Cafji.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/d\/cd0815d114a3329b5d4c2a0be07d5294.png","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/d\/cd0815d114a3329b5d4c2a0be07d5294"}Cafji.png

What am I doing wrong?

Neil Walker
Member #210
April 2000
avatar

if you change your background to a different colour do you get a black and a white triangle or just the white triange? I know nothing of the prim functions but I'm guessing it's just flipping between black and white based on your gradiant being the same colour for all corners?

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

axilmar
Member #1,204
April 2001

if you change your background to a different colour do you get a black and a white triangle or just the white triange? I know nothing of the prim functions but I'm guessing it's just flipping between black and white based on your gradiant being the same colour for all corners?

I don't think so. For example, if I change the background to gray:

{"name":"Dcb8r.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/e\/8eafc3d309cc02702905ef36d8051a45.png","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/e\/8eafc3d309cc02702905ef36d8051a45"}Dcb8r.png

Don Freeman
Member #5,110
October 2004
avatar

One thing I noticed, instead of ending at the last point, you are moving beyond it:

/* setup the bottom-right vertex */
v[3].x = right + 0.6f;
v[3].y = bottom + 0.6f;

These should probably be just right or left+right, and bottom or top+bottom. I don't understand wtf the 0.6 is for, but that's not right. I think your other problem is the order you put your vertices...it's a triangle strip, so you should have:

#SelectExpand
1/* setup the top-left vertex */ 2 v[0].x = left; 3 v[0].y = top; 4 v[0].z = 0; 5 v[0].color = top_left; 6 7 /* setup the top-right vertex */ 8 v[1].x = left; 9 v[1].y = right + 0.6f; 10 v[1].z = 0; 11 v[1].color = top_right; 12 13 /* setup the bottom-right vertex */ 14 v[2].x = right + 0.6f; 15 v[2].y = bottom + 0.6f; 16 v[2].z = 0; 17 v[2].color = bottom_right; 18 19 /* setup the bottom-left vertex */ 20 v[3].x = left; 21 v[3].y = bottom + 0.6f; 22 v[3].z = 0; 23 v[3].color = bottom_left;

And the output you had was solid white with no gradient because that is what you passed to the function, but I'm sure you knew that one.

--
"Everyone tells me I should forget about you, you don’t deserve me. They’re right, you don’t deserve me, but I deserve you."
"It’s so simple to be wise. Just think of something stupid to say and then don’t say it."

SiegeLord
Member #7,827
October 2006
avatar

Your point coordinates are probably wrong. E.g this:

v[1].x = left;
v[1].y = right + 0.6f;

And what's with the 0.6?

EDIT: Pretty sure the order of his points is fine. For triangle fans you go clockwise, for triangle strips you zig-zag.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Don Freeman
Member #5,110
October 2004
avatar

But seriously, the code you needed was posted by me here at the bottom, all you had to do was add two more color parameters to the function... ::):-X

SiegeLord:
Works for me, and not him...so I'd say it's the vertice order. Especially considering that is the portion that is missing. :P

--
"Everyone tells me I should forget about you, you don’t deserve me. They’re right, you don’t deserve me, but I deserve you."
"It’s so simple to be wise. Just think of something stupid to say and then don’t say it."

SiegeLord
Member #7,827
October 2006
avatar

Except the order in your first post is the same as in axilmar's post ;):

void DrawRoundedGradientRect( float x1, float y1, float x2, float y2,
                ALLEGRO_COLOR c1, ALLEGRO_COLOR c2)
{
    ALLEGRO_VERTEX v[] =
  {
        { x1, y1, 0, 0, 0, c1}, //top left
        { x2, y1, 0, 0, 0, c1}, //top right
        { x1, y2, 0, 0, 0, c2}, //bottom left
        { x2, y2, 0, 0, 0, c2}  //bottom right
  };
    al_draw_prim(v, NULL, NULL, 0, 4, ALLEGRO_PRIM_TRIANGLE_STRIP);
}

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Don Freeman
Member #5,110
October 2004
avatar

By GOD it is isn't it...my eyes are not what they used to be l0l! ;) Why label these top and bottom and not just x2, y2 like everyone else...

/* setup the top-left vertex */
 13    /* setup the top-right vertex */
 14    v[1].x = left;
 15    v[1].y = right + 0.6f;
 16    v[1].z = 0;
 17    v[1].color = top_right;

Oh....but we both didn't see this at first so :P Look at lines 14 and 15...I'm pretty sure that v[1].y is suppose to be v[1].y = top+0.6f. Well, that and the color value would be wrong at least going by the variable's label.

--
"Everyone tells me I should forget about you, you don’t deserve me. They’re right, you don’t deserve me, but I deserve you."
"It’s so simple to be wise. Just think of something stupid to say and then don’t say it."

axilmar
Member #1,204
April 2001

Actually, I goofed at this line:

v[1].x = left;
v[1].y = right + 0.6f;

It's two hours that I am viewing this code, and I couldn't parse it correctly. Sorry :-).

Don Freeman
Member #5,110
October 2004
avatar

Don't forget to correct the color line there as well...see my post above.

--
"Everyone tells me I should forget about you, you don’t deserve me. They’re right, you don’t deserve me, but I deserve you."
"It’s so simple to be wise. Just think of something stupid to say and then don’t say it."

axilmar
Member #1,204
April 2001

Don't forget to correct the color line there as well...see my post above.

Isn't vertex 1 the top-right vertex?

Go to: