Here is code for new material that use texture with alpha channel AND user-defined alpha-blend parameter. So now you can fade-in/fade-out objects in a flash (or in the animator) even if it has nice semitransparent texture on it. BUT there are some limitations: material uses texture 0 and texture 1 (they should point on the same texture for sprite behaviour), but you can load independent texture to slot 1 for very interesting effects.
To use it:
Code: Select all
CSpriteMat mt(driver->getExposedVideoData().D3D8.D3DDev8,driver);
s32 newMat=driver->addMaterialRenderer(&mt);
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;
billMat3->getMaterial(0).MaterialTypeParam=0.5f;
Class itself
Code: Select all
//! Transparent alpha channel material renderer
class CSpriteMat : public IMaterialRenderer
{
public:
IDirect3DDevice8* pID3DDevice;
video::IVideoDriver* Driver;
CSpriteMat(IDirect3DDevice8* p, video::IVideoDriver* d)
: pID3DDevice(p),Driver(d) {}
virtual void OnSetMaterial(SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services)
{
if (material.MaterialType != lastMaterial.MaterialType
|| material.MaterialTypeParam != lastMaterial.MaterialTypeParam
|| resetAllRenderstates)
{
s32 blendValue=(255*material.MaterialTypeParam);
pID3DDevice->SetRenderState( D3DRS_TEXTUREFACTOR , (blendValue << 24) | 0x00000000 );
pID3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_CURRENT );
pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
pID3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
pID3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pID3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
pID3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
pID3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG2, D3DTA_TEXTURE );
pID3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_BLENDFACTORALPHA);
pID3DDevice->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
pID3DDevice->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
s32 refValue = (s32)(material.MaterialTypeParam2 * 255);
if (refValue){
pID3DDevice->SetRenderState(D3DRS_ALPHAREF, refValue);
pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
}
}
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
}
virtual void OnUnsetMaterial()
{
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
}
//! Returns if the material is transparent.
virtual bool isTransparent()
{
return true;
}
};
P.S. may be the code (and renderStates) are not efficient... it would be good to hear any comments from anyone expirienced, expecially with perfomance impact of this material. may be it is possible to optimize renderState switching? or i`m miss something obvious?