Thanks slavik262.
http://irrlicht.sourceforge.net/phpBB2/ ... 03984e737e
Question:
the clipping issue is not solved in this example, do you have any suggestions?
The standalone source file.
Code: Select all
#include <irrlicht.h>
#pragma comment(lib,"irrlicht.lib")
#pragma warning( disable: 4244 )
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
IrrlichtDevice* device = 0;
scene::ISceneManager* smgr = 0;
video::IVideoDriver* driver = 0;
gui::IGUIEnvironment* env = 0;
scene::ISceneCollisionManager* coll = 0;
scene::IMeshManipulator* mm = 0;
video::IGPUProgrammingServices* gpu = 0;
bool initIrrlicht(s32 w, s32 h, bool opengl = true, s32 bpp=32, bool fullscreen=false, bool stentil = false);
const int NUM_BATCH_INSTANCES = 60;
core::matrix4 instanceWorldArray[NUM_BATCH_INSTANCES];
core::array<ISceneNode*> totalNodeArray;
core::matrix4 viewProjection;
struct InstancingShaderCB : public video::IShaderConstantSetCallBack
{
void OnSetConstants(video::IMaterialRendererServices* services,
s32 userData)
{
services->setVertexShaderConstant("instanceWorldArray", (f32*)instanceWorldArray, 16*NUM_BATCH_INSTANCES);
services->setVertexShaderConstant("viewProjection", viewProjection.pointer(), 16);
}
};
s32 addHighLevelShader(const c8* shader_file, const c8* vs_entry, const c8* ps_entry,
IShaderConstantSetCallBack* callback,
E_MATERIAL_TYPE baseMateria = video::EMT_SOLID)
{
const c8* ps_file = ps_entry ? shader_file : NULL;
return gpu->addHighLevelShaderMaterialFromFiles(
shader_file, vs_entry, video::EVST_VS_2_0,
ps_file, ps_entry, video::EPST_PS_2_0,
callback, baseMateria);
}
int main()
{
if (!initIrrlicht(800,800,false))
return -1;
device->setWindowCaption(L"instancing");
//mesh generation
IMesh* aMesh = smgr->getGeometryCreator()->createSphereMesh(4,4,4);
IMesh* bMesh = mm->createMeshWith2TCoords(aMesh);
IMeshBuffer* bBuffer = bMesh->getMeshBuffer(0);
//create dupBuffer with bBuffer repeated NUM_BATCH_INSTANCES times
SMeshBufferLightMap dupBuffer;
for (int k=0;k<NUM_BATCH_INSTANCES;k++)
{
S3DVertex2TCoords* verts = (S3DVertex2TCoords*)bBuffer->getVertices();
for (u32 i=0; i<bBuffer->getVertexCount(); ++i)
{
verts[i].TCoords2.X = k;//assign the index of instance that each vertex belongs to
}
dupBuffer.append(bBuffer);
}
aMesh->drop();
bMesh->drop();
//save transformation in one EmptySceneNode which doesn't render itself
f32 scale = 18;
for (u32 i=0;i<10;i++)
for (u32 j=0;j<10;j++)
for (u32 k=0;k<10;k++)
{
ISceneNode* empty = smgr->addEmptySceneNode();
empty->setPosition(vector3df(i*scale,j*scale,k*scale));
empty->setScale(vector3df(1+rand()%2));
empty->setRotation(vector3df(rand()%255,rand()%255,rand()%255));
totalNodeArray.push_back(empty);
}
smgr->addCameraSceneNodeFPS();
SMaterial mtrl;
//shader
s32 mtrlShader = addHighLevelShader("../../media/instancing.hlsl", "vs_main", NULL,
new InstancingShaderCB);
mtrl.Lighting = false;
mtrl.setTexture(0, driver->getTexture("../../media/fire.bmp"));
mtrl.MaterialType = (video::E_MATERIAL_TYPE)mtrlShader;
while(device->run())
{
if (device->isWindowActive())
{
driver->beginScene(true, true, SColor(255,122,122,122));
viewProjection = driver->getTransform(video::ETS_PROJECTION);
viewProjection *= driver->getTransform(video::ETS_VIEW);
smgr->drawAll();
{
driver->setMaterial(mtrl);
int nRemainingBoxes = totalNodeArray.size();
int node_idx = 0;
while( nRemainingBoxes > 0)
{
int nRenderBoxes = core::min_( nRemainingBoxes, NUM_BATCH_INSTANCES );
nRemainingBoxes -= nRenderBoxes;
for (int i=0;i<nRenderBoxes;i++)
{
instanceWorldArray[i] = totalNodeArray[node_idx++]->getAbsoluteTransformation();
}
driver->drawMeshBuffer(&dupBuffer);
}
}
env->drawAll();
driver->endScene();
u32 fps = driver->getFPS();
u32 nPolygons = driver->getPrimitiveCountDrawn();
wchar_t info[256];
swprintf(info, L"fps: %d, poly: %d", fps, nPolygons);
device->setWindowCaption(info);
}
}
device->drop();
return 0;
}
bool initIrrlicht(s32 w, s32 h, bool opengl, s32 bpp, bool fullscreen, bool stentil)
{
SIrrlichtCreationParameters param;
param.WindowSize = core::dimension2d<u32>(w, h);
param.AntiAlias = true;
param.Fullscreen = fullscreen;
param.Bits = bpp;
param.Stencilbuffer = stentil;
param.DriverType = opengl ? EDT_OPENGL : EDT_DIRECT3D9;
device = createDeviceEx(param);
if (device)
{
driver = device->getVideoDriver();
env = device->getGUIEnvironment();
//driver->setTextureCreationFlag(ETCF_ALWAYS_32_BIT,true);
smgr = device->getSceneManager();
coll = smgr->getSceneCollisionManager();
mm = smgr->getMeshManipulator();
gpu = driver->getGPUProgrammingServices();
//setCursorVisible(false);
return true;
}
else
return false;
}
The shader is directly taken from slavik262's post.
Code: Select all
float4x4 viewProjection;
#define NUM_BATCH_INSTANCES 60
float4x4 instanceWorldArray[NUM_BATCH_INSTANCES];
struct VertexInput
{
float3 position: POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
float2 uv2 : TEXCOORD1;
float4 color : COLOR0;
};
struct VertexOutput
{
float4 screenPos : POSITION;
float4 color : COLOR0;
float2 uv : TEXCOORD0;
};
VertexOutput vs_main(VertexInput IN)
{
VertexOutput OUT = (VertexOutput)0;
int index = IN.uv2.x;
float4x4 WVP = mul(instanceWorldArray[index], viewProjection);
OUT.screenPos = mul(float4(IN.position,1), WVP);
OUT.color = IN.color;
OUT.uv = IN.uv;
return OUT;
}
And the screen capture
admin-edit: Removed screenshot link as it didn't show, but instead brought up a dialog requestiong a password.