New transparent material

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Darktib
Posts: 167
Joined: Sun Mar 23, 2008 8:25 pm
Location: France

New transparent material

Post by Darktib »

Hello,

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;
};
and here for Opengl:

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;
};
Note: for OpenGL you'll need to setup 'Driver' with COpenGLDriver, so it must be recompiled with the engine.

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
Frank Dodd
Posts: 208
Joined: Sun Apr 02, 2006 9:20 pm

Post by Frank Dodd »

EDIT: Working this in I did not get the desired effect and the posted bug fix will not compile as there are no such OpenGL definitions.

Hi DarkTib,

Do you mind if I include this into my irrlicht wrapper, I believe its exactly what I need for fading out particles over distance.

Thank you very much for contributing this.
Last edited by Frank Dodd on Tue Jun 15, 2010 7:36 pm, edited 1 time in total.
Darktib
Posts: 167
Joined: Sun Mar 23, 2008 8:25 pm
Location: France

Post by Darktib »

You can use it the way you want ;)

Anyway, this material was made for the SPARK Particle Engine Irrlicht renderer.
Post Reply