游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2303|回复: 3

深入Managed DirectX9(五) (续)

[复制链接]

59

主题

984

帖子

1200

积分

金牌会员

Rank: 6Rank: 6

积分
1200
发表于 2005-2-11 04:51:00 | 显示全部楼层 |阅读模式
深入Managed DirectX9(五) (续)

仅供个人学习之用,转载请注明作者


三维场景里的所有几何体都是由三角形组成,那么如何来渲染一个盒子或一个立方体呢?Well,每个立方体由六个正方形构成,而两个三角形可以构成一个正方形(呵呵,这个都要讲,看来老外的数学真的不行)实际上,我们只需要获得立方体8个顶点的坐标就可以了。添加代码:
CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[36];
     // Front face
     verts[0] = new CustomVertex.PositionColored(-1.0f, 1.0f, 1.0f, Color.Red.ToArgb());
     verts[2] =````, verts[3] , verts[4], verts[5] =`````````
     // Back face (remember this is facing *away* from the camera, so vertices should be clockwise order)
     verts[6] = new CustomVertex.PositionColored(-1.0f, 1.0f, -1.0f, Color.Blue.ToArgb());
verts[7] , verts[8], verts[9], verts[10], verts[11]=````````
(注:详见附件中的源码,注意顶点申明的顺序)

正如前面提到的,盒子由12个三角形组成,每个三角形有三个顶点,构成一个顶点集合。还有几个需要修改的地方
vb = new VertexBuffer(typeof(CustomVertex.PositionColored),36,device,Usage.Dynamic | Usage.WriteOnly,CustomVertex.PositionColored.Format,Pool.Default);
evice.Transform.World = Matrix.RotationYawPitchRoll(angle/(float)Math.PI, angle/(float)Math.PI*2.0f, angle/(float)Math.PI);
device.DrawPrimitives(PrimitiveType.TriangleList,0,12);

这里最大的改变就是重新定义了顶点缓冲的大小。同时,我们也改变了盒子的旋转角度,让他转的更疯狂一点。最后改变所要渲染的图元数量。实际上,既然盒子完全是三维的,就没有必要看到他的背面。使用Direct3D里的默认剔除模式(逆时针):删除前面申明剔除模式的行。好了现在运行程序。
非常了不起,我们现在有了一个在屏幕中疯狂旋转的彩色盒子。但是如果需要渲染一系列盒子的话,没有人希望申明一系列顶点缓冲吧。有一个简单的方法可以做到这一点。
现在我们要肩并肩的绘制三个盒子。由于现在的摄像机设置让第一个盒子占慢了整个屏幕,我们需要把他摄像机稍稍往后移一点:
device.Transform.View = Matrix.LookAtLH(new Vector3(0,0,18.0f),new Vector3(),new Vector3(0,1,0));

如你所见,我们只是把他往后移了一点点就可以看到更多场景。为了绘制更多的盒子,我们可以再次利用现有的顶点缓冲,只需要告诉Direct3D再次绘制同样的顶点就可以了。在device.DrawPrimitives之后添加一下代码:
device.Transform.World = Matrix.RotationYawPitchRoll(angle/(float)Math.PI, angle/(float)Math.PI/2.0f, angle/(float)Math.PI*4.0f) *Matrix.Translation(5.0f,0.0f,0.0f);
device.DrawPrimitives(PrimitiveType.TriangleList,0,12);
device.Transform.World = Matrix.RotationYawPitchRoll(angle/(float)Math.PI, angle/(float)Math.PI*4.0f, angle/(float)Math.PI/2.0f)*Matrix.Translation(-5.0f,0.0f,0.0f);
device.DrawPrimitives(PrimitiveType.TriangleList,0,12);
       
        好了,这次我们又作了些什么呢?因为绘制第一个盒子时已经设置过VertexFormat属性,所以Direct3D知道我们将要绘制的顶点类型。同样,它也知道在哪里获得数据。那么绘制第二个盒子Direct3D还需要知道什么呢?只需要绘制的位置和绘制什么就可以了。
        设置world transform可以把数据从局部坐标(object space)“移动”到世界坐标(world space),那么把什么用作变换矩阵呢?首先,使用类似SetupCamera函数里的方法;做一点点改变,让盒子以不同的角度旋转。然而 world transform里的另一半则是新内容:把一个Matrix.Translation与现有的旋转矩阵相乘。变换矩阵可以把空间中的一个点移动到另一个位置。我们的变换矩阵把第二个盒子向坐移动了5个单位,第三个盒子则向右移动了5个单位。
        需要注意的是两个变换矩阵相乘得到的累积效果,是由相乘时矩阵的顺序来决定的。在这里,我们的先旋转盒子,然后再移动。如果先移动再选旋转,那么结果将有很大区别。记住变换时的顺序是很重要的。


为对象添加纹理
        虽然使用颜色和灯光来渲染很有趣,但仅使用这样的技术,对象看起来并不真实。在非三维的程序里“纹理(texture)”通常用来描述对象的粗糙程度(roughness of an object)。三维场景里的纹理就是一张用来模拟几何图元纹理的2D位图。Direct3D可以同时为每一个图元渲染8层纹理,但现在,我们只解决每个图原一张纹理的情况。因为Direct3D使用普通的位图作为它的纹理格式,任何加载的位图都能当作纹理对象。 如何把2D的纹理映射到3D的对象上呢?绘制到场景中的每个对象都有一个可以在光栅化时把每个texel映射到屏幕特定位置的纹理坐标。textl是texture element的缩写,或者表示纹理中每个address的特定颜色值。Address可以想象为一个表示行和列的数字,分别称为U,V坐标。一般来说,这些值都是标量,取值范围从0.0到1.0 。(0,0)表示纹理的左上角,(1,1)表示右下角,中央的坐标为(0.5,0.5)。
        为了使用纹理来渲染盒子,必须改变盒子的顶点格式,以及传递给图形卡的数据。使用纹理坐标来代替顶点数据中的“color”元素。虽然同时使用颜色和纹理都是有效的,当作为练习,我们只用纹理来定义图元的颜色。修改代码:
        CustomVertex.PositionTextured[] verts = new Microsoft.DirectX.Direct3D.CustomVertex.PositionTextured[36];
        verts[0] = new CustomVertex.PositionTextured(-1.0f,1.0f,1.0f,0.0f,0.0f);
        vert[1]```````````(略)
       
        显然,最大的改变就是储存顶点集合的数据类型。每个顶点中的最后两个float值储存了渲染图元所用的纹理U、V值。应为盒子每个面和纹理都为正方形,所以直接把纹理映射到每个面就可以了。注意,图元的左上角映射纹理的(0,0)textl,右下角映射到(1,1)textl。同时,我们还必须修改创建顶点缓冲的地方:
        vb = new VertexBuffer(typeof(CustomVertex.PositionTextured),36,device,Usage.Dynamic|Usage.WriteOnly,CustomVertex.PositionTextured.Format,Pool.Default);
       
有如此多的重复代码,现在让我们用一个简单的方法来绘制盒子,添加一个函数完成这个任务。
private void DrawBox(float yaw, float potch, float roll, float x, float y,float z,texture t)
        {
                ngle += 0.01f;
                device.Transform.World = Matrix.RotationYawPitchRoll(yaw,pitch,roll)*Matrix.Translation(x,y,z);
                device.SetTexture(0,t);
                device.DrawPrimitives(PrimitiveType.TriangleList,0,12);
}

前六个参数和我们之前使用的一样,最后一个新的参数表示渲染时所使用的纹理。我们还调用了SetTexture方告诉Direct3D渲染时使用哪个纹理。它的第一个参数是这张纹理的“层(stage)”。还记得先前我提过可以为一个图元渲染8层纹理吗,这个参数就是这些纹理的索引。因为只有一张纹理,我们使用第一个索引,0。同时应该注意到,我们修改了angle变量以及world transform,可以把SetupCamera里同样的几行删了。
在调用新方法渲染之前,先要申明一些将要使用的纹理,源码里附带了一个包含三张纹理的资源文件。分别为puck.bmp,ground.bmp,banana.bmp。添加如下代码:
private Texture tex = null;
     private Texture tex1 = null;
     private Texture tex2 = null;

        这是我们即将使用的三张纹理。但是,还需要真正“装配”起作为资源嵌入的三张位图。在创建顶点缓冲之后添加如下代码:
tex = new Texture(device,new Bitmap(this.GetType(),"puck.bmp"),0,Pool.Managed);
        tex1 =•••••(略)
       
        Texture的构造函数接受四个参数。第一个是用于渲染纹理的device。场景里所有的资源(纹理,顶点缓冲,等等)都要和device发生联系。下一个参数Bitmap是我们获取纹理数据的地方。第三个参数Usage,先前已经讨论过它。最后一个参数是储存纹理的内存池位置。方便起见,现在使用托管的内存池。Texture其他的构造函数包括:
        (注:此处略去一个在DX9c中已经不存在的构造函数)
        public Texture( Device device, int width, int height, int numLevels,Usage usage, Format format, Pool pool);
public Texture( Device device, Stream data, Usage usage,Pool pool);

第一个方法允许我们从“空白”开始创建一张纹理,可以指定它的高度、宽度,细节程度(number of levels of detail)。最后一个和我们使用的很相似,但使用流而不是位图对象。当然,流中的数据要能被转换为位图。TextureLoad类中还有一些关于加载位图的有趣方法,我们将在下一张讨论。
好了,现在已经定义且加载了位图,是更新绘图代码的时候了,使用如下代码代替先前的绘图代码;
DrawBox(angle / (float)Math.PI, angle / (float)Math.PI * 2.0f, angle / (float)Math.PI / 4.0f, 0.0f, 0.0f, 0.0f, tex);
     DrawBox(angle / (float)Math.PI, angle / (float)Math.PI / 2.0f, angle / (float)Math.PI * 4.0f, 5.0f, 0.0f, 0.0f, tex1);
     DrawBox(angle / (float)Math.PI, angle / (float)Math.PI * 4.0f, angle / (float)Math.PI / 2.0f, -5.0f, 0.0f, 0.0f, tex2);

~~~~~~~~~~~~~~~~~~第三章完~~~~~~~~~~~~~~~~~~~

下一章我们将要讨论各种图元类型,index buffer以及depth buffer

附上源码
在源码中,作者一共渲染了9个盒子,我删除其中的6个后,剩下三个的旋转速度却明显减慢了
,没想明白·············

sf_200521145132.rar

151.9 KB, 下载次数:

59

主题

984

帖子

1200

积分

金牌会员

Rank: 6Rank: 6

积分
1200
 楼主| 发表于 2005-2-18 17:18:00 | 显示全部楼层

Re:深入Managed DirectX9(五) (续)

hoho
自己顶一下^_^

8

主题

71

帖子

76

积分

注册会员

Rank: 2

积分
76
发表于 2005-2-18 20:50:00 | 显示全部楼层

Re:深入Managed DirectX9(五) (续)

等楼主后边的呢?
什么时候可以翻译完成?

59

主题

984

帖子

1200

积分

金牌会员

Rank: 6Rank: 6

积分
1200
 楼主| 发表于 2005-3-9 23:30:00 | 显示全部楼层

Re:深入Managed DirectX9(五) (续)

来了^_^~~~~~~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-24 18:38

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表