13 RenderToTexture
官方代码($sdk)\examples\13.RenderToTexture
渲染纹理,可以做出很多看起来非常不错的特效,如镜面、径向模糊等效果。官方例子用制作镜面来说明irr中如何渲染纹理。
scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/faerie.md2"));
创建一个动画场景节点,使用的Mesh仍然是md2的模型文件。
if (fairy)
{
fairy->setMaterialTexture(0,driver->getTexture("../../media/faerie2.bmp"));
设置纹理
fairy->setMaterialFlag(video::EMF_LIGHTING, true);
开启光照
fairy->getMaterial(0).Shininess = 20.0f;
设置自发光强度
fairy->setPosition(core::vector3df(-10,0,-100));
设置位置
fairy->setMD2Animation ( scene::EMAT_STAND );
将动画设为站立的动画
}
一般情况下模型的自发光值使用默认值0,本例中设为大一0的值。这样在开启光照时模型就能产生高亮点,而这个自发光值也将会模型上亮点的大小。
smgr->addLightSceneNode(0, core::vector3df(-15,5,-105),video::SColorf(1.0f, 1.0f, 1.0f));
为了使模型上出现高光点,例子中在模型旁边添加了一个动态光。
smgr->setAmbientLight(video::SColor(0,60,60,60));
//将环境光设为灰色,这样模型就不会显示成黑的。
scene::ISceneNode* test = smgr->addCubeSceneNode(60);
//设置一个测试立方体
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);
//关闭测试立方体的光照
test->addAnimator(anim);
//为测试立方体添加旋转控制器
anim->drop();
渲染纹理所使用的目标纹理和irr的普通纹理不同,需要使用IVideoDriver::createRenderTargetTexture函数创建一个渲染目标纹理,创建时需要指定纹理的大小。例子中没有以用户摄像机做为镜面摄像机,它创建了一个新摄像机来获取渲染出的纹理。这个例子用了两个摄像机,以往的例子中从来没有这样用过,通过它为可以学会如何切换摄像机。
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");
//创建一个渲染目标纹理,大小为256*256
test->setMaterialTexture(0, rt); // set material of cube to render target
//将渲染目标纹理做为测试立方体的材质,这样立方体上的纹理将是动态渲染出来的
fixedCam = smgr->addCameraSceneNode(0, core::vector3df(10,10,-80),
core::vector3df(-10,10,-100));
//增加一个固定摄像机
}
else
{
//驱动不支持渲染到纹理,创建报错信息。创建报错信息用到的方法全是UserInterface例子中介绍过的,没什么难度,一看就懂。
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));
}
//创建一个FPS摄像机,通过这个摄像机能够以不同位置观察渲染纹理的效果。
scene::ICameraSceneNode* fpsCamera = smgr->addCameraSceneNodeFPS();
fpsCamera->setPosition(core::vector3df(-50,50,-150));
这个例子中的帧循环跟以往的例子不同。以前每帧只绘制场景一次,这次每帧绘制场景两次。第一次绘制使用的是fixedCam固定摄像机,通过它截取绘制到纹理上的场景图像,这次绘制用户看不到,测试立方体在这次绘制中不需要被显示,它将被隐藏掉。第二次绘制的是用户看到的场景,它会将第一次绘制的纹理显示在测试立方体上。
while(device->run())
if (device->isWindowActive())
{
driver->beginScene(true, true, 0);
if (rt)
{
//绘制渲染纹理中的场景
//设置渲染目标纹理
driver->setRenderTarget(rt, true, true, video::SColor(0,0,0,255));
//将测试立方体设为不可见
test->setVisible(false);
//设置固定摄像机为活动摄像机,用于镜面取景
smgr->setActiveCamera(fixedCam);
// 绘制整个场景并将其绘制到渲染缓冲区
smgr->drawAll();
//设置为默认渲染目标
// 缓冲区已经被销毁,因此清除它
driver->setRenderTarget(0, true, true, 0);
//设置立方体可见
test->setVisible(true);
//更换活动摄像机为FPS摄像机
smgr->setActiveCamera(fpsCamera);
}
// 第二次绘制 绘制普通场景
smgr->drawAll();
env->drawAll();
driver->endScene();
// 在标题栏显示帧速
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;
}
}
渲染到纹理使用的不是普通纹理,而是IVideoDriver::addRenderTargetTexture()创建的可修改纹理。使用IVideoDriver::setRenderTarget()设置渲染目标。使用ISceneManager::setActiveCamera()设置活动摄像机,通过它就能完成切换摄像机的功能。