本节主要学习如何使用Ogre2.3加载粒子效果。为了学习方便,直接将官方粒子模块Sample_ParticleFX单独拿出来编译,学习如何实现粒子效果。
一. 前提须知
- 如果参考官方示例建议用最新版的Ogre 2.3.1。否则找不到有粒子效果的示例。不要用官网Ogre2.3 script脚本编译源码!
- Ogre 1.x中关于实现粒子效果的官方示例材质太老,不支持固管,要写shader,不建议在Ogre 2.3中使用。要使用新的材质!
Ogre 1.x中的材质:
material Examples/Flare
{
technique
{
pass
{
lighting off
scene_blend add
depth_write off
diffuse vertexcolour
texture_unit
{
texture flare.png
}
}
}
}
Ogre 2.3中的材质:
hlms Examples/Flare2 unlit
{
depth_write off
cull_hardware none
scene_blend add
diffuse_map flaretrail.png
}
二. 新建项目工程的头文件和库文件配置如下:
注意:你需要把Media文件夹和bin/Debug文件夹下的资源拷贝过来,具体拷贝到哪里大家应该很了解。
这里说下头文件和库文件的设置。
头文件:

库目录:

注意:这里改成窗口

三. 粒子效果总结
先展示下官网给的12个粒子效果,具体代码放到最后。
- 烟花效果,粒子Examples/Fireworks,材质官方没有给出,自己尝试模仿写了一个,添加到Particles.material文件中。
Particles.material:
hlms Examples/Flare unlit
{
depth_write off
cull_hardware none
scene_blend add
diffuse_map flare.png
}

2. 向上漂浮的绿色颗粒,粒子Examples/GreenyNimbus。材质自己为自己添加。
Particles.material:
hlms Examples/FlarePointSprite unlit
{
depth_write off
cull_hardware none
scene_blend add
diffuse_map flare.png
}

3. 闪闪发光的紫色喷泉。粒子Examples/PurpleFountain。材质为官方自带。

4. 雨,粒子Examples/Rain。材质自己实现。
材质Particles.material:
hlms Examples/Droplet unlit
{
depth_write off
cull_hardware none
scene_blend add
diffuse_map basic_droplet.png
}

5. 飞机喷气尾焰,粒子Examples/JetEngine1。粒子和材质代码详见官方示例。

6. 飞机喷气尾焰2,粒子Examples/JetEngine2。粒子和材质代码详见官方示例。

7. 向上漂浮的光环,类似龙卷风。粒子 Examples/Aureola。粒子和材质代码详见官方示例。

8. 四处游动的类似火花。粒子Examples/Swarm。粒子和材质代码详见官方示例。

9.漫天雪花,粒子Examples/Snow。粒子和材质代码详见官方示例。

10. 类似烟花。粒子Examples/Animated/Test1。粒子和材质代码详见官方示例。

11. 大雨滴,粒子Examples/Water/Rain。粒子和材质代码详见官方示例。

12. 烟雾。粒子Examples/Smoke。粒子代码见官方示例。材质代码自己写。如下:
材质Particles.material:
hlms Examples/Smoke unlit
{
depth_write off
cull_hardware none
scene_blend add
diffuse_map Smoke15Frames.png
}

四. 代码
具体代码参考官方模块Sample_ParticleFX,这里为了单独测试不同粒子效果,把少数代码注释了。
ParticleFXGameState.cpp
#include "ParticleFXGameState.h"
#include "CameraController.h"
#include "GraphicsSystem.h"
#include "OgreCamera.h"
#include "OgreHlmsManager.h"
#include "OgreHlmsPbs.h"
#include "OgreHlmsPbsDatablock.h"
#include "OgreHlmsSamplerblock.h"
#include "OgreItem.h"
#include "OgreMesh2.h"
#include "OgreMeshManager.h"
#include "OgreMeshManager2.h"
#include "OgreRoot.h"
#include "OgreSceneManager.h"
#include "OgreTextureFilters.h"
#include "OgreTextureGpuManager.h"
#include "OgreWindow.h"
#include "OgreParticleSystem.h"
#include <iostream>
using namespace Demo;
namespace Demo
{
ParticleFXGameState::ParticleFXGameState(const Ogre::String& helpDescription) :
TutorialGameState(helpDescription),
mTime(0.0f)
{
}
void ParticleFXGameState::createScene01()
{
Ogre::SceneManager* sceneManager = mGraphicsSystem->getSceneManager();
Ogre::v1::MeshPtr planeMeshV1 = Ogre::v1::MeshManager::getSingleton().createPlane(
"Plane v1", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::Plane(Ogre::Vector3::UNIT_Y, 1.0f), 50.0f, 50.0f, 1, 1, true, 1, 4.0f, 4.0f,
Ogre::Vector3::UNIT_Z, Ogre::v1::HardwareBuffer::HBU_STATIC,
Ogre::v1::HardwareBuffer::HBU_STATIC);
Ogre::MeshPtr planeMesh = Ogre::MeshManager::getSingleton().createByImportingV1(
"Plane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, planeMeshV1.get(), true,
true, true);
{
Ogre::Item* item = sceneManager->createItem(planeMesh, Ogre::SCENE_DYNAMIC);
item->setDatablock("Marble");
Ogre::SceneNode* sceneNode = sceneManager->getRootSceneNode(Ogre::SCENE_DYNAMIC)
->createChildSceneNode(Ogre::SCENE_DYNAMIC);
sceneNode->setPosition(0, -1, 0);
sceneNode->attachObject(item);
assert(dynamic_cast<Ogre::HlmsPbsDatablock*>(item->getSubItem(0)->getDatablock()));
Ogre::HlmsPbsDatablock* datablock =
static_cast<Ogre::HlmsPbsDatablock*>(item->getSubItem(0)->getDatablock());
Ogre::HlmsSamplerblock samplerblock(*datablock->getSamplerblock(Ogre::PBSM_ROUGHNESS));
samplerblock.mU = Ogre::TAM_WRAP;
samplerblock.mV = Ogre::TAM_WRAP;
samplerblock.mW = Ogre::TAM_WRAP;
datablock->setSamplerblock(Ogre::PBSM_ROUGHNESS, samplerblock);
}
Ogre::SceneNode* rootNode = sceneManager->getRootSceneNode();
Ogre::Light* light = sceneManager->createLight();
Ogre::SceneNode* lightNode = rootNode->createChildSceneNode();
lightNode->attachObject(light);
light->setPowerScale(Ogre::Math::PI);
light->setType(Ogre::Light::LT_DIRECTIONAL);
light->setDirection(Ogre::Vector3(-1, -1, -1).normalisedCopy());
sceneManager->setAmbientLight(Ogre::ColourValue(0.3f, 0.5f, 0.7f) * 0.1f * 0.75f,
Ogre::ColourValue(0.6f, 0.45f, 0.3f) * 0.065f * 0.75f,
-light->getDirection() + Ogre::Vector3::UNIT_Y * 0.2f);
Ogre::ParticleSystem* pSystem0 = sceneManager->createParticleSystem("Examples/Smoke");
Ogre::SceneNode* sceneNode = rootNode->createChildSceneNode();
sceneNode->attachObject(pSystem0);
unsigned short numAffectors = pSystem0->getNumAffectors();
Ogre::ParticleAffector* particleAffector = pSystem0->getAffector(0);
mGraphicsSystem->getCamera()->setPosition(Ogre::Vector3(0.0f, 40.0f, 120.0f));
mCameraController = new CameraController(mGraphicsSystem, false);
TutorialGameState::createScene01();
}
void ParticleFXGameState::update(float timeSinceLast)
{
mTime += timeSinceLast;
if (mTime > 10.0f)
mTime = 0.0f;
TutorialGameState::update(timeSinceLast);
}
}