RT Shader System in OGRE 1.7.0

1649 篇文章 12 订阅
1623 篇文章 23 订阅

OGRE在1.7.0版中,最重要的feature之一就是real-time shader system (RT Shader System),它的功能就是從OGRE的material script中自動產生shader (HLSL/CG或GLSL檔案)來取代或增加原本fix pipeline的功能。 使用RT Shader System好處呢?

  1. 美術和程式分工

    以往要要在Ogre中使用normal map必需大費周張的寫vertex shader和pixel shader再把全域變數(global variable)關連到OGRE裡的光源(lights)和座標轉換(transforms),在團隊裡程式人員和美術人員往往是不同一群人,因此新增新的美術資料,就必需勞動程式再編輯material script,分工不完全使得團隊效率降低。

  2. 開發快速

    因為shader是從shader範本(template)中產生出來,而範本函蓋大部分的繁覆的工作,所以開發人員能過集中精力去處理shader裡較重要的部份(藉由撰寫RT Shader System的plugin),使得實作新的shader更快速。而撰寫好的plugin又能在material script透過參數使用,使得整合也更快速。

使用

  1. 設罝開發環境

    使用RT Shader System需先在程式專案中連結OgreRTShaderSystem.lib (Debug組態是OgreRTShaderSystem_d.lib),放在OgreSDK\lib中。並且在初始化OGRE和RT Shader System的cpp檔include RT Shader System的header:

    #include "OGRE/RTShaderSystem/OgreRTShaderSystem.h"
    


  2. 初始化

    RT Shader System必須早於任何一個Resource Group初始化,通常是在產生第一個RenderWindow之後。

    RenderWindow* window = Root::getSingleton().initialise(true, windowTitle);
    //在這裡初始化RT Shader System
    _initializeRTShaderSystem();
    
    ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

    以下是_initializeRTShaderSystem()的definition

    bool _initializeRTShaderSystem()
    {
        if (RTShader::ShaderGenerator::initialize())
        {
            //先取得ShaderGenerator的pointer
            _shaderGenerator =
                RTShader::ShaderGenerator::getSingletonPtr();
            //設定ShaderSystem所使用的Shader語言
            _shaderGenerator->setTargetLanguage("hlsl");
            //你可以指定一個目錄來暫存RT Shader System產生的Shader,
            //這樣就不需要重覆產生Shader
            //但1.7.0的RT Shader System只接受絕對路徑,
            //因此此處使用boost::filesystem把相對路徑轉換成絕對路徑
            namespace fs = boost::filesystem;
            std::string shaderCachePath =
                fs::system_complete( fs::path("./ShaderCache/") ).string();
            _shaderGenerator->setShaderCachePath(shaderCachePath);
    
            //指定一個material listener給material manager,此處稍後說明
            _rtssMaterialListener =
                new RtShaderSystemListener(_shaderGenerator);
            MaterialManager::getSingleton().addListener(
                _rtssMaterialListener);
            return true;
        }
        return false;
    }

    RtShaderSystemListener繼承MaterialManager::Listener,是從OGRE Sample裡抄出來的class。

    /**
    當RtShaderSystemListener被註冊給MaterialManager之後,一旦找不到適當的tecnique
    來render 某一個material,便會喚起handleSchemeNotFound這個member function。因
    此我們要在handleSchemeNotFound把原本的material technique交給ShaderGenerator
    來產生以Shader為基礎的tecnique並回傳。
    */
    class RtShaderSystemListener : public MaterialManager::Listener
    {
    public:
    
    RtShaderSystemListener(RTShader::ShaderGenerator* pShaderGenerator)
    {
        mShaderGenerator = pShaderGenerator;
    }
    
    /**
    當Entity要被render時,OGRE會依指定給viewport的scheme name從material挑選符合
    的technique(在我們清況中,會指定ShaderGenerator::DEFAULT_SCHEME_NAME給
    viewport)因為material裡tecnique的scheme name預設是
    MaterialManager::DEFAULT_SCHEME_NAME,
    所以handleSchemeNotFound便會被呼叫來處理"找不到technique"事件。
    */
    
    virtual Technique* handleSchemeNotFound(
        unsigned short schemeIndex,
        const String& schemeName, 
        Material* originalMaterial, 
        unsigned short lodIndex,
        const Renderable* rend)
    {
        Technique* generatedTech = NULL;
    
        // 
        //Case this is the default shader generator scheme.
        if (schemeName == RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME)
        {
            bool techniqueCreated;
    
            // Create shader generated technique for this material.
            techniqueCreated = mShaderGenerator->createShaderBasedTechnique(
                originalMaterial->getName(),
                MaterialManager::DEFAULT_SCHEME_NAME,
                schemeName);
    
            // Case technique registration succeeded.
            if (techniqueCreated)
            {
            // Force creating the shaders for the generated technique.
                mShaderGenerator->validateMaterial(schemeName, 
                    originalMaterial->getName());
    
                // Grab the generated technique.
                Material::TechniqueIterator itTech = 
                    originalMaterial->getTechniqueIterator();
    
                while (itTech.hasMoreElements())
                {
                    Technique* curTech = itTech.getNext();
    
                    if (curTech->getSchemeName() == schemeName)
                    {
                        generatedTech = curTech;
                        break;
                    }
                }
            }
        }
        return generatedTech;
    }
    protected:
        /// The shader generator instance.
        Ogre::RTShader::ShaderGenerator*  mShaderGenerator;
    };
    最後,我們必需要讓OGRE使用RT Shader System所產生的technique(亦即以shader為基礎的technique)。因此我們設定viewport所要使用的scheme name。
    viewport->setMaterialScheme(
        RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME);
     
2 則留言:
  1. 不好意思,請問一下.

    1. 如果shader的材質已在initialiseAllResourceGroups()讀入.要如何讀入shader檔(.cg)呢?

    2. 要如何啟動或關閉該shader的功能?或是需要做什麼初始化?

    NDark

    回覆刪除
  2. 你好,
    1. RT Shader System應在 initialiseAllResourceGroups()之前初始化才能正常運作。如果要使用custom shader, 就造一般material的方式把custom shader加在material檔裡就行了。

    2. RT Shader System是以viewport會開位開關, 如果要關閉RT Shader System, 請用
    viewport->setMaterialScheme把viewport使用的material scheme設成Ogre::MaterialManager::DEFAULT_SCHEME_NAME

    回覆刪除
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值