zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    小球下落
    时隔半年再设环境变量。。笑哭了!
    Quartus+modelsim开发环境的搭建
    因式分解技巧——拆项与添项
    因式分解技巧——分组分解
    因式分解技巧——代公式
    因式分解技巧——提公因式
    一个2014年的数学日历
    用面积来证三角不等式
    一条直线若能平分矩形面积,则它必然经过矩形的中心
  • 原文地址:https://www.cnblogs.com/riasky/p/3430839.html
Copyright © 2011-2022 走看看