<!-- Wanted to avoid copying .css to each folder, so copied default .css from doxyen in here, kicked out most stuff we don't need for examples and modified some a little bit.
Target was having a single html in each example folder which is created from the main.cpp files and needs no files besides some images below media folder.
<p>This tutorials describes how to do special effects. It shows how to use stencil buffer shadows, the particle system, billboards, dynamic light, and the water surface scene node.</p>
<p>We start like in some tutorials before. Please note that this time, the 'shadows' flag in createDevice() is set to true, for we want to have a dynamic shadow casted from an animated character. If this example runs too slow, set it to false. The Irrlicht Engine checks if your hardware doesn't support the stencil buffer, and disables shadows by itself, but just in case the demo runs slow on your hardware. </p><divclass="fragment"><divclass="line"><spanclass="preprocessor">#include <irrlicht.h></span></div><divclass="line"><spanclass="preprocessor">#include <iostream></span></div><divclass="line"><spanclass="preprocessor">#include "driverChoice.h"</span></div><divclass="line"></div><divclass="line"><spanclass="keyword">using namespace </span>irr;</div><divclass="line"></div><divclass="line"><spanclass="preprocessor">#ifdef _MSC_VER</span></div><divclass="line"><spanclass="preprocessor">#pragma comment(lib, "Irrlicht.lib")</span></div><divclass="line"><spanclass="preprocessor">#endif</span></div><divclass="line"></div><divclass="line"><spanclass="keywordtype">int</span> main()</div><divclass="line">{</div><divclass="line"><spanclass="comment">// ask if user would like shadows</span></div><divclass="line"><spanclass="keywordtype">char</span> i;</div><divclass="line"> printf(<spanclass="stringliteral">"Please press 'y' if you want to use realtime shadows.\n"</span>);</div><divclass="line"></div><divclass="line"> std::cin >> i;</div><divclass="line"></div><divclass="line"><spanclass="keyword">const</span><spanclass="keywordtype">bool</span> shadows = (i == <spanclass="charliteral">'y'</span>);</div><divclass="line"></div><divclass="line"><spanclass="comment">// ask user for driver</span></div><divclass="line"> video::E_DRIVER_TYPE driverType=driverChoiceConsole();</div><divclass="line"><spanclass="keywordflow">if</span> (driverType==video::EDT_COUNT)</div><divclass="line"><spanclass="keywordflow">return</span> 1;</div></div><!-- fragment --><p> Create device and exit if creation failed. We make the stencil flag optional to avoid slow screen modes for runs without shadows. </p><divclass="fragment"><divclass="line">IrrlichtDevice *device =</div><divclass="line"> createDevice(driverType, core::dimension2d<u32>(640, 480),</div><divclass="line"> 16, <spanclass="keyword">false</span>, shadows);</div><divclass="line"></div><divclass="line"><spanclass="keywordflow">if</span> (device == 0)</div><divclass="line"><spanclass="keywordflow">return</span> 1; <spanclass="comment">// could not create selected driver.</span></div><divclass="line"></div><divclass="line">video::IVideoDriver* driver = device->getVideoDriver();</div><divclass="line">scene::ISceneManager* smgr = device->getSceneManager();</div></div><!-- fragment --><p> For our environment, we load a .3ds file. It is a small room I modelled with Anim8or and exported into the 3ds format because the Irrlicht Engine does not support the .an8 format. I am a very bad 3d graphic artist, and so the texture mapping is not very nice in this model. Luckily I am a better programmer than artist, and so the Irrlicht Engine is able to create a cool texture mapping for me: Just use the mesh manipulator and create a planar texture mapping for the mesh. If you want to see the mapping I made with Anim8or, uncomment this line. I also did not figure out how to set the material right in Anim8or, it has a specular light color which I don't really like. I'll switch it off too with this code. </p><divclass="fragment"><divclass="line">scene::IAnimatedMesh* mesh = smgr->getMesh(<spanclass="stringliteral">"../../media/room.3ds"</span>);</div><divclass="line"></div><divclass="line">smgr->getMeshManipulator()->makePlanarTextureMapping(mesh->getMesh(0), 0.004f);</div><divclass="line"></div><divclass="line">scene::ISceneNode* node = 0;</div><divclass="line"></div><divclass="line">node = smgr->addAnim
<p>There are different emitters, for example a point emitter which lets particles pop out at a fixed point. If the particle emitters available in the engine are not enough for you, you can easily create your own ones, you'll simply have to create a class derived from the IParticleEmitter interface and attach it to the particle system using setEmitter(). In this example we create a box particle emitter, which creates particles randomly inside a box. The parameters define the box, direction of the particles, minimal and maximal new particles per second, color, and minimal and maximal lifetime of the particles.</p>
<p>Because only with emitters particle system would be a little bit boring, there are particle affectors which modify particles while they fly around. Affectors can be added to a particle system for simulating additional effects like gravity or wind. The particle affector we use in this example is an affector which modifies the color of the particles: It lets them fade out. Like the particle emitters, additional particle affectors can also be implemented by you, simply derive a class from IParticleAffector and add it with addAffector().</p>
<p>After we set a nice material to the particle system, we have a cool looking camp fire. By adjusting material, texture, particle emitter, and affector parameters, it is also easily possible to create smoke, rain, explosions, snow, and so on. </p><divclass="fragment"><divclass="line"><spanclass="comment">// create a particle system</span></div><divclass="line"></div><divclass="line">scene::IParticleSystemSceneNode* ps =</div><divclass="line"> smgr->addParticleSystemSceneNode(<spanclass="keyword">false</span>);</div><divclass="line"></div><divclass="line">scene::IParticleEmitter* em = ps->createBoxEmitter(</div><divclass="line"> core::aabbox3d<f32>(-7,0,-7,7,1,7), <spanclass="comment">// emitter size</span></div><divclass="line"> core::vector3df(0.0f,0.06f,0.0f), <spanclass="comment">// initial direction</span></div><divclass="line"> 80,100, <spanclass="comment">// emit rate</span></div><divclass="line"> video::SColor(0,255,255,255), <spanclass="comment">// darkest color</span></div><divclass="line"> video::SColor(0,255,255,255), <spanclass="comment">// brightest color</span></div><divclass="line"> 800,2000,0, <spanclass="comment">// min and max age, angle</span></div><divclass="line"> core::dimension2df(10.f,10.f), <spanclass="comment">// min size</span></div><divclass="line"> core::dimension2df(20.f,20.f)); <spanclass="comment">// max size</span></div><divclass="line"></div><divclass="line">ps->setEmitter(em); <spanclass="comment">// this grabs the emitter</span></div><divclass="line">em->drop(); <spanclass="comment">// so we can drop it here without deleting it</span></div><divclass="line"></div><divclass="line">scene::IParticleAffector* paf = ps->createFadeOutParticleAffector();</div><divclass="line"></div><divclass="line">ps->addAffector(paf); <spanclass="comment">// same goes for the affector</span></div><divclass="line">paf->drop();</div><divclass="line"></div><divclass="line">ps->setPosition(core::vector3df(-70,60,40));</div><divclass="line">ps->setScale(core::vector3df(2,2,2));</div><divclass="line">ps->setMaterialFlag(video::EMF_LIGHTING, <spanclass="keyword">false</span>);</div><divclass="line">ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, <spanclass="keyword">false</span>);</div><divclass="line">ps->setMaterialTexture(0, driver->getTexture(<spanclass="stringliteral">"../../media/fire.bmp"</span>));</div><divclass="line">ps->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);</div></div><!-- fragment --><p> Next we add a volumetric light node, which adds a glowing fake area light to the scene. Like with the billboards and particle systems we also assign a texture for the desired effect, though this time we'll use a texture animator to create the illusion of a magical glowing area effect. </p><divclass="fragment"><divclass="line">scene::IVolumeLightSceneNode * n = smgr->addVolumeLightSceneNode(0, -1,</div><divclass="line"> 32, <spanclass="comment">// Subdivisions on U axis</span></div><divclass="line"> 32, <spanclass="comment">// Subdivisions on V axis</span></div><divclass="line"> video::SColor(0, 255, 255, 255), <spanclass="comment">// foot color</span></div><divclass="line"> video::SColor(0, 0, 0, 0)); <spanclass="comment">// tail color</span></div><divclass="line"></div><divclass="line"><spanclass="keywordflow">if</span> (n)</div><divclass="line">{</div><divclass="line"> n->setScale(core::vector3df(56.0f, 56.0f, 56.0f));</div><divclass="line"> n->setPosition(core::vector3df(-120,50,40));</div><divclass="line"></div><divclass="line"><spanclass="comment">// load textures for animation</span></div><divclass="line"> core::array<video::ITexture*> textures;</div><divclass="line"><spanclass="keywordflow">for</span> (s32 g=7; g > 0; --g)</div><di
<p>Because the character is a little bit too small for this scene, we make it bigger using setScale(). And because the character is lighted by a dynamic light, we need to normalize the normals to make the lighting on it correct. This is always necessary if the scale of a dynamic lighted model is not (1,1,1). Otherwise it would get too dark or too bright because the normals will be scaled too. </p><divclass="fragment"><divclass="line"><spanclass="comment">// add animated character</span></div><divclass="line"></div><divclass="line">mesh = smgr->getMesh(<spanclass="stringliteral">"../../media/dwarf.x"</span>);</div><divclass="line">scene::IAnimatedMeshSceneNode* anode = 0;</div><divclass="line"></div><divclass="line">anode = smgr->addAnimatedMeshSceneNode(mesh);</div><divclass="line">anode->setPosition(core::vector3df(-50,20,-60));</div><divclass="line">anode->setAnimationSpeed(15);</div><divclass="line"></div><divclass="line"><spanclass="comment">// add shadow</span></div><divclass="line">anode->addShadowVolumeSceneNode();</div><divclass="line">smgr->setShadowColor(video::SColor(150,0,0,0));</div><divclass="line"></div><divclass="line"><spanclass="comment">// make the model a little bit bigger and normalize its normals</span></div><divclass="line"><spanclass="comment">// because of the scaling, for correct lighting</span></div><divclass="line">anode->setScale(core::vector3df(2,2,2));</div><divclass="line">anode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, <spanclass="keyword">true</span>);</div></div><!-- fragment --><p> Finally we simply have to draw everything, that's all. </p><divclass="fragment"><divclass="line"> scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();</div><divclass="line"> camera->setPosition(core::vector3df(-50,50,-150));</div><divclass="line"> camera->setFarValue(10000.0f); <spanclass="comment">// this increase a shadow visible range.</span></div><divclass="line"></div><divclass="line"><spanclass="comment">// disable mouse cursor</span></div><divclass="line"> device->getCursorControl()->setVisible(<spanclass="keyword">false</span>);</div><divclass="line"></div><divclass="line"> s32 lastFPS = -1;</div><divclass="line"></div><divclass="line"><spanclass="keywordflow">while</span>(device->run())</div><divclass="line"><spanclass="keywordflow">if</span> (device->isWindowActive())</div><divclass="line"> {</div><divclass="line"> driver->beginScene(<spanclass="keyword">true</span>, <spanclass="keyword">true</span>, 0);</div><divclass="line"></div><divclass="line"> smgr->drawAll();</div><divclass="line"></div><divclass="line"> driver->endScene();</div><divclass="line"></div><divclass="line"><spanclass="keyword">const</span> s32 fps = driver->getFPS();</div><divclass="line"></div><divclass="line"><spanclass="keywordflow">if</span> (lastFPS != fps)</div><divclass="line"> {</div><divclass="line"> core::stringw str = L<spanclass="stringliteral">"Irrlicht Engine - SpecialFX example ["</span>;</div><divclass="line"> str += driver->getName();</div><divclass="line"> str += <spanclass="stringliteral">"] FPS:"</span>;</div><divclass="line"> str += fps;</div><divclass="line"></div><divclass="line"> device->setWindowCaption(str.c_str());</div><divclass="line"> lastFPS = fps;</div><divclass="line"> }</div><divclass="line"> }</div><divclass="line"></div><divclass="line"> device->drop();</div><divclass="line"></div><divclass="line"><spanclass="keywordflow">return</span> 0;</div><divclass="line">}</div></div><!-- fragment --></div></div><!-- contents -->