Page 1 of 1

Fix for CEGUIIrrlichtGeometryBuffer.cpp

Posted: Thu Jun 24, 2010 20:45
by agamemnus
EDIT: fix does not seem to work... must have been the heat.

Change line 285 to:

d_material.MaterialType = irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;

This seems to work.

I also had:

Code: Select all

        d_material.MaterialTypeParam = irr::video::pack_texureBlendFunc(
                irr::video::EBF_SRC_ALPHA,
                irr::video::EBF_ONE_MINUS_SRC_ALPHA,
                irr::video::EMFN_MODULATE_1X,
                irr::video::EAS_TEXTURE);

...but I don't think it's necessary.

Description for EMT_TRANSPARENT_ALPHA_CHANNEL:
//! Makes the material transparent based on the texture alpha channel.
/** The final color is blended together from the destination
color and the texture color, using the alpha channel value as
blend factor. Only first texture is used. If you are using
this material with small textures, it is a good idea to load
the texture in 32 bit mode
(video::IVideoDriver::setTextureCreationFlag()). Also, an alpha
ref is used, which can be manipulated using
SMaterial::MaterialTypeParam. This value controls how sharp the
edges become when going from a transparent to a solid spot on
the texture. */


EDIT: fix does not seem to work... must have been the heat.

Re: Fix for CEGUIIrrlichtGeometryBuffer.cpp

Posted: Thu Jul 01, 2010 08:51
by CrazyEddie
Yeah, it requires separate modes for alpha and colour blending. It should be possible to make a custom material for irrlicht to do that, though this requires an implementation for each driver for irrlicht, thus breaking the abstraction and requiring access to underlying APIs - which is unacceptable to me. Perhaps one day I'll make a proof of concept and decide where to go from there.

CE.

Re: Fix for CEGUIIrrlichtGeometryBuffer.cpp

Posted: Mon Jul 05, 2010 20:27
by agamemnus
It won't happen.

http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=38907

hybrid wrote:
agamemnus wrote:Ok, it looks like what I need is d_material.MaterialType = irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;

Is this correct?

Actually, it's not. At least not if you want to use the packed texture blend mode. For that you have to use EMT_ONE_TEXTURE_BLEND
We do indeed not support all combinations of the underlying gfx API. Simply because you cannot make them available in a simple manner. And instead of just placing them im the SMaterial, we use additional materials instead. Writing your own material is a matter of a few lines additional code. Just copy the two best matching versions for OpenGL and DirectX and adapt to your needs.

Re: Fix for CEGUIIrrlichtGeometryBuffer.cpp

Posted: Mon Jul 12, 2010 11:14
by Timo
Here's something I've been using to fix this issue. It's a horrible solution from performance point of view, but it's better than having background colors bleed through the RTT surface, which imho is unacceptable.

What it does is it renders everything twice using different color masks. First the color channels and then the alpha channel, and it uses different blend function for each rendering pass.

I haven't tested it with irrlicht 1.7, i'm still using 1.6 myself.

Code: Select all

Index: cegui/src/RendererModules/Irrlicht/CEGUIIrrlichtGeometryBuffer.cpp
===================================================================
--- cegui/src/RendererModules/Irrlicht/CEGUIIrrlichtGeometryBuffer.cpp   (revision 2567)
+++ cegui/src/RendererModules/Irrlicht/CEGUIIrrlichtGeometryBuffer.cpp   (working copy)
@@ -122,9 +122,67 @@
         for ( ; i != d_batches.end(); ++i)
         {
             d_material.setTexture(0, (*i).first);
-            d_driver.setMaterial(d_material);
-            d_driver.drawIndexedTriangleList(&d_vertices[pos], (*i).second,
-                                            &d_indices[pos], (*i).second / 3);
+
+            #if CEGUI_IRR_SDK_VERSION >= 16
+                if(d_blendMode == BM_RTT_PREMULTIPLIED)
+                {
+                    static const irr::f32 param = irr::video::pack_texureBlendFunc(
+                          irr::video::EBF_ONE,
+                          irr::video::EBF_ONE_MINUS_SRC_ALPHA,
+                          irr::video::EMFN_MODULATE_1X,
+                          irr::video::EAS_NONE);
+                    d_material.MaterialTypeParam = param;
+                    d_driver.setMaterial(d_material);
+                    d_driver.drawIndexedTriangleList(&d_vertices[pos], (*i).second,
+                                                    &d_indices[pos], (*i).second / 3);
+                }
+                else
+                {
+                    // Irrlicht (as of 1.6.1) doesn't support separate blending modes for alpha
+                    // and color channels. Meanwhile, we can get the same effect by rendering
+                    // the channels separately.
+
+                    // draw alpha channel
+                    d_material.ColorMask =  irr::video::ECP_ALPHA;
+                    static const irr::f32 param_alpha = irr::video::pack_texureBlendFunc(
+                          irr::video::EBF_ONE_MINUS_DST_ALPHA,
+                          irr::video::EBF_ONE,
+                          irr::video::EMFN_MODULATE_1X,
+                          irr::video::EAS_NONE);
+                    d_material.MaterialTypeParam = param_alpha;
+                    d_driver.setMaterial(d_material);
+                    d_driver.drawIndexedTriangleList(&d_vertices[pos], (*i).second,
+                                                    &d_indices[pos], (*i).second / 3);
+
+                    // draw color channels
+                    d_material.ColorMask = irr::video::ECP_RGB;
+                    static const irr::f32 param_rgb = irr::video::pack_texureBlendFunc(
+                          irr::video::EBF_SRC_ALPHA,
+                          irr::video::EBF_ONE_MINUS_SRC_ALPHA,
+                          irr::video::EMFN_MODULATE_1X,
+                          irr::video::EAS_NONE);
+                    d_material.MaterialTypeParam = param_rgb;
+                    d_driver.setMaterial(d_material);
+                    d_driver.drawIndexedTriangleList(&d_vertices[pos], (*i).second,
+                                                    &d_indices[pos], (*i).second / 3);
+
+                    // Reset ColorMask back to ECP_ALL and make the new material active by calling
+                    // one of the rendering functions. This is needed because of a bug in
+                    // Irrlicht OpenGL driver. All clear operations use the color mask,
+                    // but the new colormask isn't applied until something is actually rendered.
+                    d_material.ColorMask = irr::video::ECP_ALL;
+                    d_driver.setMaterial(d_material);
+                    d_driver.draw3DLine(irr::core::vector3df(0,0,0), irr::core::vector3df(0,0,0),
+                                        irr::video::SColor(0,0,0,0));
+
+                }
+
+            #else
+                d_driver.setMaterial(d_material);
+                d_driver.drawIndexedTriangleList(&d_vertices[pos], (*i).second,
+                                                &d_indices[pos], (*i).second / 3);
+            #endif
+
             pos += (*i).second;
         }
     }

Re: Fix for CEGUIIrrlichtGeometryBuffer.cpp

Posted: Fri Jul 16, 2010 08:41
by CrazyEddie
Thanks for posting the patch. I think there may be people who choose to go that same route.

I've now actually briefly looked at the custom material approach, though gave up for the time being since it was more work than I had motivation for at the time.

CE.