(C++) Material with Diffuse color + Vertex color (D3D9)

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
Klasker
Posts: 230
Joined: Thu May 20, 2004 8:53 am
Contact:

(C++) Material with Diffuse color + Vertex color (D3D9)

Post by Klasker »

The current materials ignore the diffuse color, and use the vertex color instead. That's very inconvenient when we wish to change the color of an entire model, and changing the vertex colors is slow and sometimes not an option. So here is a solid material for Direct3D 9 that multiplies texture color, vertex color and material diffuse color together.
NOTE: You need the DirectX SDK installed to compile it, because the source file includes <d3d9.h>.

CD3D9SolidVMDiffuseMaterial.h

Code: Select all

#ifndef _C_D3D9_SOLID_VM_DIFFUSE_MATERIAL_H_
#define _C_D3D9_SOLID_VM_DIFFUSE_MATERIAL_H_

#include <irrlicht.h>

class IDirect3DDevice9;

namespace irr
{
namespace video
{

class CD3D9SolidVMDiffuseMaterial : public IMaterialRenderer
{
public:
    static s32 MaterialType;
    
    CD3D9SolidVMDiffuseMaterial( IVideoDriver* driver );

	virtual void OnSetMaterial(SMaterial& material, const SMaterial& lastMaterial,
		bool resetAllRenderstates, IMaterialRendererServices* services);

private:    
    IVideoDriver* VideoDriver;
    IDirect3DDevice9* pID3DDevice;
};
    
} // namespace video
} // namespace irr

#endif
CD3D9SolidVMDiffuseMaterial.cpp

Code: Select all

#include <d3d9.h>

#include "CD3D9SolidVMDiffuseMaterial.h"

namespace irr
{
namespace video
{

s32 CD3D9SolidVMDiffuseMaterial::MaterialType = -1;

CD3D9SolidVMDiffuseMaterial::CD3D9SolidVMDiffuseMaterial( IVideoDriver* driver )
{
    VideoDriver = driver;
    pID3DDevice = VideoDriver->getExposedVideoData().D3D9.D3DDev9;
}

void CD3D9SolidVMDiffuseMaterial::OnSetMaterial(SMaterial& material, const SMaterial& lastMaterial,
		bool resetAllRenderstates, IMaterialRendererServices* services)
{
    if (material.MaterialType != lastMaterial.MaterialType|| resetAllRenderstates)
    {
        pID3DDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL );
        
        pID3DDevice->SetTextureStageState (0, D3DTSS_COLOROP, D3DTOP_MODULATE);
        pID3DDevice->SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
        pID3DDevice->SetTextureStageState (0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
        pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAOP,  D3DTOP_DISABLE);
        
        pID3DDevice->SetTextureStageState (1, D3DTSS_COLOROP, D3DTOP_MODULATE);
        pID3DDevice->SetTextureStageState (1, D3DTSS_COLORARG1, D3DTA_CURRENT );
        pID3DDevice->SetTextureStageState (1, D3DTSS_COLORARG2, D3DTA_CONSTANT);
        pID3DDevice->SetTextureStageState (1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
        
        pID3DDevice->SetTextureStageState (1, D3DTSS_CONSTANT, (DWORD)material.DiffuseColor.color);
    }
    else if ( material.DiffuseColor != lastMaterial.DiffuseColor )
    {
        pID3DDevice->SetTextureStageState (1, D3DTSS_CONSTANT, (DWORD)material.DiffuseColor.color);
    }
    
    pID3DDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE);
    pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}

    
} // namespace video
} // namespace irr
A better solution might be to use shaders, but maybe this is faster (I dunno). So use it, do like this:

Code: Select all

video::CD3D9SolidVMDiffuseMaterial* vm = new video::CD3D9SolidVMDiffuseMaterial();
video::CD3D9SolidVMDiffuseMaterial::MaterialType = driver->addMaterialRenderer(vm);
vm->drop();

// ...

node->setMaterialType( (video::E_MATERIAL_TYPE)video::CD3D9SolidVMDiffuseMaterial::MaterialType );
Maybe the same can be done for the transparent materials, so we can finally fade out scene nodes by changing the diffuse color's alpha value. But since I just switched to Linux I can't develop any more D3D9 materials.
Post Reply