程序的开始部份就如通常的一样。包含需要的头文件,询问用户使用的渲染驱动,并创建一个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;
}
|
|