"Average" blending
Bruce Pascoe

I can't figure out a way to do this using any Allegro's provided blend modes. Is there a set of parameters I can pass to al_set_blender() to average the two pixels, like this?

dest.red   = (dest.red   + src.red)   / 2
dest.green = (dest.green + src.green) / 2;
dest.blue  = (dest.blue  + src.blue)  / 2;

al_set_blend_mode(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE) gives me the addition, but I don't see a way to represent the division by two at the end.

beoran

How about using al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_ONE), and then make sure that both source images have 50% alpha set? Or draw with al_draw_tinted_bitmap with a tint that has 0.5 for all it's values, like is done in this thread: https://www.allegro.cc/forums/thread/612304

Bruce Pascoe

The thing is that I need it to work in the general case, as I am emulating an existing game engine (Sphere). My use case for Allegro is... well, quite a bit broader in scope than the norm. :) It's served me very well so far, but there are a few things like this that trip me up.

The other thing I'm having an issue with: I need some way to set the alpha channel unconditionally to 255 for blended pixels. Can that be done?

RPG Hacker

This could be tough. As far as I know, most (if not all) GPUs only support certain preset blend settings that you can combine to create your blend operation. I don't think there is an average blend setting, so you'll most likely have to do it manually. One thing you could do: render your whole game into a bitmap, then, whenever you need blending, pass this bitmap (let's call it "destination") and your source bitmap to a shader and do all the blending inside the pixel shader. Oh well, maybe it's not that tough after all. In any case, you'll most likely have to use shaders. I don't think there is another efficient way, unless you consider going with the %50 alpha solution.

I need some way to set the alpha channel unconditionally to 255 for blended pixels. Can that be done?

How about just using a bitmap without alpha channel as your target bitmap? Effectively this will just not writ anything to the alpha channel at all. If you access such a texture from a shaders, as far as I know, the alpha channel will always return 1.0.

beoran

Hmm, could you provide a few examples of the desired effects? Inputs and desired output? In the past I've found that Allegro blending is very powerful but not always straightforward. I think what you want could very well be possible, but it's easier to see what you want through examples.

Bruce Pascoe

Okay, well first off, the averaging. That isn't a big deal to me, I don't personally use it but it's something that Sphere supports so I'd have to emulate it for full compatibility. It would be very easy to implement if we had an ALLEGRO_HALF blend op:

al_set_blender(ALLEGRO_ADD, ALLEGRO_HALF, ALLEGRO_HALF);

But sadly, such a thing doesn't exist. :(

The second effect however, is VERY useful, and I personally make use of it in my own Sphere games. Here's the code for Sphere's usual mode of blending:

void Blend3(destT& d, srcT s, int alpha)
{
    d.red   = (s.red   * alpha + d.red   * (255 - alpha)) / 255;
    d.green = (s.green * alpha + d.green * (255 - alpha)) / 255;
    d.blue  = (s.blue  * alpha + d.blue  * (255 - alpha)) / 255;
}

inline void blendRGBA(RGBA& dest, RGBA src)
{
    Blend3(dest, src, src.alpha);
    dest.alpha = 255;
}

This performs traditional alpha blending on the RGB components, but sets any pixels touched to fully opaque. This is useful as it allows you to do stuff like this:

textSurface = new Surface(320, 36, new Color(0, 0, 0, 0));
for (i = 0; i < 3; ++i) {
    font.setColorMask(textColor);
    textSurface.drawText(font, 5, i * 12, textLines[i]);
}

// later on...
textSurface.blit(textbox_x, textbox_y);

When that surface is rendered, only the text is visible and everything else remains transparent. Which in turn allows effects like this:

{"name":"Untitled.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/6\/56129637a2a3df511fc5a2bf70f399c3.png","w":656,"h":519,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/6\/56129637a2a3df511fc5a2bf70f399c3"}Untitled.png

Note the fade-in effect on the end of a line of text. This is done by rendering the text to a transparent surface (which makes the text opaque but leaves the rest transparent), then switching to subtractive blending and drawing a gradient over the line with alpha going from 0 to 255, making the end of the line gradually transition from opaque to invisible. This is a difficult effect to achieve with Allegro at present.

beoran

ALLEGRO_HALF isn't possible directly because such blending functionality doesn't exist directly in OpenGL nor in DirectX. The blending functions are mostly a thin wrapper around glBlendFunc and glBlendEquation or SetRenderState(D3DRS_*BLEND*, ...). The workaround is to make the source bitmap half transparent by filling the alpha channel only with 0.5 alpha. The function al_set_separate_blender() will be useful for that.

As for the fade in effect, I'm experimenting how to do it. But I think it's certainly possible if I'm allowed to modify the text surface and draw the gradient on it.

RPG Hacker

Thinking about this, in case you're going with shaders anyways, you can get this much easier than I described in my previous post. You don't actually even need to render to texture for that. Just set up your blend state as

al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA)

And then, in your pixel shader, just return the unmodified color of a pixel except with the alpha channel set to 0.5. That should already give the desired effect if the blend state is set up correctly and the sprites are drawn in the correct order. Of course you can still render to an RGB bitmap, as described above, to eliminate the the alpha channel in your destination image.

Bruce Pascoe

All these solutions would be great, if I were making a standalone game. Unfortunately, I'm not (well, I AM, but that's a secondary goal)--I'm trying to replicate the blend semantics of an existing general-purpose game engine. So far that has gone more than well (my engine is at v1.4 already :) ), but sometimes little things like this trip me up. Ultimately it's not a big deal, I'm at the point now where minisphere is stable, I'm just trying to fix the areas where it deviates from the original engine. If at the end of the day it turns out what I want is impossible, no harm done.

That said, I found out yesterday that the averaging is quite possible using glBlendFunc set to GL_CONSTANT_COLOR and sent a PR to implement support for it in Allegro:
https://github.com/liballeg/allegro5/pull/15

D3D has similar functionality (D3DBLEND_BLENDFACTOR). So with this, to average src and dest, you would do:

al_set_blender(ALLEGRO_ADD, ALLEGRO_CONSTANT_COLOR, ALLEGRO_CONSTANT_COLOR);
al_set_blend_color(al_map_rgb(128, 128, 128, 255));

Replicating the "set dest alpha to 1.0" behavior still proves impossible however. :( Why aren't Blend Shaders a thing?

edit: Well, I got close to a "set alpha to 255" blender, anyway. It's not perfect, but much better than what I was using. The blend flags I ended up using, for the curious:

al_set_separate_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA,
  ALLEGRO_ADD, ALLEGRO_INVERSE_DEST_COLOR, ALLEGRO_ONE);

beoran

The feature of the pull request is interesting but the pull request itself won' t be acceptable, I'm afraid. Please remove the .gitignore, and add at least one example such as ex_blend_color.c Also does this work on all platforms including the mobile ones as well?

Good to hear you found a useful combination. Cloning an existing engine is hard to do if you want to keep the effects completely identical. I'm glad to hear Allegro has been of use.

Bruce Pascoe

Without the .gitignore, Git wants to commit all the CMake cruft, why is it not acceptable?

I can't possibly test on EVERY platform though, especially not mobile.

beoran

We don't have a gitignore. Please don't use git commit -a :)

Also , you don't have to test yourself, but you'll have to ask others to test this for you. That's where the example program comes in.

Bruce Pascoe

I actually use GitHub for Windows for the most part, only dropping to the shell for complex stuff. And by default it selects everything for each commit, so I have to uncheck them all and then sift through the list for the actual changes. It's quite annoying.

I'm really not much of a commandline person.

I'll see about whipping up an example program.

Thomas Fjellstrom

You can just unstage the git ignore files, and other files that aren't part of your feature.

I actually use GitHub for Windows for the most part, only dropping to the shell for complex stuff. And by default it selects everything for each commit, so I have to uncheck them all and then sift through the list for the actual changes. It's quite annoying.

And that's where the cli is a much better interface ;)

Quote:

I'll see about whipping up an example program.

I think there is an example for the blending already, you could probably add the new mode to that, I think.

Bruce Pascoe

The problem with CLI is that I don't always remember exactly which files I changed, and if "git status" lists hundreds of build files (500+ at my last count), I can't view what changed any more easily than the GUI.

I do wonder if I do gitception (add the .gitignore to .gitignore), can I get the benefit without committing it... Hm. Something to try later.

Thomas Fjellstrom

IIRC you can just remove entire directories at a time with the CLI.

Bruce Pascoe

Okay, I posted a better pull request.
https://github.com/liballeg/allegro5/pull/16

No gitignore. a much more comprehensive implementation (OGL, D3D, software) and entries in ex_blend2 to see it in action. I also summarized the API additions in the PR summary.

Polybios

Maybe I haven't read the thread carefully, but isn't that the reason for using build directories outside your source tree, i. e. out-of-source builds?

beoran

That looks better! I'll try it out on Linux as soon as I can!

Mark Oates

The CLI is better. GitHub for Windows is just silly.

Bruce Pascoe

You clearly haven't seen me with a mouse. :) I can type around 100wpm on a good day, and I'm STILL faster with a mouse than I am on the command line. Plus it helps to see the diffs right in front of me before I pull the trigger on a commit. Viewing diffs in the shell = not fun.

Keep in mind I grew up with MS-DOS so I do know my way around a command prompt. It's just not my preferred interface. ;)

Thomas Fjellstrom

Viewing diffs in the shell = not fun.

I dunno, in my shell I get working scrolling and syntax highlighting/coloring. \o/

Polybios

MS-DOS so I do know my way around a command prompt

If your concept of "command prompt" is based on MS-DOS, then you'd be surprised what you can do with a UNIX shell... not to speak of vim and friends...

Bruce Pascoe

Yeah, don't get me wrong, I won't hesitate to drop to bash (NOT Command Prompt) for complex stuff like merges, cherry-pick, bisect (things which are intrinsically serial)... But for normal day-to-day commit and branch creation I find the GUI superior.

We'll just have to agree to disagree here, I think I've derailed the thread enough (which is ironic since it's my own thread, and also because there's a guy with a Thomas the Tank Engine avatar here :P).

Thomas Fjellstrom

I just have to say I haven't yet used a gui interface to a version control system that actually worked reasonably well day to day. They often assume certain workflows that don't match up with my own, and cause a lot of unnecessary work.

there's a guy with a Thomas the Tank Engine avatar here

Someone put that in a thread a while back and it was so good I had to make it my avatar. :D8-)

RPG Hacker

I just have to say I haven't yet used a gui interface to a version control system that actually worked reasonably well day to day.

Maybe you should give Plastic a try. It's what we use at work and so far it's the best version control system I've worked with, even better than Git (with or without GUI). It's commercial software, though, but I think it's free for private use. In any case, I really prefer that one over any other version control I've used so far.

Thomas Fjellstrom

Is it a gui to an existing VCS? or is it its own thing?

Plastic SCM said:

Teams working on large projects (>300k files) and unmergeable content.

Doesn't unmergable mean something is horribly broken?

RPG Hacker

Is it a gui to an existing VCS? or is it its own thing?

I'm not sure, but I think it's its own thing. At least I don't think it's based on any of the wider known version control systems.

Quote:

Doesn't unmergable mean something is horribly broken?

I'm not sure from where you quoted that, but I'd assume they're refering to binary files here (or something like that). Normally Plastic doesn't have any problems with merging source files and is, in fact, really good at it. A lot better than Git, in fact (at least from my experience so far). That is mostly because it is really good at finding differences between files, much better than Git, and it is better at setting these differences into a correct context. Even when there are merge conflicts, which I rarely had so far, Plastic provides good tools for solving these merge conflicts (that is, a good editor that clearly visualises the conflicts and even makes suggestions on what it thinks the desired merge result). Plastic can even keep track of moved and renamed files, which I don't think Git can. Git just considers these "deleted" in one place and "added" in another place. I have come across a few situations where this was useful. Branches in Plastic also work like a charm, to me, again, a little bit better than in Git, since it's much easier to branch and merge back stuff and more. And it's easy to work on different branches simulatneously with Plastic, I haven't tried this with Git, but I'd assume you'd need to maintain each branch/workspace yourself with Git, whereas in Plastic you only need a single workspace and the client will do everything for you when you need to switch branches. You can even switch back to a certain changeset on a branch with just a click in case you want to test if something worked in an older version that doesn't work anymore. In Git it's usually a bit more evolved to go back to an older commit and test everything on that one.

Basically, to sum it up, I consider Plastic a more convenient alternative to Git. It can do everything Git can, plus a few more things, but thanks to a great GUI everything is a lot more user-friendly, faster and straightforward. And now we're just programmers talking here. Imagine you're working on a team with artists, game designers etc. Artists really aren't the kind of people who can easily work with command-line tools. They'll especially benefit from a nice and easy-to-use GUI version control system. So far, I've never experienced any of the artists here having any problems with Plastic, whereas I remember Git (and even Github for Windows) drive multiple artists (and even programmers) nuts back when we used it for our student project.

Thomas Fjellstrom

I'm not sure from where you quoted that, but I'd assume they're refering to binary files here (or something like that).

They have a separate bullet point for binary files.

I forgot to check, does it have linux support? And does it work with Kdevelop or any other IDE I might choose to use?

RPG Hacker

I forgot to check, does it have linux support?

We're using it on Mac with X11 and it's working perfectly. Didn't test on Linux since we currently have no Linux projects in development, but I'd assume it should work all the same. At least according to the documentation, the client supports Windows, Mac and various Linux distributions.

Quote:

And does it work with Kdevelop or any other IDE I might choose to use?

Can't say anything about that since I never use the direct IDE integration of any version control system. I usually use the Plastic client to commit stuff or update my workspace. The Plastic client is quite fast, though. I think a lot faster than the Github for Windows client, but I have never used that one at work, so I don't know if it's actually slow or only on my computer. In any case, starting Plastic and commiting your changes usually doesn't take too long, so that's why I never really missed any kind of direct IDE integration.

Thread #615475. Printed from Allegro.cc