Allegro 4 and 5 and indexed colors
Shadowblitz16

I am here because I am interested in learning c++ and allegro for a game engine I want to recreate.

this game is called zelda classic and it uses allegro 4 because it is dependent on index colors.

basically all graphics in the game are tiles which use a palette to change colors.
now I know that opengl can use shaders for palette swapping using palette bitmaps. however I not only would like to use data based palettes instead of bitmap based palettes, but be able to import pngs in the future and be able to map the colors using the closest color in the image to the current palette.

does anybody know if allegro 5 can do this? or if allegro 4 is too old to be used?

Edit: I am also using vs 2017 and I don't know if it supports allegro 4

Neil Roy

Allegro 5 doesn't support palettes. It will convert 8bit graphics to the current mode when you load them.

I would suggest either stick to Allegro 4, or change how you code the game. You could for example, create greyscaled tiles where you would then set the colour to draw them at and they would be drawn in shades of that colour.

I've never done this myself though. You're probably better off with Allegro 4 if palettes are really that important for you.

Allegro 4 is not too old (though it is getting there), you can download the source and recompile it using whatever compiler you wish and it should still work.

Niunio

Allegro 5 includes a demonstration about how to load 8bpp indexed bitmaps and use shaders to emulate (or simulate) indexed graphics modes. Take a look to it.

Chris Katko

Yeah, the "proper" way these days is to just use shaders to mimic palettes. (Not that hard.)

True 8-bit support isn't even supported on many videocards and screens anymore and will only continue to fade away. So unless you really NEED actual 8-bit support for a really old machine you're specifically targeting, just mimic it. It's going to be way faster using shaders (and the GPU) than throwing all that away for software mode.

Shadowblitz16

well in zelda classic the tiles and palettes are stored in the quest file which is kinda like the project file.

there would be no external images saved.

my main question is with importing graphics into the tile arrays.
I want to be able to map in to any palette I want as a base.

EDIT: maybe drawing things pixel b pixel would solve this issue?
like for example using color table lookups every time I draw a pixel?

is there a indexed bitmap for this sort of thing?

Niunio

I think that colour table lookups may work for you. But Allegro 5 doesn't have such functionality.

Audric

Shadowblitz16, it's very confusing how you are talking of many subjects, and I have a hard time believing you intend to rewrite Zelda Classic from scratch, as it would be several years of work.
If you don't, then Zelda classic is Allegro 4. It supports indexed images natively. What's the point of these discussions with opengl / scalers / allegro 5 ?
Drawing a sprite with its current palette is automatic (8bit to RGB screen), or in full 8bit mode, you can prepare a color map and use it when you call draw_lit_sprite()

Shadowblitz16

@Niunio
drawing from a array of ints representing the palettes colors shouldn't be too hard although it might not be gpu accelerated.

@Audric
sorry.
I would love to try though even if I don't succeed.
Index color mode I understand why but I don't see why indexed images are not supported in allegro 5 since it would seem they are just a image class modified to use a palette.
I was talking about shaders to ask if it was the best solution for this sort of thing.
I'm not sure I want to use allegro 4 because of how old it is and it seemingly not working with vs 2015.

Edgar Reynaldo

There's already a Zelda Classic port that is pretty much complete. You'd be better off learning from them. It works with allegro 4 as is.

In allegro 5 shaders are pretty much your only option if you want hw accel.

Shadowblitz16

I am actually a part of the dev discord channel even though I am not a dev so I have been discussing it with them.

They wanted to do a complete rewrite in allegro 5 but are not familiarwith shaders and were not sure how to go about doing it.

I can ask if they need gpu acceleration for drawing.

Chris Katko

They wanted to do a complete rewrite in allegro 5 but are not familiarwith shaders and were not sure how to go about doing it.

Just start Googling. Shaders are not magic or evil. They're just little programs. And there are way better articles on the subject than we could whip up in a few minutes for a post.

https://gamedev.stackexchange.com/questions/43294/creating-a-retro-style-palette-swapping-effect-in-opengl

http://kpulv.com/368/Index_Palette_Shader/

https://gamedevelopment.tutsplus.com/tutorials/how-to-use-a-shader-to-dynamically-swap-a-sprites-colors--cms-25129

And Allegro doesn't really change OpenGL. It just runs on top of it as a cross-platform layer.

Shadowblitz16

@Chris Katko
shaders won't work unless I can use some sort of lookup table.
I need to be able to index the bitmaps imported so users can effectively correct them

Chris Katko

Please elaborate on exactly what you want to accomplish, and your requirements. Your comment is too vague.

You want to draw 8-bit bitmaps, and have the colors cycle where appropriate. Right?

Shaders can do that. Shaders can also have lookup tables. You literally just draw the colors of a palette, into (RGB) pixels on the "lookup table bitmap" and then have the 8-bit pixel index, index into that lookup table like an array.

The lookup table would look like this, but one pixel per color (and no borders):

{"name":"rrrgggbb2.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/2\/e2169a6447e0acff0deba6f9be1e28dc.png","w":256,"h":256,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/2\/e2169a6447e0acff0deba6f9be1e28dc"}rrrgggbb2.png

- The shader sees the "desired sprite/bitmap" and reads pixel 0,0 = (say) 13.

- Then the shader reads the lookup table (at x=13, y=0) and send that to the output.

So it's like pseudocode (from memory):

//pixel shaders run for every pixel on screen:
//where u and v are texture coordinates
PIXEL pixel_shader(BITMAP sprite, BITMAP table, int u, int v)
    {
    int index = get_8bb_pixel(sprite, u, v);  //bitmap,x,y

    return getpixel(table, index, 0);  //bitmap,x,y
   //where table 1 high, 256 wide.
    }

// (making sure to not use texture filtering on the table which would blur 0.5 to be half one index, and half the other)

To cycle colors, you simply modify the lookup table every X seconds. (Either specifying another table, or, directly modifying the table.)

Whereas (for comparison) normally it's just:

PIXEL pixel_shader(BITMAP sprite, int u, int v)
    {
    return getpixel(sprite, u, v); 
    }

Shadowblitz16

@Chris Katko sorry I will try to be more clear.
I want my palettes to be a 1d array of ints with no alpha like so..

[code]
int palette[8] =
{
0x000000 // White
0xFF0000 // Red
0x00FF00 // Green
0x0000FF // Blue
0xFFFF00 // Yellow
0x00FFFF // Cyan
0xFF00FF // Magenta
0xFFFFFF // White
}
[/code]

with tile data (aka graphical data) either 2d array of lookup colors like so..
[code]
int tiles[65536][256] =
{
//Tile 0 (white rectangle)
{
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
},
...
}
[/code]

or a list of int array lookup tables like so..
[code]
std::list<int[256]> tileBank;
tileBank.push_back
(
//Tile 0 (white rectangle)
{
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
}
);
[/code]

and then draw them pixel by pixel with either a shader or primitives.

Chris Katko

Yeah, that's exactly what the articles and my code is talking about. The tutorials should work for you.

https://www.gamedev.net/forums/topic/627574-solved-applying-color-palette-to-texture/

Quote:

You can do this with a texture lookup in a shader. Create a bunch of 1d texture containing your palettes. When you're drawing something bind the appropriate palette texture to another texture unit. Do a texture lookup on the greyscale texture to get a 0...1 result, then do a lookup on the palette texture using that result to get the final colour.

You can fine-tune the behaviour by e.g. selecting a GL_NEAREST sampling mode.

That's one way of doing it; there are others, such as loading your palette into an array of uniforms (or using a UBO) and using the greyscale lookup * 255 as an index into that.

Shadowblitz16

but this uses textures as the palette sample.
I would like to use arrays

Neil Roy

By the way, it's;

<code>
// your code here
</code>

Chris Katko

While the texture is probably more appropriate (do you have an actual reason for not wanting to do it the normal way?), as the article(s) mention, you can pass the entire palette as a UNIFORM (an input) to the shaders.

Audric

Shadowblitz16, doing any work pixel by pixel using C code is too slow, video cards are not optimized for it. The algorithm of using an array for lookup is correct, and it used to be doable when game screens had 320*240 pixels, but now screens have 30 times more pixels.
The shader is exactly this idea, transferred to graphic card elements : the piece of code is in a shader, and the array is stored where the shader can access it, ie. a texture.

Edgar Reynaldo
Shadowblitz16

@Chris Katko because I need to store palettes and tiles in the binary quest file.

@Audric well the game wouldn't be larger then the sens resolution, although it might be scaled.

@Edgar Reynaldo whats this? it looks interesting.

Peter Hull

I think we had someone else from ZC posting here a while back (DarkDragon?).

Anyway, as I understand it, for optimum Allegro 5 performance you will indeed take the tiles and palettes from the binary quest file but then make them into Allegro bitmaps/textures (as Chris illustrated) and upload them to the GPU.

If you want palettes just for fading you could maybe look at al_draw_tinted_bitmap or compositing a translucent white or black rectangle over the top.

Alternatively, is quite an old program (>10 years IIRC) and not high resolution, so you might be able to do without acceleration at all, and write your own drawing and palette lookup code. I believe this is feasible because at one time I was looking into porting KQ from Allegro 4. I got acceptable performance even with a very naive implementation of A4's blit and draw_sprite

Hope that helps.

Chris Katko

@Chris Katko because I need to store palettes and tiles in the binary quest file

There is either some form of miscommunication going on, or, you're not experienced enough to be doing this yet.

We have given all the high-level information required to accomplish the task. Where-ever the data is located doesn't matter. If the data is in a file, you rip it out of the file. If the data is in the wrong format, you convert it to the right format. That's all normal programming stuff.

But the UNIFORM method shouldn't be needed. You just need to convert the files into something the shader understands (one color channel / grey textures), and write the shader. Then you just turn on the shader, and draw normally with grey textures, and the shader re-interprets the output. Then when done using pixel-changing colors, you can turn the shader back off.

Thread #617301. Printed from Allegro.cc