D3D调试必看-小白PIX篇

本文分享了作者在学习D3D过程中,如何使用微软的PIX工具来辅助图形开发,包括PIX的使用场景、安装教程、基本操作以及如何通过PIX检查顶点、索引和常量缓冲区等问题。同时强调了CPU端设置对渲染效果的影响和学习D3D的实践建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

  • 本人小白,目前学习D3D一个多月,正在独立开发一款图像引擎,本博客主要记录D3D的学习心得和微软工具PIX的使用方法。

一、PIX的使用方法

(1)为什么使用PIX?

  • 如果你踏上了这条路,那么总有一天你会开发属于自己的图形引擎。想象当你的项目已经大致完成时,你迫不及待的按下了vs stdio的运行程序按钮,但回应你的确实一个“空荡荡”的窗口,它大概率要是全白、要么是全黑,这取决于你清空后台颜色缓冲区的值是什么。总之你大概率会遇到类似下面这样一个窗口:
    在这里插入图片描述
  • 试想你此时会想什么:
     1. 是着色器写错了? 会不会是顶点着色器中的MVP变换出错了? 还是片段着色器中的PBR光照模型计算错了? 又或者二者都有?
     2. 是常量缓冲区没有上传到GPU? 会不会是忘记初始化物体的矩阵值了? 还是摄像机的位置等信息有问题? 是不是摄像机的观察矩阵计算错了?
      …
  • 上述是图形开发中经常会遇到的难题,根本原因在于图形计算过程的隐蔽性,即我们只知道自己的代码调用了DrawIndexedInstanced,我们无法查询到Shader中的值,导致我们无法确认顶点、索引、常量缓冲区是否正确上传到GPU中,也无法确认GPU执行Shader代码时每个变量的值是多少。要是我们能像CPU端开发那样,直接查询GPU端的资源和变量情况就好了!
  • PIX是微软开发的一款辅助D3D进行图形开发的软件,它可以捕获程序的渲染帧信息,让我们查询到GPU端的资源和变量情况。有了PIX,我们可以直接核对顶点和索引、常量缓冲区、渲染管线状态等一系列信息,从根源排查渲染结果的成因。

(2)怎样使用PIX?

  1. 下载PIX,下载链接点这里,看不懂英文的小朋友请看下图:
在这里插入图片描述
 2. 我下载版本的PIX的大小约为170M。下载好后同意其条款,安装时的选项也只是统计你在大公司开发3A大作还是独立开发小游戏,因此随便一路点点点就可以完成安装了,这个软件貌似无法修改语言,安装好后可以在windows的开始菜单看到它,如下图所示:
在这里插入图片描述
  3. 由于一些原因,它需要你开启Windows的开发者模式,才能对帧进行捕获,下面介绍Win11打开开发者模式的方法:打开Windows开始菜单,再打开设置,在设置的搜索栏按下图搜索。
在这里插入图片描述
点击上图中搜索到的选项,就会看到下图的画面,将开发者模式打开即可。
在这里插入图片描述
 4. 打开PIX,一些基本操作信息如下图所示:
在这里插入图片描述
 5. 点击捕获帧的图片后,即可打开新的界面,查看捕获帧的详细信息,如下图所示:
在这里插入图片描述
 6. 点击右上角的运行按钮,成功运行后就可以查询更详细的GPU端信息,如下图所示:
在这里插入图片描述
 下面是一个常规顶点缓冲区的示例,如果你的界面中缺少了一些属性,比如你预设了纹理坐标却没有显示,说明你的顶点输入布局可能写错了,可以见检查一下纹理坐标的偏移值是否正确。如果你的界面顶点很少或者都为0,说明你的数据没有上传或者上传错误。后面我会介绍一些自己踩过的坑告诉大家。
在这里插入图片描述
 如果顶点缓冲区没有问题,那么可以见检查一下索引缓冲区中的索引数据是否正确,一个常规的索引缓冲区显示情况如下:
在这里插入图片描述
 如果以上二者都正确,那么可以点击CBV检查不同的常量缓冲区中的数据是否正确。如果最后都没问题了,可以点击Output查看渲染输出,我的渲染输出示例如下:
在这里插入图片描述
 由于我未处理模型的材质,因此请不要在意其颜色。再这个界面点击鼠标左键拖动鼠标即可围绕渲染物体渲染,点击鼠标右键拖动鼠标即可进行平移,滚动鼠标滚轮可以进行放大和缩小(即沿着摄像机观察方向移动)。
 本人才疏学浅,所以对PIX的介绍到此为止,可参考PIX官方文档Unity-轻松学会PIX。英文的东西国内很少人翻译,少有的PIX相关博客内容又太过高端,我在此呼吁大家在CG领域学了好东西不妨写一篇通俗的CSDN博客,发布时点个仅粉丝可见权当多交朋友,这样D3D和中国游戏的未来才会更加光明!

二、心得体会

  • 渲染效果没有达到预期不一定是GPU端的问题,可能CPU端对D3D应用程序的构建就不到位,比如根签名、命令列表、渲染状态等是否设置正确,这些虽然一般会有调试信息输出提醒错误,但是我们还是要注意。对于小白而言,多看看D3D龙书第四章的源代码,把D3D应用程序初始化烂熟于心。要想绘制自己想要的内容,那就要把第六章的源代码反复阅读,在自己开发程序达不到预期时看看正确的示例代码,想想:有什么是它做到了我还没做到的?带着这样的疑问去看源码,慢慢自己的水平就会提升,慢慢自己的项目也会查漏补缺起来。
  • 我之前是通过GAMES101和LearnOpenGL入门图形学的,我的项目也是如LearnOpenGL中使用Assimp库导入模型的。但导入模型并非易事!假设我们定义的顶点类型为Vertex,则Mesh的核心数据就是std::vector< Vertex >,可见不同Mesh的顶点数据是离散的,则模型Model的核心数据就是std::vector< Mesh >。对于D3D而言,我们可以将顶点整合到一块CPU内存中,然后创建缓冲区存储顶点数据,通过vector< T >.data()即可获取vector连续内存的首地址,但这里可能出错,比如以下函数:
void LoadModel(std::vector<Model>& res,std::wstirng modelFilePath)
{	
	Model model = Model::LoadModelFromFile(modelFilePath);	// 解析模型文件生成Model对象
	model.BuildVIView();			// 构建模型的顶点和索引描述
	res.push_back(model);			// 将模型压入要返回的模型数组
}
  • 上述代码可能导致你在PIX中的顶点缓冲区中看到全是0,因为如果model类中包含VIView类作为成员,而VIView包含void成员指向顶点数据的首地址,以便后续创建GPU缓冲区。则model.BuildVIView()就会将model的mesh的std::vector< Vertex >成员的data()赋值给void。而当res.push_back(model);执行时,如果没有特别处理,则类实例间仅进行简单的值赋值,则返回的res中的最后一个模型的void*指针是无效的,因为其值来源于局部变量model,而函数结束后model被释放。因此对于指针、vecctor,尤其是怎样将Model、Mesh对象存入vector,是很值得思考的问题,是先构建一个临时的Model?临时的变量只不过是数据传递的中间者而已,因此要头脑清晰的对很多问题进行思考分析才行。
  • 本人学疏才浅也无法帮大家解决问题,但有兴趣的可以加入QQ: DirectX交流群,一起学习和发展!
MagicTools引擎,包括3d场景,材质,d3d与opengles两个渲染器,max导出插件,集成了cocos2d作为ui。 引擎架构如下: 1.MtFoundation:底层数学库、字符串处理、操作系统和编译器宏定义等底层封装库。这些功能放在了MtFoundation.dll中,这个库可以以后单独提取出来提供其他项目使用。 2.MtKernel:提供资源管理器、文件系统、场景树管理。所以资源均提供引用计数、加载卸载计数、资源可以按组进行预加载。同一资源可以属于多个资源组,资源组在做rpg游戏切换房间的时候比较有用,可将一个房间的资源列表做一个组进行加载,若已存在的资源会增加其加载计数,而不用重新加载。 3.MtSceneQuery:场景查询模块。场景查询是一个相对独立的模块,可以替换掉。主要做一些算法的工作,比如射线查询、视锥剔除。把它独立处理就是希望这些cpu计算工作可以与渲染分离,便于放到一个独立的线程中。 4.MtGraphic:3d引擎模块,提供网格定义、材质定义,骨骼动画和蒙皮、贴图资源、渲染设备封装等。此处对渲染设备功能做了抽象,将具体渲染调用放到了d3d9renderer和glesrenderer中去。这里的材质在d3d下直接使用d3dxeffect,并使用宏控制编译。gles下使用固定管线控制。 d3d环境下定义了自己的材质和材质模板格式,材质模板主要用于定义effect中可用的宏,这些宏的可选取值,effect代码本身等。材质文件则引用材质模板文件,并定义宏的取值,还有uniform参数值。图形模块提供effect的uniform参数与场景中光源和物体本身材质参数的绑定。 gles环境下定了一个简单的脚本,控制固定功能渲染中的diffuse、specular和第一层纹理的参数 自定义了模型网格、骨骼、动画、材质、渲染实体等文件格式,这些文件格式说明放在了fileformats目录下。 渲染实体(Model)定义了网格与材质的组合关系,目前一个子网格只能有一个材质,但能扩展成一个子网格绑定多个材质。这样可以方便制作材质的过渡效果。 5.MtGraphic2d:这个模块是将cocos2dx0.99.4的底层替换成自己封装的渲染器实现的。cocos2dx原本是使用opengles1.0作为渲染api,在windows系统下使用powervr的模拟器运行。现在可以在d3d下或是opengles下运行。并将其更新流程合并到MtGraphic中,使得cocos2d可以正常的渲染在3d场景的前方。cocos2d的大部分功能已测试完成。可以在d3d下正常运行。 6.MtEngine:对上面几个模块的统一封装,这里负责动态的加载上面的几个模块,这里可以选择使用d3d还是gles进行渲染。还提供了建议场景逻辑控制,支持加载一个xml定义的场景脚本文件。直接使用EgnObject(EngineObject的简写)对场景模型进行控制可以省去操作底层场景树和模型材质创建的流程。 7.sampler:测试项目,用于测试上述功能。加载一个xml场景(里面全是茶壶。。。等编辑器出来就可以摆场景了),cocos2d界面渲染。鼠标键盘的输入控制。(wasd控制移动、鼠标控制方向) 材质文件说明: efm(effect material):d3d专用,里面会引用mtpl(material template)文件。 mtpl:材质模板文件,里面定义可选的宏和可选取值,还有d3dxeffect的代码。 ffm(fixed function material):d3d和gles通用,固定渲染管线材质。gles下只能用这个。 工程里带的导出插件目前只能导出网格,材质需要自己动手配置.(材质的编辑打算放到编辑器里做,然后在编辑器中绑定网格和材质,这也是cryengine和《古域》的做法,这样可以保证编辑的材质和游戏最终运行时的效果一样。)编译max导出插件需要max2010的sdk,安装插件后就可以导出单个模型。一次导出一个模型,做好一个mesh后选择max的export菜单,然后选择导出成“MtEngine Mesh File”(*.mmesh)就可以。 写了这么最后解释下为啥做这个东西吧。之前在做了两年多ogre引擎的开发,ogre确实很牛x,它的代码风格、封装程度、还有大量的算法工具都很不错,降低了3d开发的门槛,在用过的引擎中它门槛是最低的,说明他的封装做的好,但其内部结构过于复杂,不适合做灵活的修改。比如一个entity只能给一个材质,材质缺乏层的概念,不利于叠加临时效果。渲染与场景管理的代码结合得太紧,不能分离。比如没渲染一次场景都得做一次renderable排序加一次八叉树遍历,一帧里的多次渲染按理这些流程应该有所优化,但ogre
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仰望—星空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值