Irrlicht 纹理 和 粒子系统的使用
创建定制的 scene node,没有用到 shader。
class CSampleSceneNode : public scene::ISceneNode
{
core::aabbox3d<f32> Box;
video::S3DVertex Vertices[4];
video::SMaterial Material;
public:
CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id)
: scene::ISceneNode(parent, mgr, id)
{
Material.Wireframe = false;
Material.Lighting = false;
Material.Thickness = 0.f;
// Pos(pos), Normal(normal), Color(color), TCoords(tcoords)
Vertices[0] = video::S3DVertex(0,0,10, 5,1,0, video::SColor(255,0,255,255), 0,1);
Vertices[1] = video::S3DVertex(10,0,-10, 10,0,0, video::SColor(255,255,0,255), 1,1);
Vertices[2] = video::S3DVertex(0,20,0, 20,1,1, video::SColor(255,255,255,0), 1,0);
Vertices[3] = video::S3DVertex(-10,0,-10, 40,0,1, video::SColor(255,0,255,0), 0,0);
Box.reset(Vertices[0].Pos);
for (s32 i=1; i<4; ++i)
Box.addInternalPoint(Vertices[i].Pos);
}
virtual void OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
virtual void render()
{
u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 };
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setMaterial(Material);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
driver->drawVertexPrimitiveList(&Vertices[0], 4, &indices[0], 4,
video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
}
};
int main()
{
CSampleSceneNode *myNode =
new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666);
scene::ISceneNodeAnimator* anim =
smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f));
if (anim)
{
myNode->addAnimator(anim);
anim->drop();
anim = 0;
}
myNode->drop();
myNode = 0; // As I shouldn't refer to it again, ensure that I can't
u32 frames=0;
while (device->run())
{
driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0,100,100,100));
smgr->drawAll();
driver->endScene();
if (++frames == 100) // don't update more often, setWindowCaption can be expensive
{
core::stringw str = L"Irrlicht Engine [";
str += driver->getName();
str += L"] FPS: ";
str += (s32) driver->getFPS();
device->setWindowCaption(str.c_str());
frames = 0;
}
}
device->drop();
return 0;
}
特效演示。深度缓冲阴影,粒子系统,广告牌,动态光,水表面。
int main()
{
mesh = smgr->addHillPlaneMesh( "myHill",
core::dimension2d<f32>(20,20),
core::dimension2d<u32>(40,40), 0, 0,
core::dimension2d<f32>(0,0),
core::dimension2d<f32>(10,10));
node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0), 3.0f, 300.0f, 30.0f);
node->setPosition(core::vector3df(0,7,0));
node->setMaterialTexture(0, driver->getTexture(mediaPath + "stones.jpg"));
node->setMaterialTexture(1, driver->getTexture(mediaPath + "water.jpg"));
node->setMaterialType(video::EMT_REFLECTION_2_LAYER);
// create a particle system
scene::IParticleSystemSceneNode* ps =
smgr->addParticleSystemSceneNode(false);
if (ps)
{
scene::IParticleEmitter* em = ps->createBoxEmitter(
core::aabbox3d<f32>(-7,0,-7,7,1,7), // emitter size
core::vector3df(0.0f,0.06f,0.0f), // initial direction
80,100, // emit rate
video::SColor(0,255,255,255), // darkest color
video::SColor(0,255,255,255), // brightest color
800,2000,0, // min and max age, angle
core::dimension2df(10.f,10.f), // min size
core::dimension2df(20.f,20.f)); // max size
ps->setEmitter(em); // this grabs the emitter
em->drop(); // so we can drop it here without deleting it
scene::IParticleAffector* paf = ps->createFadeOutParticleAffector();
ps->addAffector(paf); // same goes for the affector
paf->drop();
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(mediaPath + "fire.bmp"));
ps->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
}
// add animated character
mesh = smgr->getMesh(mediaPath + "dwarf.x");
scene::IAnimatedMeshSceneNode* anode = 0;
anode = smgr->addAnimatedMeshSceneNode(mesh);
anode->setPosition(core::vector3df(-50,20,-60));
anode->setAnimationSpeed(15);
while (device->run())
if (device->isWindowActive())
{
driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0));
smgr->drawAll();
driver->endScene();
const s32 fps = driver->getFPS();
if (lastFPS != fps)
{
core::stringw str = L"Irrlicht Engine - SpecialFX example [";
str += driver->getName();
str += "] FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
device->drop();
return 0;
}
shaders for D3D8, D3D9 and OpenGL。创建 shader material,关闭 texture mipmaps,使用 text scene nodes。
attribute vec3 inVertexPosition;
attribute vec3 inVertexNormal;
attribute vec4 inVertexColor;
attribute vec2 inTexCoord0;
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform vec3 mLightPos;
uniform vec4 mLightColor;
varying mediump vec4 v_color;
varying mediump vec2 v_texCoord;
void main(void)
{
gl_Position = mWorldViewProj * vec4(inVertexPosition,1.0);
vec4 normal = vec4(inVertexNormal, 0.0);
normal = mInvWorld * normal;
normal = normalize(normal);
vec4 worldpos = vec4(inVertexPosition,1.0) * mTransWorld;
vec4 lightVector = worldpos - vec4(mLightPos,1.0);
lightVector = normalize(lightVector);
float tmp2 = dot(-lightVector, normal);
vec4 tmp = mLightColor * tmp2;
v_color = vec4(tmp.x, tmp.y, tmp.z, 0.0);
v_texCoord = inTexCoord0;
}
precision mediump float;
varying vec2 v_texCoord;
varying vec4 v_color;
uniform sampler2D myTexture;
void main (void)
{
vec4 col = texture2D(myTexture, v_texCoord);
col *= v_color;
gl_FragColor = col * 4.0;
}
class MyShaderCallBack : public video::IShaderConstantSetCallBack
{
public:
MyShaderCallBack() : WorldViewProjID(-1), TransWorldID(-1), InvWorldID(-1), PositionID(-1),
ColorID(-1), TextureID(-1), FirstUpdate(true)
{
}
virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
{
video::IVideoDriver* driver = services->getVideoDriver();
// 获取 Shader 常量。
if (UseHighLevelShaders && FirstUpdate)
{
WorldViewProjID = services->getVertexShaderConstantID("mWorldViewProj");
TransWorldID = services->getVertexShaderConstantID("mTransWorld");
InvWorldID = services->getVertexShaderConstantID("mInvWorld");
PositionID = services->getVertexShaderConstantID("mLightPos");
ColorID = services->getVertexShaderConstantID("mLightColor");
if (driver->getDriverType() == video::EDT_OPENGL)
TextureID = services->getVertexShaderConstantID("myTexture");
FirstUpdate = false;
}
core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD);
invWorld.makeInverse();
if (UseHighLevelShaders)
services->setVertexShaderConstant(InvWorldID, invWorld.pointer(), 16);
else
services->setVertexShaderConstant(invWorld.pointer(), 0, 4);
// 设置剪裁矩阵
core::matrix4 worldViewProj;
worldViewProj = driver->getTransform(video::ETS_PROJECTION);
worldViewProj *= driver->getTransform(video::ETS_VIEW);
worldViewProj *= driver->getTransform(video::ETS_WORLD);
if (UseHighLevelShaders)
services->setVertexShaderConstant(WorldViewProjID, worldViewProj.pointer(), 16);
else
services->setVertexShaderConstant(worldViewProj.pointer(), 4, 4);
// 设置相机位置
core::vector3df pos = device->getSceneManager()-> getActiveCamera()->getAbsolutePosition();
if (UseHighLevelShaders)
services->setVertexShaderConstant(PositionID, reinterpret_cast<f32*>(&pos), 3);
else
services->setVertexShaderConstant(reinterpret_cast<f32*>(&pos), 8, 1);
// 设置光照颜色
video::SColorf col(0.0f,1.0f,1.0f,0.0f);
if (UseHighLevelShaders)
services->setVertexShaderConstant(ColorID, reinterpret_cast<f32*>(&col), 4);
else
services->setVertexShaderConstant(reinterpret_cast<f32*>(&col), 9, 1);
// 设置世界变换矩阵
core::matrix4 world = driver->getTransform(video::ETS_WORLD);
world = world.getTransposed();
if (UseHighLevelShaders)
{
services->setVertexShaderConstant(TransWorldID, world.pointer(), 16);
s32 TextureLayerID = 0;
services->setPixelShaderConstant(TextureID, &TextureLayerID, 1);
}
else
services->setVertexShaderConstant(world.pointer(), 10, 4);
}
private:
s32 WorldViewProjID;
s32 TransWorldID;
s32 InvWorldID;
s32 PositionID;
s32 ColorID;
s32 TextureID;
bool FirstUpdate;
};
int main()
{
io::path vsFileName; // filename for the vertex shader
io::path psFileName; // filename for the pixel shader
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
!driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1))
{
device->getLogger()->log("WARNING: Pixel shaders disabled "\
"because of missing driver/hardware support.");
psFileName = "";
}
if (!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
!driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1))
{
device->getLogger()->log("WARNING: Vertex shaders disabled "\
"because of missing driver/hardware support.");
vsFileName = "";
}
if (gpu)
{
MyShaderCallBack* mcSolid = new MyShaderCallBack();
MyShaderCallBack* mcTransparentAdd = new MyShaderCallBack();
if (UseHighLevelShaders)
{
newMaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(
vsFileName, "vertexMain", video::EVST_VS_1_1,
psFileName, "pixelMain", video::EPST_PS_1_1,
mcSolid, video::EMT_SOLID, 0);
newMaterialType2 = gpu->addHighLevelShaderMaterialFromFiles(
vsFileName, "vertexMain", video::EVST_VS_1_1,
psFileName, "pixelMain", video::EPST_PS_1_1,
mcTransparentAdd, video::EMT_TRANSPARENT_ADD_COLOR, 0);
}
mcSolid->drop();
mcTransparentAdd->drop();
}
// create test scene node 1, with the new created material type 1
scene::ISceneNode* node = smgr->addCubeSceneNode(50);
node->setPosition(core::vector3df(0,0,0));
node->setMaterialTexture(0, driver->getTexture(mediaPath + "wall.bmp"));
node->setMaterialFlag(video::EMF_LIGHTING, false);
node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType1);
smgr->addTextSceneNode(gui->getBuiltInFont(),
L"PS & VS & EMT_SOLID",
video::SColor(255,255,255,255), node);
scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(
core::vector3df(0,0.3f,0));
node->addAnimator(anim);
anim->drop();
node = smgr->addCubeSceneNode(50);
node->setPosition(core::vector3df(0,-10,50));
node->setMaterialTexture(0, driver->getTexture(mediaPath + "wall.bmp"));
node->setMaterialFlag(video::EMF_LIGHTING, false);
node->setMaterialFlag(video::EMF_BLEND_OPERATION, true);
node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType2);
smgr->addTextSceneNode(gui->getBuiltInFont(),
L"PS & VS & EMT_TRANSPARENT",
video::SColor(255,255,255,255), node);
anim = smgr->createRotationAnimator(core::vector3df(0,0.3f,0));
node->addAnimator(anim);
anim->drop();
逐像素光照、雾、移动光、粒子。复杂 material。用 normal maps and parallax mapping 计算每个像素的光照。烟雾的使用,和移动粒子系统。
Irrlicht 学习笔记 (10)–PerPixelLighting
渲染到一个纹理。使用 specular highlights。
创建屏幕双缓冲。颜色反转,用 HLSL and GLSL 写的。