Alpha blending - how should it work for terrain?

Started by namida, January 26, 2016, 09:03:47 AM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

namida

So - for a while, the graphic set format (and associated tool) have supported alpha blending, but as of yet, there's no support in NeoLemmix itself for blending. Although some of this is due to laziness, part of it is due to not being sure exactly how this should be handled in regards to terrain (objects are a much simpler matter).

Some discussion on IRC has occurred, in the contexts of both NeoLemmix and Lix, regarding this subject:
Quote<geoo> SimonN: do you actually support semi-transparent graphics right now?
<SimonN> geoo: not in the mask in any way
<SimonN> eventually, I want to beef up terrain tiles on loading, mask in RAM, graphic in VRAM. That makes them faster to draw (currently must get crap back out of VRAM)
<SimonN> when I make that, maybe instead of mask of bool, it can be mask of unsigned byte
<SimonN> and store alpha
<namida42> alpha blending is something i want to support eventually too, but i'm very undecided on how it should work in terms of solidity
<geoo> well the logical mask should be bool, but for drawing alpha can be convenient. Especially for objects it'd get rid of antialiasing issues
<namida42> graphic set format (although that's to be replaced eventually anyway) has supported storing alpha data since the current format was introduced, the graphic set tool also supports loading / saving images with alpha data, but currently NeoLemmix itself does not support anything other than 0 or 255
<SimonN> do you still want the threshold, where the alpha is combined in some ways I forgot, and only afterwards soliditiy is decided?
<geoo> Generate the level bitmap, and anything that has alpha < 0x80 (say) gets turned to alpha = 0 and non-solid, to ensure it's easy to distinguish between solid and non-solid
<geoo> Well I think it's important that there is no ambiguity between what's solid and what isn't
<geoo> but alpha blending is useful for making stuff look nice, and graphic set designers don't have to worry about what color to alias against
<namida42> indeed. this is something i've found to be a problem in designing all graphic sets since RGB color support was implemented; antialiasing against black works well in most cases.... until overlap between pieces occurs
<namida42> this really is something i should sort out before designing any more graphic sets, i think
<SimonN> geoo: do you know by rote how alpha combines on additive blit?
<SimonN> not additive, overwriting
<SimonN> and what properties it has etc.
<geoo> not sure, intuitively I'd say something like  alpha * [new pixel] + (1-alpha) * [pixel drawn onto]
<namida42> i believe that's used for simple, quick drawing; i believe there's a more complex algorithm used for nicer results
<SimonN> divided by some normalization depending on the alphas, yeah
<SimonN> the problem eventually is to decide anyway whether this should be used or not for solid
<SimonN> I'd very much like to crop all almost-transparent pixels and make them fully transp
<namida42> my initial thought would be to blend the terrain layout normally, then determine based on the overall output what is or isn't solid. perhaps (i would most likely make this a user option) erase any pixels altogether if they're below the cutoff threshold, to avoid confusion
<geoo> yeah, that's what I suggested

Any further input on this? I'm working on rewriting the level rendering code anyway, as the current code is a total mess (and one thing that I figure needs to be done sooner or later is having seperate maps for display and physics - certianly essential to handling alpha blending well, and probably a good idea in general), so now is a good time to decide how to go about this.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

namida

Alright, so I've started on the easy part of this, which is actually rendering the level with blending. So far, the new renderer only draws terrain, but it already supports alpha blending (although I haven't properly tested blending erasers yet). Some major setbacks with the blending not working properly for No Overwrite pieces, but got that fixed now.

I slightly modified the Dirt graphic set, by applying a radius 1 Gaussian Blur to all the grass / moss / hanging stick pieces. Here's the resulting renderings of a few Orig levels, from the current renderer (which treats any nonzero alpha value as being fully opaque) and the new one (which supports alpha blending).

Note: Please don't expect to see the new renderer in a release any time soon. It's probably going to take quite a while to get it fully working; for example, it can neither render the physics map (only the visual one) nor render objects at all yet - this is why no objects, only terrain, is shown in the new renderer shots.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

Simon

Thanks for making the thread!

According to Wikipedia on alpha compositing: Let αbottom be the alpha component of the target image (real number between 0 and 1 inclusive, with 0 = fully transparent, 1 = fully opaque). Let αtop be the image that's blitted on top the bottom image.

Then, rule of alpha composition: αresult = αtop + αbottom (1 − αtop).

Corollary: We have both αresult ≥ αtop and αresult ≥ αbottom. So, when we stack images, the opaqueness per pixel may only increase.

Air/solid threshold: This is a rule to determine which pixels are solid, and which are air. Fix a threshold value. Whenever a pixel has opaqueness under that value, we make that pixel fully transparent instead. Otherwise, we leave it alone. The fully transparent pixels become air, all others become solid.

The corollary guarantees that, with the air/solid threshold, we can't punch holes into terrain by adding more pieces. (We would have to use eraser pieces.) This is very desirable, level designers can't screw up mistakenly by adding decoration.

A problem arises when the bottom tile is steel, and the top tile is normal terrain. The rule in NL and Lix has been: It's steel iff it looks like steel. This has worked for α = 0, 1 only. Anything here needs study of the full formula for colors in dependence of the alphas, not only for the alphas themselves.

-- Simon

namida

Wow, I hadn't even thought about how it might apply to steel (and for that matter, one-way walls) yet. That is indeed another problem that needs to be considered.

Perhaps one approach is to (during rendering) use a "maybe steel" option, for semi-transparent pixels that come from a steel piece (or steel pixels overwritten by a semitransparent pixel from a non-steel piece).  Then, if the pixel is solid and adjacent to one that is steel, it's also treated as steel; if not, it becomes non-steel. This probably needs further working, but it's a starting point.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

namida

#4
So, NeoLemmix has partially supported alpha blending for terrain for a while. But the current implementation is far from ideal, with the result being that using alpha blending on terrain - even ignoring the lack of editor support - is not practical (on the other hand, it is practical for objects, as the visual appearance of them has no impact on physics and the poor editor support is only a very minor annoyance rather than a huge handicap). Indeed - I originally designed much of LPVI's terrain with alpha blending, but when it became clear NL's support for it on terrain was not good, I ditched it (on the other hand, the objects still do use alpha blending).

The current implementation, when loading a terrain piece, generates a physics image for it - any pixel with an alpha value of less than 128 is non-solid. When rendering the visual map, the image is used as-is (ie: including alpha < 128 pixels), but any pixels that are non-solid according to the physics map are subsequently erased. This means that, if one pixel were to have several semi-transparent pixels overlaid on it, such that the combined alpha is >= 128, it would still be treated as non-solid (and thus erased). Much the same also happens with steel or one-way pixels. Essentially, the physics map - from the very point of loading the terrain - is completely blind to alpha < 128 pixels, even if after blending they'd result in a pixel with alpha >= 128.

I've now written code that averts this, and generates the physics map based on the post-blending image. It's got some pretty creative stuff going on to handle steel and one-way walls correctly - and I am personally 100% satisfied with how it handles them, at least based on my testing so far. It's hard to explain it, but essentially, it's pretty much that "steel" and "one-way" are treated as color channels would be in a traditional image, with "solidity" being treated as the alpha channel - and the level's terrain layout is drawn as this kind of "image". Then, any pixel with "solidity" >= 128 is solid; and any pixel where the steel or one-way channels respectively are at least half the alpha value (this sounds weird when I write it, but it's what gives the correct result) become steel or one-way, with steel having priority if this is true for both channels (akin to the current non-blended case, where steel also has priority over one-way if both occur on the same pixel).

The only case that's iffy is when Simple Autosteel comes into play - and that's a very rarely used setting these days (to the point where the editor doesn't even support it). When Simple Autosteel is in effect, any solid pixel that's ever had a pixel of steel drawn to it, will be steel, unless it's subsequently been completely erased. Honestly, the best rule here is - don't use Simple Autosteel.

One suggestion I recall hearing mentioned, was that any pixel that's solid should then be made fully opaque. I disagree here - any opacity high enough to be treated as solid is still pretty visible.

This is in the feature/improved-terrain-alpha branch.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)