Managed Directx9 Kick Start,第一章 介绍Directx3D

DirectX11 顶点和顶点布局 顶点和顶点布局 1. 如何描述顶点? 5.5.1节已经讲过,在Direct3D中,顶点由空间位置和各种附加属性组成,Direct3D可以让我们灵活地建立属于我们自己的顶点格式;换句话说,它允许我们定义顶点的分量。要创建一个自定义的顶点格式,我们必须先创建一个包含顶点数据的结构体。例如,下面是两种不同类型的顶点格式;一个由位置和颜色组成,另一个由位置、法线和纹理坐标组成。struct Vertex 阅读详情

第一章 Introducing Direct 3D


创建设备

 

 

Device类是DirectX里的所有绘图操作所必须的。可以把这个类假想为真实的图形卡。场景里所有其他图形对象都依赖于device。你的计算机里可以有一个到几个device,在Mnaged DirctX3D里,你可以控制任意多个device。

         Device共有三个构造函数,我们现在只讨论其中的一个,但会在后边的内容里讨论其他的。先来看看具有如下函数签名的构造函数:

 

public Device(int adapter,DeviceType deviceType,Control renderWindow,CreateFlags behaviorFlags, PresentParameters[] presentationParameters);

 

(构造函数的第二种重载类似于上边这个,但它接受来自非托管(或者非windows form)的窗口句柄作为renderWindow。而只接受一个IntPtr参数的重载是非托管com组建指向Idirect3Ddevice9的接口。当你的代码需要和非托管的程序协作时则应用它)

好了,这些参数是什么意思,以及我们怎样来使用呢?呵呵,参数adapter表示我们将要使用哪个物理图形卡。计算机里的所有图形卡都有一个唯一的适配器标识符(通常是0到你的图形卡数量-1),默认的显卡总是标识为0 的图形卡。

下一个参数,DeviceType,告诉了DirectX3D你要创建哪种类型的device。这里最常用的值是DeviceType.Hardware,表示你将创建一个硬件设备。另一个选项DeviceType.Reference,这种设备允许你使用“参考光栅器”(reference rasterizer),所有的效果由DirectX3D运行时来实现,以很慢、很慢、很慢的速度运行^_^。应该仅在调试或测试你的显卡不支持的特性时使用这个选项。

(注意参考光栅器只包含在DirectX SDK里,so DirectX运行时是不能使用这个特性的。最后一个为DeviceType.Software的值允许使用用户自定义的软件光栅器(custom software rasterizer)在不确定是否有这样一个光栅器存在时,忽略这个选项吧^_^。)

rendrWindow表示把设备绑定到的窗口。因为windows form控件类都包含了一个窗口句柄(windows handle),所以很容易把一个确定的类作为渲染窗口。可以使用form、panel或其他任意的控件作为这个参数的值。但现在,我们只用form。

下一个参数用来描述设备创建之后的行为。大部分CreateFlags枚举的成员都能组合起来使用,使设备具有多种行为。但有一些flag是相互排斥的,稍后讨论它们。我们现在只使用SoftwareVertexProcessing标志。这个标志适合于所有顶点处理都用CPU计算的情况。因此,这自然比所有点都用GPU处理要慢,因为我们不确定你的显卡是否支持所有特性。So,安全第一,假设你的CPU能完成现在的任务。

最后一个参数,它表示你的设备把数据呈现到显示器的方式。Presentation Parameter类的外观都可以由这个类来控制。我们过后再来深入讨论它的构造函数,现在,我们只关心“Windowed”成员和“SwapEffect”成员。

Windowed成员是一个布尔类型的值,决定设备是全屏还是窗口模式。

SwapEffect成员用于控制缓存交换的行为。如果选择了SwapEffect.Flip,运行时会创建额外的后备缓冲(back buffer),并且在显示时拷贝front buffer。SwapEffect.Copy与Flip相似,但要求你把后备缓冲设为1。我们将要选择的SwaoEffect.Discard,如果缓冲没有准备好被显示,则会丢弃缓冲中的内容(which simply discards the contents of the buffer if it isn’t ready to be presented)。

学了这么多,现在来创建一个设备吧。回到代码上来,首先为我们的程序将创建一个device对象:

(代码略,参见DirectX sdk Tutorial 1: Create a Device)

现在让我们来重写Paint()函数:

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

    {

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

        device.Present();

    }

    我们使用Clear()方法把窗口填充为实心的颜色。它的第一个参数指定了我们要填充的对象;在例子里,我们填充的即是目标窗口。稍后再来讨论ClearFlags枚举的其它成员。第二个参数是我们所要填充的颜色。其他的两个参数先暂时忽略。在device被填充之后,我们必须更新显示:Present方法会为我们完成这个任务。这个方法也有几个重载的类型;上边使用的方法会显示device的整个区域。同样稍后再讨论。

     看的有些枯燥了吗,好吧,现在我们来真正绘制一些图形

     三维图形世界里最基本的图形就是三角形。使用足够的三角,我们可以呈现出任何东西,甚是是平滑的曲面。没有什么比画一个简单的三角形更好的了。为了使过程尽可能的简单,我们先避开“world space”以及各种变换(当然,我们马上就会提到他们),使用屏幕坐标来绘制一个简单的三角。再绘制我们迷人的三角前,我们必须做2件事。1,需要一些数据结构来保存三角的信息。2,告诉device来绘制它。

     很幸运,DirectX已经有这样一个数据结构来保存三角了。Direct3D名称空间里叫做CustomVertex的类可以用来储存大多数Direct3D中用到的“顶点格式”数据结构(vertex format)。

一个顶点格式结构把数据保存为一种DirectX3D认识并可以使用的格式。我们将讨论很多这种结构,但先看看我们即将用来创建三角的TransformedColored结构。这个结构告诉DirectX3D运行时我们的三角不需要进行坐标变换(比如旋转或移动),因为我们已经指定了使用屏幕坐标系。它也包含了每一个点(顶点)的颜色的信息。回到重写的OnPaint方法添加如下代码:

     CustomVertex.TransformedColored[] verts = new CustomVertex.TransformedColored[3];

    Verts[0].SetPosition(new Vector4(this.Width/2.0f,50.0f,0.5f,1.0f);

    Verts[0].Color = System.Drawing.Color.Aqua.ToArgb();

    Verts[1]`````````

    Verts[2]`````````

     (参见DirectX sdk Tutorial 2: Rendering Vertices)

 

 

 

         数组里的每一个元素表示三角的一个顶点,所以我们创建了3个元素。然后使用新创建的Vector4结构为每一个成员调用SetPositin方法。变换过的顶点坐标包含了在屏幕上x和y的坐标(相对于屏幕的(0,0)点而言),当然也包括z坐标和rhw成员(reciprocal of homogenous w三维齐次坐标)。先忽略后边两个参数。Vector4结构(注:Vector4其实就是(x,y,z,w)经过变换后成为(x/w,y/w,z/w))是保存这种信息最方便的方式。然后我们设置了点的颜色。注意,我们使用了标准颜色的ToArgb方法。DirectX3D假设所接收的颜色为32位int。

         既然有了数据就可以告诉DirectX我们需要绘制这个三角形,并且绘制它。在重写的OnPaint里添加如下代码

         device.BeginScene();

         device.VertexFormat = CustomVertex.TransformedColored.Format;

device. DrawUserPrimitives (PrimitiveType.TriangleList,1,verts);             注意和sdk中的示例有区别

         device.EndScene();

         好了,这几行代码是什么意思呢?其实很简单。BefinScene方法告诉DirectX3D我们即将绘制一些东西,为绘制做好准备。现在我们已经告诉了DirectX3D要绘制一些东西,接下来就必须告诉它画什么。这就是VertexFormat属性的作用。它决定了DirectX3D运行时使用哪种“固定功能管道”(fixed function pipline)格式。在我们的例子里使用变换过的,着色过的顶点管道。

不用担心你现在不明白确定的功能管道是什么意思,我们会很快来讨论它。

DrawUserPrimitives函数是真正发生绘图的地方。So,他的参数是什么意思呢?第一个参数是我们要绘制的初等几何体的类型。有很多种可用的类型,but now,我们只是画一系列的三角形。所以选择了PrimitiveType.TriangleList类型。第二个参数是我们要绘制的三角形的数量。对于一个三角形的集合来说,这个值应该是你的顶点数量除以3。我们只画一个三角,所以设为1。最后一个参数则是DirectX3D用来绘图的数据。最后一个EndSence方法通知DirectX3D我们不再绘图了。你必须再每次调用BeginSence之后都调用这个方法。  

如果现在编译运行程序,你会发现移动或重置窗口大小之后,并不会更新显示。原因是当我们需要重绘整个窗口时,Windows并不会每一次都计算窗口的收缩情况。因此,你只是移除了显示过的数据,但并没有删除已经显示的内容。很幸运,有个简单的方法解决这个问题,我们可以告诉Windows窗口总是需要被整个的重绘。在OnPaint的最后加上一下代码:

this.Invalidate();

呵呵,现在再来试试看,哦,看起来我们破坏了程序!现在只能显示一片空白了,并且我们的三角还在不停的闪烁,尤其是当调整窗口大小时。我们都干了些什么呢?原来“聪明”的Windows总是尝试在Invalidate()方法后来绘制当前的窗口(即空白的这个窗口)。在我们的OnPaint方法之外还存在其他的绘制过程!能容易的通过改变窗口的“style”属性来解决。在构造函数里加上如下代码

this.SetStyle(ControlStyles.AllPaintingInWmPaint | ConstolStyles.Opaque, true);

哦~,好了,终于erying works as expected。我们所做的就是告诉Windows一切绘图过程都在OnPaint里完成。

 

三维化三角形

 

       再看看我们的程序,它看起来并不那么“三维”。而且我们所做的都能用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除非指定一个新的世界坐标变换,否则在这段代码之后所有绘制的对象都将进行这种变换。以上的世界坐标变换是根据所给的弧度旋转Z轴。注意这里的参数必须是弧度而不是角度。有规律的改变参数值就能让三角形平滑的转动起来了(以下代码略,参考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,试试拖放窗口的大小会怎样??

 

 

拖放窗口时自动重置Device

 

 

   任何曾经使用C++或VB开发DirectX3D的人都知道,在改变窗口大小时,需要重新设置devicd,否则,DirectX3D会按原来的分辨率继续渲染场景,并且把结果拷贝到(通过拉伸)新的窗口。当通过Windows Form控件创建device时,聪明的Mamaged DirectX能发现你改变了窗口的大小,并且重置device。毫无疑问,程序总是能在正常的行为下运行,同时,你也能方便的自己重置device。在自动重置device之前,会引发一个叫做DeviceResizing的事件。捕获这个事件,把EventArgs类的Cancel成员设置为true,就能回到默认的行为,在创建device之后加上如下代码

 

     private void CancelResize(object sender, CancelEventArgs e)

 

    {

 

        e.Cancel = true;

 

}

 

 

如你所见,这个方法只是简单的say yes,我们确实想要取消这个操作。现在订阅事件处理程序,让device知道不进行这种操作:

 

device.DeviceResizing += new CancelEventHandler(this.CancelResize);(注:CancelEventHandle委托在System.ComponentModel名称空间)

 

运行程序,最大化窗口。三角的位置还和原来一样,不过这次看起来可怕极了。边缘都是锯齿,看起来糟糕透了。可以删除我们刚添加的代码了。Managed DirectX默认操作已经帮我们完成了这个任务,可以直接利用它。

 

 

我说:“要有光”,于是就有了光

 

我们绘制了三角形并且让他转起来了,怎样才能让他更好呢?当然是灯光。在前面曾简要的提到过它,事实上,那个时候我们完全关闭了灯光。首先要做的就是先回到那个黑暗的场景:

 

deviceRenderState.Lighting = true;

 

 

其实你甚至可以把整行都删了,device的默认行为是打开灯光的;只是为了让代码更清楚才保留它。现在获得了一个黑色的旋转三角。或许我们应该先定义一盏灯,再来打开它。你可能已经注意到有一个灯光数组连接到了device类上,并且这个数组的每一个元素都保存了有关灯光的大量属性。我们希望定义场景里的第一盏灯并且打开它,So,在OnPaint方法定义了三角形之后的地方(注:与sdk中有区别,不过都是一样的效果^_^)添加如下代码:

 

device.Lights[0].Type = LightType.Point;

device.Lights[0].Positon = new Vector3();

            device.Lights[0].Diffuse = System.Drawing.Color.White;

            device.Lights[0].Attenuation = 0.2f;

            device.Lights[0].Range = 1000.0f;

            device.Lights[0].Commit();

            device.Lights[0].Enabled = true;

    这些代码什么意思呢?首先申明了要创建的灯光类型,我们选择了一个在所有方向上辐射强度都一样的point light,创造了一个灯泡般的世界。当然,也有灯光沿着指定方向传播的direction light。direction light只会产生方向和颜色上的效果,忽略其他的灯光要素(比如光线的削弱(attenuation)和范围(range)),因此它也是计算量最小的灯光。最后一种能用的就是spot light了,类似于剧场里用来照亮舞台上人物的灯光。有许多的要素来描述spot light(位置,方向,角度,等等),所以它是系统里所需计算量最大的灯光。

     在对灯光类型简单的讨论之后,我们继续。接下来设置灯光的位置。因为三角形的中心在(0,0,0),所以我们把灯光也放到那个位置。Vector3无参数的构造函数完成了这个任务。把灯光的漫射颜色设置为白色,这样可以正常的照亮表面。接下来设置控制灯光强度在空间改变的削弱属性。范围是灯光能产生效果的最远距离。例子里的范围已经远远超过了我们所需要的。请查阅sdk寻找有关灯光的更多内容。

     最后我们把灯光提交给了device,并使它可用。如果你浏览灯光的属性,会注意到一个叫做“Deferred”的布尔值。默认情况下,这个值是false,所以你需要在准备使用灯光之前调用Commit函数。把这个值设为true,可以取消对Commit的调用,但会带来一定的性能损失。在观看灯光的效果前一定要确定它是enable和committed的。

     回到程序,你发现即使我们为场景定义了灯光,三角也还是黑色的!打开了灯,却看不到光,Direct3D一定没有照亮我们的三角形,事实上,它确实没有。只有在几何体的每一个面都有一条法线(normal)时,才会进行灯光的计算。知道了这点,我们来为三角添加法线吧,这样就能在场景里看到它了。最简单的方法就是把顶点格式改为一种包含了法线的格式。碰巧我们也有这样一个结构了,改变创建三角形的代码:

     CustomVertex.PositionNormalColored[] verts = new CustomVertex.PositionNormalColored[3];

     verts[0].SetPositon(new Vector3(0.0f,1.0f,1.0f));

     verts[0].SetNormal(new Vector3(0.0f,0.0f,-1.0f));

     verts[0].Color = Ststem.Drawing.Color.White.ToArgb();

     verts[1]``````

     `````````

     更新顶点格式来适应新的数据:

     device.VertexFormat = CustomVertex.PositionNormalColored.Format;

 

       这次最大的改变就是使用了一组包含法线的数据,并且把三角形的颜色改为白色。可以看到,我们把垂直于顶点指向外的方向定义为法矢量。因为点只是在Z平面内移动,所以沿着Z轴的负方向即是法线矢量的方向。现在程序就一切正常了。可以试着改变一下灯光的漫射颜色,看看会有怎样的变化。

         还有一件应该记住的事:灯光是按照每一个顶点来计算,所以在low polygon模型(就像我们简单的三角形)的情况下,灯光可能会不太真实。我们会在后边的章节里讨论一些高级灯光技术,比如per pixel linghting。这些灯光能创造一个真实的世界。

 

       Device State and Transforms

     至今为止,示例代码里还有两项没有讨论过:设备状态(device state)以及变换(transform)。对一个设备来说,有三种不同方式的设备状态:the render state,The sampler states,和 the texture state。我们仅仅使用过the render state中的几种类型;后边的两种类型是用来处理纹理的。不要担心我们很快就会谈到纹理。The render state类规定了DirectX3D怎样来对场景进行光栅化。可以使用这个类来改变很多属性,包括我们已经使用过的灯光以及剔除。其他render state可用的选项有填充模式(fill mode) (比如wire frame mode)和各种雾化参数。我们也会来接下来的几章深入讨论。

     前面提到过,变换就是用来把几何体位置从一个坐标系转到另一个坐标系的一系列矩阵。用于device上的三个主要变换就是world,view以及projection变换,但是也有一些其他的变换。比如用来控制texture stages的变换,就依赖于一个255的世界矩阵(There are transforms thst are used to modify texture stages,as well as up to 255 world matrices??).

    

 

         Swapchains and RenderTargets

         Device到底作了些什么工作来绘制这些三角形呢?device有一些固定的方法来处理在哪绘制并且如何绘制对象。每一个device都有一个交换链(swap chain)以及一个渲染目标(render target)。

         一条交换链实际上就是一系列被控制着用来渲染的缓冲区。所有绘图过程都是在交换链中的后备缓冲区发生。当使用SwapEffect.Flip来创建一条交换链时,后备缓冲区翻转(flipped)为真正被图形卡用于读取数据的前缓冲(front buffer)。同时,三号缓冲区变为新的后备缓冲,而先前的前缓冲变为未使用过的三号缓冲区。

         真正的翻转操作是通过改变图形卡当前所读的数据区、刚读过的数据区以及后备缓冲区之间的地址来实现。只有在全屏模式下,才会发生真正的翻转操作。而在窗口模式,翻转实际上只是数据的拷贝而已,因为device并没有控制着整个显示器,仅仅是一小部分而已。虽然两种模式下结果都一样。全屏模式下,有一些驱动程序也会使用翻转操作来实现SwapEffect.Discard 或者 SwapEffect.Copy。

         如果使用SwapEffect.Copy或SwapEffect.Flip来创建交换链,可以确保presen()之后不会影响后备缓冲中的内容。运行时会在需要时强制创建额外的隐藏缓冲。建议使用SwapEffect.Discard来避免这种潜在的损失。这种模式允许驱动程序选择最高效的方法分配后备缓冲。使用SwapEffect.Discard时,不值得(???)在绘制新的图形前检查你是否清除了整个后备缓冲。调试模式下的运行时将会使用随机的数据来填充(刚刚使用过的)后备缓冲,让开发者检查是否忘了调用clear()。(it is worth nothing that when usuing SwapEffect.Discardyou will want to ensure that you clear the entire back buffer before starting new drawing operations. the runtime will fill the the back buffer with random data in the debug runtime so developers can see if they forget to call clear)(注:这一段内容看的不是太明白,所以把原文也给出来。Sdk中对SwapEffect枚举的解释也不是太清除。参考sdk:交换效果明确定义了调用present()之后,后备缓冲的状态。Flip交换链是一个循环的队列,可以有0~(n-1)块后备缓冲, discard交换链是一个队列, copy交换链只有一块后备缓冲。Flip中的后备缓冲在present()之后内容不会改变,所以系统需要额外内存作为后备缓冲,带来性能损失。既然后备缓冲中的内容不改变,如何构成循环队列来使用?? Discard后备缓冲中队列的长度以及怎样变化也没有明确说明,只有“The swap chain is essentially a queue where 0 always indexes the back buffer that will be displayed by the next Present operation and from which buffers are discarded once they have been displayed. An application that uses this swap effect should update an entire back buffer before invoking a Present operation that displays it.The debug version of the runtime overwrites the contents of discarded back buffers with random data, to enable developers to verify that their applications are updating the entire back buffer surface correctly.” 随机数据能帮助检查是否更新了整个后备缓冲区??既然会丢弃数据还需要调用clear??)

         交换链的后备缓冲区也同样能作为渲染目标。毫无疑问,当创建了device,创建了交换链之后,渲染目标就被设置为链的后备缓冲。一个渲染目标就是能保存所执行的绘制任务的输出的表面(a surface that will hold the output of the drawing operations that you perform)。如果你创建了多个交换链的话,就必须确定预先更新了device的渲染目标。后边我们会稍后讨论这点。  

 

 

 

 

 

 

 

 

 

 

Direct9入门教程|Direct9官方提供的tutorial文件自己翻译的|DirectX创建设备  自己翻译的官方帮助文档里面的教程一,因为昨晚自己弄出来觉得很高兴哈。有新手觉得难入手的不妨看下我这篇。最下面有VC的设置。(我的SDK版本比较老了哈,是9.0April2006) 第一步 建立windows窗口 每一个windows程序做的第一件事就是当它运行时要产生一个程序窗口显示给使用者看。为做到这个,CreateDevice样例是在它的WinMain函数里面开始运行的。下面这个 阅读详情

相关推荐

Managed DirectX 9(中文版)

Managed DirectX 9(中文版)是受欢迎的directx教材,此版为中文版

翻译 managed DirectX9(第一章)

第一章 Introducing Direct 3D翻译:clayman创建设备  Device类是DirectX里的所有绘图操作所必须的。可以把这个类假想为真实的图形卡。场景里所有其他图形对象都依赖于device。你的计算机里可以有一个到几个device,在Mnaged DirctX3D里,你可以控制任意多个device。         Device共有三个构造函数,我们现在只讨论其中的一个,但

Clayman的专栏 9802

DirectX9_SDK中文文档.pdf

对Microsoft® Direct3D®应用程序编程接口(API)中三维图形功能的 介绍。可以在这里找到有关图形流水线的概述,以及可以快速运行,帮助开发者 了解Direct3D 基本功能的教程。

最简单的视音频播放示例5:OpenGL播放RGB/YUV

本文记录OpenGL播放视频的技术。OpenGL是一个和Direct3D同一层面的技术。相比于Direct3D,OpenGL具有跨平台的优势。尽管在游戏领域,DirectX的影响力已渐渐超越OpenGL并被大多数PC游戏开发商所采用,但在专业高端绘图领域,OpenGL因为色彩准确,仍然是不能被取代的主角。OpenGL简介从网上搜集了一些有关OpenGL简介方面的知识,在这里列出来。开放图形库(英语

雷霄骅(leixiaohua1020)的专栏 4万+

Managed DirectX 9.0 SDK 文档中文译本

Managed DirectX 9.0 SDK 文档中文译本 翻译内容选自官方帮助文档 pdf清晰版 极有价值

Managed DirectX 9.0 SDK中文文档

Managed DirectX 9.0 SDK中文文档

Direct3D基础概念和模型整理

模型主要是物理组成,数据传输和固定图形管道模型;概念主要包括IDirect3D, Adapter, Device, swap chain,surface后台缓存、前台缓存、深度和模板缓存,资源,资源类型_D3DRESOURCETYPE,格式_D3DFORMAT,资源存放的内存区域Pool,资源的使用标识Usage。 0.图形模型 1)    显卡物理组成和数据传输: 基本物理组成模型: (

自由理想的足迹 4312

Python RK3588 MPP 8路视频硬解码!全体目光向我看齐!

本文重写了官方demo、加入了Zlmediakit进行拉流并通过pybind11将代码封装成so库,现在,在python中直接通过import的方式,就能完成基础的拉流解码操作,目前支持8路拉流解码!!!

m0_46303486的博客 4879

Managed Directx 9 kick start,第五章 纹理

Rendering with Meshes 我们又向前迈进了一大步,这可比总看着立方体旋转要有趣多了。下一章我们将使用Managed DirectX来写一个真正的游戏了,最然它可能看起来很简单,但毕竟是我们的第一个三维游戏^_^,第六章内容比较,大概3、4次才能翻译完^_^。  定义Mesh    虽然有很多时候,你需要手动创建顶

bbwolfcool的专栏 1181

基于matlab版本的三维直流电法反演算法

可以使用RESINVM3D工具包等现成的MATLAB工具进行三维直流电法反演。反演问题求解:基于MATLAB的反演问题求解算法实现和应用,包括反演问题数值模拟、反演问题参数优化和反演问题结果分析。希望这个代码示例能帮助你入门三维直流电法反演。如果有更具体的需求或问题,可以进一步探讨。反演过程中可能需要调整正则化参数和优化算法的设置。需要根据实际问题实现,可能涉及复杂的数值计算。

ytttr873的博客 668

ESP32C3的I2S接口详解:以驱动PCM5102A为例,避开时序与配置的那些坑

本文深入解析ESP32C3的I2S接口驱动PCM5102A DAC的完整解决方案,涵盖时序对齐、PCB优化和寄存器级配置。通过实际案例分享时钟树分析、信号完整性设计和底层调试技巧,帮助开发者避开常见陷阱,实现高质量音频输出。重点探讨了I2S协议栈、电源滤波优化及DMA传输异常处理等关键技术要点。

weixin_30254435的博客 299

Managed Directx 9 kick start,第六章,编写游戏

第六章 使用Managed DirectX编写游戏仅供个人学习之用,勿用于任何商业用途,转载请注明作者^_^选择游戏      虽然很多关于3D游戏编程的高级主题还没有讨论,但我们已经有足够的背景知识来写一个简单游戏了。这一章,我们将使用至今学过的知识,再加上一点点新的东西来创建游戏。     真正开始写游戏之前,最好先拟一份计划。我们需要确定写什么类型

bbwolfcool的专栏 1179

基于CubeMX与lwip的STM32轻量级HTTP服务器搭建及VSCode高效开发指南

本文详细介绍了如何在STM32单片机上,利用STM32CubeMX图形化配置工具和轻量级TCP/IP协议栈lwIP,快速搭建一个轻量级HTTP服务器。通过结合VSCode的高效代码编辑能力,提供了一套从硬件连接到动态网页交互(SSI/CGI)的完整开发指南,旨在为嵌入式设备提供零成本、跨平台的Web交互界面。

weixin_29163857的博客 582

XNA Kick Start

前言        很久以前,翻译了《Managed DirectX9 Kick Start》,在过去的几年中,继续自学,虽然仍未达到自己所希望的目标,不过对托管DirectX以及实时渲染技术已稍有研究。不敢妄谈游戏引擎,但已能实现一些小把戏,以自娱。学习中深感国内资料的匮乏,故凡遇所喜之外文,则边学边翻,期望对有相同喜好之人有所帮助。《Managed DirectX9 Kick St

Clayman的专栏 4196

[SC]SystemC在CPU/GPU验证中的应用(六)

本文提供了一个SystemC学习路线图,包含50个由浅入深的编程实例,涵盖从基础模块到复杂SoC建模的全过程。示例包括:基础模块(时钟、计数器)、通道(FIFO、握手)、TLM2.0接口、总线模型(AXI-Lite)、CPU/GPU内核实现、功耗分析、断言验证等。重点展示了SystemC在硬件验证中的关键应用:VCD波形生成、UVM-SystemC框架、Verilog DPI协同仿真、Python集成、NoC路由器和完整SoC建模(CPU+Cache+DRAM+互连)。每个示例提供完整代码和详细注释,建议分

元直的博客 1492

【STM32+K210项目】基于K210智能人脸识别+车牌识别系统(完整工程资料源码)

随着时代的进步和科技的迅猛发展,人们对居住安全的重视程度不断提升,对安全防范系统的需求也日益增强。在安防系统中,门禁系统占据着重要的位置。传统的门禁控制方式主要依靠钥匙、密码和门禁卡等,这些方式易于被破解和复制,安全性较低。然而,近年来,生物识别技术的迅速发展和成熟,为解决这一问题提供了新的方案。生物识别技术具备便携性、非易失性、不易遗忘以及难以盗用等优点,逐渐被引入到门禁系统中。传统的小区门禁系统往往依赖人工管理,存在一定的局限性,难以满足用户多样化的需求,也浪费了人力资源。

嵌入式技术开发 1万+

Managed DirectX® 9学习笔记 ycl

Managed DirectX® 9学习笔记第一章       介绍1、命名空间Table 1. Managed DirectX NamespacesMicrosoft.DirectXParent namespace, holds all common code.Microsoft.DirectX.Direct3DDirect

a11s的笔记 1122

全新YOLOv11一文弄懂 | YOLOv11网络结构解读 、yolov11.yaml配置文件详细解读与说明、模型训练参数详细解析 | 通俗易懂!入门必看系列!

本文全面介绍了YOLOv11目标检测算法,包含网络结构解析、yaml配置文件详解及训练教程。YOLOv11通过改进的C3k2f模块、SPPF和C2PSA注意力机制等创新设计,在COCO数据集上实现了比YOLOv8更优的性能。文章详细解读了yolov11.yaml配置文件的参数设置、主干网络(backbone)和头部网络(head)结构,并提供了完整的训练代码示例和参数说明。训练部分涵盖了模型选择、参数设置及优化技巧,包括epochs、batch size、学习率等关键参数的调整建议。最后总结了YOLOv11

Ai缝合怪、助力小伙伴高效发论文 3万+

Managed Directx 9 kick start,第三章 简单渲染技术

使用简单的渲染技术    至今为止,我们的渲染工作效率都很低。每次渲染场景时,都要分配新的顶点列表,并且所有东西存储在系统内存里。现代显卡集成了足够显存,把顶点数据存放在显存可以获得大幅的新能提升:存放在系统内存里的数据,渲染每一帧时都要拷贝到显卡,这会带来极大的损失。只有移除每帧时的这种分配才能帮助我们提高性能。 使用顶点缓冲(Using Vertex Buffers)

bbwolfcool的专栏 1196

让 ABAP BAPI_COSTACTPLN_POSTPRIMCOST 不再沉默:一套可落地的参数一致性校验与排错打法

SAP BAPI_COSTACTPLN_POSTPRIMCOST 沉默失败分析与解决方案 问题现象 使用 BAPI_COSTACTPLN_POSTPRIMCOST 上传计划数据时,接口执行不报错但数据未写入 COSP 等计划表,呈现"沉默失败"现象。 根本原因 索引关联断裂:INDEXSTRUCTURE 中 OBJECT_INDEX 和 VALUE_INDEX 未正确关联 COOBJECT 和 PERVALUE/TOTVALUE 表的数据 对象定义冲突:COOBJECT 中同一行填写了多

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 110

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Managed Directx 9 kick start,第四章 更多渲染技术

更多渲染技术翻译:clayman     在讨论过了基础渲染方法之后,我们应该把注意力放到一些能提高性能,并且让场景看起来更好的渲染技术上来: 渲染各种图元类型     至今位置,我们只渲染过一种类型的图元,称为三角形集合。实际上,我们可以绘制很多种不同类型的图元,下边的列表描述了这些图原类型:     PointList――这是一个自我描述的图元类型,它把数据作为一系

bbwolfcool的专栏 1031

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

给立方体添加纹理

今天看了《Managed DirectX 9 Kick Start: Graphics and Game Programming 》有关加纹理的,下面我以我对书的理解谈谈如何简单的向对立方体加纹理。有不对之处,请大家指正,谢谢。首先我把原来的PositionColored类型的顶点改为PositionTextured,原因是显而易见的。顺便提一句,CustomVertex里有2种大的顶点类型,一种

Shutely@Xu.Dening的专栏 1625

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

呵呵,先开个头。。

前段时间玩了《轩辕剑4》,以前很少玩这种rpg游戏,但是玩了以后,发现其实在是做得太好了,而且自己也想学习学习3D技术,于是开始对Direct3D进行研究,开始准备学习openGL的,但是说实话,我觉得微软的东西虽然很多人说不好,但是用起来还是很方便,很舒服的。这一点,谁都得承认。于是看了两天openGL后开始看Direct了。 说中国的图形学资料少,真的是一点都不假,我在网上找了好久好久,

笑笑的程序人生 1771

Tuesday,October 19,2004

今天看DX9SDK for ManagedDX,不太顺心,后面的Direct3D Surfacces和Direct3D Textures两章,难呀。看SDK的英文确实很吃力。感觉什么都没有学到,像是在浪费光阴...今天听了学校微软技术俱乐部两个MVP(微软最具价值专家),有关的讲做,感觉他们凶啊....呜...,才20岁出头,同龄的我却毫无价值,思考他们的成长经历和我有什么不同...今天也看了

Shutely@Xu.Dening的专栏 798

Direct3D9教程1—创建设备

D3D9_Tutorial_1:Creating a Device      步骤: 1、创建窗口 (1-1)填充WNDCLASSEX结构 (1-2)注册窗口类 (1-3)创建窗口 (1-4)显示更新窗口 2、初始化Direct3D (2-1)创建D3D接口对象 (2-2)获取设备性能信息 (2-3)填充D3DPRESENT_PARAMETERS结构 (2-4)创

RyoChan的博客 2153

device.RenderState.Lighting与device.Lights[0]的关系

            device.RenderState.Lighting = true;            device.Lights[0].Type = LightType.Directional;            device.Lights[0].Ambient = Color.White;            device.Lights[0].Diffuse = Col

youganquan的专栏 777
上一篇: 数据并发控制
下一篇: Managed Directx 9,第二章 选择正确的设备
bbwolfcool
博客等级 码龄24年 6粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值