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摄像机,我们可以很方便地对场景进行漫游。

Irrlicht学习之光照的研究

         下面是程序的部分代码:

 

#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)\nMade 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;

}

 

你可能感兴趣的:(学习)