Stock Effects示例

原文地址:http://create.msdn.com/en-US/education/catalog/sample/stock_effects。

effects提供了五个effect(BasicEffect,SkinnedEffect,EnvironmentMapEffect,DualTextureEffect和AlphaTestEffect)和SpriteBatch(SpriteEffect)使用的默认shader的源代码,它们都内置在XNA框架中。这个项目还包含一个命令行工具(CompileEffect),它使用Content Pipeline将一个.fx源文件编译为二进制文件,这样二进制文件就可以直接传递到XNA框架的Effect类的构造函数中。

概览

此代码用于教育目的,当你想创建一个更高级的shader时,它可以作为一个很好的出发点。

虽然XNA框架内置的effect类非常简单易于使用,但背后的shader代码是非常复杂的,这是因为在一个shader中需要支持很多绘制的情况。例如,BasicEffect可以让你切换是否选择纹理,顶点颜色、光照,选择逐像素光照还是逐顶点光照。要支持所有的情况,BasicEffect需要至少20个不同的vertex shader和10个pixel shader,它们都编译在一个effect文件中。

如果你想从头学习shader编程,可参见官方网站的Shader Series的示例,这些示例比较简单,因为它们不包含太多的调整选项。

使用Effects

要使用这些stock effect代替内置的effect,需要进行以下步骤:

1. 编译对应的解决方案—StockEffectsWindows.sln或StockEffectsXbox.sln(这基于你的开发平台)。

2. 右击你的项目,选择Add Reference并选择Browse面板。

3. 选择StockEffects\bin\<platform>\Debug\StockEffects.dll. 这个项目提供了六个类:

但这些shader是在StockEffects命名空间而不是在Microsoft.Xna.Framework.Graphics命名空间中,所以要使用这些shader代替XNA框架内建的shader,只需将代码由:

effect = new BasicEffect(GraphicsDevice);

变为

effect = new StockEffects.BasicEffect(GraphicsDevice); 

修改Effecs

要修改shader代码,需要编辑.fx文件,然后重新编译StockEffects.dll。如果你想作出较大改变,或重用你的项目中的shader,你需要理解代码是如何进行编译的。

CompileEffect项目是一个命令行工具,它使用Content Pipeline将一个.fx文件编译到一个二进制文件中。这个操作直接调用EffectImporter和EffectProcessor类,然后保存编译后的effect代码, 这样就绕过了Content Pipeline的处理,因为Content Pipeline的处理会将这些数据嵌入到一个 .xnb格式的文件中,而这并不是我们想要的结果。

StockEffects项目有一个自定义的生成规则,它使用CompileEffect工具编译六个effect文件,要编辑这个规则,你可以进行如下的步骤:

1. 在解决方案浏览器中,右击StockEffects项目。

2. 选择属性,点击Build Events面板,然后点击Edit Pre-build按钮。

你可以看到这个生成规则调用了CompileEffect六次,将每个.fx文件编译到一个.bin文件中,这些文件存储在obj文件夹中。

如果编辑Resources.resx,你会看到它包含了六个来自于obj文件夹的.bin文件,这样编译过的shader代码就嵌入了resource中。这让诸如封装effect的BasicEffect.cs类可以通过Resources.BasicEffect访问effect代码。

如果你想添加或移除shader,你必须:

Effect Include文件

译者注:下面的两段文字与标题Effect Include文件风马牛不相及,怀疑作者贴错了。此程序包含四个Effect Include文件:Macros.fxh,Structures.fxh,Common.fxh,Lighting.fxh。其中Macros.fxh主要定义了指定寄存器绑定的宏指令用于简化代码,Structures.fxh包含顶点着色器和像素着色器的输入、输出结构定义,Common.fxh包含5个effect所共用的设置代码,Lighting.fxh包含共用的计算光照的代码,使用include文件可以共享重用代码,使effect结构更加清晰。

XNA TouchPanel API provides only a polling interface. 你的游戏可以获取当前的触摸状态,但无法获取触摸的begin/end事件的消息。对这个示例来说会发生一些困难,这是因为玩家的屏幕的初始光标定义了手柄的中心位置,当掉帧时光标可能会丢失,这样中心位置就不是玩家所期望的正确位置,这样会导致控制不正确。

幸运的是,XNA TouchPanel API通过提供TryGetPreviousLocation方法可以部分解决这个问题,这个方法可以保存事件的历史,只要游戏的帧频正常,就能保证控制的正确。

许多内建的effect有着类似的行为。例如所有shader都使用了相同的雾化算法,BasicEffect,SkinnedEffect和EnvironmentMapEffect共享了相同的Blinn/Phong光照模型。为了减少重复代码,这些函数放在了头文件中(Common.fxh, Lighting.fxh, and Structures.fxh),它们包含在所有effect中。

Macros.fxh文件要实现几个功能。这个头文件定义了一些辅助宏,让shader代码可以编译为DirectX 9 Shader Model 2.0(用于XNA Framework Content Pipeline)或Shader Model 4.0(用于DirectX 10和DirectX 11,在语义定义上有所不同)。

Preshaders

在设计effect参数时,一个非常重要的事情就是需要提供一个清晰的API,最终的参数格式并不总是最有效率的。

D3D会通过一个叫做“preshaders”的功能修正某些不匹配错误,HLSL编译器会查找对于所有顶点和像素都相同的计算过程,然后将这些过程从主shader中取出放置在一个特殊的pass中,这个pass会在会在开始前运行在CPU上。这是个很好的功能,但也带来了一些负面影响:

替代方法是,Game Studio通过重写Effect.OnApply方法在C#中实现了preshader 计算,Effect.OnApply方法在EffectPass.Apply方法前被调用,而EffectPass.Apply方法将参数设置到图形设备上。

这可以让我们的C# effect包装类将API所需的属性暴露,而无需将这些属性匹配HLSL的底层shader参数。当程序员改变了一个属性时,我们只需设置一个dirty标志,然后在OnApply过程中重新计算HLSL参数。使用这个方法我们预先计算了很多东西:

文件下载(已下载 1859 次)

发布时间:2010/12/23 下午4:50:04  阅读次数:7063

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号