[Re-Solved] Overlapping Transparencies
-
Moohasha
- Gnoll
- Posts: 672
- Joined: Fri Dec 07, 2007 7:37 pm
- x 8
[Re-Solved] Overlapping Transparencies
I have multiple objects that use the same material, which is just a solid color with 10% alpha. When these objects overlap, however, the alphas add up and you eventually get a solid color. Is there a way to avoid this? If I have 50 of these objects overlapping, I still only want 10% alpha through all of them so I can see what's behind. Do I have to use the stencil buffer or something? What's a good solution for this?
Last edited by Moohasha on Tue Feb 17, 2009 10:49 pm, edited 2 times in total.
Black holes are where God divided by 0
-
xavier
- OGRE Retired Moderator

- Posts: 9481
- Joined: Fri Feb 18, 2005 2:03 am
- Location: Dublin, CA, US
- x 22
Re: Overlapping Transparencies
What scene blending factor are you using?
-
Moohasha
- Gnoll
- Posts: 672
- Joined: Fri Dec 07, 2007 7:37 pm
- x 8
Re: Overlapping Transparencies
alpha_blend
Here's my entire material script:
Here's my entire material script:
Code: Select all
material Dome
{
technique
{
pass
{
lighting off
ambient vertexcolour
scene_blend alpha_blend
}
}
}Black holes are where God divided by 0
-
Kencho
- OGRE Retired Moderator

- Posts: 4011
- Joined: Fri Sep 19, 2003 6:28 pm
- Location: Burgos, Spain
- x 2
Re: Overlapping Transparencies
Render them to a different target (a render texture), then use that texture on a rectangle that will be overlaid on the scene (opacity of the rectangle: 10%). It's the best I can think right now.
-
Moohasha
- Gnoll
- Posts: 672
- Joined: Fri Dec 07, 2007 7:37 pm
- x 8
Re: Overlapping Transparencies
So render them to the texture without any transparency, just a solid colo(u)r? Hmm...I've never tried rendering something to a texture instead of the screen, but I'll look into it. Thanks.
Black holes are where God divided by 0
-
Kencho
- OGRE Retired Moderator

- Posts: 4011
- Joined: Fri Sep 19, 2003 6:28 pm
- Location: Burgos, Spain
- x 2
Re: Overlapping Transparencies
It's the only way I can think of achieving a non-cumulative blending amongst different entities (and even further, amongst the faces of a non-convex mesh!) other than that. Since the entities are pushed into the render pipeline without knowing of any other already-rendered mesh, you can't avoid the cumulative blending when they overlap using the usual techniques. It's a lot trickier, so maybe you're not *that* interested in removing the cumulative blending.
-
Moohasha
- Gnoll
- Posts: 672
- Joined: Fri Dec 07, 2007 7:37 pm
- x 8
Re: Overlapping Transparencies
Okay, I followed Intermediate Tutorial 7 and figured out how to render my scene to a texture. Now I have two questions about how to procede:
1) How do I set the opacity of the rectangle? Do I have to do it to the RenderTexture? This might be something that I'd like to let the user change a runtime, so an easy, flexible method is desireable. If not, we can just make it static.
2) How do I render only specific entities to the texture and not the entire scene? I've only ever used one camera, one viewport, one render target, etc... This is all pretty new, but it looks like a very powerful technique so I'd like to figure it out.
Thanks for all the help.
1) How do I set the opacity of the rectangle? Do I have to do it to the RenderTexture? This might be something that I'd like to let the user change a runtime, so an easy, flexible method is desireable. If not, we can just make it static.
2) How do I render only specific entities to the texture and not the entire scene? I've only ever used one camera, one viewport, one render target, etc... This is all pretty new, but it looks like a very powerful technique so I'd like to figure it out.
Thanks for all the help.
Black holes are where God divided by 0
-
Moohasha
- Gnoll
- Posts: 672
- Joined: Fri Dec 07, 2007 7:37 pm
- x 8
Re: Overlapping Transparencies
I solved both problems and got it working. Here's my solution, if anyone is interested:
1) I made the render target transparent by simply making the material I apply to it transparent. Duh. In my test app, I just used scene_blend add because I was using the Black and White shader effect, but for my real app I'll need to get a little more clever.
2) All entities I wanted to be semi-transparent (ie, rendered to the texture), I set their visibility flag to VF_TRANS_ENT, some value I created. All other entities have the visibility flag VF_STATIC_ENT, just a different value. In preRenderTargetUpdate() and postRenderTargetUpdate() I just set the visibility mask of the scene manager to the appropriate flag based on when render target triggered the event. That way, when rendering to the scene, it only renders the static (non-transparent) entities, and when rendering to texture it only renders the desired (transparent) entities.
Not sure how this approach will scale for my real application, but at least I have something to go off of. Thanks for the help Kencho. Here's a screenshot of the results. I have 11 Ogre heads being rendered to the texture and then overlayed on the scene, and as you see the opacities don't add up. =)

1) I made the render target transparent by simply making the material I apply to it transparent. Duh. In my test app, I just used scene_blend add because I was using the Black and White shader effect, but for my real app I'll need to get a little more clever.
2) All entities I wanted to be semi-transparent (ie, rendered to the texture), I set their visibility flag to VF_TRANS_ENT, some value I created. All other entities have the visibility flag VF_STATIC_ENT, just a different value. In preRenderTargetUpdate() and postRenderTargetUpdate() I just set the visibility mask of the scene manager to the appropriate flag based on when render target triggered the event. That way, when rendering to the scene, it only renders the static (non-transparent) entities, and when rendering to texture it only renders the desired (transparent) entities.
Not sure how this approach will scale for my real application, but at least I have something to go off of. Thanks for the help Kencho. Here's a screenshot of the results. I have 11 Ogre heads being rendered to the texture and then overlayed on the scene, and as you see the opacities don't add up. =)

Black holes are where God divided by 0
-
Kencho
- OGRE Retired Moderator

- Posts: 4011
- Joined: Fri Sep 19, 2003 6:28 pm
- Location: Burgos, Spain
- x 2
Re: Overlapping Transparencies
Glad to see you got it working
They're indeed powerful tools, so I hope you learned a lot from this experience 
-
Moohasha
- Gnoll
- Posts: 672
- Joined: Fri Dec 07, 2007 7:37 pm
- x 8
Re: [Re-Opened] Overlapping Transparencies
Now I'm having two new issues which I didn't anticipate.
1) I thought this would be easy enough to avoid, but alas it has not been. How do I disable the sky box for a render target? I'm using visibility flags to determine what objects are visible in each render target, but this doesn't seem to affect the sky box. I even tried the following code and it didn't work.
2) Objects I render to the texture are not culled by other objects in the scene, such as the ground or objects that are in front of it. Since the texture is just a full screen quad, then the semi-transparent objects just appear on top of everything else, like this:

It should look like this, which I've accomplished by rendering the ground to texture as well (not desirable):

Is there a way to use the depth buffer from one render target in another render target, so I can check the depth buffer of the main window when writing to texture to avoid writing over areas that should be culled?
1) I thought this would be easy enough to avoid, but alas it has not been. How do I disable the sky box for a render target? I'm using visibility flags to determine what objects are visible in each render target, but this doesn't seem to affect the sky box. I even tried the following code and it didn't work.
Code: Select all
mSceneMgr->setSkyBox(true, "Examples/MorningSkyBox");
Ogre::SceneNode::ObjectIterator itr = mSceneMgr->getSkyBoxNode()->getAttachedObjectIterator();
while (itr.hasMoreElements())
{
// VF_MAIN_VP is the flag for objects that only render to the main viewport
itr.getNext()->setVisibilityFlags(VF_MAIN_VP);
}
It should look like this, which I've accomplished by rendering the ground to texture as well (not desirable):

Is there a way to use the depth buffer from one render target in another render target, so I can check the depth buffer of the main window when writing to texture to avoid writing over areas that should be culled?
Black holes are where God divided by 0
-
madmarx
- OGRE Expert User

- Posts: 1671
- Joined: Mon Jan 21, 2008 10:26 pm
- x 51
Re: [Re-Opened] Overlapping Transparencies
1/ for the skybox, it is very easy. Select the viewport of your rendertexture, and then just call
myViewport->setSkiesEnabled(false);
// and I suppose you don't want overlays as well :
myViewport->setOverlaysEnabled(false);
2/ Not sure about this.
myViewport->setSkiesEnabled(false);
// and I suppose you don't want overlays as well :
myViewport->setOverlaysEnabled(false);
2/ Not sure about this.
Tutorials + Ogre searchable API + more for Ogre1.7 : http://sourceforge.net/projects/so3dtools/
Corresponding thread : http://www.ogre3d.org/forums/viewtopic. ... 93&start=0
Corresponding thread : http://www.ogre3d.org/forums/viewtopic. ... 93&start=0
-
Moohasha
- Gnoll
- Posts: 672
- Joined: Fri Dec 07, 2007 7:37 pm
- x 8
Re: [Re-Opened] Overlapping Transparencies
Ah, thank you. I figured it was something easy like that. Now I just need to figure out #2...madmarx wrote:1/ for the skybox, it is very easy. Select the viewport of your rendertexture, and then just call
myViewport->setSkiesEnabled(false);
// and I suppose you don't want overlays as well :
myViewport->setOverlaysEnabled(false);
edit: fixed quote
Last edited by Moohasha on Tue Feb 17, 2009 10:51 pm, edited 2 times in total.
Black holes are where God divided by 0
-
Kencho
- OGRE Retired Moderator

- Posts: 4011
- Joined: Fri Sep 19, 2003 6:28 pm
- Location: Burgos, Spain
- x 2
Re: [Re-Opened] Overlapping Transparencies
For number two, you can create a scheme to each opaque material so that they write only to the depth buffer (there's an option for that... somethinkg like "colour_write false"; check the manual for the details), and use that scheme in that viewport. I'm not sure if you have an alpha channel in the RT though... 
-
Moohasha
- Gnoll
- Posts: 672
- Joined: Fri Dec 07, 2007 7:37 pm
- x 8
Re: [Re-Opened] Overlapping Transparencies
I gave up on the Render-to-Texture technique. I has having too many issues with it.
I found a better solution using the stencil buffer. In the material script I add a pass before the main one with colour_write off so I only write to the depth buffer. For each entity, I add them to a special render queue group and when that group is rendered I use the following stencile buffer params:
rendersys->setStencilBufferParams(Ogre::CMPF_EQUAL, 1 ,0xFFFFFFFF, Ogre::SOP_REPLACE, Ogre::SOP_KEEP, Ogre::SOP_REPLACE, false);
The first pass that only writes to the depth buffer ensures that faces always get rendered in the right front-to-back order. The stencil buffer then makes sure I don't render over any area that's already been rendered by one of these semi-transparent objects.
And here are the results:

Notice that you can see through each Ogre head, but the alpha values never add up.
Thanks to everyone who helped/inspired.
I found a better solution using the stencil buffer. In the material script I add a pass before the main one with colour_write off so I only write to the depth buffer. For each entity, I add them to a special render queue group and when that group is rendered I use the following stencile buffer params:
rendersys->setStencilBufferParams(Ogre::CMPF_EQUAL, 1 ,0xFFFFFFFF, Ogre::SOP_REPLACE, Ogre::SOP_KEEP, Ogre::SOP_REPLACE, false);
The first pass that only writes to the depth buffer ensures that faces always get rendered in the right front-to-back order. The stencil buffer then makes sure I don't render over any area that's already been rendered by one of these semi-transparent objects.
And here are the results:

Notice that you can see through each Ogre head, but the alpha values never add up.
Black holes are where God divided by 0
-
jacmoe
- OGRE Retired Moderator

- Posts: 20570
- Joined: Thu Jan 22, 2004 10:13 am
- Location: Denmark
- x 179
Re: [Re-Solved] Overlapping Transparencies
Code, code, code! 
Looks pretty cool. Like the undead army in Lord of the Rings.
Looks pretty cool. Like the undead army in Lord of the Rings.
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
-
Kencho
- OGRE Retired Moderator

- Posts: 4011
- Joined: Fri Sep 19, 2003 6:28 pm
- Location: Burgos, Spain
- x 2
Re: [Re-Solved] Overlapping Transparencies
Ah, that's a pretty imaginative solution
The results look great!
-
Moohasha
- Gnoll
- Posts: 672
- Joined: Fri Dec 07, 2007 7:37 pm
- x 8
Re: [Re-Solved] Overlapping Transparencies
Here's an example material script (for the ogre head, I had to modify the 4 material scripts used on that mesh):
And here's the RenderQueueListener that updates the stencil buffer:
All that's left is adding any entity you want to the proper render queue group:
Code: Select all
material TransparencyMaterial
{
technique
{
pass
{
// Only write to the depth buffer
colour_write off
}
pass
{
lighting off
scene_blend alpha_blend
// Lighting is baked into the vertices, so just use vertex colour
ambient vertexcolour
}
}
}Code: Select all
#define TRANSPARENT_GROUP 91
class TransparentQueueListener : public Ogre::RenderQueueListener
{
public:
virtual void renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& skipThisInvocation)
{
//RenderQueue containing transparent objects
if (queueGroupId == TRANSPARENT_GROUP)
{
Ogre::RenderSystem * rendersys = Ogre::Root::getSingleton().getRenderSystem();
rendersys->clearFrameBuffer(Ogre::FBT_STENCIL);
rendersys->setStencilCheckEnabled(true);
rendersys->setStencilBufferParams(Ogre::CMPF_EQUAL, 1 ,0xFFFFFFFF, Ogre::SOP_REPLACE, Ogre::SOP_KEEP, Ogre::SOP_REPLACE, false);
}
}
virtual void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation)
{
if ((queueGroupId == TRANSPARENT_GROUP))
{
Ogre::RenderSystem * rendersys = Ogre::Root::getSingleton().getRenderSystem();
rendersys->setStencilCheckEnabled(false);
rendersys->setStencilBufferParams();
}
}
};Code: Select all
entity->setRenderQueueGroup(TRANSPARENT_GROUP);Black holes are where God divided by 0
