I. Surbrillance spéculaire

Image non disponible

Au début, tout comme d'habitude, incluons les en-têtes nécessaires, demandons à l'utilisateur le pilote de rendu, créons le moteur Irrlicht :

 
Sélectionnez
#include <irrlicht.h>
#include "driverChoice.h"

using namespace irr;

#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif

int main()
{
    // Demande à l'utilisateur un pilote.
    video::E_DRIVER_TYPE driverType=driverChoiceConsole();
    if (driverType==video::EDT_COUNT)
        return 1;

    // Crée le moteur et quitte si la création échoue.

    IrrlichtDevice *device =
        createDevice(driverType, core::dimension2d<u32>(640, 480),
        16, false, false);

    if (device == 0)
        return 1; // Ne peut pas créer le pilote sélectionné.

    video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();
    gui::IGUIEnvironment* env = device->getGUIEnvironment();

Maintenant, nous chargeons un mesh animé pour l'afficher. Comme dans une grande partie des exemples, nous prendrons le modèle md2 de la fée. Mais la différence est que nous définissons la brillance du modèle à une valeur différente de 0 qui est la valeur par défaut. Ceci active la surbrillance spéculaire sur le modèle si l'éclairage dynamique est activé. La valeur influe sur la force de la surbrillance.

 
Sélectionnez
    // Charge et affiche le mesh animé de la fée.

    scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode(
        smgr->getMesh("../../media/faerie.md2"));

    if (fairy)
    {
        fairy->setMaterialTexture(0,
                driver->getTexture("../../media/faerie2.bmp")); // Définit la valeur de la diffuse de la texture.
        fairy->setMaterialFlag(video::EMF_LIGHTING, true); // active l'éclairage dynamique
        fairy->getMaterial(0).Shininess = 20.0f; // Définit la force de la surbrillance spéculaire.
        fairy->setPosition(core::vector3df(-10,0,-100));
        fairy->setMD2Animation ( scene::EMAT_STAND );
    }

Pour faire apparaître la surbrillance spéculaire sur le modèle, nous avons besoin d'une lumière dynamique dans la scène. Nous en ajoutons une directement à proximité du modèle. De plus, pour que le modèle ne soit pas si sombre, nous mettons la lumière ambiante à gris.

 
Sélectionnez
    // Ajoute la lumière blanche.
    smgr->addLightSceneNode(0, core::vector3df(-15,5,-105),
            video::SColorf(1.0f, 1.0f, 1.0f));

    // Définit la lumière d'ambiance.
    smgr->setAmbientLight(video::SColor(0,60,60,60));

La suite ne contient que des choses habituelles : ajouter un cube de test et le faire tourner pour rendre la scène plus intéressante. Les options de la caméra et du curseur définies par l'utilisateur seront effectuées plus tard, juste avant la boucle de rendu.

 
Sélectionnez
    // Crée le cube de test.
    scene::ISceneNode* test = smgr->addCubeSceneNode(60);

    // Fait tourner le cube et définit quelques options de lumière.
    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); // Désactive l'éclairage dynamique.
    test->addAnimator(anim);
    anim->drop();

    // Met un titre à la fenêtre.
    device->setWindowCaption(L"Irrlicht Engine - Render to Texture and Specular Highlights example");

II. Rendu dans une texture

Pour tester la fonctionnalité du rendu dans une texture, nous avons besoin d'une texture cible. Elles ne sont pas comme les textures ordinaires, mais ont besoin d'être créées en premier. Pour en créer une, nous appelons IVideoDriver::addRenderTargetTexture() et nous indiquons la taille de la texture. Veuillez ne pas utiliser de taille plus grande que le tampon d'image pour cela, parce les cibles de rendu partagent le tampon de profondeur avec le tampon d'image. Comme nous voulons dessiner la scène, mais dans la texture d'un autre point de vue que celui de la caméra de l'utilisateur, nous ajoutons une autre caméra fixée à la scène. Mais avant de faire tout cela, nous vérifions si le pilote utilisé est capable d'effectuer un rendu dans une texture. S'il ne le peut pas, nous affichons simplement un message d'avertissement.

 
Sélectionnez
    // Crée la cible au dessin.
    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); // Fixe le matériel du cube pour la cible du dessin.

        // Ajoute une caméra fixe.
        fixedCam = smgr->addCameraSceneNode(0, core::vector3df(10,10,-80),
            core::vector3df(-10,10,-100));
    }
    else
    {
        // Crée un texte de problème.
        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));
    }
    
    // Ajoute une caméra fps.
    scene::ICameraSceneNode* fpsCamera = smgr->addCameraSceneNodeFPS();
    fpsCamera->setPosition(core::vector3df(-50,50,-150));

    // Cache le curseur de la souris.
    device->getCursorControl()->setVisible(false);

Nous avons presque fini. Maintenant, dessinons tout. À chaque image, nous dessinons la scène deux fois. La première à partir de la caméra fixe vers la texture cible et la seconde comme d'habitude. Quand nous dessinons dans la cible, nous avons besoin de désactiver la visibilité du cube parce qu'il est texturé avec la texture cible du rendu précédent. Voilà, j'espère que ce n'était pas trop compliqué;)

 
Sélectionnez
    int lastFPS = -1;

    while(device->run())
    if (device->isWindowActive())
    {
        driver->beginScene(true, true, 0);

        if (rt)
        {
            // Dessine la scène dans la cible du dessin.
            
            // Crée la texture cible.
            driver->setRenderTarget(rt, true, true, video::SColor(0,0,0,255));

            // Rend le cube invisible et active la caméra fixe.
            test->setVisible(false);
            smgr->setActiveCamera(fixedCam);

            // Dessine toute la scène dans le tampon de rendu.
            smgr->drawAll();

            // Retardons/repoussons la vieille cible du rendu.
            // Le tampon peut avoir été modifié, donc vidons-le.
            driver->setRenderTarget(0, true, true, 0);

            // Rend le cube visible et active la caméra contrôlée par l'utilisateur.
            test->setVisible(true);
            smgr->setActiveCamera(fpsCamera);
        }
        
        // Dessine la scène normalement.
        smgr->drawAll();
        env->drawAll();

        driver->endScene();

        // Affiche le nombre d'images par seconde dans le titre de la fenêtre.
        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(); // Détruit le moteur.
    return 0;
}

III. Conclusion

Vous pouvez désormais effectuer un rendu de scène dans une texture avec Irrlicht.

Dans le prochain tutoriel Fenêtre win32, nous verrons qu'Irrlicht est capable de dessiner à l'intérieur de fenêtre win32.

IV. Remerciements

Merci à Nikolaus Gebhardt de nous permettre de traduire ce tutoriel.

Merci à LittleWhite pour sa relecture technique ainsi qu'à ClaudeLELOUP pour sa relecture orthographique.