Irrlicht 1.1, opengl and 2d transparency

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
iona
Posts: 19
Joined: Mon May 29, 2006 6:29 pm

Irrlicht 1.1, opengl and 2d transparency

Post by iona »

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
iona
Posts: 19
Joined: Mon May 29, 2006 6:29 pm

Post by iona »

hmmm anyone ? PLEASE ! :cry:
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

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.
Image
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

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.
borky89
Posts: 13
Joined: Wed Aug 23, 2006 4:07 pm
Location: Switzerland

Post by borky89 »

The one you can add like that?

driver->draw2DImage(..., ..., ..., ..., video::SColor(100,255,255,255), false);

Georg
iona
Posts: 19
Joined: Mon May 29, 2006 6:29 pm

Post by iona »

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.
The problem is when i want to display half-transparent fonts (for smooth fade-up on the interface).

Currently i'm downloading Spintz's modified Irrlicht, i hope that ctrl+c ctrl+v will work :)
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

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 -

Code: Select all

if (useAlphaChannelOfTexture)
	setRenderStates2DMode(false, true, true);
else
	setRenderStates2DMode(false, true, false);
to

Code: Select all

if (useAlphaChannelOfTexture)
	setRenderStates2DMode(true, true, true);
else
	setRenderStates2DMode(true, true, false);
And then, in the setRenderStates2DMode function, change the function to this :

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;
}
The logic change in the setRenderStates2DMode function becomes this -
  • 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've tested this, with this change only applied to SVN Irrlicht rev 165, and it works for me.

I guess this should be moved to the Bug Reports forum.
Image
iona
Posts: 19
Joined: Mon May 29, 2006 6:29 pm

Post by iona »

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 :

...
Thaks ! It works !!

BTW You can also use

Code: Select all

	if (useAlphaChannelOfTexture) 
		setRenderStates2DMode(color.getAlpha() < 255, true, true);
	else 
		setRenderStates2DMode(color.getAlpha() < 255, true, false);
For a little speed-up.


Thanks again!
iona
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

True, I think I might change it to -

Code: Select all

setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture );
Image
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, that's also the way it is now in SVN. Also another 2dimage method requires such a change. And I've added a blend func set to the setup which seemed to be missing.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

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 );
Image
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes right, but you also have to move the NULL test in front of this method and use an alpha value of 255 for the temporary colors to avoid null pointers and get useful colors in all cases.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

hybrid, this reminds me about a fix that should be made to the opengl/d3d8 drivers...

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;
The current code in the d3d9 driver is much nicer

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;
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, sounds good :D
say
Posts: 1
Joined: Fri Aug 25, 2006 12:29 am

haha

Post by say »

I am d3d User. I problem it - colorkey and alpha channel Image's Smooth Blending -

draw2DImage( img, rect, rect, 0, SColor(0~255,255,255,255), true);

I hope Irrlicht 1.2 Version Change this Bug(?). :D
Post Reply