天天看点

用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实现,以后再写。

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

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

//这是贴上lightmap的图片

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

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

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

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

view plain copy to clipboard print ? ·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150

  1. #ifndef __WX_LIGHTMAP_MAKER_H__   
  2. #define __WX_LIGHTMAP_MAKER_H__   
  3. #include ”SceneManipulator.h”   
  4. namespace WX   
  5. {   
  6.     class LightMapMaker   
  7.     {   
  8.     public:   
  9.         LightMapMaker(SceneManipulator* manipulator);   
  10.         ~LightMapMaker(void);   
  11.         // 初始化,包括创建render texture,camera等   
  12.         void initial(void);   
  13.         // 销毁render texture   
  14.         void destroy(void);   
  15.         // 保存光照图到文件   
  16.         // 格式 ”emei.lightmap.png”,也支持全路径,比如../../Data/Scene/emei.lightmap.png”   
  17.         void outputTexture(const Ogre::String& fileName);   
  18.     protected:   
  19.         SceneManipulator* mSceneManipulator;   
  20.         Ogre::RenderTexture* mRenderTexture;   
  21.     };   
  22. }   
  23. #endif  

/*<br />

@filename WXLightMapMaker.h<br />

@creator LuoYinan<br />

@data 2010.6.14<br />

@remarks 创建场景光照图<br />

*/<br />

#ifndef __WX_LIGHTMAP_MAKER_H__<br />

#define __WX_LIGHTMAP_MAKER_H__</p>

<p>#include “SceneManipulator.h”</p>

<p>namespace WX<br />

{<br />

class LightMapMaker<br />

{<br />

public:<br />

LightMapMaker(SceneManipulator* manipulator);<br />

~LightMapMaker(void);</p>

<p> // 初始化,包括创建render texture,camera等<br />

void initial(void);<br />

// 销毁render texture<br />

void destroy(void);</p>

<p> // 保存光照图到文件<br />

// 格式 “emei.lightmap.png”,也支持全路径,比如../../Data/Scene/emei.lightmap.png”<br />

void outputTexture(const Ogre::String& fileName);</p>

<p> protected:</p>

<p> SceneManipulator* mSceneManipulator;<br />

Ogre::RenderTexture* mRenderTexture;</p>

<p> };<br />

}<br />

#endif

view plain copy to clipboard print ? ·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150

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