Tutorial 13 - Render To Texture - Chip - 19-08-2015
Tutorial 13: Render To Texture
Questo tutorial mostra come si fa un rendering verso una texture con Irrlicht. Il render verso texture è una feature con cui si possono creare effetti speciali molto interessanti. Inoltre nel tutorial verrà mostrato come si abilitano le specular highlights (luci speculari).
All'inizio tutto come al solito. Inclusione degli headers necessari e richiesta utente per la scelta del driver, quindi creazione del device di Irrlicht:
Codice PHP: #include <irrlicht.h> #include "driverChoice.h"
using namespace irr;
#ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif
int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1;
// create device and exit if creation failed
IrrlichtDevice *device = createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false, false);
if (device == 0) return 1; // could not create selected driver.
video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment();
Ora carichiamo una mesh animata da visulaizzare. Come in altri esempi useremo il modello fairy.md2. La differenza stavolta è che impostiamo il valore di shininess (lucentezza) ad un valore diverso dal valore di default che è 0. Così facendo, avendo le luci dinamiche presenti, abilitiamo la specular highlights sul modello. Questo valore influenza la dimensione della luminescenza (highlights).
Codice PHP: // 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")); // set diffuse texture fairy->setMaterialFlag(video::EMF_LIGHTING, true); // enable dynamic lighting fairy->getMaterial(0).Shininess = 20.0f; // set size of specular highlights fairy->setPosition(core::vector3df(-10,0,-100)); fairy->setMD2Animation ( scene::EMAT_STAND ); }
Come detto per rendere visibile la luce speculare sul modello dobbiamo attivare una luce dinamica nella scena. Ne aggiungiamo in prossimità del modello. In aggiunta, per non rendere il modello troppo scuro, impostiamo una luce ambientale su un grigio chiaro.
Codice PHP: // add white light smgr->addLightSceneNode(0, core::vector3df(-15,5,-105), video::SColorf(1.0f, 1.0f, 1.0f));
// set ambient light smgr->setAmbientLight(video::SColor(0,60,60,60));
Seguono operazioni standard: Aggiunta di un cubo rotante giusto per rendere la scena un po' più interessante. La camera e la gestione del cursore verranno fatte dopo, giusto prima del loop di render.
Codice PHP: // create test cube scene::ISceneNode* test = smgr->addCubeSceneNode(60);
// let the cube rotate and set some light settings 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();
// set window caption device->setWindowCaption(L"Irrlicht Engine - Render to Texture and Specular Highlights example");
Per testare il nostro render verso texture ci serve una texture che faccia da bersaglio per il nostro rendering. Dopodiché la applicheremo al cubo rotante. Non si tratta di texture standard, devono essere create appositamente. Per farlo dobbiamo chiamare IVideoDriver::addRenderTargetTexture() specificando la dimensione della texture stessa. Vi prego di annotare una cosa, non impostate mai la dimensione oltre la dimensione del frame buffer perché la texture per il rendering condivide lo zbuffer con lo stesso frame buffer. Poiché non vogliamo che il render sulla texture provenga dalla stessa camera dell'utente andiamo ad aggiungerne una seconda alla scena e sarà fissa. Ma prima di questo andiamo a controllare che il driver attivato sia in grado di effettuare un render su texture (oggi giorno è quasi inutile ndt). Se così non fosse mostriamo un testo di warning.
Codice PHP: // create render target video::ITexture* rt = 0; scene::ICameraSceneNode* fixedCam = 0;
if (driver->queryFeature(video::EVDF_RENDER_TO_TARGET)) { rt = driver->addRenderTargetTexture(core::dimension2d<u32>(256,256), "RTT1"); test->setMaterialTexture(0, rt); // set material of cube to render target
// add fixed camera fixedCam = smgr->addCameraSceneNode(0, core::vector3df(10,10,-80), core::vector3df(-10,10,-100)); } else { // create problem text 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<s32>(150,20,470,60));
text->setOverrideColor(video::SColor(100,255,255,255)); } // add fps camera scene::ICameraSceneNode* fpsCamera = smgr->addCameraSceneNodeFPS(); fpsCamera->setPosition(core::vector3df(-50,50,-150));
// disable mouse cursor device->getCursorControl()->setVisible(false);
Abbiamo quasi finito. Ora dobbiamo disegnare il tutto. Ad ogni frame disegneremo al scena due volte. Una volta dalla camera fissa dentro la texture e poi come al solito con la camera utente. Quando renderizziamo nella texture, dobbiamo disabilitare la visibilità del cubo, questo perché su di esso è applicata la texture su cui renderizziamo. Questo è tutto, spero non sia stato troppo complicato
Codice PHP: int lastFPS = -1;
while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0);
if (rt) { // draw scene into render target // set render target texture driver->setRenderTarget(rt, true, true, video::SColor(0,0,0,255));
// make cube invisible and set fixed camera as active camera test->setVisible(false); smgr->setActiveCamera(fixedCam);
// draw whole scene into render buffer smgr->drawAll();
// set back old render target // The buffer might have been distorted, so clear it driver->setRenderTarget(0, true, true, 0);
// make the cube visible and set the user controlled camera as active one test->setVisible(true); smgr->setActiveCamera(fpsCamera); } // draw scene normally smgr->drawAll(); env->drawAll();
driver->endScene();
// display frames per second in window title int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Irrlicht Engine - Render to Texture and Specular Highlights example"; str += " FPS:"; str += fps;
device->setWindowCaption(str.c_str()); lastFPS = fps; } }
device->drop(); // drop device return 0; }
Versione pdf scaricabile da QUI
|