irrwowview

Tutorial 12: Render To Texture

Tutorial 12: Render To Texture
本教程演示了如何在IrrLicht引擎中使用渲染到纹理(render to a texture)。渲染到纹理是一个能够创建漂亮特效的功能。另外,本教程还演示如何应用镜面高光(specular highlights)。

程序的效果如下图所示:

 

Lets start!

程序的开始部份就如通常的一样。包含需要的头文件,询问用户使用的渲染驱动,并创建一个IrrLicht设备:

#include <irrlicht.h>

 

#include <iostream>

 

 

 

using namespace irr;

 

 

 

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

 

 

 

int main()

 

{

 

          // let user select driver type

 

 

 

          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;
          }        

 

 

 

          // create device and exit if creation failed

 

 

 

          IrrlichtDevice *device =

 

                    createDevice(driverType, core::dimension2d(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();

现在,我们加载并显示一个活动的网格。就如其它例子一样,我们加载一个md2的精灵模型。不同的地方:我们设置模型的亮度为一个非0值(0是默认值)。当有动态灯光照射模型时,就能使用镜面高光了。这个傎会影响高光的大小。

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

 

          }

为了显示模型的镜面高光效果,我们需要在场景中添加一个动态灯光。我们在模型附近添加一个方向光。另外,为了使模型可见,还设置了环境光为灰色。

 

          // add white light

 

          scene::ILightSceneNode* light = smgr->addLightSceneNode(0,

 

                    core::vector3df(-15,5,-105), video::SColorf(1.0f, 1.0f, 1.0f));

 

 

 

          // set ambient light

 

          driver->setAmbientLight(video::SColor(0,60,60,60));

接着只是一些标准的部份:在场景添加一个用户可控的摄像,隐藏鼠标光标,添加一个测试立方体并使它旋转,这样使场景更有趣。

 

          // add fps camera

 

          scene::ICameraSceneNode* fpsCamera = smgr->addCameraSceneNodeFPS();

 

          fpsCamera->setPosition(core::vector3df(-50,50,-150));

 

 

 

          // disable mouse cursor

 

          device->getCursorControl()->setVisible(false);

 

 

 

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

为了测试渲染到纹理的特征,我们需要一个渲染目标纹理。虽然不同于普通的纹理,但不还是要先创建它。要创建一个渲染目标纹理,可以调用IVideoDriver::createRenderTargetTexture()方法并指定纹理的大小。使用的大小请不要超过帧缓存,因为渲染目标与帧缓存一起共享zbuffer。因为我们要渲染的纹理不是从用户摄像机得来的,所以在场景再添加一个固定的摄像机。就如之前一样,我们检测当前使用的驱动能否渲染到纹理。如果不能,就简单地显示一个警告文本。

// 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); // 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(150,20,470,60));

 

 

 

                    text->setOverrideColor(video::SColor(100,255,255,255));

 

          }

差不多结束了。现在需要把全部都绘制出来。每一帧,我们都会绘制场景两次。通常第一次是根据固定摄像机使用渲染目标节点。当我们渲染(rendering)渲染目标(render target)时,需要隐藏测试立方体,因为渲染目标纹理要应用到立方体的上面。
就这样,我希望不算太复杂.J

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

 

                               driver->setRenderTarget(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();

 

          }

 

 

 

          if (rt)

 

                    rt->drop(); // drop render target because we
                    // created if with a create() method

 

 

 

          device->drop(); // drop device

 

          return 0;

 

}

 

 

 

posted on 2008-07-04 11:26 shjy 阅读(579) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理