main.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /** Example 013 Render To Texture
  2. This tutorial shows how to render to a texture using Irrlicht. Render to
  3. texture is a feature where everything which would usually be rendered to
  4. the screen is instead written to a (special) texture. This can be used to
  5. create nice special effects.
  6. In addition, this tutorial shows how to enable specular highlights.
  7. In the beginning, everything as usual. Include the needed headers, ask the user
  8. for the rendering driver, create the Irrlicht device:
  9. */
  10. #include <irrlicht.h>
  11. #include "driverChoice.h"
  12. #include "exampleHelper.h"
  13. using namespace irr;
  14. #ifdef _MSC_VER
  15. #pragma comment(lib, "Irrlicht.lib")
  16. #endif
  17. int main()
  18. {
  19. // ask user for driver
  20. video::E_DRIVER_TYPE driverType=driverChoiceConsole();
  21. if (driverType==video::EDT_COUNT)
  22. return 1;
  23. // create device and exit if creation failed
  24. IrrlichtDevice *device =
  25. createDevice(driverType, core::dimension2d<u32>(640, 480),
  26. 16, false, false);
  27. if (device == 0)
  28. return 1; // could not create selected driver.
  29. video::IVideoDriver* driver = device->getVideoDriver();
  30. scene::ISceneManager* smgr = device->getSceneManager();
  31. gui::IGUIEnvironment* env = device->getGUIEnvironment();
  32. const io::path mediaPath = getExampleMediaPath();
  33. /*
  34. Now, we load an animated mesh to be displayed. As in most examples,
  35. we'll take the fairy md2 model. The difference here: We set the
  36. shininess of the model to a value other than 0 which is the default
  37. value. This enables specular highlights on the model if dynamic
  38. lighting is on. The value influences the size of the highlights.
  39. */
  40. // load and display animated fairy mesh
  41. scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode(
  42. smgr->getMesh(mediaPath + "faerie.md2"));
  43. if (fairy)
  44. {
  45. fairy->setMaterialTexture(0,
  46. driver->getTexture(mediaPath + "faerie2.bmp")); // set diffuse texture
  47. fairy->setMaterialFlag(video::EMF_LIGHTING, true); // enable dynamic lighting
  48. fairy->getMaterial(0).Shininess = 20.0f; // set size of specular highlights
  49. fairy->setPosition(core::vector3df(-10,0,-100));
  50. fairy->setMD2Animation ( scene::EMAT_STAND );
  51. }
  52. /*
  53. To make specular highlights appear on the model, we need a dynamic
  54. light in the scene. We add one directly in vicinity of the model. In
  55. addition, to make the model not that dark, we set the ambient light to
  56. gray.
  57. */
  58. // add white light
  59. smgr->addLightSceneNode(0, core::vector3df(-15,5,-105),
  60. video::SColorf(1.0f, 1.0f, 1.0f));
  61. // set ambient light
  62. smgr->setAmbientLight(video::SColor(0,60,60,60));
  63. /*
  64. The next is just some standard stuff: Add a test cube and let it rotate
  65. to make the scene more interesting. The user defined camera and cursor
  66. setup is made later on, right before the render loop.
  67. */
  68. // create test cube
  69. scene::ISceneNode* cube = smgr->addCubeSceneNode(60);
  70. // let the cube rotate and set some light settings
  71. scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(
  72. core::vector3df(0.3f, 0.3f,0));
  73. cube->setPosition(core::vector3df(-100,0,-100));
  74. cube->setMaterialFlag(video::EMF_LIGHTING, false); // disable dynamic lighting
  75. cube->addAnimator(anim);
  76. anim->drop();
  77. // set window caption
  78. device->setWindowCaption(L"Irrlicht Engine - Render to Texture and Specular Highlights example");
  79. /*
  80. To test out the render to texture feature, we need to define our
  81. new rendertarget. The rendertarget will need one texture to receive
  82. the result you would otherwise see on screen and one texture
  83. which is used as depth-buffer.
  84. (Note: If you worked with older Irrlicht versions (before 1.9) you might be
  85. used to only create a rendertarget texture and no explicit rendertarget. While
  86. that's still possible, it's no longer recommended.)
  87. The rendertarget textures are not like standard textures, but need to be created
  88. first. To create them, we call IVideoDriver::addRenderTargetTexture()
  89. and specify the size of the texture and the type.
  90. For depth-maps you can use types ECF_D16, ECF_D32 or ECF_D24S8. When ECF_D24S8
  91. you can also use a stencil-buffer.
  92. Because we want to render the scene not from the user camera into the
  93. texture, we add another fixed camera to the scene. But before we do all
  94. this, we check if the current running driver is able to render to
  95. textures. If it is not, we simply display a warning text.
  96. */
  97. // create render target
  98. video::IRenderTarget* renderTarget = 0;
  99. scene::ICameraSceneNode* fixedCam = 0;
  100. if (driver->queryFeature(video::EVDF_RENDER_TO_TARGET))
  101. {
  102. const core::dimension2d<u32> rtDim(256, 256); // always use same size for render target texture and it's depth-buffer
  103. video::ITexture* renderTargetTex = driver->addRenderTargetTexture(rtDim, "RTT1", video::ECF_A8R8G8B8);
  104. video::ITexture* renderTargetDepth = driver->addRenderTargetTexture(rtDim, "DepthStencil", video::ECF_D16);
  105. renderTarget = driver->addRenderTarget();
  106. renderTarget->setTexture(renderTargetTex, renderTargetDepth);
  107. cube->setMaterialTexture(0, renderTargetTex); // set material of cube to render target
  108. // add fixed camera
  109. fixedCam = smgr->addCameraSceneNode(0, core::vector3df(10,10,-80),
  110. core::vector3df(-10,10,-100));
  111. }
  112. else
  113. {
  114. // create problem text
  115. gui::IGUISkin* skin = env->getSkin();
  116. gui::IGUIFont* font = env->getFont(mediaPath + "fonthaettenschweiler.bmp");
  117. if (font)
  118. skin->setFont(font);
  119. gui::IGUIStaticText* text = env->addStaticText(
  120. L"Your hardware or this renderer is not able to use the "\
  121. L"render to texture feature. RTT Disabled.",
  122. core::rect<s32>(150,20,470,60));
  123. text->setOverrideColor(video::SColor(100,255,255,255));
  124. }
  125. // add fps camera
  126. scene::ICameraSceneNode* fpsCamera = smgr->addCameraSceneNodeFPS();
  127. fpsCamera->setPosition(core::vector3df(-50,50,-150));
  128. // disable mouse cursor
  129. device->getCursorControl()->setVisible(false);
  130. /*
  131. Nearly finished. Now we need to draw everything. Every frame, we draw
  132. the scene twice. Once from the fixed camera into the render target
  133. texture and once as usual. When rendering into the render target, we
  134. need to disable the visibility of the test cube, because it has the
  135. render target texture applied to it. That's it, wasn't too complicated
  136. I hope. :)
  137. */
  138. int lastFPS = -1;
  139. while(device->run())
  140. if (device->isWindowActive())
  141. {
  142. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0));
  143. if (renderTarget)
  144. {
  145. // draw scene into render target
  146. // set render target
  147. driver->setRenderTargetEx(renderTarget, video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0,0,0,255));
  148. // make cube invisible and set fixed camera as active camera
  149. cube->setVisible(false);
  150. smgr->setActiveCamera(fixedCam);
  151. // draw whole scene into render buffer
  152. smgr->drawAll();
  153. // set back old render target (the screen)
  154. driver->setRenderTargetEx(0, 0);
  155. // make the cube visible and set the user controlled camera as active one
  156. cube->setVisible(true);
  157. smgr->setActiveCamera(fpsCamera);
  158. }
  159. // draw scene normally
  160. smgr->drawAll();
  161. env->drawAll();
  162. driver->endScene();
  163. // display frames per second in window title
  164. int fps = driver->getFPS();
  165. if (lastFPS != fps)
  166. {
  167. core::stringw str = L"Irrlicht Engine - Render to Texture and Specular Highlights example";
  168. str += " FPS:";
  169. str += fps;
  170. device->setWindowCaption(str.c_str());
  171. lastFPS = fps;
  172. }
  173. }
  174. device->drop(); // drop device
  175. return 0;
  176. }
  177. /*
  178. **/