Sliverlight 3D——绘制一个三角形
这篇文章介绍了如何使用Silverlight在Web网页上绘制一个简单的三角形。
XNA Games Studio 4.0的图形库现在已经包含在Silverlight 5中了,如果你有XNA的开发知识,就可以很容易地在Silverlight中创建3D程序。
要创建一个Silverlight 3D应用程序,最佳的方法就是使用Toolkit提供的3D模板,这个模板提供了一个基础框架,添加了必要的引用、一个Content项目和绘制一个立方体动画的代码,你可以很容易地扩展这个框架实现更复杂的效果。
但为了理解原理,这个例子并没有从3D模板生成,而是从更基本的Silverlight应用程序开始。
最小代码
首先,使用Visual Studio创建一个新Silverlight应用程序项目,我命名为Silverlight3D_1。
生成项目后,右击项目打开属性窗口,设置允许在浏览器外运行应用程序,在下面的浏览器外设置对话框中必须选择使用GPU加速和在浏览器之外运行时需要提升的信任。
你需要在项目中添加以下引用:
- System.Windows.Xna(用于支持DrawingSurface控件)
- Microsoft.Xna.Framework
- Microsoft.Xna.Framework.Graphics
添加DrawingSurface控件
Silverlight中使用一个新控件DrawingSurface绘制3D图形,DrawingSurface是一个FrameworkElement,所以它可以像其他控件一样组合在Silverlight的visual tree(注:Visual Tree应翻译为视觉树,它是WPF和Silverlight程序组织控件的一种形式,类似于HTML中DOM树)中,它继承了Width,Height,FlowDirection,HorizontalAlignment和VerticalAlignment属性。
DrawingSurface添加了一个新事件:Draw。Draw事件处理3D图形的位置;world,view和projection矩阵的更新,调用DrawPrimitives方法让GraphicsDevice绘制图形。
当系统准备好绘制下一帧时就会引发Draw事件。当DrawingSurface添加到visual tree时会引发第一个事件,后面的Draw事件是在invalidated时引发的。Invalidated可以使用两种方法实现:调用UI线程中的DrawingSurface.Invalidate方法;或从事件处理程序中调用绘制线程中的DrawEventArgs.InvalidateSurface。
如果3D内容是静态的,就无需在Draw事件最后调用InvalidateSurface方法。如果3D内容是动态的,例如,如果3D对象具有动画,则需要在事件处理的最后调用InvalidateSurface开始绘制循环。
当DrawingSurface的视口比例发生变化时,可以在DrawingSurface的SizeChanged事件处理程序中添加对应的代码。
如果3D是不可见的,那么DrawingSurface事件不会被调用,当element或parent tree是不可见的或者图形设备被移除时就可能发生这种情况。
DrawEventArgs类提供了两个计时属性用于动画计算。DrawEventArgs.TotalTime 表示程序启动后经历的总时间,DrawEventArgs.DeltaTime表示上一次绘制更新后经历的时间。
在MainPage.xmal中添加DrawingSurface控件:
<Grid x:Name="LayoutRoot" Background="White"> <DrawingSurface Loaded="DrawingSurface_Loaded" Draw="DrawingSurface_Draw" /> </Grid>
还添加了DrawingSurface加载和绘制事件的处理程序DrawingSurface_Loaded和DrawingSurface_Draw。
后台代码
后台MainPage.xaml.cs的代码如下:
using System.Windows; using System.Windows.Controls; using System.Windows.Graphics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace Silverlight3D_1 { public partial class MainPage : UserControl { GraphicsDevice graphicsDevice; // 图形设备 public MainPage() { InitializeComponent(); } private void DrawingSurface_Loaded(object sender, RoutedEventArgs e) { // 初始化图形设备 graphicsDevice = GraphicsDeviceManager.Current.GraphicsDevice; } private void DrawingSurface_Draw(object sender, DrawEventArgs e) { // 清除后备缓冲 graphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, new Color(0.2f, 0.2f, 0.2f, 1.0f), 1.0f, 0); // 刷新DrawingSurface控件 e.InvalidateSurface(); } } }
很简单!在DrawingSurface的加载过程中获取图形设备,在绘制方法中用灰色刷新视频缓冲。但是要注意:GraphicsDevice的Clear方法中使用的Color位于Microsoft.Xna.Framework命名空间,会和System.Windows.Media.Color冲突,你要么全名定义这个Color,要么在程序文件顶部的using中删除System.Windows.Media命名空间。
运行程序,截图如下,这就是最简单的一个3D程序。
绘制一个三角形
创建顶点数据
要绘制三角形,我们需要设定三个顶点的数据,因为这个例子不需要光照,因此顶点格式为VertexPositionColor,但顶点格式位于Microsoft.Xna.Framework.Graphics.Extensions命名空间,你必须首先在项目中添加引用。然后,在DrawingSurface_Loaded方法中添加定义三角形的代码:
private void DrawingSurface_Loaded(object sender, RoutedEventArgs e) { … // 定义三角形顶点 VertexPositionColor[] vertices = new VertexPositionColor[3]; vertices[0].Position = new Vector3(-1, -1, 0); // 左边的顶点 vertices[1].Position = new Vector3(0, 1, 0); // 顶部的顶点 vertices[2].Position = new Vector3(1, -1, 0); // 右边的顶点 vertices[0].Color = new Color(255, 0, 0, 255); // 左边顶点为红色 vertices[1].Color = new Color(0, 255, 0, 255); // 顶部顶点为绿色 vertices[2].Color = new Color(0, 0, 255, 255); // 右边顶点为蓝色 }
别忘了Vector3位于Microsoft.Xna.Framework.Math命名空间,你还要在项目中添加这个命名空间。
创建顶点缓冲
首先在程序中定义顶点缓冲的全局变量:
VertexBuffer vertexBuffer; // 顶点缓冲
然后在DrawingSurface_Loaded方法中定义顶点数据之后设置顶点缓冲:
private void DrawingSurface_Loaded(object sender, RoutedEventArgs e) { … // 设置顶点缓冲 vertexBuffer = new VertexBuffer(graphicsDevice, typeof(VertexPositionColor), vertices.Length,BufferUsage.WriteOnly); vertexBuffer.SetData(0, vertices, 0, vertices.Length, 0); }
使用Effect
在这个最简单的例子中,我们使用XNA内置的BasicEffect绘制几何数据,首先需定义这个全局变量:
basicEffect = new BasicEffect(graphicsDevice);
并在DrawingSurface_Loaded方法中进行初始化:
private void DrawingSurface_Loaded(object sender, RoutedEventArgs e) { … // 初始化Effect basicEffect = new BasicEffect(graphicsDevice); }
设置矩阵
你还要在设置相机的矩阵数据,首先定义全局变量:
Matrix view; // 相机视矩阵 Matrix projection; // 相机投影矩阵
并在DrawingSurface_Loaded方法中进行初始化:
private void DrawingSurface_Loaded(object sender, RoutedEventArgs e) { … // 初始化矩阵 view = Matrix.CreateLookAt(new Vector3(0, 0, 5.0f), Vector3.Zero, Vector3.Up); projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, 4f / 3, 0.01f, 1000.0f); }
绘制图形
最后在DrawingSurface_Draw方法中添加以下代码让图形设备调用DrawPrimitives方法绘制顶点缓冲中的数据:
private void DrawingSurface_Draw(object sender, DrawEventArgs e) { // 清除后备缓冲 graphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, new Color(0.2f, 0.2f, 0.2f, 1.0f), 1.0f, 0); // 设置顶点缓冲 graphicsDevice.SetVertexBuffer(vertexBuffer); // 开始绘制 basicEffect.CurrentTechnique.Passes[0].Apply(); // 设置矩阵 basicEffect.View = view; basicEffect.Projection = projection; // 开启顶点颜色的绘制 basicEffect.VertexColorEnabled = true; // 绘制几何体 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); // 刷新DrawingSurface控件 e.InvalidateSurface(); }
运行程序后的效果如下:
文件下载(已下载 3401 次)
发布时间:2012/1/9 下午12:14:44 阅读次数:12122