Irrlicht 1.1, opengl and 2d transparency
Irrlicht 1.1, opengl and 2d transparency
Hello,
I have a big problem with opengl driver - the alpha value for draw2DImage is simply ignored.
There's a working solution for this problem for irrlicht 1.0 (http://irrlicht.sourceforge.net/phpBB2/ ... highlight=) but it does not work for v.1.1.
I cannot find the source of problem, i would be great if the author of openGL driver provide a path
This is a really serious bug, because it makes impossible to display transparent images (i'm not talking about alpha channel but alpha value of whole picture) and fonts
Plz help !
iona
I have a big problem with opengl driver - the alpha value for draw2DImage is simply ignored.
There's a working solution for this problem for irrlicht 1.0 (http://irrlicht.sourceforge.net/phpBB2/ ... highlight=) but it does not work for v.1.1.
I cannot find the source of problem, i would be great if the author of openGL driver provide a path
This is a really serious bug, because it makes impossible to display transparent images (i'm not talking about alpha channel but alpha value of whole picture) and fonts
Plz help !
iona
I've fixed this in IrrSpintz, but you can't simply take my setRenderStates2D function and copy it into Irrlicht. The problem is that the renderstates are maintained properly. In Irrlicht, every material makes sure the states it needs are set, and the ones it doesnt need are unset.
What should be happening, is that each driver( OpenGL, Direct3D ) should setup default renderstates when created. Then each material material should change only what renderstates it needs changed from the defaults in OnSetMaterial, and then reset those renderstates it changed in the OnUnsetMaterial function. This is not done consistently. This also needs to be done when switching between 2D and 3D mode. For instance, setRenderStates2DMode should change default to whatever it needs them to be( how they differ from when 3D mode is enabled ). And setRenderStates3DMode should change back to 3D defaults anything that 2D mode would change.
The temporary workaround is when setting 2D and 3D mode, to reset all states that each other may change, but only convoludes the problem. I rewrite of OpenGL and Direct3D drivers for renderstates needs to be done and put into SVN. It's the main reason I don't keep IrrSpintz up to date with SVN Irrlicht, because it's so much work to change all the materials and drivers renderstates everytime.
What should be happening, is that each driver( OpenGL, Direct3D ) should setup default renderstates when created. Then each material material should change only what renderstates it needs changed from the defaults in OnSetMaterial, and then reset those renderstates it changed in the OnUnsetMaterial function. This is not done consistently. This also needs to be done when switching between 2D and 3D mode. For instance, setRenderStates2DMode should change default to whatever it needs them to be( how they differ from when 3D mode is enabled ). And setRenderStates3DMode should change back to 3D defaults anything that 2D mode would change.
The temporary workaround is when setting 2D and 3D mode, to reset all states that each other may change, but only convoludes the problem. I rewrite of OpenGL and Direct3D drivers for renderstates needs to be done and put into SVN. It's the main reason I don't keep IrrSpintz up to date with SVN Irrlicht, because it's so much work to change all the materials and drivers renderstates everytime.
The problem is when i want to display half-transparent fonts (for smooth fade-up on the interface).hybrid wrote:Fonts are using alpha channels by using the makeColorKeyTexture method of the NullDriver. So I don't really understand the problems. Also why does your code change not work anymore? The material renderers are mostly unchanged.
Currently i'm downloading Spintz's modified Irrlicht, i hope that ctrl+c ctrl+v will work
I just looked at this and the problem is fixed in IrrSpintz, but here's the changed that were necessary for this change. ( Note, IrrSpintz code being copied and pasted in would not work, you must make the changes below. IrrSpintz keeps better track of renderStates between 2D and 3D modes and Materials, so much less renderState changes are needed when setting 2D mode. So, here's the code changes :
All of these code changes are in COpenGLDriver.cpp
In all of the draw2DImage functions, change the change the call to setRenderStates2DMode to pass true for the first arg. So change -
to
And then, in the setRenderStates2DMode function, change the function to this :
The logic change in the setRenderStates2DMode function becomes this -
I guess this should be moved to the Bug Reports forum.
All of these code changes are in COpenGLDriver.cpp
In all of the draw2DImage functions, change the change the call to setRenderStates2DMode to pass true for the first arg. So change -
Code: Select all
if (useAlphaChannelOfTexture)
setRenderStates2DMode(false, true, true);
else
setRenderStates2DMode(false, true, false);
Code: Select all
if (useAlphaChannelOfTexture)
setRenderStates2DMode(true, true, true);
else
setRenderStates2DMode(true, true, false);
Code: Select all
//! sets the needed renderstates
void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel)
{
if (CurrentRenderMode != ERM_2D || Transformation3DChanged)
{
// unset last 3d material
if (CurrentRenderMode == ERM_3D && Material.MaterialType >= 0 &&
Material.MaterialType < (s32)MaterialRenderers.size())
MaterialRenderers[Material.MaterialType].Renderer->OnUnsetMaterial();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Transformation3DChanged = false;
glDisable(GL_DEPTH_TEST);
glDisable(GL_FOG);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_LIGHTING);
if (MultiTextureExtension)
{
extGlActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
extGlActiveTextureARB(GL_TEXTURE0_ARB);
}
glEnable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_ALPHA_TEST);
glCullFace(GL_BACK);
}
if (texture)
{
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
if (alphaChannel)
{
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
}
else
{
if (alpha)
{
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
glDisable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
}
else
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
}
}
}
else
{
if (alpha)
{
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisable(GL_ALPHA_TEST);
}
else
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
}
}
CurrentRenderMode = ERM_2D;
}
- If there is a texture and alphaChannel is true then use the texture as the source of alpha with the calls :
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); - If there is no texture and alpha is true then use the vertex color as the alpha source with the calls :
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
And we enable blend and set the proper BlendFunc - Finally, at this point, we don't use alpha values, so disable alpha blend all together and ignore alpha values that are present.
I guess this should be moved to the Bug Reports forum.
Thaks ! It works !!Spintz wrote:I just looked at this and the problem is fixed in IrrSpintz, but here's the changed that were necessary for this change. ( Note, IrrSpintz code being copied and pasted in would not work, you must make the changes below. IrrSpintz keeps better track of renderStates between 2D and 3D modes and Materials, so much less renderState changes are needed when setting 2D mode. So, here's the code changes :
...
BTW You can also use
Code: Select all
if (useAlphaChannelOfTexture)
setRenderStates2DMode(color.getAlpha() < 255, true, true);
else
setRenderStates2DMode(color.getAlpha() < 255, true, false);
Thanks again!
iona
True, I think I might change it to -
Code: Select all
setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture );
Yes, the other draw2DImage uses SColor*, to be able to specify the color for each corner of the image. I use this -
Code: Select all
setRenderStates2DMode( colors[0].getAlpha() < 255 ||
colors[1].getAlpha() < 255 ||
colors[2].getAlpha() < 255 ||
colors[3].getAlpha() < 255, true, useAlphaChannelOfTexture );
hybrid, this reminds me about a fix that should be made to the opengl/d3d8 drivers...
The current code in the d3d9 driver is much nicer
Code: Select all
// from COpenGLDriver.cpp
1071 if(colors==NULL)
1072 {
1073 colors=new SColor[4];
1074 for(int i=0;i<4;i++)
1075 colors[i]=SColor(255,255,255,255);
1076 bTempColors=true;
1077 }
//...
1104 if(bTempColors)
1105 delete [] colors;
Code: Select all
844 video::SColor temp[4] =
845 {
846 0xFFFFFFFF,
847 0xFFFFFFFF,
848 0xFFFFFFFF,
849 0xFFFFFFFF
850 };
851
852 video::SColor* useColor = colors ? colors : temp;