For a particle renderer I am developping I needed a new material. So, this material behave exactly as a mix of TRANSPARENT_VERTEX_ALPHA and TRANSPARENT_ADD_COLOR, i.e. using vertex alpha and adding the resulting color instead of modulate it.
Here is the code for DirectX 9:
Code: Select all
class CVertexAlphaAddColorMaterial_D3D9 : public IMaterialRenderer
{
public:
//! Constructor
CVertexAlphaAddColorMaterial_D3D9(irr::video::IVideoDriver* d):IMaterialRenderer()
{
pID3DDevice = Driver->getExposedVideoData().D3D9.D3DDev9;
}
//! Destructor
~CVertexAlphaAddColorMaterial_D3D9() {}
//! Called by the IVideoDriver implementation the let the renderer set its needed render states.
virtual void OnSetMaterial(const irr::video::SMaterial &material, const irr::video::SMaterial &lastMaterial,
bool resetAllRenderstates, irr::video::IMaterialRendererServices *services)
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if(material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
// multiply color of texture and vertices
pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
// set alpha
if(material.MaterialTypeParam==1)
{
pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
}
else
{
pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
}
// disable other textures
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
// add the resulting color to the dest color
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
}
}
//! Returns if the material is transparent.
virtual bool isTransparent() const
{
return true;
}
private:
IDirect3DDevice9* pID3DDevice;
};Code: Select all
class CVertexAlphaAddColorMaterial_OPENGL : public IMaterialRenderer
{
public:
//! Constructor
CVertexAlphaAddColorMaterial_OPENGL(irr::video::COpenGLDriver* d):IMaterialRenderer(),OGLDriver(d)
{
}
//! Destructor
~CVertexAlphaAddColorMaterial_OPENGL() {}
//! Called by the IVideoDriver implementation the let the renderer set its needed render states.
virtual void OnSetMaterial(const irr::video::SMaterial &material, const irr::video::SMaterial &lastMaterial,
bool resetAllRenderstates, irr::video::IMaterialRendererServices *services)
{
OGLDriver->disableTextures(1);
OGLDriver->setActiveTexture(0, material.getTexture(0));
OGLDriver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if(material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
// set texture mode
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
// multiply color of texture and vertices
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PRIMARY_COLOR_EXT );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE);
// set alpha
if(material.MaterialTypeParam==1)
{
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE);
}
else
{
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
}
// add the resulting color to the dest color: source*srcA + dest
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glEnable(GL_BLEND);
}
}
virtual void OnUnsetMaterial()
{
// default values
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_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_PREVIOUS_EXT);
glDisable(GL_BLEND);
}
//! Returns if the material is transparent.
virtual bool isTransparent() const
{
return true;
}
private:
irr::video::COpenGLDriver* OGLDriver;
};
Maybe it can be included in the engine because it can be very useful for particle systems...
While coding this material, I found a bug that I fixed now : https://sourceforge.net/tracker/?func=d ... tid=540678
Hope it can be useful,
Darktib