快整整两年了,感叹“转眼已是百年”诗句的精妙,两年内浪费了太多时光,所以决定重新起航,相信这次可以走的更远更宽广.....
两年来一直在研究XNA的二次开发,从一开始的兴奋到中间的恶补空间几何到后来慢慢的力不从心再到最后得心应手,整个过程用了很长的时间,不过仍然还需要自己钻研很多知识点,对待HLSL依然有点力不从心,这将是我今年一年利用空闲时间恶补的主要知识点之一,为了鞭策自己会想所有的HLSL的学习感悟都记录到这里,和志同道合的朋友一起研究和学习。
感慨完了,进入正题........
XNA中的3D文字一直是挺让人纠结的问题,SpriteBatch中的DrawString只能绘制屏幕文字,下面利用简单的代码绘制一个3D文字,原地址为https://devel.nuclex.org/framework/wiki/VectorFonts,感觉不错。
private GraphicsDeviceManager graphics; private SpriteBatch spriteBatch; /// <summary> /// load the font /// </summary> private VectorFont vectorFont; /// <summary> /// text string /// </summary> private Text text; /// <summary> /// draw the string /// </summary> private TextBatch textBatch; /// <summary> /// camera viewMatrix /// </summary> private Matrix viewMatrix = Matrix.Identity; /// <summary> /// camera projectionMatrix /// </summary> private Matrix projectionMatrix = Matrix.Identity; /// <summary> /// record the update number /// </summary> private int Index = 0; /// <summary> /// text rotate matrix /// </summary> private Matrix RotateMatrix = Matrix.Identity; public MyText() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } /// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { base.Initialize(); } /// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); this.textBatch = new TextBatch(this.graphics.GraphicsDevice); viewMatrix = Matrix.CreateLookAt(new Vector3(0 , 0 , 50) , new Vector3(0 , 0 , -100) , Vector3.Up); projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4 , GraphicsDevice.Viewport.AspectRatio , 1.0f , 1000); this.vectorFont = this.Content.Load<VectorFont>("Fonts/defaultFont"); this.text = this.vectorFont.Extrude("H0"); } /// <summary> /// UnloadContent will be called once per game and is the place to unload /// all content. /// </summary> protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } /// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); Index++; if (Index % 60 == 0) { string str = "H" + (Index / 60).ToString(); this.text = this.vectorFont.Extrude(str); } // TODO: Add your update logic here RotateMatrix *= Matrix.CreateRotationY(MathHelper.Pi / 180); base.Update(gameTime); } /// <summary> /// This is called when the game should draw itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); this.textBatch.ViewProjection = viewMatrix * projectionMatrix; this.textBatch.Begin(); this.textBatch.DrawText(this.text , Matrix.CreateScale(0.1f) * RotateMatrix * Matrix.CreateTranslation(0 , 0 , 30) , Color.Red); this.textBatch.End(); base.Draw(gameTime); }
其中有几点需要注意的地方,首先是需要将名称为defaultFont的字体文件放在项目的Content目录下面,其次对于defaultFont.spritefont文件需要修改其属性:将其Content Porcessor修改为Vector Font,接着就可以编译通过了(测试版本VS2010+XNA4.0)......