Irrlicht3D tutoriál - Render to Texture
Po delší době Vám opět přináším volnější překlad dalšího oficiálního tutoriálu grafického C++ enginu Irrlicht.
Ukážeme si, jak renderovat scénu do textury. Render to texture (neboli RTT) je technologie často využívaná pro tvorbu různých speciálních efektů, využívá se například také při post-processingu obrazu. Jako bonus se také naučíme jak aktivovat spekulární highlighty (volně přeloženo “zrcadlové odrazy”).
Ukážeme si, jak renderovat scénu do textury. Render to texture (neboli RTT) je technologie často využívaná pro tvorbu různých speciálních efektů, využívá se například také při post-processingu obrazu. Jako bonus se také naučíme jak aktivovat spekulární highlighty (volně přeloženo “zrcadlové odrazy”).
Výsledný program
Na začátku jako obvykle includneme hlavičkové soubory Irrlichtu, vytvoříme renderovací zařízení, atd.:
Kód:
#include <iostream> #include <irrlicht.h> using namespace irr; #pragma comment(lib, "Irrlicht.lib") int main() { //nechme uživatele vybrat video driver video::E_DRIVER_TYPE driverType; printf("Please select the driver you want for this example:\n"\ " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\ " (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\ " (f) NullDevice\n (otherKey) exit\n\n"); char i; std::cin >> i; switch(i) { case 'a': driverType = video::EDT_DIRECT3D9; break; case 'b': driverType = video::EDT_DIRECT3D8; break; case 'c': driverType = video::EDT_OPENGL; break; case 'd': driverType = video::EDT_SOFTWARE; break; case 'e': driverType = video::EDT_SOFTWARE2; break; case 'f': driverType = video::EDT_NULL; break; default: return 1; } //vytvoříme Irrlicht zařízení a v případě neúspěchu ukončíme program IrrlichtDevice *device = createDevice(driverType, core::dimension2d(640, 480), 16, false, false); if (device == 0) return 1; //zařízení nemohlo být vytvořeno. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment();
Nyní načteme animovaný model faerie a vytvoříme mu scénový uzel. Novinkou je nastavení lesklosti materiálu na jinou hodnotu, než je 0 (což je výchozí nastavení). To aktivuje ty již zmíněné spekulární odrazy. Co stojí také za povšimnutí je, že zapínáme dynamické nasvětlování modelu, bez něj by nebyly žádné tyto světelné efekty možné.
Kód:
//načteme faerii a vytvoříme ji node scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode( smgr->getMesh("../../media/faerie.md2")); if (fairy) { fairy->setMaterialTexture(0, driver->getTexture("../../media/faerie2.bmp")); // nastavíme difuzní texturu fairy->setMaterialFlag(video::EMF_LIGHTING, true); // povolíme dynamické nasvětlování fairy->getMaterial(0).Shininess = 20.0f; // nastavíme velikost spekulárních odrazů fairy->setPosition(core::vector3df(-10,0,-100)); }
Nyní musíme nastavit světla. Jedno přidáme přímo do blízkosti uzlu samotného a aby nebyl model celkově příliš tmavý (= tedy pro vykompenzování toho, že jsme na něm povolili dynamické nasvětlování), aktivujeme ambientní světlo scény. Ambientní světla nemají žádnou pevně danou pozici ani směr a ovlivňují rovnoměrně všechny objekty ve scéně.
Kód:
//přidáme bílé světlo scene::ILightSceneNode* light = smgr->addLightSceneNode(0, core::vector3df(-15,5,-105), video::SColorf(1.0f, 1.0f, 1.0f)); //nastavíme ambientní světlo driver->setAmbientLight(video::SColor(0,60,60,60));
Dalším bodem v kódu jsou klasické a dobře známé standardní úkony – přidání uživatelsky kontrolované kamery, vypnutí zobrazování kurzoru myši a přidání testovací krychle, kterou necháme pro oživení rotovat.
Kód:
//přidáme FPS-style kameru scene::ICameraSceneNode* fpsCamera = smgr->addCameraSceneNodeFPS(); fpsCamera->setPosition(core::vector3df(-50,50,-150)); //zakážeme kurzor myši device->getCursorControl()->setVisible(false); //vytvoříme testovací krychli scene::ISceneNode* test = smgr->addCubeSceneNode(60); test->setPosition(core::vector3df(-100,0,-100)); test->setMaterialFlag(video::EMF_LIGHTING, false); // zakážeme dynamická světla //vytvoříme rotační animátor krychle a zakážeme u ní dynamická světla scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator( core::vector3df(0.3f, 0.3f,0)); test->addAnimator(anim); anim->drop(); //nastavíme titulek okna device->setWindowCaption( L"Irrlicht Engine - Render to Texture and Specular Highlights example");
Pro otestování RTT potřebujeme nejdříve vytvořit speciální render target texturu. Ta není jako jiné, klasické textury, potřebujeme ji nejdříve ručně vytvořit. To uděláme zavoláním metody IvideoDriver::createRenderTargetTexture() a specifikováním jejích rozměrů. Vzhledem k tomu, že RTT sdílí ZBuffer s Vaším normálním video driverem, nepoužívejte rozměry větší, než má Váš aktuální frame buffer. (Pozn.: Pokud byste chtěli využívat větších RTT, existuje pro Irrlicht patch, který to umožňuje – pak hledejte na oficiálním fóru v Code Snippets.)
Protože nechceme renderovat do textury ze stejné pozice, jako má uživatel, přidáme další kameru, tentokrát již s fixní pozicí. Ještě před provedením těchto všech kroků ale pro jistotu ověříme, zda-li současný video driver podporuje RTT a pokud ne, zobrazíme varování.
Kód:
//render target textura video::ITexture* rt = 0; scene::ICameraSceneNode* fixedCam = 0; if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET)) { rt = driver->createRenderTargetTexture(core::dimension2d(256,256)); test->setMaterialTexture(0, rt); //přiřadíme testovací krychli render target texturu //přidáme fixní kameru fixedCam = smgr->addCameraSceneNode(0, core::vector3df(10,10,-80), core::vector3df(-10,10,-100)); } else { //vytvoříme varování v případě chyby gui::IGUISkin* skin = env->getSkin(); gui::IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp"); if(font) skin->setFont(font); gui::IGUIStaticText* text = env->addStaticText( L"Your hardware or this renderer is not able to use the "\ L"render to texture feature. RTT Disabled.", core::rect(150,20,470,60)); text->setOverrideColor(video::SColor(100,255,255,255)); }
Téměř hotovo. Nyní musíme vše vykreslit. Každý snímek budeme renderovat scénu dvakrát – jednou do textury, podruhé tak jak to běžně známe, přímo do okna naší aplikace. Před RTT renderováním ovšem nejdříve zakážeme viditelnost naší testovací krychle, protože sama má na sobě výslednou renderovací texturu.
Kód:
while(device->run()) { if (device->isWindowActive()) { driver->beginScene(true, true, 0); if (rt) { //vykreslíme scénu do RTT //nastavíme render target na naší texturu driver->setRenderTarget(rt, true, true, video::SColor(0,0,0,255)); //zneviditelníme krychli a přepneme kameru test->setVisible(false); smgr->setActiveCamera(fixedCam); //vykreslíme celou scénu do render bufferu smgr->drawAll(); //nastavíme původní render target driver->setRenderTarget(0); //zviditelníme krychli a přepneme kameru zpět test->setVisible(true); smgr->setActiveCamera(fpsCamera); } //vykreslíme scénu normálním způsobem smgr->drawAll(); env->drawAll(); driver->endScene(); } } if(rt) rt->drop(); //dropneme RTT protože jsme //ji vytvořili pomocí create() metody device->drop(); // dropneme Irrlicht zařízení return 0; }
A to je pro dnešek vše - nyní už víte, jak používat RTT v Irrlichtu. :-)
Tento tutoriál je volnějším překladem oficiálního Irrlicht Engine tutoriálu Render To Texture. Můžete ho také nalézt na portálu Irrlicht3D.cz, jehož jsem spoluautorem.
Přidat do:
Komentáře:
U článku zatím nejsou žádné komentáře.
Buďte první!
Buďte první!