DirectX9 3D 快速上手 6

讲了很多,最基础的部分就剩下纹理没有讲到了。Texture是Directx里面非常重要的一部分。为了简便起见,我们还是以SDK的Tutorial5为例子。

纹理就像一张墙纸,用来贴在物体的表面,当然,如果足够大,贴一次就能覆盖整个物体的表面,也可以用适当的方法让纹理排列成你要的效果。

来看看纹理的比较重要的函数:Device.SetTexture

public void SetTexture(
    int stage, //纹理混合阶段序号,从0开始
    BaseTexture texture //要设置的纹理对象
);

 

public void SetTextureStageState(
    int stage, //纹理混合阶段序号
    TextureStageStates state, // TextureStageStates enumeration的成员
    int value //对应阶段状态的值
);

SetTextureStageState函数对处理不同的纹理坐标,颜色操作,Alpha操作,和凹凸映射/环境映射比较适用,但是这些操作只对DX9的固定功能的多纹理单元有效,不能将他们与像素shader连用。

public void SetSamplerState(
    int stage, //纹理混合阶段序号
    SamplerStageStates state, // SamplerStageStates enumeration的成员
  int value  //对应采样器状态的值
);

知道了这些下面读懂这些代码就很容易了,我们需要建立Vertex,这里我们需要有一点点地改变,在以前我们接触到的Vertex里面都不涉及到纹理,所以我们选择了CustomVertex里面不包括纹理的类型,现在我们要用CustomVertex.PositionNormalTextured,从名字就可以看出来,这个类型包括了法线还包括了位置的X,Y,Z,以及纹理坐标的Tu和Tv。

当然如果使用CustomVertex.PositionTextured 也是可以的,它不包括法线信息。

接下来我们需要为每个Vertex指定信息,我们先打断一下讲讲纹理坐标,为了通过指定纹理坐标来访问纹理中的每个图素,DX采用了一个一般化的编址方案,纹理地址由[0.0,1.0]区间内的坐标组成,这样我们就不用关心纹理的实际尺寸,例如可以使用(0.0f,0.0f) ,(1.0f,0.0f),(1.0f,1.0f),(0.0f,1.0f)把一个纹理贴到一个矩形上,同样如果(0.0f,0.0f) ,(0。5f,0.0f),(0.5,1.0f),(0.0f,1.0f)就是纹理的左半边。

我们可以通过TextureLoader.FromFile方法来读入图片作为纹理。

这里代码很简单里面有详细的注释,我就不多讲了,

//-----------------------------------------------------------------------------

// File: texture.cs

//

// Desc: Better than just lights and materials, 3D objects look much more

//       convincing when texture-mapped. Textures can be thought of as a sort

//       of wallpaper, that is shrinkwrapped to fit a texture. Textures are

//       typically loaded from image files, and D3DX provides a utility to

//       function to do this for us. Like a vertex buffer, textures have

//       Lock() and Unlock() functions to access (read or write) the image

//       data. Textures have a width, height, miplevel, and pixel format. The

//       miplevel is for "mipmapped" textures, an advanced performance-

//       enhancing feature which uses lower resolutions of the texture for

//       objects in the distance where detail is less noticeable. The pixel

//       format determines how the colors are stored in a texel. The most

//       common formats are the 16-bit R5G6B5 format (5 bits of red, 6-bits of

//       green and 5 bits of blue) and the 32-bit A8R8G8B8 format (8 bits each

//       of alpha, red, green, and blue).

//

//       Textures are associated with geometry through texture coordinates.

//       Each vertex has one or more sets of texture coordinates, which are

//       named tu and tv and range from 0.0 to 1.0. Texture coordinates can be

//       supplied by the geometry, or can be automatically generated using

//       Direct3D texture coordinate generation (which is an advanced feature).

//

// Copyright (c) Microsoft Corporation. All rights reserved.

//-----------------------------------------------------------------------------

using System;

using System.Drawing;

using System.Windows.Forms;

using Microsoft.DirectX;

using Microsoft.DirectX.Direct3D;

using Direct3D=Microsoft.DirectX.Direct3D;

 

namespace TextureTutorial

{

     public class Textures : Form

     {

         // Our global variables for this project

         Device device = null; // Our rendering device

         VertexBuffer vertexBuffer = null;

         Texture texture = null;

         PresentParameters presentParams = new PresentParameters();

         bool pause = false;

 

 

         public Textures()

         {

              // Set the initial size of our form

              this.ClientSize = new System.Drawing.Size(400,300);

              // And its caption

              this.Text = "Direct3D Tutorial 5 - Textures";

         }

 

         public bool InitializeGraphics()

         {

              try

              {

                   presentParams.Windowed=true; // We don't want to run fullscreen

                   presentParams.SwapEffect = SwapEffect.Discard; // Discard the frames

                   presentParams.EnableAutoDepthStencil = true; // Turn on a Depth stencil

                   presentParams.AutoDepthStencilFormat = DepthFormat.D16; // And the stencil format

                   device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams); //Create a device

                   device.DeviceReset += new System.EventHandler(this.OnResetDevice);

                   this.OnCreateDevice(device, null);

                   this.OnResetDevice(device, null);

                   pause = false;

 

                   return true;

              }

              catch (DirectXException)

              {

                   // Catch any errors and return a failure

                   return false;

              }

         }

         public void OnCreateDevice(object sender, EventArgs e)

         {

              Device dev = (Device)sender;

              // Now Create the VB

              vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionNormalTextured), 100, dev, Usage.WriteOnly, CustomVertex.PositionNormalTextured.Format, Pool.Default);

              vertexBuffer.Created += new System.EventHandler(this.OnCreateVertexBuffer);

              this.OnCreateVertexBuffer(vertexBuffer, null);

         }

         public void OnResetDevice(object sender, EventArgs e)

         {

              Device dev = (Device)sender;

              // Turn off culling, so we see the front and back of the triangle

              dev.RenderState.CullMode = Cull.None;

              // Turn off D3D lighting

              dev.RenderState.Lighting = false;

              // Turn on the ZBuffer

              dev.RenderState.ZBufferEnable = true;

              // Now create our texture

              texture = TextureLoader.FromFile(dev, Application.StartupPath + @"\..\..\banana.bmp");

         }

         public void OnCreateVertexBuffer(object sender, EventArgs e)

         {

              VertexBuffer vb = (VertexBuffer)sender;

              // Create a vertex buffer (100 customervertex)

              CustomVertex.PositionNormalTextured[] verts = (CustomVertex.PositionNormalTextured[])vb.Lock(0,0); // Lock the buffer (which will return our structs)

              for (int i = 0; i < 50; i++)

              {

                   // Fill up our structs

                   float theta = (float)(2 * Math.PI * i) / 49;

                   verts[2 * i].Position = new Vector3((float)Math.Sin(theta), -1, (float)Math.Cos(theta));

                   verts[2 * i].Normal = new Vector3((float)Math.Sin(theta), 0, (float)Math.Cos(theta));

                   verts[2 * i].Tu = ((float)i)/(50-1);

                   verts[2 * i].Tv = 1.0f;

                   verts[2 * i + 1].Position = new Vector3((float)Math.Sin(theta), 1, (float)Math.Cos(theta));

                   verts[2 * i + 1].Normal = new Vector3((float)Math.Sin(theta), 0, (float)Math.Cos(theta));

                   verts[2 * i + 1].Tu = ((float)i)/(50-1);

                   verts[2 * i + 1].Tv = 0.0f;

              }

              // Unlock (and copy) the data

              vb.Unlock();

         }

         private void SetupMatrices()

         {

              // For our world matrix, we will just rotate the object about the y-axis.

              device.Transform.World = Matrix.RotationAxis(new Vector3((float)Math.Cos(Environment.TickCount / 250.0f),1,(float)Math.Sin(Environment.TickCount / 250.0f)), Environment.TickCount / 1000.0f );

 

              // Set up our view matrix. A view matrix can be defined given an eye point,

              // a point to lookat, and a direction for which way is up. Here, we set the

              // eye five units back along the z-axis and up three units, look at the

              // origin, and define "up" to be in the y-direction.

              device.Transform.View = Matrix.LookAtLH( new Vector3( 0.0f, 3.0f,-5.0f ), new Vector3( 0.0f, 0.0f, 0.0f ), new Vector3( 0.0f, 1.0f, 0.0f ) );

 

              // For the projection matrix, we set up a perspective transform (which

              // transforms geometry from 3D view space to 2D viewport space, with

              // a perspective divide making objects smaller in the distance). To build

              // a perpsective transform, we need the field of view (1/4 pi is common),

              // the aspect ratio, and the near and far clipping planes (which define at

              // what distances geometry should be no longer be rendered).

              device.Transform.Projection = Matrix.PerspectiveFovLH( (float)Math.PI / 4.0f, 1.0f, 1.0f, 100.0f );

         }

 

         private void Render()

         {

              if (pause)

                   return;

 

              //Clear the backbuffer to a blue color

              device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, System.Drawing.Color.Blue, 1.0f, 0);

              //Begin the scene

              device.BeginScene();

              // Setup the world, view, and projection matrices

              SetupMatrices();

              // Setup our texture. Using textures introduces the texture stage states,

              // which govern how textures get blended together (in the case of multiple

              // textures) and lighting information. In this case, we are modulating

              // (blending) our texture with the diffuse color of the vertices.

              device.SetTexture(0,texture);

              device.TextureState[0].ColorOperation = TextureOperation.Modulate;

              device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;

              device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;

              device.TextureState[0].AlphaOperation = TextureOperation.Disable;

    

              device.SetStreamSource(0, vertexBuffer, 0);

              device.VertexFormat = CustomVertex.PositionNormalTextured.Format;

              device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, (4*25)-2);

              //End the scene

              device.EndScene();

              // Update the screen

              device.Present();

         }

 

         protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)

         {

              this.Render(); // Render on painting

         }

         protected override void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)

         {

              if ((int)(byte)e.KeyChar == (int)System.Windows.Forms.Keys.Escape)

                   this.Dispose(); // Esc was pressed

         }

        protected override void OnResize(System.EventArgs e)

        {

            pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible);

        }

 

       

       

        /// <summary>

         /// The main entry point for the application.

         /// </summary>

         static void
Main
()

         {

 

            using (Textures frm = new Textures())

            {

                if (!frm.InitializeGraphics()) // Initialize Direct3D

                {

                    MessageBox.Show("Could not initialize Direct3D.  This tutorial will exit.");

                    return;

                }

                frm.Show();

 

                // While the form is still valid, render and process messages

                while(frm.Created)

                {

                    frm.Render();

                    Application.DoEvents();

                }

            }

         }

 

     }

}

这里还有一个简单的方法处理纹理,其实也差不多,看上去简单一些而已:

tex
= new Texture(device, new Bitmap(this.GetType(), "puck.bmp"), Usage.Dynamic, Pool.Default);

然后在画图的时候用一句

device.SetTexture(0,
tex
);

就可以把纹理设置到物体上了,不过如果要进行稍微复杂的纹理操作,这个方法就不管用了。

关于纹理的东西还有很多很多,比如纹理的寻址模式,纹理包装,纹理过滤抗锯齿以及alpha混合 和多重纹理等等,这里介绍的只是九牛一毛,不过这些在后面都会慢慢介绍到。

By sssa2000

 

时间: 2024-10-30 01:21:30

DirectX9 3D 快速上手 6的相关文章

DirectX9 3D 快速上手 5

DirectX9 3D 快速上手  5By sssa2000     这一章的内容相对很简单,控制Mesh的移动,旋转等等,其实这一切都是在对矩阵进行操作.在 DX中,用到的变换有3种,一种是基于Word坐标系的,一种是基于View坐标系的,还有一种是基于投影的变换.而这些变换都是通过矩阵的运算来实现的,在.Net的托管环境下,实现这些操作相对于非托管来说简单一写,不用对矩阵的每个值运算. 关于矩阵的运算和变换的关系,很多文章都有分析,GameRes也有很多这样的好文章,例如:http://de

DirectX9 3D快速上手 3

DirectX9 3D快速上手 3 By sssa2000 4/15/2005 我们这里暂时先跳过,乏味的索引缓冲和深度缓冲的内容,先看看怎么在3D空间中实现一个东西,给自己来点成就感. 正好SDK的向导也是这么安排的,呵呵,那我们就继续从向导出发吧,以Tutorial 3为例子. 这个例子主要讲解运用变换矩阵来实现物体的变换,学过图形学或者线性代数的肯定就很容易理解,没学过的,找点这方面的资料看看就可以了. 先看看这个例子实现了什么,编译运行,噢,相比前面两个例子,有耳目一新的感觉,一个三角形

DirectX9 3D 快速上手 4

接下来我们要使用Mesh读入.X文件,关于.X文件,其实可以说很多,我们可以用外部的工具例如3DS MAX来建立.3ds文件,然后利用微软提供给我们的工具转换成.X文件,如果你同时会用3DS你也许会问,那材质怎么办? 你不用担心,.X文件能自动的包含材质,和动画,所以利用Mesh我们可以方便的八我们在3DS MAX的做品用在游戏中. .X文件允许自定义的扩展,当然这个我们在以后的内容也会讲到,我们先看怎么使用,顺便提一句,还有一种用得比较多的文件格式.Md3格式的文件,也就是Quake3使用的文

DirectX9 3D 快速上手 7

这里我想继续写点和Mesh有关的东西,毕竟我们可能还需要对它有很多别的要求.在3D游戏的实际运用中,一般来说都是运用低多边形模型,简称低模.这样才能有更加好的速度来运行游戏,恰好DX中有提供给我们这样的函数让我们来控制读入的Mesh的复杂程度. public void WeldVertices ( Microsoft.DirectX.Direct3D.WeldEpsilonsFlags flags ,//标志     Microsoft.DirectX.Direct3D.WeldEpsilons

DirectX9 3D 快速上手 8

 上一次中途结束了本来应该讲到的控制Mesh的细节程度的方法的,这一次补上.我们这里使用的是简单的方法,并没有涉及到场景剔出等等复杂的方法,我这里主要还是用DX9提供给我们的类库,progressive meshe.progressive meshes主要的优点就是允许我们控制顶点和面的数目,这样我们就可以灵活的控制mesh细节的显示程度.和Mesh一样,progressive meshe也都是继承自BaseMesh这个类.比较重要的属性主要有2个NumberFaces和NumberVertic

19条小技巧让你快速上手Ubuntu 11.04

Ubuntu 11.04在4月底正式发布了,新版本首次采用Unity界面,很多操作和GNOME都不相同,也许你在使用过程中会出现手足无措,不过新鲜事物总是要花费一段时间适应,之后你会发现Ubuntu 11.04还是很不错的. 下面我们为大家收集了19个小技巧,能让你快速上手Ubuntu 11.04,新手们不妨看看: 1.不喜欢Unity?切换到Ubuntu GNOME经典桌面 注销unity桌面环境,然后选择登录环境为"经典桌面"即可进入. 若是你喜欢Unity,可是你的显卡不给力3D

Win8强大兼容性无需适应快速上手

  如果说使用Win7是在一个我们熟悉的环境中操作,那么Win8就是给我们带来了两个激动人心的环境,一个是新颖的"开始"屏幕及它的应用生态,还有一个就是我们熟悉的跟Win7一样的桌面系统.这也就意味着Win8具有很强的兼容性,可以毫不费力地运行Win7的程序,轻松上手无压力. 其实一个操作系统做到Windows这样,基本也不用太多的在意兼容性问题了.作为一个使用最广泛的操作系统,任何软件厂商都会千方百计地向其靠拢,以便能在新系统上运行它们的程序,这是一个向上兼容的过程. Win8不仅仅

Eclipse快速上手Hibernate--4. 继承映射(3)

继承     前两篇文章<Eclipse快速上手Hibernate--4. 继承映射(1) >和<继承映射(2)>中已经谈了每个类层次结构一个表(table per class hierarchy)与每个子类一个表(table per subclass)的策略,这篇文章主要说的是每个具体类一个表(table per concrete class).一些重复的部分这里就不说了,请参考前两篇文章.    这个策略很简单,抽象的基类不参与映射,具体子类参与映射.  1. 创建项目 · 

Eclipse快速上手Hibernate--4. 继承映射(1)

继承    前面的<Eclipse快速上手Hibernate--1. 入门实例 >等三篇文章已经谈了Hibernate的入门以及利用工具创建的方法.这篇文章主要说说在Hibernate中的继承映射.相关配置请参考前三篇文章.    如果程序中的对象含有继承的关系,在Hibernate中有以下三种策略将这种关系映射到数据表上:· 每个类层次结构一个表(table per class hierarchy)· 每个子类一个表(table per subclass) · 每个具体类一个表(table