Transparency: Texture Alpha + Vertex alpha?

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.
Nyxojaele
Posts: 98
Joined: Mon Sep 18, 2006 4:06 am

Transparency: Texture Alpha + Vertex alpha?

Post 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.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post 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.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post 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.
Nyxojaele
Posts: 98
Joined: Mon Sep 18, 2006 4:06 am

Post 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.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post 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.
mk.1
Posts: 76
Joined: Wed Oct 10, 2007 7:37 pm

Post 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
Nyxojaele
Posts: 98
Joined: Mon Sep 18, 2006 4:06 am

Post 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.
qez111
Posts: 54
Joined: Mon Apr 28, 2008 9:44 pm

Post 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?
Nyxojaele
Posts: 98
Joined: Mon Sep 18, 2006 4:06 am

Post by Nyxojaele »

Yes, you need to include <d3d9.h>
qez111
Posts: 54
Joined: Mon Apr 28, 2008 9:44 pm

Post 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.
Nyxojaele
Posts: 98
Joined: Mon Sep 18, 2006 4:06 am

Post 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.
qez111
Posts: 54
Joined: Mon Apr 28, 2008 9:44 pm

Post 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..
Nyxojaele
Posts: 98
Joined: Mon Sep 18, 2006 4:06 am

Post 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
qez111
Posts: 54
Joined: Mon Apr 28, 2008 9:44 pm

Post by qez111 »

oops... I should have mentioned it as EMT_TRANSPARENT_ALPHA_CHANNEL. I want to use this along with EMT_LIGHTMAP_M2.
qez111
Posts: 54
Joined: Mon Apr 28, 2008 9:44 pm

Post 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
Post Reply