青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 94, comments - 250, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

GPU程序在GameByro中的使用

Posted on 2009-04-22 11:18 Condor 閱讀(1891) 評論(0)  編輯 收藏 引用

引言:

GameBryo擁有一套復雜的材質系統,這套材質系統可以根據渲染對象的狀態和屬性生成不同的shader代碼,提高了渲染流程的適應性,可以使你定義一套材質能適應多種渲染對象。同時,GameByro將shader的初始化和使用插件化,方便與美術工具集成,并且實現了平臺無關性。為了實現這些目的,GameByro使用了一套復雜的機制,本文主要解析GameByro如何生成、編譯并使用shader代碼。

Shader

GameBryo的shader的接口封裝在NiShader中,頂點數據流聲明,常量表的訪問,渲染狀態的設置都是通過這個類(有點類似于D3Deffect)。在程序運行NiShader是由NiShaderFactory負責管理的,NiShaderFactory通過NiShaderLibrary從文件中創建shader,用全局性的map管理起來。NiShaderLibrary通過解析shader文本創建NiShader對象,并調用3D圖形接口編譯shader代碼,將這個類以dll的形式封裝,就可以作為插件來使用。NiShader類的創建可以通過解析文件來進行,也可以通過C++的類來定制,只需從NiShader上繼承即可。GameByro為PC平臺提供了一個NiD3DXEffectShaderLib庫,這個庫提供了解析shader文件和初始化shader對象的功能。用戶只需按GameByro定義的格式編寫shader代碼的語意和注釋,NiD3DXEffectShaderLibrary就會根據文本來創建NiD3Dshader對象,在應用程序中就可以通過Techinqe的名稱來訪問這個對象。通過這種機制,我們將shader文本文件放在相關美術工具指定的目錄下,在工具中就可以使用這些shader,并且能夠通過shader的語意和注釋為相關參數和變量生成UI,方便美術調試。

WIN平臺上的整個流程如下:

1. 應用程序在啟動時會先初始化整個shader系統,接下來導入Shader解析庫和加載庫(dll的形式)。

2. 接下來應用程序將NiD3DShader的初始化工作委托給NiShaderLibrary來處理,NiShaderLibrary首先通過NiD3DXEffectLoader載入所有的shader文本文件,并通過NiD3DXEffectParser解析文本生成NiD3DXEffectFile對象,同時NiD3DXEffectLoader還負責將shader代碼編譯成二進制形式的GPU程序。

3. 最后由NiD3DXEffectTechnique負責通過NiD3DXEffectFile上的信息生成NiD3Dshader對象。

4. 所有的shader對象創建后,NiShaderLibrary的初始化就結束了,最后由NiShaderFactory負責統一管理。

材質:

NiMaterial為渲染對象生成和定義Shader,NiMaterialInstance為渲染對象分配 和Cach Shader。NiFragmentMaterial提供了一個Shader Tree框架,在它的繼承類中可以使用這個框架搭建shader tree。這個機制允許NiFragmentMaterial根據對象不同的渲染狀態生成不同的shader代碼,Cach在內存中,并保存到磁盤文件。GameByro描述符的概念大量使用,包括前面提到的Shader解析過程也是通過描述符來傳遞信息。在材質系統中主要使用了NiMaterialDescriptor和NiGPUProgramDescriptor這個兩個類做描述符,這兩個類中保存的信息是兼容的,都是為了描述某種材質在渲染對象的某一特定渲染狀態下所對應的GPU程序的特征。NiFragmentMaterial通過渲染目標的狀態和屬性生成NiMaterialDescriptor,并通過NiMaterialDescriptor查找匹配的shader,如果找不到,則通過shader tree生成相應的shader程序,并保存到磁盤文件中。當下一次應用程序啟動時就可以通過這個文件直接創建NiShader對象。可以說通過NiFragmentMaterial生成的shader代碼是為特定的渲染對象在特定的情況下量身打造的。

整個過程的詳細流程如下:

1. 在每次渲染一個物體之前,NiMaterialInstance會先判斷這個物體的shader程序是否需要更新,如果不需要更新,就直接返回當前Cach的NiShader;如果需要更新, NiMaterialInstance首先會根據物體的渲染狀態為其生成一個NiMaterialDescriptor,然后將這個NiMaterialDescriptor和當前Cach住的NiShader進行比較,如果匹配仍然返回當前Cach的NiShader,如果不匹配,將獲得shader的工作轉交給NiMaterial進行。

2. NiMaterial首先通過這個NiShaderFactory 查詢匹配這個NiMaterialDescriptor的NiShader,如果找不到,就通過NiMaterialDescriptor生成NiShader,同時生成一段Shader代碼,并保存到以shader描述符中的特征碼來命名對應的shader文件。

3. 當獲得相應的NiShader對象后,NiMaterialInstance會調用NiShader的SetupGeometry接口,在這個接口中會進行頂點聲明。

以下是NiMaterialInstance為Geometry選擇shader的代碼:

NiShader* NiMaterialInstance::GetCurrentShader(NiRenderObject* pkGeometry,

const NiPropertyState* pkState,

const NiDynamicEffectState* pkEffects)

{

if (m_spMaterial)

{

bool bGetNewShader = m_eNeedsUpdate == DIRTY;

if (m_eNeedsUpdate == UNKNOWN)

bGetNewShader = pkGeometry->GetMaterialNeedsUpdateDefault();

// Check if shader is still current

if (bGetNewShader && m_spCachedShader)

{

bGetNewShader = !m_spMaterial->IsShaderCurrent(m_spCachedShader,

pkGeometry, pkState, pkEffects, m_uiMaterialExtraData);

}

// Get a new shader

if (bGetNewShader)

{

NiShader* pkNewShader = m_spMaterial->GetCurrentShader(

pkGeometry, pkState, pkEffects, m_uiMaterialExtraData);

if (pkNewShader)

{

NIASSERT(m_spCachedShader != pkNewShader);

ClearCachedShader();

m_spCachedShader = pkNewShader;

if (!pkNewShader->SetupGeometry(pkGeometry, this))

ClearCachedShader();

}

else

{

ClearCachedShader();

}

}

m_eNeedsUpdate = UNKNOWN;

}

return m_spCachedShader;

}

如果想通過NiFragmentMaterial實現自己的shader tree就需要在NiFragmentMaterial提供的接口中實現自己拼裝代碼的邏輯,代碼塊由NiMaterialLibraryNode封裝,NiMaterialLibraryNode既可以直接寫C++代碼來定義,也可以先寫成XML腳本,再由專門的解析工具轉換成C++代碼。

由NiStandardMaterial生成的shader代碼文件如下圖所示:

clip_image002

文件名就是NiMaterialDescriptor的掩碼,用來標識的shader代碼的行為。

Shader代碼的行為描述如下:

Shader description:

APPLYMODE = 1

WORLDPOSITION = 0

WORLDNORMAL = 0

WORLDNBT = 0

WORLDVIEW = 0

NORMALMAPTYPE = 0

PARALLAXMAPCOUNT = 0

BASEMAPCOUNT = 1

NORMALMAPCOUNT = 0

DARKMAPCOUNT = 0

DETAILMAPCOUNT = 0

BUMPMAPCOUNT = 0

GLOSSMAPCOUNT = 0

GLOWMAPCOUNT = 0

CUSTOMMAP00COUNT = 0

CUSTOMMAP01COUNT = 0

CUSTOMMAP02COUNT = 0

CUSTOMMAP03COUNT = 0

CUSTOMMAP04COUNT = 0

DECALMAPCOUNT = 0

FOGENABLED = 0

ENVMAPTYPE = 0

PROJLIGHTMAPCOUNT = 0

PROJLIGHTMAPTYPES = 0

PROJLIGHTMAPCLIPPED = 0

PROJSHADOWMAPCOUNT = 0

PROJSHADOWMAPTYPES = 0

PROJSHADOWMAPCLIPPED = 0

PERVERTEXLIGHTING = 1

UVSETFORMAP00 = 0

UVSETFORMAP01 = 0

UVSETFORMAP02 = 0

UVSETFORMAP03 = 0

UVSETFORMAP04 = 0

UVSETFORMAP05 = 0

UVSETFORMAP06 = 0

UVSETFORMAP07 = 0

UVSETFORMAP08 = 0

UVSETFORMAP09 = 0

UVSETFORMAP10 = 0

UVSETFORMAP11 = 0

POINTLIGHTCOUNT = 0

SPOTLIGHTCOUNT = 0

DIRLIGHTCOUNT = 0

SHADOWMAPFORLIGHT = 0

SPECULAR = 1

AMBDIFFEMISSIVE = 0

LIGHTINGMODE = 1

APPLYAMBIENT = 0

BASEMAPALPHAONLY = 0

APPLYEMISSIVE = 0

SHADOWTECHNIQUE = 0

ALPHATEST = 0

NiStanderMaterial就是根據這些掩碼的數據來生成shader代碼,用戶可以通過重載GenerateVertexShadeTree、GeneratePixelShadeTree、CreateShader這些接口來定義自己的shader生成規則。

增加自己的渲染效果:

通過前幾節我們可以了解到,想定義自己的材質,一是通過編寫shader代碼完成。在應用程序初始化的時候,這些shader代碼會被初始化成NiShader對象,進一步的通過NiShader對象來初始化NiSingleShaderMaterial對象,并分配給渲染對象。在GameByro默認的渲染流程中,這些步驟都是自動進行的,美術只需在3DMAX插件中為幾何體的材質指定Shader程序,導出到nif文件,應用程序就能正確加載并渲染;二是定義自己的NiMaterialFragment類,在類中定義如何生成shader,在應用程序運行時只要將這個類的實例指派給幾何體,這個類就會自動為幾何體生成shader。這兩種方式對于美術人員來說,主要區別在于,采用第一種方法定義的材質,其渲染數據的設置必須嚴格符合shader代碼中所需的數據,否則就會報錯。(比如說,頂點數據流必須嚴格符合shader程序的定義,必須為shader中每個采樣器提供格式正確的紋理);而采用第二種方法定義的材質,就有很高的容錯和適應性,但是這種容錯性和適應性需要自己寫代碼來完成,GameByro提供的NiStanderMaterial就提供了這套完整的機制。每個貼圖槽內的貼圖如果你設置就會生成相應的貼圖處理流程,如果不設置,就沒有這張貼圖的處理流程。

為了驗證這個過程,筆者嘗試增加了一個自己的shader特效——SubSurfaceScattering,簡稱3s,其原理是模擬光在半透明物體中散射的效果。由于該效果無須預處理過程,所有的貼圖均來自磁盤文件,所以比較容易融合到GameByro工作流中。

筆者將在FX COMPOSER中調試通過的fx文件放入SDK中的SDK\Win32\Shaders\Data目錄下,在3DMAX的材質面板選擇GameByroShader,然后就可在顯示shader的組合框中看到文件中定義的Techinqe,選擇點擊apply按鈕,就會出現自定義的參數調整界面。

clip_image004

clip_image006

通過調整參數,最終得到皮膚和玉器的渲染效果如下:

clip_image007

皮膚

clip_image009

玉器

總結

GameByro的這套開發流程非常方便直觀,但是美術僅能為shader程序分配靜態的數據源,比如說光照圖等,CubeMap等;而一些在程序中實時生成的紋理數據則無法整合到美術工具中,比如說陰影圖、折射圖、反射圖等,這些都需要程序寫代碼來實現。調試起來就不大方便了。大部分情況下,我們只需要使用GameByro提供的NiStanderMaterial就可以完成大部分材質的需求,特殊的效果可以自己寫shader或者通過引擎提供的shader庫來完成,只有當我們需要即根據復雜的情況做很多不同的處理時,我們才需要重載NiFragmentMaterial搭建自己的shader tree。不過搭建shader tree的程序一般比較復雜,編寫難度大,雖然引擎允許通過XML文件來編寫材質節點,但是使用起來仍然不方便。GameByro并沒有提供相關的后期處理的開發工具,后期處理的特效并不能所見即所得,這方面還需完善。

GameByro為幾何體在特定的環境下生成專用的shader代碼,具有一定的靈活性,但是也付出了以下代價:

l 分析幾何體的屬性和當前狀態,為其生成shader代碼的過程有性能損耗。

l Shader代碼生成后會保存到磁盤文件中,這個過程如果不使用異步,可能會引起阻塞。

l 生成的NiShader對象會有內存消耗。由于GameByro默認的實現是將所有的shader文件初始化成NiShader對象,所以當游戲運行的時間久了以后會生成大量的shader文件,這時候內存的消耗可能會很可觀,同時加載的時間也會增加。不過可以自己控制加載的流程,在這里進行性能優化。

作者:葉起漣漪


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品一区在线观看| 99re热这里只有精品免费视频| 亚洲欧美在线免费观看| 夜夜嗨av一区二区三区免费区| 亚洲裸体视频| 宅男噜噜噜66国产日韩在线观看| 欧美一区二区三区四区在线| 久久福利视频导航| 亚洲国产mv| 999在线观看精品免费不卡网站| 亚洲视频在线观看网站| 欧美一区二区三区电影在线观看| 亚洲综合视频在线| 乱码第一页成人| 欧美日韩日本国产亚洲在线| 国产精品主播| 蜜臀99久久精品久久久久久软件| 一区二区黄色| 老鸭窝毛片一区二区三区| 国产精品久久婷婷六月丁香| 激情小说亚洲一区| 一级日韩一区在线观看| 亚洲一区欧美| 欧美色一级片| 亚洲精品久久| 美女黄色成人网| 欧美日韩精品欧美日韩精品一| 在线观看欧美日韩国产| 先锋影音国产精品| 亚洲视频在线二区| 欧美日韩在线视频一区| 亚洲在线国产日韩欧美| 亚洲第一福利在线观看| 国产精品videossex久久发布| 99亚洲一区二区| 欧美一区二区三区四区夜夜大片| 欧美日韩一二三区| 久久综合久久久久88| 午夜综合激情| 国产主播在线一区| 久久精品视频免费观看| 亚洲在线黄色| 亚洲理论在线观看| 欧美在线一二三四区| 国产亚洲亚洲| 久久久人成影片一区二区三区观看| 亚洲一区在线视频| 日韩亚洲在线观看| 久久中文字幕一区| 久久精品日产第一区二区| 国产精品劲爆视频| 久久se精品一区精品二区| 欧美日韩八区| 亚洲第一福利社区| 亚洲国产cao| 欧美.www| 欧美精品一区二区久久婷婷| 国产视频一区三区| 欧美成人午夜激情在线| 欧美国产欧美亚州国产日韩mv天天看完整| 在线观看亚洲一区| 亚洲精品国产精品国自产观看| 欧美看片网站| 亚洲精美视频| 国产日韩精品久久| 亚洲国产精品第一区二区三区| 欧美日韩精选| 亚洲精品视频在线观看网站| 国产精品三上| 亚洲电影第1页| 亚洲电影免费观看高清完整版在线| 欧美一区二区三区视频免费播放| 欧美一区二区高清在线观看| 国产精品日韩在线观看| 亚洲专区在线| 久久久精品五月天| 欧美日韩国产片| 99在线视频精品| 国内精品亚洲| 久久综合九色欧美综合狠狠| 美女主播一区| 亚洲美女电影在线| 欧美日韩一视频区二区| 亚洲亚洲精品在线观看| 欧美一区二区精品| 黄色av日韩| 一区二区三区四区在线| 亚洲国产日韩欧美综合久久| 亚洲视频精品| 久久久久久久久久久久久久一区| 影音先锋久久精品| 欧美国产在线观看| 亚洲精品视频在线看| 欧美一区二区性| 激情久久影院| 欧美日韩一区二区三区在线观看免 | 欧美韩日一区二区三区| 一区二区三区欧美亚洲| 久久精品av麻豆的观看方式 | 欧美理论电影在线观看| 亚洲永久免费av| 欧美大片va欧美在线播放| 99re8这里有精品热视频免费| 国产精品久久久久久久久久久久久 | 欧美福利一区二区| 亚洲一区国产精品| 欧美电影免费观看高清完整版| 一本色道久久综合亚洲二区三区 | 国产精品亚洲成人| 猫咪成人在线观看| 国产精品99久久久久久人 | 久久久999国产| 亚洲美女在线国产| 国产中文一区二区| 欧美日韩国产精品| 久久美女性网| 久久综合久久综合久久综合| 一本一道久久综合狠狠老精东影业 | 欧美成人精品| 亚洲福利国产精品| 欧美一级视频一区二区| 亚洲裸体视频| 狠色狠色综合久久| 国产精品美女久久久久av超清 | 中日韩视频在线观看| 欧美高清免费| 久久中文字幕导航| 欧美在线观看日本一区| 亚洲午夜精品视频| 国产精品爽爽ⅴa在线观看| 欧美va亚洲va日韩∨a综合色| 亚洲电影免费观看高清完整版在线| 欧美一区二区视频在线| 亚洲一区二区不卡免费| 日韩亚洲欧美一区二区三区| 亚洲国产一区二区a毛片| 一区二区三区在线不卡| 国产一区二区三区免费不卡| 国产精品毛片a∨一区二区三区| 欧美日韩国产精品自在自线| 模特精品裸拍一区| 久热国产精品| 米奇777超碰欧美日韩亚洲| 欧美一区二视频在线免费观看| 亚洲一本视频| 亚洲一区国产一区| 亚洲一区精品电影| 亚洲自拍偷拍一区| 午夜精品久久久久久久久久久久| 免费中文字幕日韩欧美| 六月丁香综合| 亚洲私拍自拍| 亚洲午夜极品| 欧美一级网站| 久久久久一区| 欧美va天堂在线| 亚洲电影免费观看高清完整版在线观看 | 国产亚洲一区二区三区在线播放| 国产精品腿扒开做爽爽爽挤奶网站| 国产精品久久久久久久久久尿| 国产精品久久久久秋霞鲁丝 | 国产色爱av资源综合区| 国产一区二区三区网站| 精品av久久707| 亚洲精品黄色| 午夜日韩在线| 另类春色校园亚洲| 亚洲茄子视频| 亚洲欧美一区二区原创| 久久精品亚洲国产奇米99| 日韩一二三区视频| 亚洲深爱激情| 久久亚洲精品一区| 欧美日本在线一区| 国产精品久久久久久久久果冻传媒| 国产欧美丝祙| 亚洲日本在线观看| 亚洲欧美日韩国产一区二区| 999在线观看精品免费不卡网站| 亚洲欧美国产日韩中文字幕| 久久午夜视频| 99精品久久久| 久久久综合网站| 久久精品亚洲乱码伦伦中文| 欧美激情综合在线| 国产一区二区三区久久| 亚洲美女色禁图| 久久精品人人爽| 日韩亚洲不卡在线| 久久全球大尺度高清视频| 欧美日韩亚洲系列| 在线高清一区| 欧美在线播放| 日韩视频在线观看免费| 久久露脸国产精品| 国产精品一区二区三区免费观看 | 亚洲第一黄色| 欧美在线91| 亚洲午夜精品久久久久久浪潮| 免费亚洲电影|