It seems like I am not the only one who is having trouble with Hardware Instancing on Directx9. So here is my code only draws 1 Instance instead of 1000. When I compile other Directx9 hardware Instancing projects It renders fine. Eventhough I tried various things I still can't figured it out. Any help will be appreciated.
#define MAXINSTANCE 1000
LPD3DXEFFECT Effect;
LPDIRECT3DVERTEXBUFFER9 InstanceVB;
LPDIRECT3DVERTEXDECLARATION9 InstanceDecl;
LPD3DXMESH Box;
LPDIRECT3DVERTEXBUFFER9 BoxVB;
LPDIRECT3DINDEXBUFFER9 BoxIB;
LPDIRECT3DTEXTURE9 Texture;
struct CInstanceData
{
D3DXMATRIX Transform;
};
CInstanceData *InstanceData[MAXINSTANCE];
bool GenerateInstanceInfo();
bool GenerateInstanceInfo()
{
Engine->GetDevice()->CreateVertexBuffer(sizeof(CInstanceData)*MAXINSTANCE,
D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,0,D3DPOOL_DEFAULT,&InstanceVB,0);
CInstanceData *PInstances;
InstanceVB->Lock(0,0,(void**)&PInstances,D3DLOCK_DISCARD);
// THIS IS THE PLACE I GENERATE RANDOM INSTANCE POSITIONS
for(int i=0;i<MAXINSTANCE;i++)
{
InstanceData[i]=new CInstanceData();
D3DXMATRIX RandomMatrix;
D3DXMatrixTranslation(&InstanceData[i]->Transform,Engine->GetRandom(0,200),1.0f,Engine->GetRandom(0,200));
}
InstanceVB->Unlock();
D3DVERTEXELEMENT9 VertexElements[] ={
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{1, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1},
D3DDECL_END()
};
if(FAILED(D3DXCreateEffectFromFile(Engine->GetDevice(),"ManagedInstancing.fx",0,0,0,0,&Effect,0)))
{
::MessageBox(Engine->GetHWND(),"Failed D3DXCreateEffectFromFile(InstanceEffect)","ERROR",MB_OK);
}
if(FAILED(Engine->GetDevice()->CreateVertexDeclaration(VertexElements, &InstanceDecl)))
{
::MessageBox(Engine->GetHWND(),"Failed CreateVertexDeclaration(InstanceDecl)","ERROR",MB_OK);
return false;
}
D3DXLoadMeshFromX("Box.x",0,Engine->GetDevice(),0,0,0,0,&Box);
if(FAILED(Box->GetVertexBuffer(&BoxVB)))
{
::MessageBox(0,"Box->GetVertexBuffer()","ERROR",MB_OK);
return false;
}
if(FAILED(Box->GetIndexBuffer(&BoxIB)))
{
::MessageBox(Engine->GetHWND(),"Box->GetIndexBuffer()","ERROR",MB_OK);
return false;
}
return true;
D3DXCreateTextureFromFile(Engine->GetDevice(),"Box.jpg",&Texture);
}
bool SetupScene()
{
Engine->Setup(1024,768,false);
Camera->SetProjection(45.0f,1024/768,1.0f,5000.0f);
Engine->SetupFps();
GenerateInstanceInfo();
return true;
}
void RenderScene()
{
GameInput->detectInput();
SceneInput();
Engine->BEGINRENDER(119,136,153);
Engine->ShowFPS();
D3DXMATRIX PWorld;
D3DXMatrixIdentity(&PWorld);
D3DXMatrixTranslation(&PWorld,0,0,0);
Effect->SetTechnique( "BatchedShaderInstancing" );
Effect->SetMatrix( "ViewProjection", &(Camera->GetViewProj()));
Effect->SetTexture("Tex0",Texture);
UINT Pass, Passes;
Effect->Begin(&Passes, 0);
for (Pass = 0; Pass < Passes; Pass++)
{
Engine->GetDevice()->SetStreamSourceFreq(0,D3DSTREAMSOURCE_INDEXEDDATA | MAXINSTANCE);
Engine->GetDevice()->SetStreamSource(0,BoxVB,0,Box->GetNumBytesPerVertex());
Engine->GetDevice()->SetStreamSourceFreq(1,D3DSTREAMSOURCE_INSTANCEDATA | 1);
Engine->GetDevice()->SetStreamSource(1,InstanceVB,0,sizeof(InstanceData));
Engine->GetDevice()->SetVertexDeclaration(InstanceDecl);
Engine->GetDevice()->SetIndices(BoxIB);
Engine->GetDevice()->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0,Box->GetNumVertices(), 0, Box->GetNumFaces() );
Engine->GetDevice()->SetStreamSourceFreq( 0, 1 );
Engine->GetDevice()->SetStreamSourceFreq( 1, 1 );
Effect->EndPass();
}
Effect->End();
Engine->ENDRENDER();
}
And here is the shader I am Using.
//--------------------------------------------------------------------------------------
// File: ManagedInstancing.fx
//
// The effect file for the ManagedInstancing sample.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
float4x4 ViewProjection; // View * Projection matrix
texture Tex0;
sampler Tex0Sampler=
sampler_state
{
Texture = <Tex0>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
//application to vertex structure
struct a2v
{
float4 position : POSITION0;
float3 normal : NORMAL;
float2 tex0 : TEXCOORD0;
float4 instanceData : COLOR0;
};
//vertex to pixel shader structure
struct v2p
{
float4 position : POSITION0;
float2 tex0 : TEXCOORD0;
float texIndex : TEXCOORD1; // yeah, right
};
//pixel shader to screen
struct p2f
{
float4 color : COLOR0;
};
void ps( in v2p IN, out p2f OUT)
{
float2 tex0 = IN.tex0;
tex0.x = (tex0.x + IN.texIndex) / 4; // shift u texcoord to appropriate index
OUT.color = tex2D(Tex0Sampler, tex0);
};
void vs( in a2v IN, out v2p OUT )
{
float4 data = IN.instanceData;
float4 instancePos = IN.position;
instancePos.x += data.x;
instancePos.y += data.y;
instancePos.z += data.z;
OUT.texIndex = data.w;
OUT.position = mul(instancePos, ViewProjection);
OUT.tex0 = IN.tex0;
};
//--------------------------------------------------------------------------------------
// Techniques
//--------------------------------------------------------------------------------------
technique BatchedShaderInstancing
{
pass P0
{
VertexShader = compile vs_2_0 vs();
PixelShader = compile ps_2_0 ps();
}
}