书法字典:https://www.shufadict.com

DirectX怪像之一,我的模型不见了

引言

对于刚刚编写DirectX程序的朋友来说,经常遇到的一个问题就是,风风火火写了一大堆代码,编译-运行!哇塞,窗口里黑乎乎一片,啥也没有,或者是之前运行好好的程序,不只修改了哪里,导致以前渲染的画面现在都没有了。我在学习的过程中也经常遇到这种问题,索性总结下来,与大家分享。希望能给刚入门的兄弟们一个提醒。

场景为何消失?

根据我自己的经验,如果渲染场景中某些东西不见了,一般有以下几个主要的原因

光照设置不正确

很简单,在一个伸手不见五指的黑夜里,你能指望看见什么呢?光照是D3D中必不可少的东西,用来计算顶点的最终颜色。但是并不是所有的顶点格式都需要光照,有些定点格式,如果设置了光照反而会导致模型无法显示,比如LT(Lit and Transformed)格式。我们来看看D3D中的光照原理。

  • 如果将光照设置为enable(通过D3DRS_LIGHTING=TRUE设置),那么系统会对所有法向量不为0的顶点进行光照计算,即使输入的顶点中包含颜色信息,也将被丢弃。
  • 如果将光照设置为disable,那么对于LT格式,将使用顶点自带的颜色信息,而对于其他类型的顶点,将没有光照计算,也就无法显示。
  • 创建并开启了depth buffer,但是并没有enable lighting,这个有待确定,目前上不知原因。

所以如果顶点是LT格式的,而且设置了光照为enable,那么模型也是无法显示的,因为LT格式的顶点不包含法向量,没有法向量是无法完成光照计算的。

视图矩阵设置不正确

这个也很简单,在一个阳光明媚的日子,一位绝色美女站在你旁边,可是你却背对着她!如何欣赏到她的美呢?有了光照,有了场景,可是如果场景不在你的视野内,你依然什么都看不见,比如模型绘制在X轴正半轴上,而视线却指向X轴负半轴。所以,正确的设置视图矩阵也是看见场景的重要因素。DirectX使用左手系,Z轴指向屏幕内部的方向为正,一般来说模型都绘制在坐标系的原点,而观察点也设置为原点,眼睛的位置只要设置成Z轴负半轴上的某个位置就可以了。下面就是一个典型的设置代码,也就是说,eyePt的z坐标一般都是负值,如果你一不小心将其设置为正值,那么屏幕上肯定会空无一物的。

D3DXVECTOR3 lookCenter(0.0f, 0.0f, 0.0f) ;
D3DXVECTOR3 upVec(
0.0f, 1.0f, 0.0f) ;
D3DXVECTOR3 eyePt(
0.0f, 0.0f, -20.0f) ;

剔除方式不正确

D3D默认的剔除方式是逆时针,也就是CULL_CCW,如果你的顶点是按照逆时针顺序定义的,而且使用了默认的剔除方式,那么肯定什么都看不见。所以一定要确保顶点定义的顺序和剔除顺序是相反的,也就是说,如果程序中定义了顺时针剔除,那么你的顶点就应该保持逆时针顺序。在D3D中可以指定如下三种剪裁方式:

D3DCULL_CW  顺时针

D3DCULL_CCW  逆时针

D3DCULL_NONE   不剪裁

如何诊断剪裁问题?

如果你怀疑程序可能是由于剪裁导致了错误,那么可以将剪裁方式指定为D3DCULL_NONE,并按照下面步骤诊断。

  • 问题不存在了,这说明是剔除方式不对,可以分别试试D3DCULL_CW和D3DCULL_CCW这两种方式。
  • 问题依旧,这说明不是剔除的问题,因为D3DCULL_NONE不进行任何剔除操作,所有的面都该显示。应该是其他原因引起的。

转换矩阵设置不正确

比如不小心将模型平移到了视野之外。如果有多个模型,要为每个模型单独设置world matrix,且这些world matrix之间不能互相影响。

启用了ZBuffer却没有清除ZBuffer

如果在创建Device的时候启用了ZBuffer,如下:

d3dpp_.EnableAutoDepthStencil = TRUE ;
d3dpp_.AutoDepthStencilFormat    = D3DFMT_D16 ;

那么在clear render target的时候一定要记得clear ZBuffer,如下:

d3ddevice_->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x4F94CD, 1.0f, 0);

如果是下面这样,那么将什么也看不见。

d3ddevice_->Clear(0, NULL, D3DCLEAR_TARGET, 0x4F94CD, 0.0f, 0);

注意,如果在创建Device的时候像上面那样指定了ZBuffer,那么就不用显示设置开启ZBuffer了。因为D3D会自动设置ZBuffer为开启状态,也就是下面的代码其实是多余的。

d3ddevice_->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);

模型颜色与窗口背景色一致

这也算是一个低级错误了,是在StackOverFlow上看到的一个问题,有一哥们将窗口背景设置为白色,输出的模型也是白色,结果,啥也看不见。

没有绘制内容

这个原因听起来很滑稽,不过不可否认的是,我曾多次犯了这个错误,程序中没有绘制任何东西!其实这个问题的原因往往是修改代码造成的,一开始程序的行为是正确的,但是后来为了修改某些功能为Render函数就行修改,可能会无意间注释掉某些内容,如果将绘制的代码注释掉,那肯定就什么也看不见了。

总结

当然,看不见模型的原因远不止这些,本文只是抛砖引玉,欢迎大家补充指正!

posted on 2012-05-02 08:49  翰墨小生  阅读(3596)  评论(0编辑  收藏  举报

导航

书法字典:https://www.shufadict.com