您的位置:首页 > 编程语言

3D游戏编程入门(十)D3D程序Debug技巧和D3D基础

2012-09-27 16:39 155 查看

3D游戏编程入门(十)D3D程序Debug技巧和D3D基础

(2007-01-01 21:52:19)


转载▼

呼,现在开始D3D专门相关的东西开始介绍了,果然一天之内一直复习有点顶不住的感觉,需要补充一些感性方面的东西哇。恩,可又不愿
意花过多的时间,着实令人烦恼,稍后再想想做点什么来休闲吧。

D3D程序BUG测试技巧

这东西本来应该是程序最后才总结的,但是想了想,对于初次涉及D3D编程的朋友还是先说一下的比较好,对自学有很大的好处。

了解编程的新手朋友会明白,我们初心者进行一个项目开发时最头疼的莫过于一连串的错误了,即使经过反复的调试,也可能有很多的
BUG我们依旧难以找到,下面是一些总结的经验,大家在以后进行测试时会有一定的帮助的。

1:在CPP文件开头,include<window.h>之前,我们定义(define)STRICT符号的话,将导致更严格的类型检查,帮助我们进行错误的定位


2:在DXSDK中,DXDiag实用程序可以进行错误报告,但这并不值得推荐给新手,使用它时,我们必须很清楚我们系统上有些什么东西。

3:在DX控制面板中允许调设debugoutput level等级,我建议使用4级,另打开Debugging中的四个选项MaximumValidation,Enable
Shader Debugging,Break on Memory Leaks,Break on D3DError,另外一定要记得在D3D程序调试时设置为Use DebugVersion,恩,当然,
进行别的游戏运行时,一定记得调整回来,不然可无法正常运行的哦--(似乎我开始就多次犯这个错误)

4:D3DX库是一个静态库,为了方便调试,我们可以导入一个动态库,d3dx9d.lib它是专门用做调试的库。

5:从网上下载个内存管理器可以减少内存分配和释放的问题,当然VC++提供了一个称为CRT的内存管理器。根据个人爱好了

6:下载VC++.Net的插件来调试顶点Shader和象素Shader

7:使用OutputDebugString();Debugbreak();等调试辅助函数

8:尽量避免在调试时使用全屏模式,在创建窗口时应传参isWindowed来控制全屏与否。

9;对于释放时,经常SafeRealse,SafeFree来替代Realse,free,其实仅仅需要自己去加个判断为空的定义。

10:一般DX的方法都会返回一个HRESULT,我们可以用SUCCEEDED(),FAILED()的函数对它返回值进行判断,防止出错。

11:还有VC环境中设置断点,进行监视等技巧,相信大家比较熟悉了

D3D基础

又是Windows编程基础,又是向量矩阵介绍,又是DX介绍,现在又是D3D介绍,会不会比较郁闷,怎么还没开始打代码啊00呵呵,别着急
,学习是慢慢积累的,编程就象写文章,这些知识是思想,函数调用等代码是文字。我们要写好的文章,光有文字没有思想是不行滴,而且
高程们更多的倒是整体流程框架思想的把握,我们这样的低级程序员到是象打字员一样的忙来忙去,呼,向高手看齐。不多说了,现在把D3D
里面的一些术语介绍下。

1:PageFlipping(页翻动)。我们要明白,屏幕上显示的图象并非直接绘制在屏幕上的,而是先将这些图象绘制在一个不可见的页面上
,这个页面我们称为“后台缓冲”,当绘制完毕后,系统快速的将它放到屏幕的可见的“前台缓冲”上,并且将我们刚才看到的页面再放到
“后台缓冲”进行重复绘制。所以我们的屏幕显示要分为60桢,75桢,85桢的频率的问题,那就是每秒种后台缓冲放置到前台缓冲的页面频
率。当这个频率过低,我们眼睛的视觉残留能够捕捉时,我们就会发现屏幕的翻动了,想想,电视里录制的电脑屏幕是否是一闪一闪的,那
就是因为摄象机的录制频率比电脑屏幕刷新速率快的问题。

2:Pixel和Resolution象素和分辨率。屏幕上的显示的图象是由一块块的小点组成的,这个最小单元我们叫做象素,它也是颜色缓冲区中
最小的图形单元。分辨率则是我们的显示设备可以显示的最大象素个数。例如,我们现在电脑屏幕大部分可以支持1024X768的象素,则代表
他上面有1024X768=78万多的象素。也就是说我们此时的屏幕是由78万多个小点组成的。

3:颜色缓冲区FrameBuffer。这是位于系统内存或者显存中的一块内存。它存放者我们需要显示的一块二维显示区。

4:设备Device。说白点,就是我们的显卡

5:本地空间。是指我们在定义组成物体的三角形列表时使用的坐标系。在其中创建物体模型时,我们不需要关心物体位置和其他世界空
间内的物体关系,可以很大程度上简化我们的模型处理工作。

6:世界空间。我们每个模型都是在自己的本地空间创建,创建好了之后,我们需要将这些模型物体组合到一起,形成一个整个的场景,
这时我们需要一个统一的世界坐标系。在其中,我们开始考虑与其他物体之间的位置关系,到底谁遮挡谁?

7:视图空间。我们在D3D的场景中需要设置一个虚拟的摄象机,以确认我们可以看到的场景,这个由虚拟摄象机决定的空间是视图空间。
在其中,我们需要考虑到底我们可以看到什么,哪些我们又看不到?

8:视口。这个很好理解,当我们游戏全屏运行时,我们的视口就是全屏幕,当我们设置为窗口模式时,窗口上显示游戏的矩形区域就是视
口。

9:顶点Vertices。就是模型物体的一个顶点。我们将模型物体都看为由一个个三角形组成时,这些三角形的三个顶点,就是我们这里说
的顶点。

10:T&L流水线。在介绍OpenGL时我曾做过介绍。我们渲染图形时通常是可以分为两大步的。第一部分是转换和照明(T&L)在这阶段我们
将顶点进行矩阵转换,再根据灯光材质等计算每个顶点的照明效果。第二部分是光栅化处理,这里我们开始控制纹理,深度缓冲,来判断哪
些用户可见的顶点,并将绘制结果显示在屏幕上。

在这个流水线中,我们将未处理的顶点从其中一端送入,经过处理操作,从另一端就会出来我们所需要的3D图形。这里在详细的介绍下
吧。

1:首先进行顶点坐标的转换。我们可以通过SetTransfrom的方法来实现对应的变换。我们首先需要创建一个D3D设备的指针。

我们可以写以下代码

IDirect3DDeviceg_pD3DDevice = NULL ; /*创建D3D设备指针 */

g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld ); /*其中D3DTS_WORLD代表矩阵转换的类型,matWorld是一个变换矩
阵 */

/*在上述代码中,我们实现了将一个独立的物体放到世界坐标系的功能,在世界转换中我们主要完成对模型的旋转,缩放,平移等*/

等我们将物体转换到世界空间后,我们需要确定视图空间,我们需要定义好摄象机的一些属性,其中包括摄象机的位置,摄象机的朝向,
摄象机的正方向,这些我们都是使用向量来表示。

D3DXMATRIX*D3DXMatrixLookAtLH

(

D3DXMATRIX*pOut, //输出用于视图变换的矩阵

const D3DXVECTOR3* pEye, //摄像机的位置

const D3DXVECTOR3* pAt, //摄像机朝向的位置

const D3DXVECTOR3* pUp //摄像机的正方向

);

在这里我们需要注意的是两点:1,这里的函数是D3DX开头的,这代表这是一种比较高层的接口,它是捆绑了一定的低层接口的方法的,
在一定程度上,它方便了我们的设计,但是也硬性的捆绑了一些设定,对我们编程时的调整有很大的坏处,我们尽量可能的使用D3D开头的函
数。2:大家看到了,此函数第一个参数是输出的矩阵,我们接下来进行使用的矩阵也就是这个矩阵,我们在此可以先声明一个空的矩阵
D3DXMATRIX* pOut =NULL;在函数运行完毕之后,我们进行监视,会发现其值发生了变化,我们就可以使用这个变换过的结构变量进行下面
的处理了,这是DX中很常见的一种设计模式。

然后我们来设置视图变换。

g_pD3DDevice->SetTransfrom(D3DTS_VIEW, &matView); //其中D3DTS_VIEW依旧是转换类型,后面matView是一个视图变换矩阵。
之后我们将视图变换完的顶点提取出来,根据其位置,法线位置,本身颜色,和材料材质来计算每个顶点上的光亮度,并将其颜色信息存
贮在顶点信息中。

在光照计算后,我们将进行投影变换,它将帮助我们去生成一个投影图,该图中我们将离摄象机远的物体成像进行缩小,使图具有纵深感
,依旧是g_pD3DDevice->SetTransfrom( D3DTS_PROJECTION,&matProj); //D3DTS_PROJECTION转换类型,matProj是一个投影变换矩


之后我们对一些不可见的点进行剪裁,在我们设置物体三角行图元顶点时,我们就需要很注意这一点,默认的时候D3D会将顶点顺时针排
列的三角型作为前向多边形,逆时针的做为后向多边形。我们可以跟着来确认该图元是否可见。

代码为g_pD3DDevice->SetRenderState( D3DRS_CULLMODE, Value); //参数为剪裁方式

此时我们的大致流程就差不多了,最后在定义屏幕显示区域(视口)的大小,通过它来将顶点从投影坐标系转换为最终显示的屏幕坐标。

在D3D中定义了视口结构为

typedef struct_D3DVIEWPORT9

{

DWORDX; //视口区域的左上角x坐标

DWORDY; //视口区域的左上角y坐标

DWORDWidth; //视口区域的宽度

DWORDHeight; //视口区域的高度

floatMinZ; //视口内景物的最小深度值,0-1.0之间,通常为0

floatMaxZ; //视口内景物的最大深度值,0-1.0之间,通常为1

} D3DVIEWPORT9;

我们通常使用SetViewport()函数来设置D3D视口。

HRESULT SetViewport

(

const D3DVIEWPORT9*pViewport //视口

);

呼,其他的明天再说了,累了>_<写这些东西那是相当费神的。。还有两天,继续努力00
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: