Ogre初体验

Ogre初体验
  最近游戏又要封测了,工作比较紧张,晚上下班了比较累,回家懒得写代码了,不过顺便倒是继续完成了对 新剑侠情缘(和月影传说的资源格式相同)的资源逆向。完成了资源逆向后,突然兴致来了,写了个简单的地图查看器,到目前为止,一切运行正常。后来做了个简单的Demo,实现了基本的寻路和技能动画播放,其实新剑侠情缘原本的技能效果以今天的眼光看起来也还可以,即便如此,我还是集成了hge的粒子系统进去,试了下效果,还是挺奇怪的。
做完了这些之后,本想为我的PSP山寨一个新剑侠情缘。不料后来连续加了好几天班,加了几天班之后,人也懒了,山寨游戏的事情也就无疾而终了。
前面写过几篇逆向工程的文章,前几天翻出来看了下,感觉像是另一个人写的天书,我自己看自己的文章尚且如此,别人就更不用说了,其实对大部分人而言,关心的只是逆向的成果。对新剑侠情缘的资源和相关渲染感兴趣的朋友可以单独Email我。
  开始阅读Ogre代码正是在这百无聊赖的状态下开始的,Ogre推出来很多年了,貌似05年就听说朋友说起过这个项目,不过我一向是专注服务端开发,对客户端开发经验不是很多,在3D领域就完全是的新手了,所以一直也没仔细研究。这几天拿起原来下载的一个版本,简单读了下代码。
Ogre的结构还是很清晰的,和手册上说的一样,主要就是那几个对象,Demo大部分也很简单,代码量不多,看起来很振奋人心。
但是对我这样的新手来说,首先想了解的当然是渲染流程。 Ogre的渲染流程确实会让3D新手不适应,它是从RenderTarget开始的,一个RenderTarget可以有几个ViewPort,每个ViewPort都有一个独立的摄像机,这可以实现同屏幕多个渲染。
通过ViewPort对象的update调用
 mCamera->_renderScene(this, mShowOverlays);
来执行场景渲染,而场景渲染里,最重要的要算_findVisibleObjects了,
这个函数将可见的物体添加到渲染队列里,这个函数非常的绕,里面还用到了Vistor,精神不好容易被绕晕,好在我挺住了,熬过来了。
熟悉了大致的渲染流程后,我觉得该写点东西来实战了。
3D教程的开始一般会教大家画三角形,所以我也想用Ogre画个三角形玩玩,
一开始,我也想从像那些Demo一样从ExampleApplication继承,不过我发现这样启动太慢了,而且我不需要加载那么多的材质,
所以自己手动Configure了,代码如下:
Ogre::LogManager* pLogManager = new Ogre::LogManager;
    Ogre::Log* pLog = pLogManager->createLog("ogreLearn1.log");
    pLog->setDebugOutputEnabled(true);

    Ogre::Root* pRootObject = new Ogre::Root;
    pRootObject->loadPlugin("RenderSystem_Direct3D9_d.dll");
    pRootObject->loadPlugin("Plugin_OctreeSceneManager_d.dll");
    
    Ogre::RenderSystem* pRenderSystem = pRootObject->getRenderSystemByName("Direct3D9 Rendering Subsystem");
    pRenderSystem->setConfigOption("Full Screen", "False");
    pRootObject->setRenderSystem(pRenderSystem);   
    Ogre::RenderWindow* pRenderWindow = pRootObject->initialise(true);

编译测试了下,可以正常运行,不过发现屏幕是花的,我还没有创建场景呢,继续添加摄像机和ViewPort以及场景
// 创建场景和摄像机以及ViewPort
    Ogre::SceneManager* pSceneManager = pRootObject->createSceneManager(Ogre::ST_GENERIC, "OgreLearn1");
    Ogre::Camera* pCamera = pSceneManager->createCamera("MainCamara");
    pCamera->setPosition(0.0, 0.0, -20.0);
    pCamera->lookAt(0, 0, 0);
    pCamera->setNearClipDistance(2);

    Ogre::Viewport* pViewPort = pRenderWindow->addViewport(pCamera);
    pViewPort->setBackgroundColour(Ogre::ColourValue(0, 0, 0, 1.0f) );
    pCamera->setAspectRatio(pViewPort->getActualWidth()/pViewPort->getActualHeight() );

最后加上pRootObject->startRendering();
编译运行,一切正常,屏幕颜色也变成了想要的黑色,恩,下一步该添加三角形了,我不太喜欢用OgreManualObject,一堆的繁琐操作。这里用自定义的Mesh来绘制3角形。
pSceneManager->setAmbientLight(Ogre::ColourValue(0.2, 0.2, 0.2) );
        Ogre::MeshPtr pMeshData = Ogre::MeshManager::getSingleton().createManual("Learn", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
        Ogre::SubMesh* pSubMesh = pMeshData->createSubMesh();
        pSubMesh->useSharedVertices = false;
        pSubMesh->vertexData = new Ogre::VertexData;
        pSubMesh->vertexData->vertexStart = 0;
        pSubMesh->vertexData->vertexCount = 3;

先设置了环境光(其实没啥用,我后面会禁止),然后创建了一个自定义的Mesh,
紧接着的是创建一个SubMesh,要知道Ogre中最小的网格就是SubMesh,创建好SubMesh后,要填充网格结构了,
创建了一个VertexData,设置顶点数目为3(也就是一个三角形),下面该定义顶点格式了,
Ogre::VertexDeclaration* pDecle = pSubMesh->vertexData->vertexDeclaration;
        size_t sOffset = 0;
        pDecle->addElement(0, sOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
        sOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
        pDecle->addElement(0, sOffset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
        sOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);

上述代码定义了顶点格式,只有基本的坐标和颜色。
下一步将是申请显存,填充顶点结构。
Ogre::HardwareVertexBufferSharedPtr vBuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(sOffset, 3, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
        float* pReal = static_cast<float*>(vBuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
        Ogre::RGBA* pColor = NULL;

        *pReal++ = -2.0f;
        *pReal++ = 0.0f;
        *pReal++ = 0.0f;
        pColor = (Ogre::RGBA*)pReal;
        pRenderSystem->convertColourValue(Ogre::ColourValue(1.0f, 0.0, 0, 0.0f), pColor);
        pReal = (float*)(pColor+1);
        
        *pReal++ = 0.0f;
        *pReal++ = 2.0f;
        *pReal++ = 0.0f;
        pColor = (Ogre::RGBA*)pReal;
        pRenderSystem->convertColourValue(Ogre::ColourValue(0.0f, 0, 1.0, 1.0f), pColor);
        pReal = (float*)(pColor+1);


        *pReal++ = 2.0f;
        *pReal++ = 0.0f;
        *pReal++ = 0.0f;
        pColor = (Ogre::RGBA*)pReal;
        pRenderSystem->convertColourValue(Ogre::ColourValue(1.0f, 0, 0, 1.0f), pColor);
        pReal = (float*)(pColor+1);
        vBuf->unlock();
        pSubMesh->vertexData->vertexBufferBinding->setBinding(0, vBuf);
       
        pMeshData->load();
        pMeshData->_setBounds(Ogre::AxisAlignedBox(-2, 0, -1, 2, 2, 1) );
填充顶点后,设置网格包围盒,这样一个自定义的网格就创建好了,接下来要创建一个使用该网格的实体了
    Ogre::Entity* pEntity = pSceneManager->createEntity("TestEntity", "Learn");
        pEntity->setMaterialName("BaseWhiteNoLighting");

        pSceneManager->getRootSceneNode()->createChildSceneNode()->attachObject(pEntity);
        pEntity->getParentNode()->setPosition(3, 0, 0);
        pEntity->getParentNode()->rotate(Ogre::Quaternion(1.0f, 1.0f, 0, 1.0f) );

好了,这样实体也创建好了,接下来执行渲染吧:
pRootObject->startRendering();

遇到的问题

  上述代码是运行正常的,但是一开始,我执行的结果是看不到任何东西,跟踪了下,发现实体每次都被摄像机裁剪了,才发觉自定义Mesh要自己设置包围盒子,
设置可包围盒子。
 设置了包围盒后,数据已经进入了D3D的渲染管道,但是还是没看到三角形,仔细观察,原来摄像机对着的是三角形的背面。。。
调整摄像机后,终于能看到一个三角形了,不过是白色的。。。
从这个症状看,应该是没有关闭光照导致的,但是我明明主动调用RenderSystem关闭光照了啊,仔细跟踪了下原来是材质在捣乱,
默认的材质是开启了光照的,所以在渲染前的SceneManager::_setPass 的时候,开启了光照。
这好办,主动设置了关闭光照的材质"BaseWhiteNoLighting" 后,终于看到了彩色三角形了。


你可能感兴趣的:(Ogre初体验)