Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5] Front-to-back Alpha Blending

This thread is locked; no one can reply to it. rss feed Print
[A5] Front-to-back Alpha Blending
abenthy
Member #12,735
April 2011
avatar

Hello,

for my GUI code its essential that what I draw last gets drawn above everything drawn after it. So I want to reverse the usual painters algorithm.

I tried figuring out how to do this using al_set_blender or al_set_separate_blender, but I failed.

Can someone help me out?

al_set_blender( ? ? ? );
al_draw_filled_rectangle( ... button ... );
al_draw_filled_rectangle( ... label ... );

// I want this to be behind the widgets drawn above.
al_draw_filled_rectangle( ... here comes the frame ... );

Trent Gamblin
Member #261
April 2000
avatar

Draw them in the order you want, simple as that. Blending won't help. When you draw something, OpenGL/DX renders pixels to a frame buffer. There is only one framebuffer so once those pixels are there, anything you draw goes on top of them.

Arthur Kalliokoski
Second in Command
February 2005
avatar

If you were using OpenGL you could set an orthogonal perspective and use the depth buffer along with 3d vertices, incrementing the Z value a bit for everything you drew.

“Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”

― Robert A. Heinlein

Edgar Reynaldo
Member #8,592
May 2007
avatar

abenthy said:

for my GUI code its essential that what I draw last gets drawn above everything drawn after it.

This does not make sense - there can't be anything drawn after the last one gets drawn by definition of the term 'last'. Like Trent said, draw from the bottom up. There's no other way to do it.

Elias
Member #358
May 2000

Besides the depth buffer as Arthur said, you could also use the stencil buffer.

--
"Either help out or stop whining" - Evert

jmasterx
Member #11,410
October 2009

Why not just draw them recursively, I simply do:
baseContainer->paintChildren();

and then the whole gui is painted!

#SelectExpand
1void AguiWidget::paintChildren(const AguiPaintEventArgs &paintargs ) 2{ 3 stackOffset = paintargs.graphics()->getOffset(); 4 stackRects = paintargs.graphics()->getClippingStack(); 5 recursiveDrawChildren(this,isEnabled(),paintargs.graphics()); 6 paintargs.graphics()->setClippingStack(stackRects,stackOffset); 7} 8 9void AguiWidget::recursiveDrawChildren( AguiWidget *root, bool enabled, 10 AguiGraphicsManager *graphicsContext ) 11{ 12 //recursively calls itself to render widgets from back to front 13 14 if(!root->isVisible()) 15 { 16 return; 17 } 18 19 bool widgetEnabled = root->isEnabled(); 20 21 if(enabled == false) 22 { 23 widgetEnabled = false; 24 } 25 26 if(root != this) 27 { 28 root->clip(AguiPaintEventArgs(enabled,graphicsContext)); 29 30 root->paint(AguiPaintEventArgs(enabled,graphicsContext)); 31 32 if(root->isPaintingChildren()) 33 { 34 return; 35 } 36 } 37 38 for(std::vector<AguiWidget*>::iterator it = 39 root->getPrivateChildBegin(); 40 it != root->getPrivateChildEnd(); ++it) 41 { 42 recursiveDrawChildren(*it,widgetEnabled,graphicsContext); 43 } 44 for(std::vector<AguiWidget*>::iterator it = 45 root->getChildBegin(); 46 it != root->getChildEnd(); ++it) 47 { 48 recursiveDrawChildren(*it,widgetEnabled,graphicsContext); 49 } 50 51}

abenthy
Member #12,735
April 2011
avatar

Thanks for your answers so far, really! I read them all carefully.
But I probably described very badly what I want to do, so to give you some details:

  • I'm coding an Immediate Mode GUI (like the one in Unity3D, this means no retainted state in a class hierarchy), this is a complicated/new subject to most GUI programmers. Here is a cool tutorial:

Sol IMGui Tutorial

  • My problem with the implementation is quite good explained here:

Molly Rocket Immediate Mode GUI Forums

  • The problem is that I can only draw the frame background image after the buttons/labels inside of it are drawn.

  • Take a look at this example code, to see how it works:

gui.begin_frame(); // We do not yet know how big the frame will have to be.
// We also do not know if it's active, because one of the buttons/labels
// could become active, but we do not know about them yet.

gui.label("MyLabel");
if(gui.button("MyButton")) {
   printf("The button was pressed!\n");
}

// Now that we _do_ know about the widgets in the frame, we could draw the frame.
// but this place doesn't really fit the rendering order.
gui.end_frame();

  • I do know that there are other solutions to this (buffer images, render queues). Anyway, I would like to know if there is a way to draw the frame right by just using blending in A5. Like sean from Molly Rocket points out:

Quote:

4. Process widgets front-to-back and draw with the crazy front-to-back blend mode that still lets you use alpha values for anti-aliased edges.

Trent Gamblin
Member #261
April 2000
avatar

Destination alpha is a possibility but I don't think that is very well supported by video cards. Especially for the framebuffer itself... I don't know about using a buffer with destination alpha though it seems clear you don't want to do that.

Go to: