用Ogre生成天龙八部的lightmap和minimap的简单方法

自从在一家创业小公司当了客户端主程以后,就忙的没有时间写博客了,整个公司没有一个人有完整的项目经验,所有一切都在摸索中前进,但初生牛犊不怕虎,项目还算进展顺利。但我始终认为,安静下来总结整理一下工作心得是必要的,可惜这个愿望恐怕得等到这个项目忙完以后。

周末有点时间,还是可以抽空随便写点东西。

lightmap的重要性不用多说,没必要所有阴影都动态去渲染,那些一辈子也不会动的静态物体,贴一张lightmap就行了,可惜Ogre只提供动态阴影给我们,帮人也不帮到底。

如何生成天龙八部一样lightmap,如果你去百度一下,他们会告诉你各种方法,什么光线追踪,shader,之类

以上都是告诉你,自己去产生一个阴影。但是Ogre已经帮我们产生了动态阴影,我们就没必要再自己去生成阴影,

只要用动态阴影的渲染一张静态阴影图,保存下来不就行了么。

那么如何用Ogre的动态阴影去产生一张静态的阴影图呢?

1)先学会渲染一张minimap的缩略图,缩略图大家都应该会吧,创建一个垂直俯瞰的摄像机,平行投影拍一张就是

2)改进minimap,让垂直俯瞰的摄像机的视口只渲染地形队列。不渲染其他队列

这样拍出来的minimap就只有阴影和地形纹理混合后效果了

   Ogre::RenderQueueInvocationSequence* rqis =
    Ogre::Root::getSingleton().createRenderQueueInvocationSequence(“Lightmap maker”);
   Ogre::RenderQueueInvocation* rqi =
    rqis->add(Ogre::RENDER_QUEUE_WORLD_GEOMETRY_1, “World Geometry”);
   viewport->setRenderQueueInvocationSequenceName(“Lightmap maker”);

3)再改进一下,把地形材质设置为BaseWhite,全白,那么minimap就变成了lightmap了。

4)Ogre的阴影并不好用,所以你需要优化,怎么优化,或者用shader实现,以后再写。

//这是动态阴影的图片、、、、、、、、、、、、、、、、、、、、、、、、、、

//这是贴上lightmap的图片

./这是阴影图、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

附上代码,看看思路就好!

 

·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. /*  
  2. @filename WXLightMapMaker.h   
  3. @creator  LuoYinan  
  4. @data     2010.6.14  
  5. @remarks  创建场景光照图  
  6. */  
  7. #ifndef __WX_LIGHTMAP_MAKER_H__   
  8. #define __WX_LIGHTMAP_MAKER_H__   
  9.   
  10. #include ”SceneManipulator.h”   
  11.   
  12. namespace WX   
  13. {   
  14.     class LightMapMaker   
  15.     {   
  16.     public:   
  17.         LightMapMaker(SceneManipulator* manipulator);   
  18.         ~LightMapMaker(void);   
  19.   
  20.         // 初始化,包括创建render texture,camera等   
  21.         void initial(void);   
  22.         // 销毁render texture   
  23.         void destroy(void);   
  24.   
  25.         // 保存光照图到文件   
  26.         // 格式 ”emei.lightmap.png”,也支持全路径,比如../../Data/Scene/emei.lightmap.png”   
  27.         void outputTexture(const Ogre::String& fileName);   
  28.   
  29.     protected:   
  30.   
  31.         SceneManipulator* mSceneManipulator;   
  32.         Ogre::RenderTexture* mRenderTexture;   
  33.            
  34.     };   
  35. }   
  36. #endif  

·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. #include ”WXLightMapMaker.h”   
  2.   
  3. #include ”GameScene/TerrainData.h”   
  4. #include ”GameScene/WXScene.h”   
  5. #include ”GameScene/WXSceneInfo.h”   
  6. #include ”GameScene/WXStaticEntityObject.h”   
  7. #include ”GameScene/WXModelObject.h”   
  8. namespace WX   
  9. {   
  10.     //———————————————————————————-   
  11.     LightMapMaker::LightMapMaker(SceneManipulator* manipulator)   
  12.         : mSceneManipulator(manipulator)   
  13.         , mRenderTexture(0)   
  14.     {   
  15.   
  16.     }   
  17.   
  18.     //——————————————————————————–   
  19.     LightMapMaker::~LightMapMaker(void)   
  20.     {   
  21.   
  22.     }   
  23.   
  24.     //——————————————————————————–   
  25.     void LightMapMaker::initial(void)   
  26.     {   
  27.         // 确保地形已经载入   
  28.         TerrainData* data = mSceneManipulator->getTerrainData();   
  29.         assert(data && “TerrainData* == NULL”);   
  30.   
  31.         // 创建lightmap摄像机,垂直俯瞰整个地图   
  32.         Ogre::SceneManager* mSceneManager = mSceneManipulator->getSceneManager();   
  33.         //if (mSceneManipulator->getTerrainData()->mLightmapImage == NULL)   
  34.         {   
  35.             static const String msLightmapMaker(“Lightmap maker”);   
  36.             Ogre::Camera* camera = 0;   
  37.             try  
  38.             {   
  39.                 camera = mSceneManager->getCamera(msLightmapMaker);   
  40.             }   
  41.             catch (const Ogre::Exception& e)   
  42.             {   
  43.                 // 只提示异常,而不退出程序   
  44.                 if (e.getNumber() == e.ERR_ITEM_NOT_FOUND)   
  45.                 {   
  46.                     //MessageBox(NULL, e.what(), ”An exception has occured!”, MB_OK | MB_ICONERROR | MB_TASKMODAL);   
  47.                 }   
  48.                 else  
  49.                 {   
  50.                     throw;   
  51.                 }   
  52.                        
  53.             }   
  54.             if (!camera)   
  55.             {   
  56.                 camera = mSceneManager->createCamera(msLightmapMaker);   
  57.                 camera->setAutoAspectRatio(true);   
  58.                 camera->setProjectionType(Ogre::PT_ORTHOGRAPHIC); // 平行投影   
  59.                 // 在Ogre1.6版本中,平行投影的大小改为setOrthoWindowWidth和setOrthoWindowHeight来决定,   
  60.                 // 而不是以前版本用的FOV和近截面,so…   
  61.                 camera->setFOVy(Ogre::Degree(90));   
  62.                 camera->setOrthoWindowWidth(mSceneManipulator->getTerrainData()->getXSize()*mSceneManipulator->getBaseScale());   
  63.                 camera->setOrthoWindowHeight(mSceneManipulator->getTerrainData()->getZSize()*mSceneManipulator->getBaseScale());   
  64.   
  65.                 Ogre::Quaternion orientation;   
  66.                 orientation.FromAxes(Ogre::Vector3::UNIT_X, Ogre::Vector3::NEGATIVE_UNIT_Z, Ogre::Vector3::UNIT_Y);   
  67.                 camera->setOrientation(orientation);   
  68.             }   
  69.   
  70.             // 计算所有对象包围盒,以此来决定摄像机的参数   
  71.             Ogre::AxisAlignedBox aabb;   
  72.             Ogre::SceneManager::MovableObjectIterator itm =   
  73.                 mSceneManager->getMovableObjectIterator(Ogre::EntityFactory::FACTORY_TYPE_NAME);   
  74.             while (itm.hasMoreElements())   
  75.             {   
  76.                 Ogre::MovableObject* movable = itm.getNext();   
  77.                 aabb.merge(movable->getWorldBoundingBox(true));   
  78.             }   
  79.             camera->setNearClipDistance(32 * mSceneManipulator->getBaseScale() / 2);    
  80.             camera->setFarClipDistance(camera->getNearClipDistance() + aabb.getMaximum().y - aabb.getMinimum().y);   
  81.             camera->setPosition(0, camera->getNearClipDistance() + aabb.getMaximum().y, 0);   
  82.   
  83.             // 调整阴影参数   
  84.             Ogre::Real distance = camera->getNearClipDistance() * Ogre::Math::Sqrt(1 + Ogre::Math::Sqr(camera->getAspectRatio()));   
  85.             mSceneManager->setShadowFarDistance(distance);   
  86.             Ogre::Real camHeight = camera->getPosition().y;   
  87.             mSceneManager->setShadowDirLightTextureOffset(camHeight / distance);   
  88.   
  89.   
  90.             // 创建lightmap的Rtt纹理,和天龙一样,设为地形大小的8倍   
  91.             Ogre::TexturePtr pTexture = (Ogre::TexturePtr)Ogre::TextureManager::getSingleton().getByName(“LightmapRttTex”);   
  92.             if (pTexture.isNull())   
  93.             {   
  94.                 size_t width = data->getXSize() * 8;   
  95.                 size_t height = data->getZSize() * 8;   
  96.                 pTexture = Ogre::TextureManager::getSingleton().createManual(   
  97.                     “LightmapRttTex”, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,   
  98.                     Ogre::TEX_TYPE_2D,   
  99.                     width, height, 1, 0, Ogre::PF_BYTE_RGB,   
  100.                     Ogre::TU_RENDERTARGET, 0);   
  101.             }   
  102.             Ogre::HardwarePixelBufferSharedPtr pBuffer = pTexture->getBuffer(0, 0);   
  103.             mRenderTexture = pBuffer->getRenderTarget(0);     
  104.   
  105.             // 创建lightmap的视口   
  106.             Ogre::Viewport* viewport = mRenderTexture->addViewport(mSceneManipulator->getSceneManager()->getCamera(“Lightmap maker”));   
  107.             viewport->setOverlaysEnabled(false);   
  108.             viewport->setSkiesEnabled(false);   
  109.             viewport->setShadowsEnabled(true);   
  110.             // 自定义一个渲染队列调用组,只渲染地形队列,这是关键,我们只要阴影,不要其他的.   
  111.             // 如果你全部都渲染了,那就变成了minimap,缩略图了.   
  112.             Ogre::RenderQueueInvocationSequence* rqis =   
  113.                 Ogre::Root::getSingleton().createRenderQueueInvocationSequence(“Lightmap maker”);   
  114.             Ogre::RenderQueueInvocation* rqi =   
  115.                 rqis->add(Ogre::RENDER_QUEUE_WORLD_GEOMETRY_1, “World Geometry”);   
  116.             viewport->setRenderQueueInvocationSequenceName(“Lightmap maker”);   
  117.         }   
  118.   
  119.     }   
  120.     //——————————————————————————–   
  121.     void LightMapMaker::destroy(void)   
  122.     {   
  123.         if (mRenderTexture)   
  124.         {   
  125.             mSceneManipulator->getSceneManager()->destroyCamera(“Lightmap maker”);   
  126.   
  127.             mRenderTexture->removeAllViewports();   
  128.   
  129.             Ogre::TextureManager::getSingleton().remove(“LightmapRttTex”);   
  130.   
  131.             mRenderTexture = NULL;   
  132.         }   
  133.     }   
  134.   
  135.     //——————————————————————————–   
  136.     void LightMapMaker::outputTexture(const Ogre::String& fileName)   
  137.     {   
  138.         // 如果已经有lightmap了,跳过   
  139.         if (mSceneManipulator->getTerrainData()->mLightmapImage)    
  140.         {   
  141.             // 需要提示么?   
  142.             return;   
  143.         }   
  144.   
  145.         // 让所有静态物体都可以投射阴影,来制作lightmap   
  146.         Scene::ObjectsByTypeRange objests = mSceneManipulator->getSceneInfo()->findObjectsByType(StaticEntityObject::msType);   
  147.         for (Scene::ObjectsByTypeIterator it = objests.first; it != objests.second; ++ it)   
  148.         {   
  149.             ObjectPtr object = (*it);   
  150.             object->setPropertyAsString(“cast shadows”“true”);   
  151.             //object->setPropertyAsString(“receive shadows”, ”true”);   
  152.         }   
  153.         objests = mSceneManipulator->getSceneInfo()->findObjectsByType(ModelObject::msType);   
  154.         for (Scene::ObjectsByTypeIterator it = objests.first; it != objests.second; ++ it)   
  155.         {   
  156.             ObjectPtr object = (*it);   
  157.             object->setPropertyAsString(“cast shadows”“true”);   
  158.             //object->setPropertyAsString(“receive shadows”, ”true”);   
  159.         }   
  160.   
  161.         // 用BaseWhite代替原来的地形材质,并重构地形   
  162.         TerrainData::MaterialTemplates& materials = mSceneManipulator->getTerrainData()->mMaterialTemplates;   
  163.         TerrainData::MaterialTemplates materialsCopy(materials);   
  164.         materials["OneLayer"] = “BaseWhite”;   
  165.         materials["OneLayerLightmap"] = “BaseWhite”;   
  166.         materials["TwoLayer"] = “BaseWhite”;   
  167.         materials["TwoLayerLightmap"] = “BaseWhite”;   
  168.         mSceneManipulator->getTerrain()->buildGeometry(mSceneManipulator->getBaseSceneNode(), true);   
  169.   
  170.         // 更新   
  171.         //mSceneManipulator->getSceneManager()->_updateSceneGraph(mSceneManipulator->getSceneManager()->getCamera(“Lightmap maker”));   
  172.          mRenderTexture->update();   
  173.   
  174.         // 保存lightmap到文件   
  175.         Ogre::String LightmapFileName(fileName);   
  176.         String baseName, path, outExtention;   
  177.         if (fileName.empty())   
  178.         {   
  179.             WX::TerrainData* data = mSceneManipulator->getTerrainData();   
  180.             Ogre::StringUtil::splitBaseFilename(data->mHeightmapFilename, baseName, outExtention);   
  181.             LightmapFileName = baseName + “.lightmap.png”;   
  182.         }   
  183.         mRenderTexture->writeContentsToFile(LightmapFileName);   
  184.   
  185.         // 载入lightmap   
  186.         static const String TEMP_GROUP_NAME = “#TEMP#”// 临时资源组   
  187.         Ogre::StringUtil::splitFilename(LightmapFileName, baseName, path);   
  188.         mSceneManipulator->getTerrainData()->mLightmapFilename = baseName;   
  189.         Ogre::ResourceGroupManager& rgm = Ogre::ResourceGroupManager::getSingleton();   
  190.         rgm.addResourceLocation(path, “FileSystem”, TEMP_GROUP_NAME, false);   
  191.         // 这个函数本来是protected,以后最好还是重新载入整个地形,而不是单独载入lightmap   
  192.         mSceneManipulator->getTerrainData()->_loadLightmap(baseName, “image”, TEMP_GROUP_NAME);    
  193.   
  194.         // 换回原来的地形材质,并重构地形   
  195.         std::swap(materials, materialsCopy);   
  196.         mSceneManipulator->getTerrain()->buildGeometry(mSceneManipulator->getBaseSceneNode(), true);   
  197.   
  198.         // 所有静态物体不再需要投射阴影了,因为我们有lightmap   
  199.         objests = mSceneManipulator->getSceneInfo()->findObjectsByType(StaticEntityObject::msType);   
  200.         for (Scene::ObjectsByTypeIterator it = objests.first; it != objests.second; ++ it)   
  201.         {   
  202.             ObjectPtr object = (*it);   
  203.             object->setPropertyAsString(“cast shadows”“false”);   
  204.             //object->setPropertyAsString(“receive shadows”, ”true”);   
  205.         }   
  206.         objests = mSceneManipulator->getSceneInfo()->findObjectsByType(ModelObject::msType);   
  207.         for (Scene::ObjectsByTypeIterator it = objests.first; it != objests.second; ++ it)   
  208.         {   
  209.             ObjectPtr object = (*it);   
  210.             object->setPropertyAsString(“cast shadows”“false”);   
  211.             //object->setPropertyAsString(“receive shadows”, ”true”);   
  212.         }   
  213.   
  214.         // 销毁临时资源组   
  215.         rgm.destroyResourceGroup(TEMP_GROUP_NAME);   
  216.     }   
  217.   
  218.   
  219. }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值