天天看點

Ogre分層渲染

轉載請注明出處!http://www.cnblogs.com/pulas

在超大的場景中,如果既想看到近處的物體,又想看到很遠的物體,則必須把相機的遠近裁剪面距離設得很大。遠近裁剪面距離比例太大了,由于Depth Buffer的精度有限,這樣就會導緻Z-Fighting,挨在一起的物體表面會發生閃爍。

解決這個問題有兩種方法,一是用Logarithmic Depth Buffer,但是由于此方法需要對每個物體在shader中計算其對數深度,是以不太具有通用性,故沒有深入研究。感興趣的可以自己試試。

相關參考資料:

http://www.gamasutra.com/blogs/BranoKemen/20090812/2725/Logarithmic_Depth_Buffer.php

http://www.gamedev.net/blog/73/entry-2006307-tip-of-the-day-logarithmic-zbuffer-artifacts-fix/

第二種方法是使用分層渲染。首先設定一個比例合适的遠近裁剪面距離,渲染很遠處的物體,然後清除Depth Buffer,但是保留Color Buffer。然後再設定一個比例合适的遠近裁剪面距離,渲染近處的物體。Madmarx寫的一系列Ogre教程so3dtools中,其中A_1_FrustumSlicing例子很好的示範了怎麼在Ogre中使用分層渲染。

http://sourceforge.net/projects/so3dtools/

http://www.ogre3d.org/forums/viewtopic.php?f=2&t=65275

http://www.ogre3d.org/forums/viewtopic.php?f=2&t=46418

         bool COgreApplication::layeredRendering()      

         {

// This is the same, but it updates internal statistics
            // and get Listeners correctly called.
            m_pMainRenderWindow->_beginUpdate();

            Ogre::Real fFarClipDistance = m_pCamera->getFarClipDistance();
            Ogre::Real fNearClipDistance = m_pCamera->getNearClipDistance();

            // first render
            m_pSceneManager->setVisibilityMask(0x00000001);

            {
                m_pCamera->setNearClipDistance(fFarClipDistance);
                m_pCamera->setFarClipDistance(fFarClipDistance*1000);
                m_pMainViewport->setOverlaysEnabled(false);
                m_pMainViewport->setShadowsEnabled(false);

                m_pMainRenderWindow->_updateViewport(m_pMainViewport);

                // back to normal
                m_pMainViewport->setOverlaysEnabled(true);
                m_pMainViewport->setShadowsEnabled(true);
            }

            // second render
            // 第二遍渲染要渲染所有物體,以免處于兩層交界處的物體發生異樣

            m_pSceneManager->setVisibilityMask(0xFFFFFFFF);

            {
                m_pMainViewport->setClearEveryFrame(true, Ogre::FBT_DEPTH);
                m_pMainViewport->setSkiesEnabled(false);
                m_pCamera->setNearClipDistance(fNearClipDistance);
                m_pCamera->setFarClipDistance(fFarClipDistance);

                m_pMainRenderWindow->_updateViewport(m_pMainViewport);

                // go back to normal
                m_pMainViewport->setSkiesEnabled(true);
                m_pMainViewport->setClearEveryFrame(true, Ogre::FBT_COLOUR | Ogre::FBT_DEPTH);
            }

            // update all other viewports...
            m_pMainRenderWindow->_updateAutoUpdatedViewports();

            m_pMainRenderWindow->_endUpdate();

            // The drawn surface is then shown on the screen
            // (google "double buffering" if you want more details).
            // I always use vertical synchro.
            bool lVerticalSynchro = true;
            m_pMainRenderWindow->swapBuffers(lVerticalSynchro);

            return true;
        }      

調用方法:

// I don't want it to be re-drawn when I do window->update() [2/22/2012 zhangzhonghui]
            m_pMainRenderWindow->setAutoUpdated(false);


            // I want to update myself the content of the window, not automatically. [2/22/2012 zhangzhonghui]
            m_pMainViewport->setAutoUpdated(false);


            // 分層渲染
            layeredRendering();

            // This update some internal counters and listeners.
            // Each render surface (window/rtt/mrt) that is 'auto-updated' has got its 'update' function called.
            m_pOgreRoot->renderOneFrame();      

轉載于:https://www.cnblogs.com/pulas/archive/2013/01/18/2866134.html

上一篇: ogre渲染過程