Page 1 of 2

Transparency: Texture Alpha + Vertex alpha?

Posted: Mon May 19, 2008 7:14 am
by Nyxojaele
Is it possible to combine both transparency methods?
Everything I've found in the forum seems to do one, but not the other.

Unless maybe I'm just missing some setting somewhere...?

What I'm looking at is having billboards that use the alpha channel on the texture to define their transparency, but I want to be able to fade these billboards out over time. I was hoping to be able to do this via simply setting the vertices' alpha value, since it'll only be 4 iterations thru a loop that way.

The only other thing I can think of would be to lock the texture to get access to the bytes and manually apply the alpha value I require thru the whole texture.

Posted: Mon May 19, 2008 1:31 pm
by rogerborg
Stillborn here. I'd like to say that I'll take a look at the practicality of implementing this, but I suspect that I won't have time.

Posted: Mon May 19, 2008 5:10 pm
by arras
It is not possible without coding yourself new material or using shader. There is no existing material which is able to do it.

Posted: Mon May 19, 2008 6:38 pm
by Nyxojaele
Hmm, I was afraid of that.

Okay, let's say we look at the possibility of using a shader:
I was looking at this briefly already, using a shader that somebody else posted a while back in this thread.

I managed to get this all running and such, but I came across almost the same issue. Using that shader that sio2 posted (about halfway down the thread) would only apply to the areas of the texture defined as "alpha" by the material type that was passed in as the base when the shader was loaded.

Unless maybe we just need a completely new shader as well-- is it possible to write a shader to handle alpha channel transparency without having the base material set as EMT_TRANSPARENT_ALPHA_CHANNEL? (So for example, if it was set as EMT_TRANSPARENT_VERTEX_ALPHA, as would be needed to pull off the fade effect..?)

<EDIT>
Hmm, I just found this thread- I'm going to see if maybe I can adopt this to my needs.

Posted: Mon May 19, 2008 7:30 pm
by arras
Unless maybe we just need a completely new shader as well-- is it possible to write a shader to handle alpha channel transparency without having the base material set as EMT_TRANSPARENT_ALPHA_CHANNEL? (So for example, if it was set as EMT_TRANSPARENT_VERTEX_ALPHA, as would be needed to pull off the fade effect..?)
It is, you can use any material as a base. However they may give different results. If you gona use transparency you should use some of the transparent materials since they are rendered in different pass by Irrlicht I think. EMT_TRANSPARENT_VERTEX_ALPHA should work fine in this regard.

Posted: Mon May 19, 2008 9:05 pm
by mk.1
What is important that the render function for the transparent scene node is called at the correct time (i.e. after the solid pass) so your material needs to be one of the "transparent" materials. Which one doesn't matter since you can write any effect you want if you use shaders (vertex + texture + overall alpha as well).

Hopefully I'll find some free time to work on it but as I have never created any patches I don't know how this will work out

Posted: Tue May 20, 2008 1:10 am
by Nyxojaele
Okay, I've finally gotten the complete desired effect- this is shader free- it's just a custom IMaterialRenderer.

I used some information from this post, but I had to modify things a bit to make it do everything properly- specifically a bunch of the SetTextureStageState() calls (I'm kinda thinking these things should have been modified this way to begin with, actually...?), and the minor adjustments to switch to D3D9.

Please note that a lot of this code is just straight copied, since it's functional the way it was, so I can't take full credit for it- but I'm definitely going to go thru and clean it up to be safer- I just wanted to get an iteration of this out there that is functional so anybody who's come across this issue as well can get things working.

Here's my custom IMaterialRenderer:

Code: Select all

class irrMaterialRendererDualTransparent: virtual public IMaterialRenderer {
public:
	IDirect3DDevice9	*mID3DDevice;
	IVideoDriver		*mDriver;
	
			irrMaterialRendererDualTransparent(IDirect3DDevice9 *dev, IVideoDriver *driver): mID3DDevice(dev),
					mDriver(driver) {}
	
	//Wrapped functions
	virtual void	OnSetMaterial(const SMaterial &material, const SMaterial &lastMaterial, bool resetAllRenderstates,
							IMaterialRendererServices *services) {
						if (material.MaterialType != lastMaterial.MaterialType ||
								material.MaterialTypeParam != lastMaterial.MaterialTypeParam ||
								resetAllRenderstates) {
							
							//Set the blend factor
							s32 blendValue = (u32)(255 * material.MaterialTypeParam);
							mID3DDevice->SetRenderState(D3DRS_TEXTUREFACTOR, (blendValue << 24) | 0x00000000);
							
							//Blend the alpha channel
							mID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
							mID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
							mID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
							
							mID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
							mID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
							
							//Blend the blend factor
							mID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
							mID3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
							
							mID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_BLENDFACTORALPHA);
							mID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
							mID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
							
							mID3DDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE);
							mID3DDevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
							
							mID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
							mID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
							mID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
							
							s32 refValue = (s32)(material.MaterialTypeParam2 * 255);
							if (refValue) {
								mID3DDevice->SetRenderState(D3DRS_ALPHAREF, refValue);
								mID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
								mID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
							}
						}
						
						services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
					}
	virtual void	OnUnsetMaterial() {
						mID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
					}
	virtual bool	isTransparent() const {
						return true;
					}
};
And the small bit of code to put it into place to be used by Irrlicht (unmodified from original post):

Code: Select all

irrMaterialRendererDualTransparent mt(driver->getExposedVideoData().D3D9.D3DDev9,driver);
   s32 newMat=driver->addMaterialRenderer(&mt);
And a bit of an example of using it:

Code: Select all

   IBillboardSceneNode *billMat3=smgr->addBillboardSceneNode(0,core::dimension2d<f32>(9.0f, 9.0f),core::vector3df(0,0,-0.8f));
   billMat3->setMaterialType((E_MATERIAL_TYPE)newMat);
   ITexture* imgLogo=driver->getTexture("logo1.png");
   billMat3->setMaterialTexture(0, imgLogo);
   billMat3->setMaterialTexture(1, imgLogo);
   billMat3->setMaterialFlag(video::EMF_LIGHTING, false);
   billMat3->getMaterial(0).MaterialTypeParam2=0;  //Ref value
   billMat3->getMaterial(0).MaterialTypeParam=0.5f;   //Vertex alpha value

Unfortunately, as posted in the original thread, there doesn't seem to be a way to get around the need to apply the same texture to both texture layers 0 and 1. This is just because of how Irrlicht automatically calls the Direct3D function SetTexture() with each of the 4 texture layers in the material.

I don't suspect that this is enough of an issue to warrant much action on any of the devs' parts, but at least I'll put my request out there: Can we get implemented a means to define which textures get applied to which Texture Stage in Direct3D? Then we could only define the first texture, and tell Direct3D to use that texture for both Texture Stages, leaving us with our other 3 texture layers to be used as we see fit.

Posted: Sat May 24, 2008 2:27 pm
by qez111
I'm getting compiler error when compiling the above class.
.\main.cpp(51) : error C2027: use of undefined type 'IDirect3DDevice9'

and related to it there are other errors...
Any specific header file to be included?

Posted: Sat May 24, 2008 8:59 pm
by Nyxojaele
Yes, you need to include <d3d9.h>

Posted: Sat May 24, 2008 11:09 pm
by qez111
it compiles successfully now.
I have been facing problems with using EMT_LIGHTMAP_M4 or EMT_ONETEXTUREBLEND and emt_transparent_alpha at the same time.
Will it be possible to derive a code from your material example which can do this? Thanks.

Posted: Sun May 25, 2008 9:45 am
by Nyxojaele
Yes, I see no reason why you shouldn't be able to do that, assuming you understand how to set up texture stages.

Posted: Sun May 25, 2008 2:22 pm
by qez111
Can u provide a code on how to do it, if possible? I am not into advanced programming so I don't know quite how to do it..
Thanks..

Posted: Sun May 25, 2008 6:37 pm
by Nyxojaele
I might be able to take a stab at it- but don't get your hopes up, I don't typically dabble in this stuff anymore than I absolutely need for my own purposes.

First question for you tho: Which transparent material type are you referring to? There's no such thing as EMT_TRANSPARENT_ALPHA... Are you talking about perhaps one of these:?
  • EMT_TRANSPARENT_ALPHA_CHANNEL
  • EMT_TRANSPARENT_ALPHA_CHANNEL_REF
  • EMT_TRANSPARENT_VERTEX_ALPHA

Posted: Sun May 25, 2008 11:28 pm
by qez111
oops... I should have mentioned it as EMT_TRANSPARENT_ALPHA_CHANNEL. I want to use this along with EMT_LIGHTMAP_M2.

Posted: Mon May 26, 2008 6:10 pm
by qez111
I have written a material that can use EMT_LIGHTMAP_M2 and EMT_TRANSPARENT_ALPHA_CHANNEL_REF at the same time.
http://irrlicht.sourceforge.net/phpBB2/ ... 641#158641