Silverlight Toolkit (December 2011)的新功能

原文地址:Silverlight Toolkit (December 2011) for Silverlight 5–What’s new?(http://blogs.msdn.com/b/eternalcoding/archive/2011/12/10/silverlight-toolkit-september-2011-for-silverlight-5-what-s-new.aspx?PageIndex=4)。

用于Silverlight 5的新版本Silverlight Toolkit (December 2011) 已经发布,你可以在http://silverlight.codeplex.com/releases/view/78435下载。

更新:Babylon Engine现在也使用了了Silverlight 5 Toolkit::http://code.msdn.microsoft.com/Babylon-3D-engine-f0404ace。

这篇文章帮助你发现这个Toolkit是如何通过下述功能增强Silverlight 5的:

与Content Pipeline的无缝整合

这个新Toolkit带来了一个新组件:Microsoft.Xna.Framework.Content.dll。这个组件使你可以加载.xnb格式的素材(这些素材是由Content Pipeline创建的)。

使用新的Visual Studio模板(在后面会提到),你可以将已有的3D项目直接导入到Silverlight 5中!

Microsoft.Xna.Framework.Content.dll在Silverlight 5中添加了以下类:

这个Toolkit还带来了Microsoft.Xna.Framework.Tookit.dll程序集,这个程序集在Silverlight 5中添加了以下类:

ContentManager

这个类的文档地址为:

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.content.contentmanager.aspx。

ContentManager类代表代码中的Content Pipeline,它用来从.xnb文件加载对象。

要创建一个ContentManager执行调用以下代码:

ContentManager contentManager = new ContentManager(null, "Content");

这个类有一些限制:用于Silverlight的ContentManager只支持一个Content项目,RootDirectory必须设置为“Content”。

使用这个类很简单,因为它提供了一个简单的Load方法创建对象:

// 加载字体
hudFont = contentManager.Load<spritefont>("Fonts/Hud"); 
// 加载纹理
winOverlay = contentManager.Load<Texture2D>("Overlays/you_win");
// 加载音乐
backgroundMusic = contentManager.Load<SoundEffect>("Sounds/Music");

模型Model类

这个类的文档的地址为:

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.model.aspx。

Model类使用的API与在XNA 4中是一样的,通过这个类你可以从XNB文件加载并绘制3D模型:

// 绘制模型
Model tankModel = content.Load<Model>("tank");
tankModel.Draw(); 

如果模型支持bone也可以使用:

Model tankModel = content.Load<Model>("tank");
tankModel.Root.Transform = world; 
tankModel.CopyAbsoluteBoneTransformsTo(boneTransforms);

// 绘制模型
foreach (ModelMesh mesh in tankModel.Meshes)
{
    foreach (BasicEffect effect in mesh.Effects)
    {
        effect.World = boneTransforms[mesh.ParentBone.Index]; 
        effect.View = view; 
        effect.Projection = projection;
        effect.EnableDefaultLighting();
    }
    mesh.Draw();
}

你可以导入.x或.fbx格式的模型:

导入.x或.fbx格式的模型

使用FBX导入器,你也可以导入.3ds, .obj, .dxf和Collada。

SpriteFont和SpriteBatch

这些类的文档的地址为:

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritebatch.aspx,

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritefont.aspx。

SpriteBatch类用来在顶层显示2D纹理,用来显示UI或Sprite。

SpriteBatch spriteBatch = new SpriteBatch(graphicsDevice); 
spriteBatch.Begin(SpriteSortMode.Immediate,BlendState.Opaque);
spriteBatch.Draw(texture, new Rectangle(0, 0, width, height),Color.White);
spriteBatch.End();

从以上的代码可以看出SpriteBatch只需要指定一个纹理用于显示。

SpriteFont可以使用Sprite显示文字。

SpriteFont hudFont = contentManager.Load<SpriteFont>("Fonts/Hud");
spriteBatch.DrawString(hudFont, value, position + new Vector2(1.0f, 1.0f), Color.Black);
spriteBatch.DrawString(hudFont, value, position, color);

SpriteFont的绘制依赖于SpriteBatch,而且需要在ContentManager中定义一个font:

在ContentManager中定义一个font

SilverlightEffect

Toolkit还提供了一个叫做SilverlightEffect的新类用于处理.fx文件。

它还支持扩展名为.slfx的shader文件,.slfx和.fx并没有区别,但是因为XNA Effect Processor已经关联了.fx文件,所以Silverlight Content Pipeline只能选择另一个扩展名了。

你可以在Content项目中定义一个完整的effect,使用这个effect绘制模型。

步骤为:

例如下面是一个简单的.fx文件:

float4x4 WorldViewProjection;
float4x4 World;
float3 LightPosition;

// 着色器输入输出结构
struct VS_INPUT
{
    float4 position : POSITION;
    float3 normal : NORMAL;
    float4 color : COLOR0;
};

struct VS_OUTPUT
{
    float4 position : POSITION;
    float3 normalWorld : TEXCOORD0; 
    float3 positionWorld : TEXCOORD1; 
    float4 color : COLOR0; 
};

// 顶点着色器
VS_OUTPUT mainVS(VS_INPUT In)
{
    VS_OUTPUT Out = (VS_OUTPUT)0; 
    
    // 坐标转换 
    Out.position = mul(In.position, WorldViewProjection);
    
    // 计算世界空间中的法线
    Out.normalWorld = mul(In.normal,(float3x3)WorldViewProjection);
    
    // 计算世界空间中的位置
    Out.positionWorld = (mul(In.position, World)).xyz;
    
    // 直接传递顶点颜色 Out.color = In.color; 
    
    return Out;
}

// 像素着色器 
float4 mainPS(VS_OUTPUT In) : COLOR
{
    // 光照方程
    float3 lightDirectionW = normalize(LightPosition - In.positionWorld);
    float ndl = max(0, dot(In.normalWorld, lightDirectionW));
    
    // 最终颜色
    return float4(In.color.rgb * ndl, 1);
}

// Technique
technique MainTechnique
{
    pass P0
    {
        VertexShader = compile vs_2_0 mainVS(); // 必须无参数
        PixelShader = compile ps_2_0 mainPS(); // 必须无参数 
    }
}

Toolkit会在Content Pipeline中添加所需的处理器,为这个effect创建.xnb文件:

添加所需的处理器

要使用这个effect,你必须在代码中实例化一个新SilverlightEffect对象:

mySilverlightEffect = scene.ContentManager.Load<Silverlighteffect>("CustomEffect");

然后你就可以访问effect的参数:

worldViewProjectionParameter = mySilverlightEffect.Parameters["WorldViewProjection"];
worldParameter = mySilverlightEffect.Parameters["World"]; 
lightPositionParameter = mySilverlightEffect.Parameters["LightPosition"];

使用effect绘制对象的代码与XNA4是一样的:

worldParameter.SetValue(Matrix.CreateTranslation(1, 1, 1)); 
ProjectionParameter.SetValue(WorldViewProjection);
lightPositionParameter.SetValue(LightPosition);

foreach (var pass in mySilverlightEffect.CurrentTechnique.Passes)
{
    // Apply
    pass pass.Apply();
    
    // 设置顶点缓冲和索引缓冲
    graphicsDevice.SetVertexBuffer(vertexBuffer);
    graphicsDevice.Indices = indexBuffer;
    
    // 绘制primitives
    graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,0, 0, VerticesCount, 0, FaceCount); 
}

Texture2D, TextureCube和SoundEffect

Silverlight 5提供了Texture2D、TextureCube和SoundEffect类,使用Toolkit你可以从ContentManager加载这些类:

// 加载2D纹理
winOverlay = contentManager.Load<Texture2d>("Overlays/you_win"); 
// 音乐 
backgroundMusic = contentManager.Load<SoundEffect>("Sounds/Music");

鼠标与键盘

为了更好地输出已经存在的3D项目,Toolkit中还添加了对Microsoft.Xna.Framework.Input命名空间的部分支持。

这样就可以在想要的任何地方调用MouseState和KeyboardState:

public MainPage()
{
    InitializeComponent();
    Mouse.RootControl = this; 
    Keyboard.RootControl = this;
}

但是与原始的XNA有一点不同:你必须注册提供鼠标和键盘事件的根控件,MouseState位置是相对于这个控件的左上角位置的:

private void myDrawingSurface_Draw(object sender, DrawEventArgs e)
{
    // 绘制场景
    scene.Draw();
    
    // 刷新 
    e.InvalidateSurface();
    
    // 获取鼠标和键盘状态
    MouseState mouseState = Mouse.GetState();
    KeyboardState keyboardState = Keyboard.GetState(); 
    
    ...
}

MouseState和KeyboardState类似于XNA中的版本:

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.input.mousestate.aspx,

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.input.keyboardstate.aspx。

扩展

Silverlight Content Pipeline可以使用与XNA Content相同的方式进行扩展。你可以提供自己的实现方式实现从其他地方加载素材,而默认情况是加载内嵌的.xnb文件。

例如,你可以写一个类从网络加载.xnb文件流,要实现以上功能,你必须从inherit继承,提供自己的OpenStream实现:

public class MyContentManager : ContentManager
{
    public MyContentManager() : base(null)
    { }
    
    protected override System.IO.Stream OpenStream(string assetName) 
    {
        return base.OpenStream(assetName);
    }
}

你也可以编写自己的type reader,以下代码是用于SilverlightEffect的自定义type reader:

 /// <summary>
/// 读取SilverlightEffect. 
/// </summary>
public class SilverlightEffectReader : ContentTypeReader<Silverlighteffect>
{
    /// <summary> 
    /// 读取并创建一个SilverlightEffect
    /// </summary>
    protected override SilverlightEffect Read(ContentReader input, SilverlightEffect existingInstance)
    {
        int techniquesCount = input.ReadInt32();
        EffectTechnique[] techniques = new EffectTechnique[techniquesCount]; 
        
        for (int techniqueIndex = 0; techniqueIndex < techniquesCount; techniqueIndex++)
        {
            int passesCount = input.ReadInt32(); 
            EffectPass[] passes = new EffectPass[passesCount];
            
            for (int passIndex = 0; passIndex < passesCount;passIndex++)
            {
                string passName = input.ReadString(); 
                // 顶点着色器
                int vertexShaderByteCodeLength = input.ReadInt32();
                byte[] vertexShaderByteCode = input.ReadBytes(vertexShaderByteCodeLength);                
                int vertexShaderParametersLength = input.ReadInt32(); 
                byte[] vertexShaderParameters = input.ReadBytes(vertexShaderParametersLength); 
                
                // 像素着色器 
                int pixelShaderByteCodeLength = input.ReadInt32();
                byte[] pixelShaderByteCode = input.ReadBytes(pixelShaderByteCodeLength);
                int pixelShaderParametersLength = input.ReadInt32(); 
                byte[] pixelShaderParameters = input.ReadBytes(pixelShaderParametersLength); 
                
                MemoryStream vertexShaderCodeStream = new MemoryStream(vertexShaderByteCode); 
                MemoryStream pixelShaderCodeStream = new MemoryStream(pixelShaderByteCode); 
                MemoryStream vertexShaderParametersStream = new MemoryStream(vertexShaderParameters); 
                MemoryStream pixelShaderParametersStream = new MemoryStream(pixelShaderParameters); 
                
                // 实例化pass 
                SilverlightEffectPass currentPass = new SilverlightEffectPass(passName, Manager.Current.GraphicsDevice,vertexShaderCodeStream, pixelShaderCodeStream, vertexShaderParametersStream, pixelShaderParametersStream);
                passes[passIndex] = currentPass; 
                
                vertexShaderCodeStream.Dispose();
                pixelShaderCodeStream.Dispose();
                vertexShaderParametersStream.Dispose();
                pixelShaderParametersStream.Dispose();
                
                // 渲染状态
                int renderStatesCount = input.ReadInt32();
                for (int renderStateIndex = 0; renderStateIndex < renderStatesCount; renderStateIndex++) 
                {
                    currentPass.AppendState(input.ReadString(),input.ReadString());
                }
            }
            
            // 实例化technique
            techniques[techniqueIndex] = new EffectTechnique(passes);
        }
        return new SilverlightEffect(techniques);
    }
}

新的Visual Studio模板

Toolkit会安装两个新的项目模板和一个新item模板:

Silverlight3DApp

这个模板会创建一个完整的可工作的Silverlight 3D应用程序。

Silverlight3DApp模板

这个新解决方案由四个项目组成:

Silverlight3DwebContent

主项目(Silverlight3Dapp)创建了两个对象:

默认效果

Silverlight3DLib

这个模板创建一个不包含content但包含Microsoft.Xna.Framework引用的Silverlight库:

Silverlight3DLib模板

项目的结构如下图所示:

Silverlight3DLib模板结构

SilverlightEffect

这个item模板在Content项目中使用,它可以添加一个自定义的.slfx文件,与SilverlightEffect类协同工作:

SilverlightEffect模板

文件的内容如下:

float4x4 World; 
float4x4 View;
float4x4 Projection;

// TODO: add effect parameters here.
struct VertexShaderInput
{
    float4 Position : POSITION0; 
    
    // TODO: add input channels such as texture 
    // coordinates and vertex colors here.
};

struct VertexShaderOutput
{
    float4 Position : POSITION0; 
    
    // TODO: add vertex shader outputs such as colors and texture
    // coordinates here. These values will automatically be interpolated
    // over the triangle, and provided as input to your pixel shader.
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output; 
    
    float4 worldPosition = mul(input.Position, World); 
    float4 viewPosition = mul(worldPosition,View);
    output.Position = mul(viewPosition, Projection); 
    
    // TODO: add your vertex shader code here.
    
    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    // TODO: add your pixel shader code here. 
    return float4(1, 0, 0, 1);
}

technique Technique1
{
    pass Pass1 
    {
        // TODO: set renderstates here. 
        
        VertexShader = compile vs_2_0 VertexShaderFunction(); 
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

演示新功能的新示例

最后,为了帮你学习这些新功能,我们添加了一些很酷的示例:

Bloom

这个示例介绍了如何使用sprite实现“bloom”后期处理效果,它还使用了Content Pipeline从一个.fbx文件导入了一个坦克模型。

Bloom

CustomModelEffect(自定义模型Effect)

这个示例介绍了如何使用Content Pipeline 在模型上施加自定义effect。

CustomModelEffect

Generated geometry(生成几何体)

这个示例介绍了如何在Content Pipeline生成过程中使用代码创建3D模型。

Generated geometry

Particles(粒子)

这个示例介绍了粒子系统的概念,如何使用SpriteBatch绘制粒子效果。示例中有两个粒子效果:爆炸和烟雾:

Particles

Primitives3D(3D图元)

这个例子介绍了如何重用代码绘制基本几何图元:

Primitives3D

Platformer(平台游戏)

这个例子介绍了一个具有3个关卡的完整游戏(你也可以很容易地添加自己的关卡)。展示了在一个平台游戏中的SpriteBatch,SpriteFont和SoundEffect的用法,还使用了键盘类控制玩家。

Platformer

SimpleAnimation(简单动画)

这个示例介绍了如何在一个3D模型上实现刚体动画:

SimpleAnimation

Skinning(蒙皮动画模型)

这个例子介绍了如何使用Content Pipeline处理并绘制一个蒙皮动画模型。

Skinning

文件下载(已下载 7298 次)

发布时间:2012/1/5 下午4:29:41  阅读次数:11902

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

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号