PDA

View Full Version : Alpha Blending and Sorting - 2D



AGlass0fMilk
03-23-2011, 03:03 PM
I am making an application to render scenes in 2D and I want to get Alpha blending working. I have heard that this is a troublesome thing to do in OpenGL. Ultimately, what I want to do is make a framework that allows one to render scenes - both with opaque and translucent objects - using z-ordering to choose what objects render in front of others. I want the z-ordering to be practically seamless with the alpha blending, but I haven't really found resources that explain it blatantly.

What I want to know is:
GL states (such as blending states) to use How exactly to configure OpenGL to render alpha color values Basic algorithm of rendering (the order of stuff)
From my understanding, I am supposed to render all opaque objects first with depth testing on, and then render the translucent objects with depth testing off from back to front (smallest z value to largest z value).

My post may be confusing, but I'm confused too. :confused:

Any tips would be nice, pseudocode would be best.

Dark Photon
03-23-2011, 04:35 PM
I am making an application to render scenes in 2D and I want to get Alpha blending working. I have heard that this is a troublesome thing to do in OpenGL.

Not at all. In general, enabling and using alpha blending is pretty simple.


Ultimately, what I want to do is make a framework that allows one to render scenes - both with opaque and translucent objects - using z-ordering to choose what objects render in front of others.
You said you're rendering a 2D scene, so I'm confused why you're talking about Z and what's in front.

Is it really a "3D" scene (objects positioned in x, y, and z)?


I want the z-ordering to be practically seamless with the alpha blending, but I haven't really found resources that explain it blatantly.

Sounds like you need to get the OpenGL Programming Guide (http://www.amazon.com/OpenGL-Programming-Guide-Official-Learning/dp/0321552628/ref=sr_1_1?ie=UTF8&qid=1300922417&sr=8-1), or refer to an online copy:

Others (to list a few):

* http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=08
* http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=32
* http://users.polytech.unice.fr/~buffa/cours/synthese_image/DOCS/Tutoriaux/Nehe/lesson8.htm
* http://www.opengl.org/wiki/Transparency_Sorting
* http://www.opengl.org/resources/faq/technical/transparency.htm


What I want to know is:
GL states (such as blending states) to use How exactly to configure OpenGL to render alpha color values Basic algorithm of rendering (the order of stuff)
From my understanding, I am supposed to render all opaque objects first with depth testing on, and then render the translucent objects with depth testing off from back to front (smallest z value to largest z value).
Your understanding is correct, except you want depth testing ON when rendering the alpha objects (so you can have opaque objects occluding alpha objects).

#1: glEnable( GL_BLEND ) and glBlendFunc(). That'll get you going. Make sure you've allocated a render target (e.g. window) with alpha.

#2: Send colors with an alpha value through the rendering pipeline. Simplest way is to send them in your draw batches via 4-component vectors as vertex attributes, though you can generate them in shaders too. For the former, glVertexAttribPointer (or legacy: glColorPointer) are the way to pass those in -- read up on passing vertex attributes if you don't know how.


My post may be confusing, but I'm confused too. :confused:

No problem! We all start somewhere. The guy that told you alpha blending in general is hard in OpenGL doesn't know what he's talking about (or he's talking about something more specific than just general alpha blending). Once you make sure your render target supports alpha, enable blending (glEnable GL_BLEND), set the blending function you want (glBlendFunc), and pass down 4-component colors (R,G,G,A), there's really not anything left for you to do except pre-sort your surfaces back-to-front.

Note that are are other algorithms for doing this sorting (on a per-pixel or per-sample level, rather than per object or per surface/triangle), which let you have a polygon intersect others or itself and still get proper per-sample-sorted blending results. But if not or you can ensure they won't, you don't need them so I won't confuse you.

If you still have questions, let us know! And talk a bit more about the translucent objects in your scene. Are they effectively 2D (flat sheets, like windows, canopies, etc.)? If not, are they convex? If not, how are you modeling transmission through the medium? Do they intersect? If so, do the component triangles of those objects intersect?

_ShaderRookie_
03-23-2011, 05:26 PM
Easiest way to do is with shaders.
In the fragment shader:


if ( color.a <= 0.1f )
discard;

Easy and cheap Alpha Test.

AGlass0fMilk
03-23-2011, 09:22 PM
You said you're rendering a 2D scene, so I'm confused why you're talking about Z and what's in front.

Well, it's 2D, but the objects are positioned behind and in front of each other by a z-value



Is it really a "3D" scene (objects positioned in x, y, and z)?

It's not supposed to be, but I guess you could technically consider it a "3D" scene.

It may be best for me to give you a diagram (not my application, made in GIMP):
http://dl.dropbox.com/u/2000603/alphaExample.png
In that picture, both the white and red quads are translucent, and green and blue quads are opaque. And the background is gray and obviously opaque. The z-odering goes like this:
Red is on the bottom (lowest z value, arbitrarily 0.0f)
Blue is second from the bottom (second lowest z value, 0.2f)
White is the second from the top (second highest z value, 0.5f)
And Green is at the top (highest z value, 1.0f)

I heard that the only hard part about alpha blending and ordering is that actual ordering part, because translucent objects aren't sorted correctly. That is basically how my geometry would look, except later on there will be textures (which alpha-texture blending is probably a whole 'nother thing).

My code looks like this:
Some of the main setup code


//Sets "glUnit" to the size of a pixel
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, winWidth, 0, winHeight);

//loadImage();
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glMatrixMode(GL_MODELVIEW);


And the geometry creation code


float behind = 0.3f;
float infront = 1.0f;

glEnable(GL_BLEND);

glBegin(GL_QUADS); //White Box (should appear behind)
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glVertex3f(posX, posY + extY, behind);

glVertex3f(posX + extX, posY + extY, behind);

glVertex3f(posX + extX, posY, behind);

glVertex3f(posX, posY, behind);
glEnd();

glBegin(GL_QUADS); //Red box (no pun intended, should be in front)
glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
glVertex3f(posX-20.0f, posY + extY -20.0f, infront);

glVertex3f(posX + extX-20.0f, posY + extY-20.0f, infront);

glVertex3f(posX + extX-20.0f, posY-20.0f, infront);

glVertex3f(posX-20.0f, posY-20.0f, infront);
glEnd();

And this yields this in my application:
http://dl.dropbox.com/u/2000603/myAlpha.png
Thanks for the help so far, and I will look at some of the references you posted.

AGlass0fMilk
03-23-2011, 09:28 PM
I read the official OpenGL tutorial, and I used the blending functions they said to use, and it worked much better. I guess now it's just a matter of sorting. Thanks for your help. I may use this thread in the future to host more shouts for help. OpenGL is pretty new to me and I appreciate your help. I'll take some time to read through the references (especially the official book) to learn more about what all of these different settings do. For now, I'm good

Alfonse Reinheart
03-23-2011, 09:30 PM
I heard that the only hard part about alpha blending and ordering is that actual ordering part, because translucent objects aren't sorted correctly.

Yes, but they're talking about actual 3D scenes. In 3D scenes, objects can be viewed from any direction, so computing an ordering has to be done per-frame.

Your objects are all flat. You have an explicit ordering for objects which persists between frames. So just draw all your stuff from back to front. For objects that are opaque, turn off blending. And for objects that are transparent, turn blending on.