[A5] how to draw a rectangle filled with a gradient?
axilmar

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

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

Elias

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.

Don Freeman

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

axilmar

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

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?

axilmar

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

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.

SiegeLord

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.

Don Freeman

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

SiegeLord

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);
}

Don Freeman

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.

axilmar

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

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

axilmar

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

Isn't vertex 1 the top-right vertex?

Thread #606569. Printed from Allegro.cc