HRESULT SetClipPlane(
DWORD Index,
CONST float * pPlane
);
参数:
第一个是索引,不用说了。
第二个是存着 A B C D的数组。
这个数组最后会用来构建 Ax+By+Cz+Dw = 0;平面。
然后顶点会根据自已的位置(x,y,z,w)来进行判断。如果Ax+By+Cz+Dw >= 0。则表示在平面前方,保留。反之则在后方,被裁剪掉。
值得注意的时,在固定管线使用平面裁剪的时候,是在世界坐标系中处理的。
而用SHADER的时候,是在裁剪空间中处理的。(即顶点输出的时候的坐标系)
貌似还是太抽象。比如顶点输入坐标是pos 此时的坐标变换阵是WVP,则 Output.pos = mul(pos,WVP); 那么,此时的裁剪空间就是Output.pos对应的坐标系空间。
另外,默认情况下D3DRS_CLIPPLANEENABLE 是没有打开的,应该在SetRenderState中手工打开。
值得注意的是:D3DXPLANE进行矩阵变换的时候,要将需要乘的那个矩阵进行求逆和转置,再相乘。SDK中代码如下
上面的D3DXPLANE plane(0,1,1,0)如果你觉得不直观的话,DX提供了以下一些生成PLANE的函数
上面的PV1 PV2 PV3则是平面上的三个点。这个函数可以很容易地求得一个三角形所在的平面。
pPoint为平面上的一个点。 pNormal是平面的法线方向。
比如,你想创建一个水平平面,并且朝上。 则可以将pPoint传入0,0,0 而pNormal传入0,1,0即可。
附加一个讨论贴: http://topic.csdn.net/t/20040414/16/2964767.html
1.今天突然发现了这两个函数,看过了所有的remarks,好象这两个函数的功能就是根据当前设置的视锥体对所有被渲染的物体进行不可见物剔除。
既然D3D都提供了这样的功能,为什么还有这么多的人要去写什么场景管理器呢?
而且,D3D实现这个功能也许是直接在最底或者使用硬件什么的实现的,可能会比你手写的任何代码都要快,是这样吗?
很不明白中…………
2. 不是这样。你说的这两个函数是把整个场景都根据当前设置的视锥体对所有被渲染的物体进行不可见物剔除。这样的话有一些明显不需要计算的是否剔除的物体(比如在视点背后)都进行了是否剔除的计算,这样的计算是不必要的。
而场景管理器就是先把一些明显是要剔除的先计算出来,再交给D3D区剔除。
本人也是菜鸟,不知道对不对,请高手指教
3.我想大多数学习3D的人都是看重了这方面的技术有一定的含金量. 而不像写网页之类的IT高新技术那么... 场景管理可能是一个主要的技术指标, 大部分人遇到的第一个难题可能就是它了. 当然后面还有许多比如真实感, 动画, 物理模型之类的大类. 我想有些人虽然实现了场景管理, 但以后还对它进行修改, 扩展. 所以人们都喜欢写, 另外亲手做的话, 很多问题都会变的明朗化. 再说招聘的时候要求的技术条件都是要会场景管理的.
场景管理可以把物体或地形或多边形按空间顺序, 渲染状态顺序进行组织成树型结构. 我想D3D不会把场景组织成树型结构吧.
在遍历树型结构时,可以利用视锥(可以根据实际情况加视锥面)对树进行剪枝。这样有许多的根本不可能显示的物体,可能在树上面的几层就被剪掉了。
另外如果是树中有PORTAL或PVS的话, 实际上的树是一个图结构, 这样的话, 根本不用遍历整个树, 而只要找到CAMERA所在的结点, 然后按PORTAL这样的图结构中的边找到可能可见的部分, 当然其中的物体和PORTAL也要进行观察体可视检测. 这个实际上D3D可能更做不到了吧.
另外, 观察体(视锥)平面也是可以在3D中动态的增加, 减少的. 这一点的话D3D可能就更更不可能做到了吧?
4.ClipPlane是指除了视锥之外的、额外的裁剪面。关于场景管理的问题,需要知道:硬件再快,也需要和内存打交道。内存读写越多,硬件效率越差。场景管理的目的就是减少向图形硬件发送不必要的数据,减少内存的吞吐。GPU运算也需要时间,并不是硬件做就一定快。CPU和GPU协同、平衡处理才是最快的。
5.观察体(视锥)平面也是可以在3D中动态的增加, 减少的.
是什么意思?
6.室内PORTAL可能缩小观察体的范围. 这时就根据视点到PORTAL的各个边形成一个新的观察体.
室外的高大建筑可以遮挡观察体, 这时也可以增加平面, 缩小观察体的范围.
总结:视锥由6个平面组成,其中除了远近裁剪面之外还有其余上下左右四个面,上下左右四个面的裁剪由cpu计算,远近裁剪面定义的裁剪由gpu计算。 SetClipPlane定义的裁剪面也由gpu计算。
....SetClipPlane(0,...);
....SetClipPlane(1,...);
....SetClipPlane(2,...);
m_pd3dDevice-> SetRenderState( D3DRS_CLIPPLANEENABLE, D3DCLIPPLANE0 | D3DCLIPPLANE1 | D3DCLIPPLANE2);
RenderScene();
.....
pd3dDevice-> SetRenderState( D3DRS_CLIPPLANEENABLE, 0x00 );