Irrlicht Engine logo

Tutorial 12: Render To Texture
Přeložil: Martin Zima alias "RedDragCZ"

V tomto tutoriálu si ukážeme, 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”).


Lets start!

Na začátku jako obvykle includneme hlavičkové soubory Irrlichtu, vytvoříme renderovací zařízení, atd.:

#include <irrlicht.h>

#include <iostream>



using namespace irr;



#pragma comment(lib, "Irrlicht.lib")



int main()

{

	// nechme uživatele vybrat video driver



	video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;



	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é.

// load and display animated fairy mesh



	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ě.


	// 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 Vám již jistě 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.


	// 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);



	// 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->setPosition(core::vector3df(-100,0,-100));

	test->setMaterialFlag(video::EMF_LIGHTING, false); // disable dynamic lighting

	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í.

// create render target

	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.

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 
// jsem 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. :-)

 

 

 

 


Kopírování obsahu bez souhlasu autorů je zakázáno.
Copyright 2007 Irrlicht3d.cz