XNA中的Render State管理
XNA中的Render State管理
僅供個人學習使用,請勿轉載,勿用于任何商業用途。
The Problem:
????? ?XNA中一個設計的非常不好的地方,就是把各種render state定義為RenderState類的成員,而不是枚舉。在DX/MDX中,如果有一系列render state需要設置,只需要
foreach state in renderStates
??? gfxDevice.SetRenderState( stateName,stateValue);
????簡單,明了。
??? 而同樣的操作在XNA中,則要麻煩很多,你不得不”顯式” 訪問每一個render state成員來設置相應的值:
gfxDevice.RenderState.XXXX = value;
gfxDevice.RenderState.XXXX = value;
……
????? 這樣的代碼非糟糕,簡直是在”hard code”。假如事先不確定有多少render state需要設置,如何編碼呢?
The Solution:
????? 解決這個問題并不困難,我希望仍然使用傳統的老方法來設置狀態。首先,自然是定義一系列常量,表示所有渲染狀態,這里使用了一個靜態類,當然替換為枚舉也是一樣的。
{
????//alpha?state
????public?const?byte?AlphaBlendEnable?=?0;
????public?const?byte?AlphaBlendOperation?=?1;
????public?const?byte?SourceBlend?=?2;
????public?const?byte?DestinationBlend?=?3;
????public?const?byte?AlphaDestinationBlend?=?4;
????public?const?byte?AlphaSourceBlend?=?5;
????public?const?byte?AlphaFunction?=?6;
????public?const?byte?AlphaTestEnable?=?7;
????public?const?byte?BlendFactor?=?8;
????public?const?byte?BlendFunction?=?9;
????public?const?byte?SaparateAlphaBlendEnable?=?10;
????public?const?byte?ReferenceAlpha?=?11;
????//depth?state
????public?const?byte?DepthWriteEnable?=?12;
????.
}
?
????? 接下來,需要統一所有render state的值。這樣,才能把每種render state作為相同的key-value對,放到同一個容器中。觀察一下所有的render state,他們的值不外乎以下幾種:枚舉,int,float,bool,color. 非常幸運,他們都能用一個32位的值來表示。但是具體如何編碼呢?這種情況下,C++程序員首先想到的一定是使用union。C#中雖然沒有內置的union類型,但這并不妨礙我們用struct模擬union的行為:
public?struct?HaRenderStateValue
{
????[FieldOffset(0)]
????public?int?IntegerValue;
????[FieldOffset(0)]
????public?float?FloatValue;
????[FieldOffset(0)]
????public?Color?Color;
????[FieldOffset(0)]
????public?bool?BooleanValue;
????public?void?SetValue(int?value)
????public?void?SetValue(Color?value)
????public?void?SetValue(float?value)
????public?void?SetValue(bool?value)
}
public?struct?HaRenderState
{
????public?readonly?byte?Id;
????public?HaRenderStateValue?Value;
}
?
??? 最后則是實際設置渲染狀態的函數,這一步并沒有什么技巧可言,只是用了一個非常長的switch把所有需要hard code的部分集中到這里。這是目前為止我能想到的最簡單有效的方法,使用Dictionary也許能減少代碼長度,但實際測試表明,switch有更好的性能:
?public?static?void?SetRenderState(GraphicsDevice?graphics,?HaRenderState?renderState)
?{
?????switch?(renderState.Id)
?????{
?????????case?HaRenderStateId.AlphaBlendEnable:
?????????????graphics.RenderState.AlphaBlendEnable?=?renderState.Value.BooleanValue;
?????????????break;
?????????case?HaRenderStateId.AlphaBlendOperation:
?????????????graphics.RenderState.AlphaBlendOperation?=?(BlendFunction)renderState.Value.IntegerValue;
?????????????break;
?????????case?HaRenderStateId.SourceBlend:
?????????????graphics.RenderState.SourceBlend?=?(Blend)renderState.Value.IntegerValue;
?????????????break;
????????
??????}
}
?????? ?擴展結束,現在可以像文章開頭介紹的那樣,使用循環設置所有render state,更重要的是可以隨時添加或者刪除集合中的render state,這樣給為渲染器設計帶來了非常大的便利和靈活性:
material.AddRenderState(RenderState)
material.RemoveRenderState(RenderState)
......
material.ApplyRenderState()
{
????? foreach renderState in this.renderStates
?????????? SetRenderState(gfxDevice,renderState)
}
?
轉載于:https://www.cnblogs.com/clayman/archive/2009/06/23/1509707.html
總結
以上是生活随笔為你收集整理的XNA中的Render State管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开源日志审计系统_一文掌握mysql数据
- 下一篇: python打包工具哪个好用_pytho