Advertisement
Guest User

Untitled

a guest
Jan 30th, 2014
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #ifdef _MSC_VER
  2. // We'll also define this to stop MSVC complaining about sprintf().
  3. #define _CRT_SECURE_NO_WARNINGS
  4. #pragma comment(lib, "Irrlicht_d.lib")
  5. #endif
  6.  
  7. #include <irrlicht.h>
  8. #include <driverChoice.h>
  9.  
  10. using namespace irr;
  11.  
  12. using namespace core;
  13. using namespace scene;
  14. using namespace video;
  15. using namespace io;
  16. using namespace gui;
  17.  
  18. struct StarInst
  19. {
  20. irr::core::matrix4 Transformation;
  21. //irr::f32 Temperature;
  22. //irr::f32 Temperature1;
  23. //irr::f32 Temperature2;
  24. //irr::f32 Temperature3;
  25. bool operator==(const StarInst &other) const
  26. {
  27. if ((this->Transformation == other.Transformation) /*&& (this->Temperature == other.Temperature)*/)
  28. return true;
  29.  
  30.  
  31. return false;
  32. }
  33. };
  34.  
  35.  
  36. class ShaderCB : public video::IShaderConstantSetCallBack
  37. {
  38. public:
  39. ShaderCB(irr::video::E_DRIVER_TYPE currentdriver)
  40. : firstUpdate(true)
  41. {
  42. Currentdriver = currentdriver;
  43. }
  44.  
  45. void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
  46. {
  47. if (firstUpdate)
  48. {
  49. viewProjectionId = services->getVertexShaderConstantID("viewProjection");
  50. firstUpdate = false;
  51. }
  52.  
  53. core::matrix4 viewProjection;
  54. viewProjection = services->getVideoDriver()->getTransform(video::ETS_PROJECTION);
  55. viewProjection *= services->getVideoDriver()->getTransform(video::ETS_VIEW);
  56. services->setVertexShaderConstant(viewProjectionId, viewProjection.pointer(), 16);
  57.  
  58. //setPixelShaderConstant
  59. }
  60.  
  61. private:
  62. irr::video::E_DRIVER_TYPE Currentdriver;
  63. bool firstUpdate;
  64.  
  65. s32 viewProjectionId;
  66. };
  67.  
  68. class InstanceManager : public scene::ISceneNode
  69. {
  70.  
  71. /*
  72. First, we declare some member variables:
  73. The Node array, the mesh buffer, the mesh and the material instanced scenenode
  74. we also need to keep track of the shader callback.
  75. */
  76. video::SMaterial Material;
  77. IMeshBuffer* bBuffer;
  78. IMesh* aMesh;
  79. ShaderCB* callback;
  80. /*Variable to handle shader instancing*/
  81. IMesh* bMesh;
  82. bool fakeinstancing;
  83. //CMeshBuffer dupBuffer;
  84. /*
  85. We treat the instance manager as a scene node so we don't really have to care about it in the future
  86. */
  87. core::aabbox3d<f32> mbb;
  88. public:
  89.  
  90. InstanceManager(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, bool Fakeinstancing)
  91. : scene::ISceneNode(parent, mgr, id)//, dupBuffer( irr::video::E_INDEX_TYPE::EIT_16BIT)
  92. {
  93. fakeinstancing = false;
  94.  
  95. //lodused =0;
  96.  
  97.  
  98. //scene::ISceneNode* bg= mgr->addCubeSceneNode(50000,0,ID_IsNotPickable);
  99. //bg->setMaterialFlag(irr::video::E_MATERIAL_FLAG::EMF_LIGHTING,false);
  100. //bg->setMaterialFlag(irr::video::E_MATERIAL_FLAG::EMF_BACK_FACE_CULLING,false);
  101.  
  102. //shader
  103. s32 mtrlShader = -1;
  104.  
  105. callback = new ShaderCB(mgr->getVideoDriver()->getDriverType());
  106.  
  107. if (mgr->getVideoDriver()->getDriverType() == EDT_OPENGL)
  108. mtrlShader = SceneManager->getVideoDriver()->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("media/shaders/instancing.vert", "", video::EVST_VS_2_0,
  109. "media/shaders/instancing.frag", "", video::EPST_PS_2_0, callback, video::EMT_SOLID);
  110. else if (mgr->getVideoDriver()->getDriverType() == EDT_DIRECT3D9)
  111. mtrlShader = SceneManager->getVideoDriver()->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("../../media/InstancingFVF.hlsl", "vsmain", video::EVST_VS_3_0,
  112. "../../media/InstancingFVF.hlsl", "psmain", video::EPST_PS_3_0, callback, video::EMT_SOLID);
  113. else if (mgr->getVideoDriver()->getDriverType() == EDT_DIRECT3D11)
  114. mtrlShader = SceneManager->getVideoDriver()->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("../../media/InstancingFVF.hlsl", "vsmain", video::EVST_VS_4_0,
  115. "../../media/InstancingFVF.hlsl", "psmain", video::EPST_PS_4_0, callback, video::EMT_SOLID);
  116.  
  117. callback->drop();
  118.  
  119. aMesh = SceneManager->getGeometryCreator()->createSphereMesh(2);
  120. Material.Lighting = false;
  121. Material.setTexture(0, SceneManager->getVideoDriver()->getTexture("../../media/wall.jpg"));
  122. Material.MaterialType = (video::E_MATERIAL_TYPE)mtrlShader;
  123. //Material.BackfaceCulling = false;
  124.  
  125. IVertexDescriptor* index = mgr->getVideoDriver()->getVertexDescriptor("BaseInstanceIndex");
  126.  
  127. if (!index)
  128. {
  129. IVertexDescriptor* stdv = mgr->getVideoDriver()->getVertexDescriptor(0);
  130. index = mgr->getVideoDriver()->addVertexDescriptor("BaseInstanceIndex");
  131.  
  132. for (u32 i = 0; i < stdv->getAttributeCount(); i++)
  133. {
  134. index->addAttribute(stdv->getAttribute(i)->getName(), stdv->getAttribute(i)->getElementCount(), stdv->getAttribute(i)->getSemantic(), stdv->getAttribute(i)->getType(), 0);
  135. }
  136.  
  137. index->addAttribute("InstancingIndex1", 4, EVAS_TEXCOORD1, EVAT_FLOAT, 1);
  138. index->addAttribute("InstancingIndex2", 4, EVAS_TEXCOORD2, EVAT_FLOAT, 1);
  139. index->addAttribute("InstancingIndex3", 4, EVAS_TEXCOORD3, EVAT_FLOAT, 1);
  140. index->addAttribute("InstancingIndex4", 4, EVAS_TEXCOORD4, EVAT_FLOAT, 1);
  141. //index->addAttribute("InstancingIndex5", 4, EVAS_TEXCOORD5, EVAT_FLOAT, 1);
  142. }
  143.  
  144. //dupBuffer.SetvertexDescriptor(Instanced2tcoords);
  145. IVertexBuffer* InstanceIndex = new CVertexBuffer<StarInst>(index);
  146.  
  147. bBuffer = aMesh->getMeshBuffer(0);
  148.  
  149. mgr->getVideoDriver()->setMinHardwareBufferVertexCount(0);
  150. bBuffer->setHardwareMappingHint(scene::EHM_STATIC);
  151. bBuffer->getVertexBuffer()->setVertexDescriptor(index);
  152. InstanceIndex->setHardwareMappingHint(scene::EHM_DYNAMIC);
  153. bBuffer->addVertexBuffer(InstanceIndex);
  154.  
  155. InstanceIndex->drop();
  156. }
  157.  
  158. /*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*/
  159.  
  160. core::array<ISceneNode*> totalNodeArray;
  161.  
  162.  
  163. /*Create an empty scenenode and return the pointer to the user
  164. this empty scene node is used for irrlicht and the user to manage the instance
  165. Each instance can be manipulated individualy through thier own empty scenenode*/
  166. ISceneNode* AddInstance(vector3df pos, f32 scale, vector3df rotation)
  167. {
  168. ISceneNode* empty = SceneManager->addEmptySceneNode();
  169. //empty->grab();
  170. //empty->setParent(NULL);
  171. empty->setPosition(pos);
  172. empty->setScale(vector3df(scale));
  173. empty->setRotation(rotation);
  174. totalNodeArray.push_back(empty);
  175. return empty;
  176. }
  177. /*
  178. we always register this for rendering since visibility is handeled in the sub node
  179. */
  180. virtual void OnRegisterSceneNode()
  181. {
  182. SceneManager->registerNodeForRendering(this);
  183.  
  184. ISceneNode::OnRegisterSceneNode();
  185. }
  186.  
  187. /*
  188. 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
  189. 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
  190. 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
  191. */
  192. virtual void OnAnimate(u32 timeMs)
  193. {
  194. ISceneNode::OnAnimate(timeMs);
  195.  
  196. bBuffer->getVertexBuffer(1)->clear();
  197. mbb.reset(0,0,0);
  198.  
  199. const SViewFrustum* frust = SceneManager->getActiveCamera()->getViewFrustum();
  200. for (u32 i = 0; i<totalNodeArray.size(); i++)
  201. {
  202. //totalNodeArray[i]->OnAnimate(timeMs);
  203. bool cliped = false;
  204. for (s32 e = 0; e<scene::SViewFrustum::VF_PLANE_COUNT; ++e)
  205. if ((frust->planes[e].classifyPointRelation(totalNodeArray[i]->getAbsolutePosition())) == core::EIntersectionRelation3D::ISREL3D_FRONT)
  206. {
  207. // cliped = true;
  208. break;
  209. }
  210. if (!cliped)
  211. {
  212. StarInst currinst;
  213. currinst.Transformation = totalNodeArray[i]->getAbsoluteTransformation();
  214. bBuffer->getVertexBuffer(1)->addVertex(&currinst);
  215. mbb.addInternalPoint(totalNodeArray[i]->getAbsolutePosition());
  216. }
  217. }
  218. bBuffer->getVertexBuffer(1)->setDirty();
  219.  
  220. // std::cout<<bBuffer->getVertexBuffer(1)->getVertexCount()<<std::endl;
  221. }
  222.  
  223. virtual void render()
  224. {
  225. SceneManager->getVideoDriver()->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  226. SceneManager->getVideoDriver()->setMaterial(Material);
  227. int nRemainingBoxes = totalNodeArray.size();
  228.  
  229.  
  230. // if (fakeinstancing == false)
  231.  
  232. SceneManager->getVideoDriver()->drawInstancedMeshBuffer(bBuffer);
  233.  
  234. video::SMaterial m;
  235. m.Lighting = false;
  236. SceneManager->getVideoDriver()->setMaterial(m);
  237.  
  238. for (u32 i = 0; i < totalNodeArray.size(); ++i)
  239. {
  240. core::aabbox3df box = aMesh->getBoundingBox();
  241. totalNodeArray[i]->getAbsoluteTransformation().transformBoxEx(box);
  242. SceneManager->getVideoDriver()->draw3DBox( box, video::SColor(255, 255, 255, 255));
  243. }
  244.  
  245. SceneManager->getVideoDriver()->draw3DBox(mbb, video::SColor(255, 255, 255, 255));
  246. // else
  247. // SceneManager->getVideoDriver()->drawMeshBuffer(&dupBuffer);
  248.  
  249. }
  250.  
  251. /*
  252. 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
  253. */
  254.  
  255. virtual const core::aabbox3d<f32>& getBoundingBox() const
  256. {
  257. return mbb;
  258. }
  259.  
  260. virtual u32 getMaterialCount() const
  261. {
  262. return 1;
  263. }
  264.  
  265. virtual video::SMaterial& getMaterial(u32 i)
  266. {
  267. return Material;
  268. }
  269. };
  270.  
  271. int main()
  272. {
  273.  
  274. video::E_DRIVER_TYPE driverType = driverChoiceConsole();
  275. if (driverType == video::EDT_COUNT)
  276. return 1;
  277. bool usefakeinst = false;
  278. bool animate = false;
  279. char i;
  280.  
  281. printf("Please press 'y' if you want to use Shader Instancing.\n");
  282. std::cin >> i;
  283. if (i == 'y')
  284. {
  285. usefakeinst = true;
  286. }
  287. printf("Please press 'y' if you want each instance to be animated.\n");
  288. std::cin >> i;
  289. if (i == 'y')
  290. {
  291. animate = true;
  292. }
  293. // create device and exit if creation failed
  294.  
  295. IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(800, 600), 32u, false);
  296.  
  297. if (device == 0)
  298. return 1; // could not create selected driver.
  299.  
  300. /* The creation was successful, now we set the event receiver and
  301. store pointers to the driver and to the gui environment. */
  302.  
  303.  
  304. device->setWindowCaption(L"Irrlicht Engine - Hardware Instancing Demo");
  305.  
  306. video::IVideoDriver* driver = device->getVideoDriver();
  307. scene::ISceneManager* smgr = device->getSceneManager();
  308. IGUIEnvironment* env = device->getGUIEnvironment();
  309. InstanceManager* InstancingTest = new InstanceManager(smgr->getRootSceneNode(), smgr, -1, usefakeinst);
  310.  
  311. //!save transformation in one EmptySceneNode which doesn't render itself
  312. f32 scale = 1.5f;
  313. for (f32 i = 0; i<5; i++)
  314. for (f32 j = 1; j<5; j++)
  315. for (f32 k = 0; k<10; k++)
  316. {
  317.  
  318. scene::ISceneNode* empty = InstancingTest->AddInstance(vector3df(i*scale, j*scale, k*scale), scale, vector3df(rand() % 360, rand() % 360, rand() % 360));
  319. if (animate)
  320. {
  321. scene::ISceneNodeAnimator* anim =
  322. smgr->createFlyCircleAnimator(vector3df(i*scale, j*scale, k*scale), rand() / 20, rand()*0.0000001);
  323. if (anim)
  324. {
  325. empty->addAnimator(anim);
  326. anim->drop();
  327. }
  328. }
  329.  
  330. }
  331.  
  332. scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS();
  333. cam->setFarValue(2000);
  334.  
  335. device->getCursorControl()->setVisible(false);
  336.  
  337. InstancingTest->drop();
  338.  
  339. s32 lastFPS = -1;
  340. while (device->run())
  341. {
  342. if (device->isWindowActive())
  343. {
  344. driver->beginScene(true, true, SColor(255, 122, 122, 122));
  345.  
  346. smgr->drawAll();
  347. env->drawAll();
  348.  
  349. driver->endScene();
  350.  
  351. int fps = driver->getFPS();
  352.  
  353. if (lastFPS != fps)
  354. {
  355. core::stringw str = L"fps: ";
  356. str += fps;
  357. str += ", poly: ";
  358. str += driver->getPrimitiveCountDrawn();
  359. str += ", Node count:";
  360. str += InstancingTest->totalNodeArray.size();
  361. device->setWindowCaption(str.c_str());
  362. lastFPS = fps;
  363. }
  364. }
  365. }
  366.  
  367. device->drop();
  368.  
  369. return 0;
  370. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement