深入Managed DirectX9(二)

转载 2006年05月20日 22:16:00
三维化三角形

  再来看看我们的程序,看起来并不是那么“三维”。而且我们所做的都能用GDI+轻易完成。So,我们应该怎样在3维空间里绘图,并且给人留下深刻的印象呢?实际上,简单的修改就能达到这样的效果。

  如果你还记得,先前在我们创建第一个三角形的时候,我们使用了一个叫做“经过变换的”(transformed)坐标系统。这种坐标是显示器的屏幕区所使用的坐标,也是最容易定义的。如果我们使用未变换过的坐标系统会怎样呢?实际上,未变换过的坐标系统被广泛的用于现代游戏场景。

  与屏幕坐标(screem space)相比我们定义这些坐标时,还应在世界坐标(world space)里定义每一个顶点。你可以把世界坐标设想为一个无限大的三维笛卡儿坐标。你可以把你的对象放到这个“世界”的任意位置。现在来修改我们的程序,绘制一个未经过世界坐标变换的三角形。

  首先使用未变换顶点格式类型中的一种来改变三角形的数据。在这里我们只关心顶点的位置,以及颜色,因此使用CustomVertex.PositionColored。

  CustomVertex.positionColored[] verts = new CustomVertex. positionColored[3];
  Verts[0].SetPosition(new Vector3(0.0f,1.0f,1.0f));
  Verts[0].Color = System.Drawing.Color.Aqua.ToArgb();
  Verts[1]`````````
  Verts[2]`````````
  (参见DirectX sdk Tutorial 3: Using Matrices)

  同样改变VertexFormat属性:

  device.VertexFormat = CustomVertex.PositionColored.Format;

  好了,现在运行程序:什么也没有发生,仅获得一个填充过的窗口。在讨论为什么之前,先来看看我们都作了些什么。就像你看到的,我们选择了PositonColored结构来保存数据。这个结构用世界坐标保存了顶点的位置,也保存了它的颜色。因为为顶点是没有变换过的,所以我们使用Vector3类来代替Vector4类,没有变换过的顶点是没有rhw值的。Vector3结构的成员直接映射为世界坐标系里x,y,z的值。同时,我们需要确定DirectX3D知道所做的改变,所以我们通过更新VertexFormat属性来让固定功能管道使用新的未变换但填充过颜色的顶点。

  So,为什么程序运行时没有正确的显示呢?问题在于,我们只是在世界坐标里绘图,但并没有给DirectX3D任何关于如何来显示它们的信息。我们需要为场景添加一个摄像机来确定如何观看我们的顶点。在经过变换的坐标系统里不需要摄像机的原因是:DirectX3D已经知道在屏幕的哪个位置来显示顶点。

  在device上通过两个不同的变换来控制摄像机。每一种变换都被定义为一个4×4的矩阵传递给DirectX3D。(???each transform is defined as a 4*4 matrix that you can pass in to DirectX3D)

  映射变换定义了场景被怎样投影到显示器。最简单的产生投影矩阵的方法就是使用Matrix类的PerspectiveFovLH方法。它将会使用左手坐标系创建一个正对场景的透视投影变换。(关于左右手坐标系的详细内容请参见sdk,或你的高等数学、高等物理教材^_^)DirectX3D通常使用左手坐标系。

以下是投影函数的签名:
  public static Matrix PerspectiveFovLH( float fieldOfViewY,float aspectRatio,float znearPlane,float zfarPlane);

  投影变换描绘了场景的视见体(注:即可见部分)。视见体是由可视角度和前裁剪面(Near Plane)与后裁剪面(Far Plane)定义的一个平截头体(注:比如四棱锥横截面与底面之间的部分,上帝保佑,你还记得高中几何),在这个平截头体之内的即是可见部分。函数头里的nearPlane和farPlane两个参数,描绘了锥体的边界:farPlane就是锥体的底面,而nearPlane则是横截面。fieldOfView参数描绘了锥体的角度。aspectRatio类似于电视的高宽比,比如,宽银幕电视的高宽比是1.85。你可以用可视区域的宽度来比上高度得出这个值。DirectX3D只绘制在这个平截头体中的物体。

  既然我没从来没有进行过投影变换,也就根本不存在一个视见体,应此DirectX3D什么也没有绘制。但是,就算我们进行了投影变换,我们还没有进行包含了摄像机信息的view transform。可以用一下函数完成这个任务:

  public static Matrix LookAtLH(Matrix pOut, Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector);

  仅仅通过各变量的名字你就可以知道如何使用这个函数。其中三个是用来描述摄像机的属性:它的位置、它观察点的位置以及一个被参考为“up”的方向。有了投影变换和view transform的帮助,DirectX3D已经有足够的信息来绘制三角了。添加代码:(参见DirectX sdk Tutorial 3: Using Matrices中的SetupMatrices()函数)

  再运行一次试试,哦,我们已经有一个三角了,不过它完全是黑色的!问题在哪呢?在没有经过变换的环境里,DirectX3D默认使用灯光来计算场景中几何体每一个象素的颜色,我们没有定义灯光,也没有额外的光照在三角上,So,它完全是黑色的。既然我们已经为每一个点定义过了颜色,所以现在,可以安全并且简单的把场景里的灯关了。加上如下带码:

  dev.RenderState.Lighting = false;

  再试一次,终于,我们回到了未变换坐标前的样子。做了这么多改变到底有什么好处呢?最大的好处就是和在屏幕上直接绘制相比我们获得了一个三维空间里的三角形——迈向伟大三维作品的第一步!^_^

  既然有了三维空间里的三角,我们怎样做才能让他看起来确实是一个三维空间里的三角呢?最简单的事就是让它旋转起来。如何来做呢?很简单,我们只需要更改世界坐标就可以了。

  Device的世界坐标变换会把每一个用局部坐标定义的顶点位置转换为用世界坐标定义的顶点位置。(the world transform on the device is used to transform the objects being drawn from model space ,whice is where each vertex is defined with respect to the model, to world space,where each vertex is actually placed in the world.)Matrix对象的很多方法能完成这种变换:

  device.Transform.World = Matrix.RotationZ( (float)Math.PI/6.0f );

  它告诉DirectX3D除非指定一个新的世界坐标变换,否则在这段代码之后所有绘制的对象都将进行这种变换。以上的世界坐标变换是根据所给的弧度旋转x轴。注意这里的参数必须是弧度而不是角度。有规率的改变参数的值就能让三角形平滑的转动起来了(以下代码略,参考sdk中的示例)。
我们旋转的三角并不能给人留下深刻的印象。我们来试试让他变得特别一点,并且同时旋转多个轴。很幸运,恰好有这样一个方法,好了,更新代码:

  device.Transform.World = Matrix.RotationAxis( new Vector3(angle/((float)Math.PI*2.0f), angle/((float)Math.PI*4.0f), angle/((float)Math.PI*6.0f)), angle/((float)Math.PI);

  这里使用了RotationAxis函数,通过这个函数,我们先定义了旋转轴,并在每一维上用一个简单的式子不停改变轴的位置,然后再传入三角形围绕着轴旋转的角度,就像我们先前做的一样。

  再次运行程序,哦,我们确实得到了一个围绕着旋转轴转动的三角形,但似乎三角形会有规律的消失一阵,然后再显示出来。好了,还记得我们先前提到的背面剔除(back face culling)吗?这就是背面剔除在起作用的最好例子。当DirectX3D渲染物体的时候,如果它发现某一个面没有对着摄相机,就不会绘制它,这就叫做背面剔除。那么程序在运行时,又是怎样知道某一个特定的几何面是否对着摄像机呢?快速的看看DirectX3D中的裁剪选项或许能给你一点提示。三种可用的剔除选项分别是:none,clockwise(顺时针)以及counterclockwise(逆时针)。在clockwise以及counterclockwise的情况下,当简单几何体的顶点排列顺序与剔除模式相反时,它就不会被绘制。

  看看我们的三角形,它的顶点是按逆时针顺序来排列的(注:有关顶点的排列顺序,可参考sdk文档Face and Vertex Normal Vectors)。DirectX3D默认的剔除模式就是逆时针模式。

  你可以简单在顶点集合中把第一个和第三个元素交换一下,看看会有什么不同。

  现在我们知道背面剔除是怎样工作的,很显然,我们简单的程序并不需要剔除功能。有一个简单的render state来控制剔除模式,添加如下代码:

  Device.RenderStates.CullMode = Cull.None;

  再一次,erying works as expected,试试拖放窗口的大小会怎样??

  添上关于投影变换的图片一张
  摄像机位于o点,视见体为ABCD--A'B'C'D',ABCD为后裁剪面,A'B'DC'D'前裁剪面
    

(第二部分完,下一次我们将要讨论灯光了,并且解决拖放窗口时出现的问题)

深入理解Java内存模型(二)——重排序

原文出处:http://www.infoq.com/cn/articles/java-memory-model-2
  • acs713
  • acs713
  • 2014年06月05日 10:42
  • 1021

[深入理解Android卷二 全文-第六章]深入理解ActivityManagerService

由于《深入理解Android 卷一》和《深入理解Android卷二》不再出版,而知识的传播不应该因为纸质媒介的问题而中断,所以我将在CSDN博客中全文转发这两本书的全部内容第6章 深入理解Activi...
  • Innost
  • Innost
  • 2015年08月03日 12:36
  • 35173

Directx9.0编程学习笔记二(Direcx接口的初始化)

在代码中加入以下两条预处理语句: #include "d3dx9.h" //Driect9.0的头文件 #pragma comment(lib,"d3d9.lib") 初始化DirectX首先要声明以...
  • lishunihaoa
  • lishunihaoa
  • 2016年06月09日 00:40
  • 147

Directx9.0 学习教程5 光照

光照   1.      首先需要定义这样的顶点结构   struct CUSTOMVERTEX { D3DXVECTOR3position; // 顶点 D3DXVECTOR...
  • cq361106306
  • cq361106306
  • 2014年09月29日 18:45
  • 2156

DirectX9 10 11对比区别摘抄整理

dx8使得可编程的硬件进入管线成为了双重构造。对于DirectX 9的顶点处理与像素处理,则被真正的可编程处理器调换。而在向DirectX 10的转移为了实现更灵活的可编程性,需要GPU架构进行根本的...
  • skyell
  • skyell
  • 2015年03月08日 11:53
  • 1505

SpringMVC结合Mybatis事务失效的问题

这几天一直在写自己的代码,碰到了事务
  • ckao7470
  • ckao7470
  • 2014年06月29日 00:38
  • 3814

通过Xcodeproj深入探究Xcode工程文件

你是否好奇Cocoapods是如何修改掉Xcode工程的结构?你也是否曾被Xcode工程的配置文件里面杂乱的内容搞得摸不清头脑?你又是否知道Xcodeproj这个神奇的Ruby库?下面我将通过这个系列...
  • CSDN_Liuzongyi
  • CSDN_Liuzongyi
  • 2016年10月31日 09:27
  • 579

[深入理解Android卷一 全文-第二章]深入理解JNI

由于《深入理解Android 卷一》和《深入理解Android卷二》不再出版,而知识的传播不应该因为纸质媒介的问题而中断,所以我将在CSDN博客中全文转发这两本书的全部内容。(出版社排版好的PDF版正...
  • Innost
  • Innost
  • 2015年08月02日 09:39
  • 10187

深入理解Java Class文件格式(二)

在上一篇文章 深入理解Java Class文件格式(一) 中, 介绍了class文件在整个java体系结构中的位置和作用, 并对class文件的整体格式做了说明, 介绍了其中的魔数和版本号的相关内容,...
  • brave2211
  • brave2211
  • 2014年03月19日 21:28
  • 9174

Spark修炼之道(高级篇)——Spark源码阅读:第八节 Task执行

Task执行在上一节中,我们提到在Driver端CoarseGrainedSchedulerBackend中的launchTasks方法向Worker节点中的Executor发送启动任务命令,该命令的...
  • lovehuangjiaju
  • lovehuangjiaju
  • 2015年10月29日 12:00
  • 4642
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深入Managed DirectX9(二)
举报原因:
原因补充:

(最多只允许输入30个字)