Irrlicht学习之光照的研究

Irrlicht学习之光照的研究

         最近研究一下Irrlicht的光照。发现Irrlicht的光照还是比较简单的,相比低于它的OpenGL和Direct3D,设置光源以及设置光照的参数更加人性化(可能是因为OpenGL是基于C的,Direct3D是基于COM的,都没有面向对象那么简洁易懂?)但是光照的实现还是根据底层的渲染器来决定的,也就是说可能是OpenGL的高洛德光照模型,也可能是Direct3D中的光照模型。

         演示程序和源代码下载地址:这里

         为了准确地展现Irrlicht设置和显示光照的特性,需要载入一个场景模型。这里我从游艺网中下载了一个max模型,然后通过3DS Max转为obj格式,这样能被Irrlicht识别并显示。模型在载入后需要设置其材质以便能够接受到光照。下面是设置的代码:

pDoorNode->setMaterialFlag(EMF_LIGHTING, true );// 接受光照
pDoorNode->setMaterialFlag(EMF_ANISOTROPIC_FILTER, true );// 使用各向异性过滤
pDoorNode->setMaterialType(EMT_TRANSPARENT_ALPHA_CHANNEL_REF );// 材质开启Alpha通道

这里第一句是让Irrlicht的光照能够作用于该节点的材质上;第二句是使用各项异性过滤,通常在投影的时候能够在远处获得清晰的过滤效果;第三句则是开启材质的Alpha通道,能够解决一些Alpha以及深度的问题,具体功能还需探究(可以注释掉来看看效果)。

在进行完准备工作后,开始设置光照了。就我的学习实践来说会分为这几步:

1、设置全局光颜色;

2、向场景添加光源节点(俗称打灯);

3、设置各个光源的属性。

         光源的属性有漫反射颜色、镜面反射颜色、自发光颜色等,OpenGL和Direct3D所有的Irrlicht应该也不会缺少(有关光源的属性参见我以前写的一篇日志)。所不同的是,Irrlicht的光源作为节点属性成为场景管理的一部分,这和Blender和其它成熟3D建模软件的场景管理属性差不多。

         下面是演示程序的截图,截图中开了四盏灯,分别位于四个火把的位置。原作者似乎只想制作一个静态的模型,所以火把什么的没有做成粒子系统,而是一张面片而已。程序还创建了一个FPS摄像机,我们可以很方便地对场景进行漫游。

         下面是程序的部分代码:

 

#include "IrrInclude.h"
 
void CreateMap( ISceneManager* pSMgr )
{
    IMesh* pDoorMesh = pSMgr->getMesh( "Door/Door.obj");
    if ( pDoorMesh == nullptr ) return;
 
    ISceneNode* pDoorNode = pSMgr->addMeshSceneNode( pDoorMesh );
    if ( pDoorNode == nullptr ) return;
 
    pDoorNode->setMaterialFlag( EMF_LIGHTING, true );// 接受光照
    pDoorNode->setMaterialFlag( EMF_ANISOTROPIC_FILTER, true );// 使用各向异性过滤
    pDoorNode->setMaterialType( EMT_TRANSPARENT_ALPHA_CHANNEL_REF);// 材质开启Alpha通道
 
    // 设置全局光照
    pSMgr->setAmbientLight( SColor( 255, 80, 0, 0 ) );
 
    // 添加点光源
    ILightSceneNode* pBlueFireLight_1 = pSMgr->addLightSceneNode(pDoorNode );
    ILightSceneNode* pBlueFireLight_2 = pSMgr->addLightSceneNode(pDoorNode );
    ILightSceneNode* pRedFireLight_1 = pSMgr->addLightSceneNode(pDoorNode );
    ILightSceneNode* pRedFireLight_2 = pSMgr->addLightSceneNode(pDoorNode );
 
    SLight blueFireLight;
    blueFireLight.DiffuseColor = SColor( 255, 80, 80, 225 );
    blueFireLight.SpecularColor = SColor( 255, 230, 230, 210 );
 
    SLight redFireLight;
    blueFireLight.DiffuseColor = SColor( 255, 225, 80, 80 );
    blueFireLight.SpecularColor = SColor( 255, 230, 230, 210 );
 
    // 设置光源属性
    pBlueFireLight_1->setLightData( blueFireLight );
    pBlueFireLight_1->setPosition( vector3df( 7.0f, 12.0f, 9.0f ));
 
    pBlueFireLight_2->setLightData( blueFireLight );
    pBlueFireLight_2->setPosition( vector3df( -7.0f, 12.0f, 9.0f ));
 
    pRedFireLight_1->setLightData( redFireLight );
    pRedFireLight_1->setPosition( vector3df( 20.0f, 2.0f, 6.0f ));
 
    pRedFireLight_2->setLightData( redFireLight );
    pRedFireLight_2->setPosition( vector3df( -20.0f, 2.0f, 6.0f ));
 
}
 
void CreateGUI( IGUIEnvironment* pGUIEnv )
{
    // 创建中文字体
    IGUIFont* pChineseFont = CGUITTFont::createTTFont(
       pGUIEnv,                        // GUI环境
       FONTPATH,                       // 字体名称
       20,                             // 字体大小(多少磅)
       true,                           // 抗锯齿吗?
       true );                            // 半透明吗?
 
    // 设置GUI风格
    pGUIEnv->getSkin( )->setFont( pChineseFont );
    pGUIEnv->getSkin( )->setColor( EGDC_BUTTON_TEXT, SColor(255, 255, 255, 255 ) );
}
 
int main( int argc, char** argv )
{
    IrrlichtDevice* pDevice = createDevice(
       EDT_OPENGL,                     // 渲染设备
       dimension2d<u32>( 640, 480 ),   // 宽和高
       16,                         // 颜色位
       false,                      // 是否全屏
       false,                      // 模版缓存
       false,                      // 垂直同步
       nullptr );                  // 事件接收器
 
    if ( pDevice == nullptr ) return -1;
    pDevice->setWindowCaption( L"鬼火引擎演示- 光照的研究" );
 
    IVideoDriver* pDriver = pDevice->getVideoDriver( );
    ISceneManager* pSMgr = pDevice->getSceneManager( );
    IGUIEnvironment* pGUIEnv = pDevice->getGUIEnvironment( );
 
    CreateMap( pSMgr );// 创建地图
    ICameraSceneNode* pCamera = pSMgr->addCameraSceneNodeFPS(
       nullptr,
       100.0f,
       0.2f );
    pCamera->setPosition( vector3df( -4.0f, -4.0f, 12.0f ) );
    pCamera->setRotation( vector3df( 0.0f, 90.0f, 90.0f ) );
 
    CreateGUI( pGUIEnv );// 创建GUI
    IGUIStaticText* pInfoText = pGUIEnv->addStaticText( L"", rect<s32>( 10, 10, 400, 100 ));
 
    pDevice->getCursorControl( )->setVisible( false );// 隐藏鼠标光标
 
    while ( pDevice->run( ) )
    {
       vector3df pos = pCamera->getPosition( );
       wchar_t info[100] = { 0 };
       swprintf( info, L"当前摄像机坐标(%.2f,%.2f, %.2f)
Made By Jiangcaiyang",
           pos.X, pos.Y, pos.Z );
       pInfoText->setText( info );
 
       pDriver->beginScene(
           true,                       //后台缓存
           true,                       //Z缓存
           SColor( 0, 0, 0, 0 ) );         // 填充颜色
       pSMgr->drawAll( );
       pGUIEnv->drawAll( );
       pDriver->endScene( );
    }
 
    return 0;
}
原文地址:https://www.cnblogs.com/riasky/p/3430839.html