XNA学习笔记——线、三角形的绘制

来源:互联网 发布:centos cp 拷贝文件夹 编辑:程序博客网 时间:2024/05/21 08:55
   1: namespace WindowsGame4
   2: {
   3:     public class Game1 : Microsoft.Xna.Framework.Game
   4:     {
   5:         GraphicsDeviceManager graphics;
   6:         SpriteBatch spriteBatch;
   7:  
   8:         public Game1()
   9:         {
  10:             graphics = new GraphicsDeviceManager(this);
  11:             Content.RootDirectory = "Content";
  12:         }
  13:  
  14:         protected override void Initialize()
  15:         {
  16:             // TODO: Add your initialization logic here
  17:  
  18:             base.Initialize();
  19:         }
  20:  
  21:         protected override void LoadContent()
  22:         {
  23:             // Create a new SpriteBatch, which can be used to draw textures.
  24:             spriteBatch = new SpriteBatch(GraphicsDevice);
  25:  
  26:             // TODO: use this.Content to load your game content here
  27:         }
  28:  
  29:         protected override void UnloadContent()
  30:         {
  31:             // TODO: Unload any non ContentManager content here
  32:         }
  33:  
  34:         protected override void Update(GameTime gameTime)
  35:         {
  36:             // Allows the game to exit
  37:             if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  38:                 this.Exit();
  39:  
  40:             // TODO: Add your update logic here
  41:  
  42:             base.Update(gameTime);
  43:         }
  44:         protected override void Draw(GameTime gameTime)
  45:         {
  46:             GraphicsDevice.Clear(Color.CornflowerBlue);
  47:  
  48:             // TODO: Add your drawing code here
  49:  
  50:             base.Draw(gameTime);
  51:         }
  52:     }
  53: }

上面就是XNA自动生成的代码,整个类执行的流程如下图所示: http://img.ddvip.com/2009_03_14/1237027284_ddvip_4250.jpeg
按F5,即可运行,弹出如下对话框:  
默认是800x600

1、修改窗口的宽度和高度,还有标题。
在构造函数中添加下面两行代码

   1: Window.Title = "Hello XNA";
   2: graphics.PreferredBackBufferWidth = 640;
   3: graphics.PreferredBackBufferHeight = 480;

注:是在构造函数中,如果添加在Initialize(),没有效果。graphics的类型是GraphicsDeviceManager,也就是图形设备管理器,相当于D3D中的
D3D对象(LPDIRECT3D9   pD3D)。GraphicsDevice device = graphics.GraphicsDevice 通过图形设备管理器得到图形设备,相当于D3D中的设备对象(LPDIRECT3DDEVICE9  pd3dDevice )。图形设备对象可以用来绘制。

2、设置观察矩阵(Matrix viewMatrix)和投影矩阵(Matrix projectMatrix)

   1: protected override void Initialize()
   2: {
   3:     // TODO: Add your initialization logic here
   4:            
   5:     float viewAngle = MathHelper.PiOver4;
   6:     float aspectRatio = graphics.GraphicsDevice.Viewport.AspectRatio;
   7:     float nearPlane = 0.1f;
   8:     float farPlane = 1000.0f;
   9:     projectMatrix = Matrix.CreatePerspectiveFieldOfView(viewAngle, aspectRatio, nearPlane, farPlane);
  10:  
  11:     Vector3 camPostion = new Vector3(10, 10, -10);
  12:     Vector3 camTarget = new Vector3(0, 0, 0);
  13:     Vector3 camUpVector = new Vector3(0, 1, 0);
  14:     viewMatrix = Matrix.CreateLookAt(camPostion, camTarget, camUpVector);
  15:  
  16:     base.Initialize();
  17:  
  18: }

3、设置顶点

   1: private void InitVertices()
   2: {
   3:     vertices = new VertexPositionColor[30];
   4:  
   5:     vertices[0] = new VertexPositionColor(new Vector3(0, 0, 0), Color.Red);
   6:     vertices[1] = new VertexPositionColor(Vector3.Right * 5, Color.White);
   7:     vertices[2] = new VertexPositionColor(new Vector3(5, 0, 0), Color.White);
   8:     vertices[3] = new VertexPositionColor(new Vector3(4.5f, 0.5f, 0), Color.Plum);
   9:     vertices[4] = new VertexPositionColor(new Vector3(5, 0, 0), Color.White);
  10:     vertices[5] = new VertexPositionColor(new Vector3(4.5f, -0.5f, 0), Color.White);
  11:  
  12:     vertices[6] = new VertexPositionColor(new Vector3(0, 0, 0), Color.White);
  13:     vertices[7] = new VertexPositionColor(Vector3.Up * 5, Color.White);
  14:     vertices[8] = new VertexPositionColor(new Vector3(0, 5, 0), Color.White);
  15:     vertices[9] = new VertexPositionColor(new Vector3(0.5f, 4.5f, 0), Color.White);
  16:     vertices[10] = new VertexPositionColor(new Vector3(0, 5, 0), Color.White);
  17:     vertices[11] = new VertexPositionColor(new Vector3(-0.5f, 4.5f, 0), Color.White);
  18:  
  19:     vertices[12] = new VertexPositionColor(new Vector3(0, 0, 0), Color.White);
  20:     vertices[13] = new VertexPositionColor(Vector3.Forward * 5, Color.White);
  21:     vertices[14] = new VertexPositionColor(new Vector3(0, 0, -5), Color.White);
  22:     vertices[15] = new VertexPositionColor(new Vector3(0, 0.5f, -4.5f), Color.White);
  23:     vertices[16] = new VertexPositionColor(new Vector3(0, 0, -5), Color.White);
  24:     vertices[17] = new VertexPositionColor(new Vector3(0, -0.5f, -4.5f), Color.White);
  25:  
  26:     vertices[18].Position = new Vector3(3, 0, 0);
  27:     vertices[18].Color = Color.Blue;
  28:  
  29:     vertices[19].Position = new Vector3(0, 3, 0);
  30:     vertices[19].Color = Color.Red;
  31:  
  32:     vertices[20].Position = new Vector3(0, 0, -3);
  33:     vertices[20].Color = Color.Green;
  34: }

private VertexPositionColor[] vertices; //VertexPositionColor表示该Vertex中有位置(Position)和颜色(Color)信息
private VertexDeclaration vertDeclaration;//VertexDeclaration是用来声明该Vertex中有哪些信息(位置、颜色、纹理、发现)
看下面的代码

   1: public void DrawUsingPresetEffect()
   2: {
   3:     device.VertexDeclaration = new VertexDeclaration(device, VertexPositionColor.VertexElements);
   4:     device.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, vertices, 0, 12);
   5:     device.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleList, vertices, 18, 1);
   6: }

device.vertDeclaration = new VertexDeclaration(device, VertexPositionColor.VertexElements);
DrawUserPrimitives中的第三个参数表示从哪个位置开始,第四个参数表示绘制多少个图元
0,12 表示vertices数组中从下标为0开始,绘制12条直线。18,1表示vertices数组中从下标18开始,绘制一个三角形
注:XNA的坐标系是右手坐标系,和D3D不同。

4、BasicEffect

一开始接触的是2D,绘制用的是SpriteBatch的Draw方法。到了3D,就迷糊了。

   1: protected override void Draw(GameTime gameTime)
   2: {
   3:     GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.CornflowerBlue, 1, 0);
   4:  
   5:     // TODO: Add your drawing code here
   6:     basicEffect.World = Matrix.Identity;
   7:     basicEffect.View = viewMatrix;
   8:     basicEffect.Projection = projectMatrix;
   9:     basicEffect.VertexColorEnabled = true;//如果没有这句,颜色的效果体现不出来
  10:     basicEffect.Begin();
  11:     foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
  12:     {
  13:         pass.Begin();
  14:         cCross.DrawUsingPresetEffect();
  15:         pass.End();
  16:     }
  17:     basicEffect.End();
  18:     base.Draw(gameTime);
  19: }

以前用的FFP(Fixed Function Pipeline 固定渲染管道)XNA已不再支持。XNA默认的是可编程的渲染管道,进行顶点渲染(Vertex Shader )和像素渲染(Pixel Shader),用HLSL编写,也就是说在3D中绘制物体都要用到HLSL。但由于HLSL的语法接近于C,所以在XNA中提供了一个BasicEffect这样的类,所有绘制在basicEffect.Begin()和basicEffect.End()中。像代码中的pass,Technique都是HLSL中的东西。需要对HLSL有一个基本的了解。

注:ClearOptions.Target是颜色缓存的刷新。上面漏了一个非常重要的知识点:在Draw函数的开始添加device.RenderState.CullMode = CullMode.None; 不然绘制的三角形有50%是看不见的。这就是背面剔除。

5、程序逻辑

   1: protected override void Update(GameTime gameTime)
   2: {
   3:     // Allows the game to exit
   4:     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed
   5:         || Keyboard.GetState().IsKeyDown(Keys.Escape))
   6:         this.Exit();
   7:  
   8:     // TODO: Add your update logic here          
   9:     base.Update(gameTime);
  10: }

键盘状态的判断:Keyboard.GetState().IsKeyDown(Keys.Escape)
注:关于Update的参数GameTime。因为XNA默认的刷新频率是60Hz。也就是1秒钟,调用Update方法60次。但是游戏的帧数并不一定是60fps,所以提供了GameTime,可以根据相关的属性进行设置。下面是其中一种方式。

   1: if(timeElapse >= ((double)1/fps)*1000)
   2: {
   3:     hero.UpdateHero();
   4:     timeElapse = 0;  
   5: }
   6: else
   7: {
   8:     timeElapse += gameTime.ElapsedGameTime.Milliseconds;
   9: }
原创粉丝点击