Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifdef _MSC_VER
- // We'll also define this to stop MSVC complaining about sprintf().
- #define _CRT_SECURE_NO_WARNINGS
- #pragma comment(lib, "Irrlicht_d.lib")
- #endif
- #include <irrlicht.h>
- #include <driverChoice.h>
- using namespace irr;
- using namespace core;
- using namespace scene;
- using namespace video;
- using namespace io;
- using namespace gui;
- struct StarInst
- {
- irr::core::matrix4 Transformation;
- //irr::f32 Temperature;
- //irr::f32 Temperature1;
- //irr::f32 Temperature2;
- //irr::f32 Temperature3;
- bool operator==(const StarInst &other) const
- {
- if ((this->Transformation == other.Transformation) /*&& (this->Temperature == other.Temperature)*/)
- return true;
- return false;
- }
- };
- class ShaderCB : public video::IShaderConstantSetCallBack
- {
- public:
- ShaderCB(irr::video::E_DRIVER_TYPE currentdriver)
- : firstUpdate(true)
- {
- Currentdriver = currentdriver;
- }
- void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
- {
- if (firstUpdate)
- {
- viewProjectionId = services->getVertexShaderConstantID("viewProjection");
- firstUpdate = false;
- }
- core::matrix4 viewProjection;
- viewProjection = services->getVideoDriver()->getTransform(video::ETS_PROJECTION);
- viewProjection *= services->getVideoDriver()->getTransform(video::ETS_VIEW);
- services->setVertexShaderConstant(viewProjectionId, viewProjection.pointer(), 16);
- //setPixelShaderConstant
- }
- private:
- irr::video::E_DRIVER_TYPE Currentdriver;
- bool firstUpdate;
- s32 viewProjectionId;
- };
- class InstanceManager : public scene::ISceneNode
- {
- /*
- First, we declare some member variables:
- The Node array, the mesh buffer, the mesh and the material instanced scenenode
- we also need to keep track of the shader callback.
- */
- video::SMaterial Material;
- IMeshBuffer* bBuffer;
- IMesh* aMesh;
- ShaderCB* callback;
- /*Variable to handle shader instancing*/
- IMesh* bMesh;
- bool fakeinstancing;
- //CMeshBuffer dupBuffer;
- /*
- We treat the instance manager as a scene node so we don't really have to care about it in the future
- */
- core::aabbox3d<f32> mbb;
- public:
- InstanceManager(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, bool Fakeinstancing)
- : scene::ISceneNode(parent, mgr, id)//, dupBuffer( irr::video::E_INDEX_TYPE::EIT_16BIT)
- {
- fakeinstancing = false;
- //lodused =0;
- //scene::ISceneNode* bg= mgr->addCubeSceneNode(50000,0,ID_IsNotPickable);
- //bg->setMaterialFlag(irr::video::E_MATERIAL_FLAG::EMF_LIGHTING,false);
- //bg->setMaterialFlag(irr::video::E_MATERIAL_FLAG::EMF_BACK_FACE_CULLING,false);
- //shader
- s32 mtrlShader = -1;
- callback = new ShaderCB(mgr->getVideoDriver()->getDriverType());
- if (mgr->getVideoDriver()->getDriverType() == EDT_OPENGL)
- mtrlShader = SceneManager->getVideoDriver()->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("media/shaders/instancing.vert", "", video::EVST_VS_2_0,
- "media/shaders/instancing.frag", "", video::EPST_PS_2_0, callback, video::EMT_SOLID);
- else if (mgr->getVideoDriver()->getDriverType() == EDT_DIRECT3D9)
- mtrlShader = SceneManager->getVideoDriver()->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("../../media/InstancingFVF.hlsl", "vsmain", video::EVST_VS_3_0,
- "../../media/InstancingFVF.hlsl", "psmain", video::EPST_PS_3_0, callback, video::EMT_SOLID);
- else if (mgr->getVideoDriver()->getDriverType() == EDT_DIRECT3D11)
- mtrlShader = SceneManager->getVideoDriver()->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("../../media/InstancingFVF.hlsl", "vsmain", video::EVST_VS_4_0,
- "../../media/InstancingFVF.hlsl", "psmain", video::EPST_PS_4_0, callback, video::EMT_SOLID);
- callback->drop();
- aMesh = SceneManager->getGeometryCreator()->createSphereMesh(2);
- Material.Lighting = false;
- Material.setTexture(0, SceneManager->getVideoDriver()->getTexture("../../media/wall.jpg"));
- Material.MaterialType = (video::E_MATERIAL_TYPE)mtrlShader;
- //Material.BackfaceCulling = false;
- IVertexDescriptor* index = mgr->getVideoDriver()->getVertexDescriptor("BaseInstanceIndex");
- if (!index)
- {
- IVertexDescriptor* stdv = mgr->getVideoDriver()->getVertexDescriptor(0);
- index = mgr->getVideoDriver()->addVertexDescriptor("BaseInstanceIndex");
- for (u32 i = 0; i < stdv->getAttributeCount(); i++)
- {
- index->addAttribute(stdv->getAttribute(i)->getName(), stdv->getAttribute(i)->getElementCount(), stdv->getAttribute(i)->getSemantic(), stdv->getAttribute(i)->getType(), 0);
- }
- index->addAttribute("InstancingIndex1", 4, EVAS_TEXCOORD1, EVAT_FLOAT, 1);
- index->addAttribute("InstancingIndex2", 4, EVAS_TEXCOORD2, EVAT_FLOAT, 1);
- index->addAttribute("InstancingIndex3", 4, EVAS_TEXCOORD3, EVAT_FLOAT, 1);
- index->addAttribute("InstancingIndex4", 4, EVAS_TEXCOORD4, EVAT_FLOAT, 1);
- //index->addAttribute("InstancingIndex5", 4, EVAS_TEXCOORD5, EVAT_FLOAT, 1);
- }
- //dupBuffer.SetvertexDescriptor(Instanced2tcoords);
- IVertexBuffer* InstanceIndex = new CVertexBuffer<StarInst>(index);
- bBuffer = aMesh->getMeshBuffer(0);
- mgr->getVideoDriver()->setMinHardwareBufferVertexCount(0);
- bBuffer->setHardwareMappingHint(scene::EHM_STATIC);
- bBuffer->getVertexBuffer()->setVertexDescriptor(index);
- InstanceIndex->setHardwareMappingHint(scene::EHM_DYNAMIC);
- bBuffer->addVertexBuffer(InstanceIndex);
- InstanceIndex->drop();
- }
- /*The node array is put here to be public only for the purpose of the demo in the future a function coud take care of this without having it public*/
- core::array<ISceneNode*> totalNodeArray;
- /*Create an empty scenenode and return the pointer to the user
- this empty scene node is used for irrlicht and the user to manage the instance
- Each instance can be manipulated individualy through thier own empty scenenode*/
- ISceneNode* AddInstance(vector3df pos, f32 scale, vector3df rotation)
- {
- ISceneNode* empty = SceneManager->addEmptySceneNode();
- //empty->grab();
- //empty->setParent(NULL);
- empty->setPosition(pos);
- empty->setScale(vector3df(scale));
- empty->setRotation(rotation);
- totalNodeArray.push_back(empty);
- return empty;
- }
- /*
- we always register this for rendering since visibility is handeled in the sub node
- */
- virtual void OnRegisterSceneNode()
- {
- SceneManager->registerNodeForRendering(this);
- ISceneNode::OnRegisterSceneNode();
- }
- /*
- In the render() method most of the interesting stuff happens: The manager goes through the node array and upload thier matrices to the shader callback
- In OpenGL we render per batches of 248 and in dx per batches of 62 this is due to the amount of variable register availible being diferent in both drivers
- in the future if a vertex texture patch is accepted both could be made to render every node in a single draw call and fetch thier matrices from a texture
- */
- virtual void OnAnimate(u32 timeMs)
- {
- ISceneNode::OnAnimate(timeMs);
- bBuffer->getVertexBuffer(1)->clear();
- mbb.reset(0,0,0);
- const SViewFrustum* frust = SceneManager->getActiveCamera()->getViewFrustum();
- for (u32 i = 0; i<totalNodeArray.size(); i++)
- {
- //totalNodeArray[i]->OnAnimate(timeMs);
- bool cliped = false;
- for (s32 e = 0; e<scene::SViewFrustum::VF_PLANE_COUNT; ++e)
- if ((frust->planes[e].classifyPointRelation(totalNodeArray[i]->getAbsolutePosition())) == core::EIntersectionRelation3D::ISREL3D_FRONT)
- {
- // cliped = true;
- break;
- }
- if (!cliped)
- {
- StarInst currinst;
- currinst.Transformation = totalNodeArray[i]->getAbsoluteTransformation();
- bBuffer->getVertexBuffer(1)->addVertex(&currinst);
- mbb.addInternalPoint(totalNodeArray[i]->getAbsolutePosition());
- }
- }
- bBuffer->getVertexBuffer(1)->setDirty();
- // std::cout<<bBuffer->getVertexBuffer(1)->getVertexCount()<<std::endl;
- }
- virtual void render()
- {
- SceneManager->getVideoDriver()->setTransform(video::ETS_WORLD, AbsoluteTransformation);
- SceneManager->getVideoDriver()->setMaterial(Material);
- int nRemainingBoxes = totalNodeArray.size();
- // if (fakeinstancing == false)
- SceneManager->getVideoDriver()->drawInstancedMeshBuffer(bBuffer);
- video::SMaterial m;
- m.Lighting = false;
- SceneManager->getVideoDriver()->setMaterial(m);
- for (u32 i = 0; i < totalNodeArray.size(); ++i)
- {
- core::aabbox3df box = aMesh->getBoundingBox();
- totalNodeArray[i]->getAbsoluteTransformation().transformBoxEx(box);
- SceneManager->getVideoDriver()->draw3DBox( box, video::SColor(255, 255, 255, 255));
- }
- SceneManager->getVideoDriver()->draw3DBox(mbb, video::SColor(255, 255, 255, 255));
- // else
- // SceneManager->getVideoDriver()->drawMeshBuffer(&dupBuffer);
- }
- /*
- Here we return the bounding box for the whole instance batch to make sure the node does not get culled wen there is still even a single instance in the view fulstrum
- */
- virtual const core::aabbox3d<f32>& getBoundingBox() const
- {
- return mbb;
- }
- virtual u32 getMaterialCount() const
- {
- return 1;
- }
- virtual video::SMaterial& getMaterial(u32 i)
- {
- return Material;
- }
- };
- int main()
- {
- video::E_DRIVER_TYPE driverType = driverChoiceConsole();
- if (driverType == video::EDT_COUNT)
- return 1;
- bool usefakeinst = false;
- bool animate = false;
- char i;
- printf("Please press 'y' if you want to use Shader Instancing.\n");
- std::cin >> i;
- if (i == 'y')
- {
- usefakeinst = true;
- }
- printf("Please press 'y' if you want each instance to be animated.\n");
- std::cin >> i;
- if (i == 'y')
- {
- animate = true;
- }
- // create device and exit if creation failed
- IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(800, 600), 32u, false);
- if (device == 0)
- return 1; // could not create selected driver.
- /* The creation was successful, now we set the event receiver and
- store pointers to the driver and to the gui environment. */
- device->setWindowCaption(L"Irrlicht Engine - Hardware Instancing Demo");
- video::IVideoDriver* driver = device->getVideoDriver();
- scene::ISceneManager* smgr = device->getSceneManager();
- IGUIEnvironment* env = device->getGUIEnvironment();
- InstanceManager* InstancingTest = new InstanceManager(smgr->getRootSceneNode(), smgr, -1, usefakeinst);
- //!save transformation in one EmptySceneNode which doesn't render itself
- f32 scale = 1.5f;
- for (f32 i = 0; i<5; i++)
- for (f32 j = 1; j<5; j++)
- for (f32 k = 0; k<10; k++)
- {
- scene::ISceneNode* empty = InstancingTest->AddInstance(vector3df(i*scale, j*scale, k*scale), scale, vector3df(rand() % 360, rand() % 360, rand() % 360));
- if (animate)
- {
- scene::ISceneNodeAnimator* anim =
- smgr->createFlyCircleAnimator(vector3df(i*scale, j*scale, k*scale), rand() / 20, rand()*0.0000001);
- if (anim)
- {
- empty->addAnimator(anim);
- anim->drop();
- }
- }
- }
- scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS();
- cam->setFarValue(2000);
- device->getCursorControl()->setVisible(false);
- InstancingTest->drop();
- s32 lastFPS = -1;
- while (device->run())
- {
- if (device->isWindowActive())
- {
- driver->beginScene(true, true, SColor(255, 122, 122, 122));
- smgr->drawAll();
- env->drawAll();
- driver->endScene();
- int fps = driver->getFPS();
- if (lastFPS != fps)
- {
- core::stringw str = L"fps: ";
- str += fps;
- str += ", poly: ";
- str += driver->getPrimitiveCountDrawn();
- str += ", Node count:";
- str += InstancingTest->totalNodeArray.size();
- device->setWindowCaption(str.c_str());
- lastFPS = fps;
- }
- }
- }
- device->drop();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement