玩弄了一把 XNA4的開發。
首先說安裝,兩台筆記本安裝順利。沒有完整下載包非常麻煩,我一共安裝了6次。。。。。。
家裡的台式電腦死活裝不上,重裝了window7才行,死活想來可能和曾經裝過vs2010有關。
測試了一下windows 和 windows phone7 模擬器的開發,做個簡單的圖形操作,基本上還是Dx那組介面,看起來很熟悉,沒碰到什麼困難。就是在c#的文法上糾結了半天。說起來c++和c#,#就是把倆+重疊起來而已,著實還是差了不少,雖然曾經系統的學習過一點兒dotnet,年代久遠,還是花了不少功夫。
一、關於引用。
1.windows平台和windows phone 7 平台乍一看引用的庫差不多,展開一看差了還不是一點兒半點鐘兒,以後要真搞,得隨時關注使用windows phone 7 相容的代碼。
2.項目和 content項目,資源管道這東西真是沒覺得有什麼方便的,可能是被虐待慣了,非要給整個自動化的,反而綁手綁腳的。我就一直在拚命要從外部載入資源,這個有點兒成果了,等下再說。項目裡能夠引用的庫和content裡能夠引用的庫完全不能通用,看來dotnet還是博大精神啊,怎麼能產生這樣的限制我還沒搞懂。於是在XNA4中RunTime處理資源幾乎就不可能了,囧。
二、關於資源
看文檔使勁介紹資源管道那個架勢是讓我們都按照這個路數來,增加自己的資源格式得這麼跑一遍。我對這個很反感。
PC製作->content項目編譯->runtime調用,這種固定下來的模式產生的限制禁錮了我的創意。
貼圖、模型、shader,其它自訂格式,我要全面繞開microsoft給設計的這種玩意兒。
模型就是一堆頂點資料,貼圖只要能lock表面寫入,應該都沒有什麼問題。
於是我關注了一下Shader,吐血吐了一地,XNA4中找到的和Shader編譯有關的模組全都只能在content項目中引用。
runtime編譯Effect路完全被堵死了……
於是我用二進位格式開啟由fx產生的xnb檔案,做了一些分析測試。最起碼我現在可以直接載入由fxc編譯過的effect檔案。
還看到XNA3.1裡有一個ShaderCompiler模組可以在RunTime使用,我有時間再測試一下。
三、令人愉悅的地方
快速的移植,pc和windows phone7 上幾乎可以用一致的代碼。dotnet架構跨平台不是蓋得。
對多點觸摸的支援,堪稱完美,在windows 7上和 我的Tx2z配合很好,多點觸摸的介面很好用。而且tx2z在windows phone7 模擬器裡也表現出完全一致的行為,在多點觸摸調試這個問題上,只要有台支援多點觸摸的螢幕,我們就可以忘了這是個問題。
最近HP又出了一台TM2,支援多點觸摸,緩一緩在入手一台。
加速器的支援也有了,但在pc上一點用都沒有,而且我一直覺得在地鐵裡用加速器來進行遊戲很囧,不過這也是個令人興奮的特性。
自動翻轉螢幕,這個特性我還沒測試在XNA裡有沒有直接的介面,即使沒有,用加速器來判斷也可以。這個也是不容易調試的功能--p。
比較新的DX,從研究effect的時候發現shader編譯器的用的是 D3DCompiler_41 D3DX9_41 ,09年11月的dxsdk裡是_42.
關於Effect檔案我做的研究記錄。
一、fxc 產生的 fx_2_0
通過二進位比較發現XNB裡明碼將fxc編譯的fx_2_0檔案直接插入。
二、獨特的檔案頭
public Effect ( GraphicsDevice graphicsDevice, byte[] effectCode)
effectcode,沒有任何說明,看起來是code,弄個字串放進去,一個異常給出了答案,需要編譯過的code。
找到xnb裡的編譯過的fx_2_0的檔案頭部,放進去,異常too。
這還難不倒我們,嘿嘿。早料到你可能在前面加點兒什麼沒用的東西,一個一個試過去。
for (int a = 0; a < 100; a++)
{
System.IO.Stream s = System.IO.File.Open("content\glow.xnb", System.IO.FileMode.Open);
int n = (int)s.Length;
byte[] b = new byte[n];
s.Seek(a * 4, System.IO.SeekOrigin.Begin);
s.Read(b, 0, n);
// byte[] fg = b + 12;
s.Close();
try
{
e = new Effect(GraphicsDevice, b);
npos = a;
}
catch(Exception)
{
}
}
npos=42的時候通過了,多找了一些測試,結論穩定。
前面168是xnb的檔案頭,只要從168開就是 XNA4中使用的EffectCode格式了。
現在開始搞一些dx的effect檔案來用fxc編譯,載入測試,不通過。在
xna content 裡建立一個預設的effect檔案,用fxc編譯,加上和xnb裡一致的檔案頭
CF0BF0BC 0C000000 00000000 載入測試,通過。
看來這12個位元組還有很多名堂在裡面。
又多測試了,得到了更多的情報,首先雖然都是 fx_2_0 但有些fx在XNA content裡編譯不通過。
ColorOp[0] = SELECTARG2;
提示如下:
Error 1 Errors compiling E:UserslightsDocumentsVisual Studio 2010ProjectsXNAShaderXNAShaderXNAShaderContentGlow.fx:
Error: The effect state 'ColorOp' is obsolete and can no longer be used. E:UserslightsDocumentsVisual Studio 2010ProjectsXNAShaderXNAShaderXNAShaderContentGlow.fx XNAShader
我不知道怎麼設定fxc才能得到和XNA content裡一模一樣的編譯環境。
總之過了這關單technique 單pass的effect檔案用fxc編譯過就可以載入了。
但是多個pass時,檔案頭不一樣。。。。。。
CF0BF0BC 是一樣的, 0C000000 一個pass 10000000 兩個pass 14000000 三個pass
以四遞增的,後面的 00000000 隨便寫什麼資料測試無關, 一個pass 4位元組 兩個pass 8位元組 三個pass 12位元組
以四遞增too。
寫一段程式如下:
int passsize = 2;//pass數
{
System.IO.Stream s = System.IO.File.Open("content\glow.fxo", System.IO.FileMode.Open);
int n = (int)s.Length;
int headlen = 8 + passsize * 4;
byte[] b = new byte[n + headlen];
b[0] = 0xCF;
b[1] = 0x0B;
b[2] = 0xF0;
b[3] = 0xBC;
int tag = 0x0C + (passsize-1) * 4;
b[4] = (byte)tag;
s.Read(b, headlen, n);
s.Close();
e2 = new Effect(GraphicsDevice, b);
}
測試了幾個情況,均OK,基本掌握了XNA4 Effect runtime載入的問題。
三、為什麼要這樣
寫出結論來看著很簡單,用16進位編輯器去分析可不是個愉快的事兒。
我做這個主要是想能夠在運行時方便的載入shader,更進一步可以做出ShaderTree,在運行時產生Shader。
現在已經基本解決了載入的問題,剩下就是編譯的問題。
現在有最不濟的方式,將動態產生的effectcode存入檔案,調用fxc編譯,再載入。可行,不優雅,依賴windows平台。
還有方案二、寫一個庫,用XNA3.1編譯Effect返回code,我還沒測試。windows平台應該有一定的可行性,不知道windows phone7上的XNA會不會保留3.1
方案三、正式版的XNA4 會允許runtime compier effect,等吧,其實微軟要是不解決,我們這個ShaderTree也成為技術特色了。
方案四、由於方案二經測試無果。XNA3.1的shaderCompier不包括fx。。。。,所以等XNA正式發布後,可以用c++調用DX來直接編譯。不過c++原生代碼調用DX估計只能在Windows平台上使用了。