星期三, 五月 23, 2007

XNA GSE入门(二) 在三维世界中显示图片

上一篇文章中讲叙了如何在2d的世界中显示一张图片。我们知道XNA是支持3D的,这一篇和上一篇一样,显示一张图片,不过是在3D世界中。本文中需要牵涉一些基本的3D数学,比如世界矩阵,视矩阵,投影矩阵,纹理坐标,HLSL等等,如果不明白这些概念的读者,请先补充以下相关知识。接着我们进入正题。
建立一个工程,取名DisplayPicture3D,并保存工程。(方法同上一篇,点击这里看上一篇)
在Game1类文件中添加如下代码
//texture and effect object纹理对象和shader对象 private Texture ObjectTexture; private static Effect effect; //view projection matrix and view point投影矩阵和视矩阵,以及视点坐标,世界矩阵在这个程序中不改变,所有没有定义了 public static Matrix Projection; public static Matrix View; private static Vector3 ViewPosition = new Vector3(0.0f, 1.8f, 5f); //record last mouse wheel state记录鼠标滚轮的位置,用来控制视点的移动 private static int mouseWheelValue = 0; //vertex array顶点数组,这个程序中没有用复杂的模型,所以直接将顶点数据写在程序中了 VertexPositionTexture[] nonIndexedCube; 这些就是我们建立3D世界需要的元素的了
和上一个例子一样,我们用Construct函数初始化我们的资源
protected virtual void Construct() { IGraphicsDeviceService graphicsService = (IGraphicsDeviceService)this.GameServices.GetService(typeof(IGraphicsDeviceService)); //Inital textures, 从文件中创建纹理 ObjectTexture = Texture.FromFile(graphics.GraphicsDevice, “logo_head.png”);//从DisplayPicture3d.fx文件中创建效果对象 CompiledEffect compiledEffect = Effect.CompileEffectFromFile(”DisplayPicture3d.fx”, null, null, CompilerOptions.None, TargetPlatform.Windows); effect = new Effect(graphicsService.GraphicsDevice, compiledEffect.GetShaderCode(), CompilerOptions.None, null); //init vertex,初始化顶点 nonIndexedCube = new VertexPositionTexture[6]; Vector3 topLeft = new Vector3(-1.0f, 1.0f, 1.0f); Vector3 bottomLeft = new Vector3(-1.0f, -1.0f, 1.0f); Vector3 topRight = new Vector3(1.0f, 1.0f, 1.0f); Vector3 bottomRight = new Vector3(1.0f, -1.0f, 1.0f); Vector2 topLeftT = new Vector2(0.0f, 0.0f); Vector2 bottomLeftT = new Vector2(0.0f, 1.0f); Vector2 topRightT = new Vector2(1.0f, 0.0f); Vector2 bottomRightT = new Vector2(1.0f, 1.0f); nonIndexedCube[0] = new VertexPositionTexture(topLeft, topLeftT); nonIndexedCube[1] = new VertexPositionTexture(bottomLeft, bottomLeftT); nonIndexedCube[2] = new VertexPositionTexture(topRight, topRightT); nonIndexedCube[3] = new VertexPositionTexture(topRight, topRightT); nonIndexedCube[4] = new VertexPositionTexture(bottomLeft, bottomLeftT); nonIndexedCube[5] = new VertexPositionTexture(bottomRight, bottomRightT); //compute Porjection matrix and apply texture,计算投影矩阵,设定纹理对象 Projection = Matrix.CreatePerspectiveFieldOfView((float)Math.PI / 2.0f, (float)Window.ClientWidth / (float)Window.ClientHeight, 0.1f, 1000.0f); effect.Parameters[”UserTexture”].SetValue(ObjectTexture); }添加Construct函数后,在Game1()中调用它public Game1() { InitializeComponent(); Construct(); }
在Update函数中添加如下代码
protected override void Update() { …… //move camera according wheel state,根据鼠标滚轮位置移动摄像机 MouseState currentMouseState = Mouse.GetState(); int mouseoffset = mouseWheelValue - currentMouseState.ScrollWheelValue; mouseWheelValue = currentMouseState.ScrollWheelValue; if (mouseoffset != 0) { ViewPosition.Z += (float)mouseoffset / 5000; } …… }
在Draw函数中添加如下代码
protected override void Draw() { …… //设置顶点格式和消隐模式 using (VertexDeclaration decl = new VertexDeclaration(graphics.GraphicsDevice, VertexPositionTexture.VertexElements)) graphics.GraphicsDevice.VertexDeclaration = decl; graphics.GraphicsDevice.RenderState.CullMode = CullMode.CullClockwiseFace; //update camera position更新视矩阵,重新计算转换矩阵,并通过effect设置它 View = Matrix.CreateLookAt(ViewPosition, Vector3.Zero, Vector3.Up); Matrix matrix = View * Projection; effect.Parameters[”WorldViewProj”].SetValue(matrix); //开始应用效果 effect.Begin(EffectStateOptions.Default); effect.Techniques[0].Passes[0].Begin(); //绘制三角型 graphics.GraphicsDevice.DrawUserPrimitives (PrimitiveType.TriangleList, 2, nonIndexedCube); effect.Techniques[0].Passes[0].End(); effect.End(); …… }
和上一篇一样,添加logo_head.png到工程中来
新建一个DisplayPicture3D.fx文件,并添加到工程中,这个文件将用HLSL语言将纹理应用到我们的顶点模型上来。Fx文件的内容如下
uniform extern float4×4 WorldViewProj : WORLDVIEWPROJECTION;uniform extern texture UserTexture;struct VS_OUTPUT{ float4 position : POSITION; float4 textureCoordinate : TEXCOORD0;};sampler textureSampler = sampler_state{ Texture = ; mipfilter = LINEAR;}; VS_OUTPUT VS( float4 Position : POSITION, float4 TextureCoordinate : TEXCOORD0 ){ VS_OUTPUT Out = (VS_OUTPUT)0; //转换顶点 Out.position = mul(Position, WorldViewProj); Out.textureCoordinate = TextureCoordinate; return Out;}float4 PS(float2 textureCoordinate : TEXCOORD0) : COLOR{ //将纹理应用于顶点 return tex2D(textureSampler, textureCoordinate).rgba;}technique TransformAndTexture{ pass P0 { vertexShader = compile vs_1_1 VS(); pixelShader = compile ps_1_1 PS(); } }
Ctrl+F5,就可以看到运行效果了,用鼠标滚轮控制图片的远近 ,




欢迎与我交流分享ledwinka@gmail.com

没有评论: