Irrlicht学习笔记(8)--SpecialFX

说明:

本例程介绍:
阴影
粒子系统
布告板
动态光照
水面节点


1.载入一个房间

用于表现动态光照
关键步骤为;1.1,1.3. 1.2是为了优化贴图效果
//1.加载一个房间模型

1.1加载模型网格

scene::IAnimatedMesh* mesh = smgr->getMesh("../media/room.3ds");

1.2可选:获得网格控制器

//旋转,缩放,颜色设置,透明度设置,反转表面,诸如此类
scene::IMeshManipulator* meshman = smgr->getMeshManipulator();
//在网格上创建平铺的纹理图,优化贴图效果
meshman->makePlanarTextureMapping(mesh->getMesh(0), 0.004f);

1.3

scene::ISceneNode* node = 0;//创建场景节点
node = smgr->addAnimatedMeshSceneNode(mesh);//将网格加载到场景节点
node->setMaterialTexture(0, driver->getTexture("../media/wall.jpg"));//设置节点纹理
node->getMaterial(0).SpecularColor.set(0, 0, 0, 0);//

2.第一个特殊效果:水波

工作原理:

WaterSurfaceSceneNode接受一个输入mesh,使之像水面一样扰动.
还可以为它添加材质,反射效果.
至于mesh,使用Irrlicht内部方法创建一个山作为表面网格,也可以是其他任何网格,比如上面的room.3ds

mesh = smgr->addHillPlaneMesh(
"Hill",//名字,用于获取这个生成的网格:smgr->getMesh()
core::dimension2d<f32>(20,20),//titlesize,尺寸
core::dimension2d<u32>(40,40),//titlecount,制定title的数量
0,//irr::video::SMaterial
0,//hillheight
core::dimension2d<f32>(10,10),//counthills
core::dimension2d<f32>(1.0,1.0)//textureRepeatCount,纹理重复次数
);
想要看到生成的hill,可以绑定到一个动画网格节点,并设置相关材质.

创建水波节点

将hill网格绑定到水面节点.
node = smgr->addWaterSurfaceSceneNode(
mesh->getMesh(0),//irr::IMesh*
3.0f,//waveheight
300,//wavespeed
30.0f//wavelength
// 0,//parent
// -1,//id
// core::vector3df(0, 7, 0),//position
// core::vector3df(0, 0, 0),//rotation
// core::vector3df(1.0f, 1.0f, 1.0f)//scale
);

设置水面节点的属性

石头和水面纹理分别设置为0,1层纹理,并设置反射
//位置,材质,以及材质属性
node->setPosition(core::vector3df(0, 10, 0));
node->setMaterialTexture(0, driver->getTexture("../media/stones.jpg"));
node->setMaterialTexture(1, driver->getTexture("../media/water.jpg"));

node->setMaterialType(video::EMT_REFLECTION_2_LAYER);




3.布告板和移动光源

建立一个光源,绑定一个移动动画,再绑定一个布告板
//将布告板绑定到动态移动的光源

3.1创建一个灯光节点

node = smgr->addLightSceneNode(
0, //parent
core::vector3df(0, 0, 0),//position
video::SColorf(1.0f, 0.6f, 0.7f, 1.0f),//rgba:0-1
700,//radius
-1//id
);

3.2创建一个动画,并绑定到灯光节点

scene::ISceneNodeAnimator* anim = 
smgr->createFlyCircleAnimator(
core::vector3df(0, 150, 0),//center
250,//radius
0.001,//speed
core::vector3df(0,1,0),//position方向
0.0,//startPosition
0.0//radiusEllipsoid
);
node->addAnimator(anim);
anim->drop();

3.3绑定一个布告板,并初始化布告板的属性:材质,颜色,透明度

node = smgr->addBillboardSceneNode(
node,//parent,绑定到灯光节点
core::dimension2d<f32>(50,50)//size
);
node->setMaterialFlag(video::EMF_LIGHTING, false);//关闭布告板的光照属性
node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
node->setMaterialTexture(0, driver->getTexture("../media/particlewhite.bmp"));

4.粒子系统

关键:粒子发射器(Emitter),粒子控制器(Affector)
粒子系统在Irrlicht引擎中被高度模块化,可扩展性强,使用方便
粒子系统场景节点用于管理,
加入粒子发射器,
加入粒子控制器

例子发射器有很多种,若不满意,可以自己扩展:
1创建一个类,继承IParticleEmitter接口
2绑定自己的发射器到粒子系统,setEmitter()

本例创建一个box粒子发射器:在一个盒子内随机生成粒子
参数:方向,范围,频率,存活时间

粒子控制器用于模拟外界对粒子的影响,比如重力和风
本例只影响颜色
粒子控制器也可以自己定义,
1自定义类,继承IParticleAffector
2绑定到粒子系统,addAffector()


创建好粒子系统,设置材质,纹理,发射器,控制器,可以模拟大量效果,比如烟雾,雨等

4.1创建粒子系统

scene::IParticleSystemSceneNode* ps =
smgr->addParticleSystemSceneNode(
false//是否带默认发射器
);

4.2创建粒子发射器

scene::IParticleEmitter* em = ps->createBoxEmitter(
core::aabbox3df(-7, 0, -7, 7, 1, 7),//发射器盒子范围
core::vector3df(0, 0.06, 0),//方向
20,//最小发射速度
100,//最大速度
video::SColor(0, 255, 255, 255),//最深的颜色
video::SColor(0, 255, 255, 255),//最亮的颜色
200,//最短存活时间
2000,//最长存活时间
0,//最大角度
core::dimension2df(10, 10),//最小尺寸
core::dimension2df(20, 20)//最大尺寸
);
//绑定
ps->setEmitter(em);
em->drop();

4.3创建粒子控制器

//此处没有用到
scene::IParticleAffector* paf = ps->createFadeOutParticleAffector();

ps->addAffector(paf);
paf->drop();

4.4设置粒子系统

ps->setPosition(core::vector3df(-70, 60, 40));
ps->setScale(core::vector3df(2, 2, 2));
ps->setMaterialFlag(video::EMF_LIGHTING, false);
ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
ps->setMaterialTexture(0, driver->getTexture("../media/fire.bmp"));
ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);

5.创建一个空间灯光节点


scene::IVolumeLightSceneNode* n = smgr->addVolumeLightSceneNode(
0,//parent
-1,//id
32,//sub u
32,//sub v
video::SColor(0, 255, 255, 255),//foot color
video::SColor(0, 0, 0, 0)//tail color
);
//设置属性
if (n)
{
n->setScale(core::vector3df(56, 56, 56));
n->setPosition(core::vector3df(-120, 50, 40));
//n->setMaterialFlag(video::EMF_LIGHTING, false);

//创建一个动画,由7张连续图片组成
core::array<video::ITexture*> textures;
for (s32 g = 7; g > 0; --g)
{
core::stringc tmp;
tmp = "../media/portal";
tmp += g;
tmp += ".bmp";
video::ITexture* t = driver->getTexture(tmp.c_str());
textures.push_back(t);
}
//创建动画
scene::ISceneNodeAnimator* glow = smgr->createTextureAnimator(
textures,//
150,//每帧的时间
true//loop
);
n->addAnimator(glow);
glow->drop();
}

6.动态阴影

//创建一个动画模型投射出阴影,

6.1创建动画节点

mesh = smgr->getMesh("../media/dwarf.x");
scene::IAnimatedMeshSceneNode* anode = 0;
anode = smgr->addAnimatedMeshSceneNode(mesh);
anode->setPosition(core::vector3df(-50, 20, -60));
anode->setAnimationSpeed(15);

6.2增加阴影

anode->addShadowVolumeSceneNode();
smgr->setShadowColor(video::SColor(150, 0, 0, 0));//全局的

6.3设置

//放大模型,随后需要重新单位化法向量
anode->setScale(core::vector3df(2, 2, 2));
anode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);


代码

#include <iostream>
#include <irrlicht.h>

using namespace irr;


#ifdef _IRR_WINDOWS_
#pragma comment(lib, "irrlicht.lib")
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif

int main(int argc, char** argv)
{
	IrrlichtDevice *device =
		createDevice(video::EDT_OPENGL, core::dimension2d<u32>(720, 455), 16,
		false, true, false, 0);
	if (!device)
		return 1;
	device->setWindowCaption(L"SpecialFX");


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


	/*********************初始化...******************/

	//1.加载一个房间模型
	//1.1加载模型网格
	scene::IAnimatedMesh* mesh = smgr->getMesh("../media/room.3ds");
	//1.2可选:获得网格控制器
	//旋转,缩放,颜色设置,透明度设置,反转表面,诸如此类
	scene::IMeshManipulator* meshman = smgr->getMeshManipulator();
	//在网格上创建平铺的纹理图,优化贴图效果
	meshman->makePlanarTextureMapping(mesh->getMesh(0), 0.004f);
	//1.3
	scene::ISceneNode* node = 0;//创建场景界定啊
#if(1)
	node = smgr->addAnimatedMeshSceneNode(mesh);//将网格加载到场景节点
	node->setMaterialTexture(0, driver->getTexture("../media/wall.jpg"));//设置节点纹理

//	node->setMaterialFlag(video::EMF_LIGHTING, false);//设置了光照之后需要将材质光照打开
	node->getMaterial(0).SpecularColor.set(0, 0, 0, 0);//
#endif
	//2.特效1:水波
	//2.1获得一个网格
	video::SMaterial material;
	material.setTexture(0, driver->getTexture("../media/wall.jpg"));
	mesh = smgr->addHillPlaneMesh(
		"Hill",//名字,用于获取这个生成的网格:smgr->getMesh()
		core::dimension2d<f32>(20,20),//titlesize,尺寸
		core::dimension2d<u32>(40,40),//titlecount,制定title的数量
		&material,
	//	0,//irr::video::SMaterial
		0,//hillheight
		core::dimension2d<f32>(10,10),//counthills
		core::dimension2d<f32>(1.0,1.0)//textureRepeatCount,纹理重复次数
		);
	node = smgr->addAnimatedMeshSceneNode(mesh);
//	node->setMaterialFlag(video::EMF_LIGHTING, false);
	node->setPosition(core::vector3df(0, -1, 0));

	//2.2创建水面场景节点
	node = smgr->addWaterSurfaceSceneNode(
		mesh->getMesh(0),//irr::IMesh*
		3.0f,//waveheight
		300,//wavespeed
		30.0f//wavelength
	//	0,//parent
	//	-1,//id
	//	core::vector3df(0, 7, 0),//position
	//	core::vector3df(0, 0, 0),//rotation
	//	core::vector3df(1.0f, 1.0f, 1.0f)//scale
		);
	//2.3设置水波节点
	//位置,材质,以及材质属性
	node->setPosition(core::vector3df(0, 10, 0));
	node->setMaterialTexture(0, driver->getTexture("../media/stones.jpg"));
	node->setMaterialTexture(1, driver->getTexture("../media/water.jpg"));

	node->setMaterialType(video::EMT_REFLECTION_2_LAYER);

	//node->setMaterialFlag(video::EMF_LIGHTING, false);//设置灯光后可以注释掉

	//3.布告板
	//将布告板绑定到动态移动的光源
	//3.1创建一个灯光节点
	node = smgr->addLightSceneNode(
		0, //parent
		core::vector3df(0, 0, 0),//position
		video::SColorf(1.0f, 0.6f, 0.7f, 1.0f),//rgba:0-1
		700,//radius
		-1//id
		);
	//3.2创建一个动画,并绑定到灯光节点
	scene::ISceneNodeAnimator* anim = 
		smgr->createFlyCircleAnimator(
		core::vector3df(0, 150, 0),//center
		250,//radius
		0.001,//speed
		core::vector3df(0,1,0),//position方向
		0.0,//startPosition
		0.0//radiusEllipsoid
		);
	node->addAnimator(anim);
	anim->drop();

	//3.3绑定一个布告板,并初始化布告板的属性:材质,颜色,透明度
	node = smgr->addBillboardSceneNode(
		node,//parent,绑定到灯光节点
		core::dimension2d<f32>(50,50)//size
		);
	node->setMaterialFlag(video::EMF_LIGHTING, false);//关闭布告板的光照属性
	node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
	node->setMaterialTexture(0, driver->getTexture("../media/particlewhite.bmp"));

	//4.例子系统
	//4.1创建粒子系统
	scene::IParticleSystemSceneNode* ps =
		smgr->addParticleSystemSceneNode(
		false//是否带默认发射器
		);
	//4.2创建粒子发射器
	scene::IParticleEmitter* em = ps->createBoxEmitter(
		core::aabbox3df(-7, 0, -7, 7, 1, 7),//发射器盒子范围
		core::vector3df(0, 0.06, 0),//方向
		20,//最小发射速度
		100,//最大速度
		video::SColor(0, 255, 255, 255),//最深的颜色
		video::SColor(0, 255, 255, 255),//最亮的颜色
		200,//最短存活时间
		2000,//最长存活时间
		0,//最大角度
		core::dimension2df(10, 10),//最小尺寸
		core::dimension2df(20, 20)//最大尺寸
		);
	//绑定
	ps->setEmitter(em);
	em->drop();
	//4.3创建粒子控制器
	//此处没有用到
	scene::IParticleAffector* paf = ps->createFadeOutParticleAffector();

	ps->addAffector(paf);
	paf->drop();

	//4.4设置粒子系统
	ps->setPosition(core::vector3df(-70, 60, 40));
	ps->setScale(core::vector3df(2, 2, 2));
	ps->setMaterialFlag(video::EMF_LIGHTING, false);
	ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
	ps->setMaterialTexture(0, driver->getTexture("../media/fire.bmp"));
	ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);

	//5.创建一个空间灯光节点
	scene::IVolumeLightSceneNode* n = smgr->addVolumeLightSceneNode(
		0,//parent
		-1,//id
		32,//sub u
		32,//sub v
		video::SColor(0, 255, 255, 255),//foot color
		video::SColor(0, 0, 0, 0)//tail color
		);
	//设置属性
	if (n)
	{
		n->setScale(core::vector3df(56, 56, 56));
		n->setPosition(core::vector3df(-120, 50, 40));
		//n->setMaterialFlag(video::EMF_LIGHTING, false);

		//创建一个动画,由7张连续图片组成
		core::array<video::ITexture*> textures;
		for (s32 g = 7; g > 0; --g)
		{
			core::stringc tmp;
			tmp = "../media/portal";
			tmp += g;
			tmp += ".bmp";
			video::ITexture* t = driver->getTexture(tmp.c_str());
			textures.push_back(t);
		}
		//创建动画
		scene::ISceneNodeAnimator* glow = smgr->createTextureAnimator(
			textures,//
			150,//每帧的时间
			true//loop
			);
		n->addAnimator(glow);
		glow->drop();
	}
	//6.动态阴影
	//创建一个动画模型投射出阴影,
	//6.1创建动画节点
	mesh = smgr->getMesh("../media/dwarf.x");
	scene::IAnimatedMeshSceneNode* anode = 0;
	anode = smgr->addAnimatedMeshSceneNode(mesh);
	anode->setPosition(core::vector3df(-50, 20, -60));
	anode->setAnimationSpeed(15);

	//6.2增加阴影
	anode->addShadowVolumeSceneNode();
	smgr->setShadowColor(video::SColor(150, 0, 0, 0));//全局的

	//6.3设置
	//放大模型,随后需要重新单位化法向量
	anode->setScale(core::vector3df(2, 2, 2));
	anode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);


	/***********************初始化结束*************/ 
//	smgr->addCameraSceneNode(0, core::vector3df(0, 30, -40), core::vector3df(0, 5, 0));
	scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(
		);
	camera->setPosition(core::vector3df(-50, 50, -150));
	device->getCursorControl()->setVisible(false);
	int lastFPS = -1;
	while (device->run())
	{
		driver->beginScene(true, true, video::SColor(255, 100, 101, 140));

		smgr->drawAll();
		guiev->drawAll();

		driver->endScene();

		int fps = driver->getFPS();
		if (lastFPS != fps)
		{
			core::stringw str = L"Campfire FX example [";
			str += driver->getName();
			str += "]FPS.",
				str += fps;
			device->setWindowCaption(str.c_str());
			lastFPS = fps;
		}
	}
	device->drop();

	return 0;
}



你可能感兴趣的:(Irrlicht)