2012-12-11 50 views
13

所以我正在做的事情與XNA 3.1,我有很多的,它們通過像素着色器應用單獨的效果。這些來自各種來源,如特殊攻擊,環境等等。我遇到的問題是我注意到幀速率的顯着降低。合併多個像素着色器有效

目前,我畫整個場景的RenderTarget2D,這我然後將所有的效果。餘存儲包含的影響和它們的ID一個SortedDictionary(ID被用於在運行時改變參數),並且我遍歷它和其他之後施加每個效果之一:

foreach(KeyValuePair<Ref<int>,Effect> p in renderEffects) 
{ 
    Effect r = p.Value; 
    g.SetRenderTarget(0, MainGame.MainRenderTarget); 
    //Change RenderTarget to allow code to grab existing texture in the same draw area. 
    levelDraw = MainGame.LevelRenderTarget.GetTexture(); 
    //Change back to draw back to this texture, allowing render effects to be layered. 
    g.SetRenderTarget(0, MainGame.LevelRenderTarget); 

    MainGame.StartDraw(MainGame.GameBatch); 
    //Starts the sprite batch and sets some parameters 
    r.Begin(); 
    r.CurrentTechnique.Passes[0].Begin(); 
    MainGame.GameBatch.Draw(levelDraw, new Rectangle(0, 0, levelDraw.Width, levelDraw.Height), Color.White); 
    r.CurrentTechnique.Passes[0].End(); 
    r.End(); 
    MainGame.GameBatch.End(); 
} 

現在,這將產生明顯的當分層只有3個效果時幀丟失,而當應用10時,幀速從60FPS下降到16FPS,這當然是不可接受的。我想知道是否有更有效的方法來做到這一點。考慮到我只有一個紋理,我認爲我可以將這些效果組合到一個文件中,並執行多次通過而不會抓取紋理。但我不確定這是否可行。

我真的不知道要做到這一點的最好辦法究竟是怎麼一回事,但我想有一定比我做的方式更好的辦法。

+3

我編輯了自己的冠軍。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。 –

+0

謝謝你。我傾向於將它們包括在內,讓人們知道他們是否能夠一目瞭然,而不必查看標籤,但是我可以看到不使用它們的邏輯。 – Hoeloe

+2

這些標籤包含比查看亂碼標題更好的機制。你可以設置「喜歡的標籤」,這將導致與這些標籤的消息被突出顯示;和「忽略標籤」,這些標籤會導致隱藏這些標籤的消息。 –

回答

1

當你畫完時,你是否完全遮蔽了一切?如果着色器的計算量很大,則應先進行「深度傳遞」,只測試/寫入Z緩衝區(顏色緩衝區寫入關閉)。此外,使用瑣碎的簡單着色器來「深度填充」屏幕。

換言之,渲染所有不透明的物體僅更新在第一道次的深度緩衝器。

在第二遍,你打開着色器(和關閉深度寫入,無需使用帶寬,以寫回的已經存在相同的值)。這將掩蓋掉任何透支像素的所有不必要的工作,因爲它們會立即通過深度測試。

編輯:現在我意識到OP是在做全屏效果,而不是場景渲染。

+0

我只將着色器應用於單個紋理,因此深度緩衝區應該沒有問題,因爲每個像素僅在每次通過時繪製一次,並且沒有像素會在深度緩衝區中透支。 – Hoeloe

+0

我明白你的意思了,你只是「廣告牌」一個巨大的四方應用一系列的全屏效果,這就是瓶頸表現? – doug65536

+0

是否可以對效果循環進行排序以最大限度地減少狀態變化?通常,降低昂貴程度:着色器程序,紋理綁定,緩衝區綁定等。也許你可以通過重新排序來最大限度地減少狀態變化來避免狀態改變。頂點緩衝區和紋理可以平鋪到較大的紋理/較大的頂點緩衝區,以消除一些不斷變化的狀態。 – doug65536

2

在片段的方法可能是很慢的,因爲你正在做一個紋理抓取併爲每效果全屏平局,強調CPU和GPU在你的心裏去的頂部之間的內存帶寬在着色器內部。您可能需要按照您在帖子中的建議創建一組着色器,其中每個着色器都包含多個操作,而不是一遍又一遍地運行讀寫循環:一個昂貴的着色器通常仍會比許多讀寫重複簡單的着色器。

你可能想看看Shawn Hargreaves article on shader fragments in HLSLTim Jones's code for doing this in XNA

+0

蒂姆瓊斯的代碼對我來說沒用,因爲它在XNA 4中,而我使用的是3.1。但感謝您鏈接這些文章。 – Hoeloe

+0

對於您的問題大小,您可能會更好地手動進行組合操作 - 無論如何,您可能會發現堆疊效果會使視覺解碼變得更加困難,這意味着可以優化複雜的多重效果版本,使其更便宜減損外觀。 – theodox

+0

這讓我想到了,我正在考慮編寫一個解析器和編譯器來獲取HLSL着色器的列表,每個着色器都帶有特定的參數,並將它們全部推送到一個文件中。它會以字符串形式讀取代碼,然後將字符串形式的代碼轉換爲字節數組,然後將其寫入新的效果文件。我不確定這是否會起作用,或者它會有什麼用處,但可能值得一試。我只是不知道如何從文件中獲取原始代碼作爲字符串... – Hoeloe