光照与粒子系统:打造逼真虚拟场景
立即解锁
发布时间: 2025-08-21 00:29:38 阅读量: 1 订阅数: 2 


Irrlicht 1.7实时3D引擎初学者指南精华
### 光照与粒子系统:打造逼真虚拟场景
#### 光照基础与不同类型光照
在虚拟场景中,光照是营造氛围和真实感的关键因素。如果场景中没有光源,而物体的材质又设置为反射入射光,那么场景将会完全黑暗。比如,当移除场景中的环境光,同时立方体的 `EMF_LIGHTING` 属性仍设置为 `true` 时,立方体就会变得完全黑暗。
为了创建自定义的光照效果,我们可以添加具有自定义漫反射颜色的光照节点。以下是实现代码:
```cpp
smgr->addCameraSceneNode(0, vector3df(0, 10, -20), vector3df(0, 0, 0));
smgr->setAmbientLight(SColor(255, 80, 80, 80));
ILightSceneNode* myLight = smgr->addLightSceneNode();
myLight->setPosition(vector3df(0.0f, 20.0f, 0.0f));
SLight lightData;
lightData.DiffuseColor = SColor(255, 0, 255, 0);
myLight->setLightData(lightData);
vector3df cubeRotation = vector3df(0.0f, 0.0f, 0.0f);
while(device->run())
{
myCube->setRotation(cubeRotation);
cubeRotation += 0.02f;
if (cubeRotation.X >= 360.0f)
{
cubeRotation.X = 0.0f;
cubeRotation.Y = 0.0f;
cubeRotation.Z = 0.0f;
}
}
```
上述代码中,我们通过场景管理器对象的 `addLightSceneNode()` 方法添加了一个新的光照节点。光照数据存储在 `SLight` 结构体中,我们创建了该结构体的新实例并设置了所需的漫反射颜色,最后通过 `setLightData()` 方法将其分配给光照节点。其余代码则是让立方体旋转,增加场景的趣味性。
计算机图形学中主要有三种类型的光照:平行光、聚光灯和点光源,Irrlicht 引擎支持所有这些类型的光照。下面我们来详细了解一下平行光和点光源。
- **平行光**:平行光会在特定方向上产生平行光线。对于平行光来说,位置属性无效,但旋转属性有效。我们可以将太阳看作平行光的一个例子,虽然太阳有实际位置,但由于它距离我们非常遥远,我们可以假设平行光位于无限远处。在游戏场景中,通常不需要太多平行光,大多数情况下,一个或两个平行光就足够了。而且,平行光被认为不受衰减影响,即其强度不会随着传播距离的增加而减弱。利用平行光,我们可以创建游戏中的昼夜循环效果,通过根据游戏中太阳的位置旋转平行光,并使用不同的天空盒图像来区分白天和黑夜。
- **点光源**:点光源就像灯泡一样,会向各个方向发光。由于它向各个方向发光,所以旋转和方向值对于点光源来说并不重要。与平行光不同,点光源会受到衰减和范围值的影响。在 Irrlicht 中,创建新的光照节点时,默认类型就是点光源。
#### 添加聚光灯和动画效果
为了让场景更加生动,我们可以添加旋转的聚光灯和点光源的圆周飞行动画。以下是实现代码:
```cpp
ICameraSceneNode* fpsCamera = smgr->addCameraSceneNodeFPS(0, 80.0f, 0.3f);
fpsCamera->setPosition(vector3df(0, 15, -25));
fpsCamera->setTarget(vector3df(0, 0, 0));
ILightSceneNode* myPointLight = smgr->addLightSceneNode();
myPointLight->setPosition(vector3df(0.0f, 20.0f, 0.0f));
scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(vector3df(0, 0, 0), 50.0f, 0.0005f);
myPointLight->addAnimator(anim);
anim->drop();
ISceneNode* pointLightBill = smgr->addBillboardSceneNode(myPointLight, dimension2d<f32>(20, 20));
pointLightBill->setMaterialFlag(video::EMF_LIGHTING, false);
pointLightBill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
pointLightBill->setMaterialTexture(0, driver->getTexture("../../media/portal1.bmp"));
SLight pointLightData;
pointLightData.DiffuseColor = SColor(255, 0, 255, 0);
pointLightData.SpecularColor = SColor(255, 0, 0, 255);
myPointLight->setLightData(pointLightData);
ILightSceneNode* mySpotLight = smgr->addLightSceneNode();
mySpotLight->setPosition(vector3df(0.0f, 10.0f, 0.0f));
SLight spotLightData;
spotLightData.Type = ELT_SPOT;
spotLightData.DiffuseColor = SColor(255, 255, 0, 0);
spotLightData.OuterCone = 100;
spotLightData.InnerCone = 10;
mySpotLight->setLightData(spotLightData);
while(device->run())
{
mySpotLight->setRotation(rotation);
}
```
在这段代码中,我们首先将相机类型更改为 FPS 相机,通过 `addCameraSceneNodeFPS()` 方法并传递旋转和移动速度,这样就可以使用鼠标和箭头键在场景中移动。点光源添加了圆周飞行动画,但它本身不可见,因此我们添加了一个公告板场景节点,并将点光源节点作为其父节点,使其跟随点光源移动。同时,我们设置了公告板的材质纹理为 `portal1.bmp`。对于聚光灯,我们创建了一个新的光照节点,并设置其类型为 `ELT_SPOT`,同时设置了外锥角和内锥角这两个特殊属性。运行代码后,旋转的聚光灯照射到物体时会产生红色光照效果。
#### 聚光灯的特点
聚光灯类似于手电筒,具有方向和颜色。其方向由旋转计算得出,并且会随着传播距离的增加而衰减。聚光灯还有两个额外的属性:外锥角和内锥角。聚光灯有一个较亮的内锥和一个较大的外锥,从内锥到外锥,亮度逐渐降低。
#### 调整光泽度和镜面反射颜色
我们可以设置简单点光源的镜面反射颜色,并为材质设置光泽度值。以下是实现代码:
```cpp
IMeshSceneNode* myCube = smgr->addCubeSceneNode();
IMeshSceneNode* mySphere = smgr->addSphereSceneNode();
if (!myCube || !mySphere)
return 1;
myCube->setPosition(vector3df(-10.0f, 0.0f, 0.0f));
mySphere->setPosition(vector3df(10.0f, 0.0f, 0.0f));
if (myCube && mySphere)
{
myCube
```
0
0
复制全文
相关推荐









