Allegro 5... no al_draw_gouraud_bitmap() function?
Chris Katko

A4:

void draw_gouraud_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4);

Quote:

More sophisticated version of draw_lit_sprite(): the 'color' parameter is not constant across the sprite image anymore but interpolated between the four specified corner colors, which have the same actual meaning as it.
See also: draw_sprite, draw_lit_sprite, color_map, set_trans_blender, bitmap_mask_color.

A5:

???

It seems like a natural way to do smoothly lit, tiled maps.

Right now I'm kind of stuck with block level lighting.

{"name":"609371","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/c\/4cdbb2469c2b34156bdc4c0d9a09f85a.png","w":479,"h":476,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/c\/4cdbb2469c2b34156bdc4c0d9a09f85a"}609371

Is this a depreciated way of doing things? Should I be spamming transparent polygons to the GPU instead?

SiegeLord

You can do something like this relatively easily:

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_primitives.h> 3#include <allegro5/allegro_image.h> 4 5void draw_gouraud(ALLEGRO_BITMAP* bmp, float x, float y, ALLEGRO_COLOR tl, ALLEGRO_COLOR tr, ALLEGRO_COLOR bl, ALLEGRO_COLOR br) 6{ 7 ALLEGRO_VERTEX vtx[4]; 8 float w = al_get_bitmap_width(bmp); 9 float h = al_get_bitmap_height(bmp); 10 11 vtx[0].x = x; 12 vtx[0].y = y; 13 vtx[0].z = 0; 14 vtx[0].color = tl; 15 vtx[0].u = 0; 16 vtx[0].v = 0; 17 18 vtx[1].x = x + w; 19 vtx[1].y = y; 20 vtx[1].z = 0; 21 vtx[1].color = tr; 22 vtx[1].u = w; 23 vtx[1].v = 0; 24 25 vtx[2].x = x + w; 26 vtx[2].y = y + h; 27 vtx[2].z = 0; 28 vtx[2].color = br; 29 vtx[2].u = w; 30 vtx[2].v = h; 31 32 vtx[3].x = x; 33 vtx[3].y = y + h; 34 vtx[3].z = 0; 35 vtx[3].color = bl; 36 vtx[3].u = 0; 37 vtx[3].v = h; 38 39 al_draw_prim(vtx, NULL, bmp, 0, 4, ALLEGRO_PRIM_TRIANGLE_FAN); 40} 41 42int main(int argc, char** argv) 43{ 44 al_init(); 45 al_init_primitives_addon(); 46 al_init_image_addon(); 47 ALLEGRO_DISPLAY* d = al_create_display(800, 600); 48 49 al_clear_to_color(al_map_rgb_f(0, 0, 0)); 50 draw_gouraud(al_load_bitmap(argv[1]), 0, 0, al_map_rgb_f(1, 1, 1), al_map_rgb_f(1, 1, 0), al_map_rgb_f(1, 1, 1), al_map_rgb_f(1, 0, 1)); 51 al_flip_display(); 52 53 al_rest(5); 54}

It'll have some artifacts due to using triangles, but it might be okay for lighting. To avoid the artifacts, you could use more triangles (e.g. add a vertex in the center of the bitmap) or a shader.

Chris Katko

You wonderful genius! I don't have it working perfect yet but that looks great.

[edit]

{"name":"609372","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/2\/024e2eab472b7b96dd2374e9d4e4fdbd.png","w":496,"h":462,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/2\/024e2eab472b7b96dd2374e9d4e4fdbd"}609372

Looks better! Though it's still looks segmented. I'm not sure if that's from my distance calculations, or this function doing that.

SiegeLord said:

(e.g. add a vertex in the center of the bitmap) or a shader.

Not a bad idea.

Thomas Fjellstrom

I dunno, I don't hate the block level lighting. It fits in with it being a block based map.

SiegeLord

Looks better! Though it's still looks segmented. I'm not sure if that's from my distance calculations, or this function doing that.

Try also turning off the texture (by passing NULL to al_draw_prim). It's easier to see what the actual lighting artifacts look like then.

Chris Katko

In case anyone is interested:

#SelectExpand
1//not sure what to call it, but we add a midpoint 2void al_draw_gouraud_bitmap_2x(ALLEGRO_BITMAP* bmp, float x, float y, ALLEGRO_COLOR tl, ALLEGRO_COLOR tr, ALLEGRO_COLOR bl, ALLEGRO_COLOR br, ALLEGRO_COLOR mid) 3 { 4 ALLEGRO_VERTEX vtx[6]; 5 float w = al_get_bitmap_width(bmp); 6 float h = al_get_bitmap_height(bmp); 7 8 9//center 10 vtx[0].x = x + w/2; 11 vtx[0].y = y + h/2; 12 vtx[0].z = 0; 13 vtx[0].color = mid; 14 vtx[0].u = w/2; 15 vtx[0].v = h/2; 16 17 vtx[1].x = x; 18 vtx[1].y = y; 19 vtx[1].z = 0; 20 vtx[1].color = tl; 21 vtx[1].u = 0; 22 vtx[1].v = 0; 23 24 vtx[2].x = x + w; 25 vtx[2].y = y; 26 vtx[2].z = 0; 27 vtx[2].color = tr; 28 vtx[2].u = w; 29 vtx[2].v = 0; 30 31 vtx[3].x = x + w; 32 vtx[3].y = y + h; 33 vtx[3].z = 0; 34 vtx[3].color = br; 35 vtx[3].u = w; 36 vtx[3].v = h; 37 38 vtx[4].x = x; 39 vtx[4].y = y + h; 40 vtx[4].z = 0; 41 vtx[4].color = bl; 42 vtx[4].u = 0; 43 vtx[4].v = h; 44 45 vtx[5].x = vtx[1].x; //end where we started. 46 vtx[5].y = vtx[1].y; 47 vtx[5].z = vtx[1].z; 48 vtx[5].color = vtx[1].color; 49 vtx[5].u = vtx[1].u; 50 vtx[5].v = vtx[1].v; 51 52 al_draw_prim(vtx, NULL, bmp, 0, 6, ALLEGRO_PRIM_TRIANGLE_FAN); 53}

{"name":"609373","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/9\/d98ee67c88783d69bfd7296ad0e1b1c9.png","w":802,"h":625,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/9\/d98ee67c88783d69bfd7296ad0e1b1c9"}609373

I'm not running my ray caster at the moment, so this is purely distance based.

[edit]

Oh, and I noticed a bug from when I came over from A4. I was using 16x16 map size, but my tiles were 32x32, so when I stopped using blit and used the A5 routines, they all drew the whole thing, which overlapped. The overlap was mostly invisible (except at the borders) but when I turned on alpha blending, things really exploded.

Now dividing the maximum alpha by the number of lights (in my case two for testing) makes multiple light sources work with a rendering pass per light.

Probably a better way to do it with colored triangles, but I'll get to that later.

{"name":"609374","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/b\/9\/b91fe5cf5896ed297d1896aa146d0b40.png","w":802,"h":625,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/b\/9\/b91fe5cf5896ed297d1896aa146d0b40"}609374

SiegeLord

Your mid-color calculation seems a bit odd, as I definitely see some pyramidal structures inside the individual tiles.

The overlap was mostly invisible (except at the borders) but when I turned on alpha blending, things really exploded.

Is this overlap due to an issue with your code, or are you drawing everything at ingeger coordinates?

Chris Katko
SiegeLord said:

Is this overlap due to an issue with your code,

Originally I was using blit (Allegro 4) with an explicit width and height and then switched to al_draw_bitmap which does not. They're still integer coordinates, so everything needs a + 0.5f I guess. But that is/was a minor issue compared to the other bugs I've been fixing today/yesterday.

Quote:

Your mid-color calculation seems a bit odd, as I definitely see some pyramidal structures inside the individual tiles.

Hhmm, that's possible. I made the midpoint addition because of that pyramidal issue. It seemed to make it better (see previous post, first image vs second) but I guess it's still there.

My color function was thrown together quickly as the relevant systems are still being built.

#SelectExpand
1//globals until we have a light system 2//<------- 3int LIGHT_X = 0; 4int LIGHT_Y = 0; 5//... 6 7//WARN, using global LIGHT_X/Y 8//NOTE, we're using FLOATS so we can have sub-tile coordinates like 9//giving i_tile=1.5, j_tile=1.5 for the CENTER COORDINATES of a tile. 10ALLEGRO_COLOR build_color(float i_tile, float j_tile) 11 { 12 ALLEGRO_COLOR temp; 13 14 float x = LIGHT_X - i_tile*TILE_WIDTH; 15 float y = LIGHT_Y - j_tile*TILE_HEIGHT; 16 float d = sqrt(x*x+y*y); 17 if(d < 0)d=0; 18 if(d > 255)d=255; 19 d = 255-d; //reverse 20 21 return al_map_rgba(d,d,d,128); //NOTE hardcoded alpha 22 }

[edit] ahh crap.

//... in tile drawing code
ALLEGRO_COLOR c1 = build_color(i  ,j  ); //tl
ALLEGRO_COLOR c2 = build_color(i+1,j  ); //tr
ALLEGRO_COLOR c3 = build_color(i  ,j+1); //bl
ALLEGRO_COLOR c4 = build_color(i+1,j+1); //br
ALLEGRO_COLOR c5 = build_color(i+0.5,j+0.1); //mid
al_draw_gouraud_bitmap_2x(source, TILE_WIDTH*i - offset_x, TILE_HEIGHT*j - offset_y, c1, c2, c3, c4, c5);

+0.5, plus... 0.1. Oops!

How about now?

{"name":"609375","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/6\/96cf3e38396ccadcfe12b726dde67e6a.png","w":802,"h":625,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/6\/96cf3e38396ccadcfe12b726dde67e6a"}609375

SiegeLord

They're still integer coordinates, so everything needs a + 0.5f I guess.

No, shouldn't need that. If everything is flush on your end, everything should be flush on Allegro's end too, especially if you don't enable linear filtering.

Occasionally people report this issue, but I've never been able to reproduce it with my tile-drawing code...

Quote:

How about now?

Oooooh yeah! 8-)

Chris Katko

It's getting late here and I probably won't even be using this function for this game later (shadow casting coming up next), but I want to solve this problem should I need it for the future project:

I want to have a brightness gradient mapping function. That is, I want to say "I want a maximum radius of 50, or 300" and it'll ramp the number down faster, or slower to accomplish that. Right now, my code seems to work between 0 and 255 (though small values look crude, they still work). Above that radius though, the mapping function seems to never hit 0. The background far away will still be showing once the light ramps down, with higher values for radius further above 255.

#SelectExpand
1// WORKS for Radius 0 - 255 2// BUG LEAVES EXTRA (does not hit zero alpha) for radius > 255 3ALLEGRO_COLOR build_color2(float i_tile, float j_tile, float radius) 4 { 5 6 ALLEGRO_COLOR temp; 7 8 float x = LIGHT_X - i_tile*TILE_WIDTH; 9 float y = LIGHT_Y - j_tile*TILE_HEIGHT; 10 float d = sqrt(x*x+y*y); 11 float output; 12 13 if(d < 0)d=0; 14 if(d > 255)d=255; 15 const int MAX = 255; 16 17 //does this make sense? We going to zero at large distances? 18 output = MAX - d*(MAX/radius); //ramp down faster for smaller radius 19 if(output < 0)output=0; 20 if(output > 255)output = 255; 21 22 return al_map_rgba(output,output,output,128); 23 }

[edit] DOH, I need to go to bed. Of course it can't see above 255 because d is capped at 255 from the old version of the function.

SiegeLord said:

especially if you don't enable linear filtering.

Is that opposed to cubic filtering? When and what would this be used, in the case I need it? For zooming in/out of my map?

SiegeLord

Is that opposed to cubic filtering? When and what would this be used, in the case I need it? For zooming in/out of my map?

As opposed to no filtering at all, aka nearest filtering (which is the Allegro default). Linear filtering is typically useful for zooming in/out and for rotating bitmaps (check out the ex_filter example for a comparison).

Thread #615262. Printed from Allegro.cc