您的位置:首页 > 其它

RT Shader System in OGRE 1.7.0 .

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

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

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

使用

設罝開發環境
使用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"


初始化

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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: