玩弄了一把 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平台上使用了。