酱坛子

专注C++技术 在这里写下自己的学习心得 感悟 和大家讨论 共同进步(欢迎批评!!!)

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  65 Posts :: 16 Stories :: 236 Comments :: 0 Trackbacks

公告

王一伟 湖南商学院毕业 电子信息工程专业

常用链接

留言簿(19)

我参与的团队

搜索

  •  

积分与排名

  • 积分 - 352861
  • 排名 - 53

最新随笔

最新评论

阅读排行榜

评论排行榜

        OpenGL,或者D3D 的深度缓存都存在精度问题,在最新的Nvidia GF8 系列显卡中已经开始应用float point depth buffer. 而在此之间,深度缓存其实只有位平面的概念. 这随API的不同,都需要指定后缓存深度缓存精度, Depth ,我一般使用24位,也就是D3D中常见的 D24S8. 但除非你是用浮点,否则都会有精度损失的问题,这种情况总是发生在2个几乎共面的片面,他们投影在后裁减平面时都会被赋予一个深度(当然,如果深度缓存可写的话),而上面已经说过,目前来说,深度只是位平面, 你可以把他假设为这样的形势

depth              w
0                  [near_clip,               near_clip + 0.1]
1                 [near_clip + 0.1,        near_clip +0.2]
2                 [near_clip + 0.3 ,        near_clip +0.4]
........
max             [far_clip - 0.1,                 far_clip]
上面假设硬件的最小深度单元 r = 0.1

那么将会出现这样的问题.
当2个片元距离近裁减平面 w  落在同一个区间的时候,他们的深度是相等的. 最终你所看到的结果,就是下面的这种样子:

注意到蓝色线框里面.


要解决这个问题, 你只要google 或者去 beyond3d,等论坛,搜索 depth fighting ,得到的答案往往就是设置深度偏移. OpenGL : Polygon offset. D3D: Depth Bais.
拿OpenGL 来说,就是对有存在深度冲突的2个 Mesh Object  A,B如下方式渲染.
A.Render();
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(
0.0f,-1.0f);
B.Render();
glDisable(GL_POLYGON_OFFSET_FILL);

这是一个不错的方法,但是实际操作起来很麻烦,而且没有效率. 注意到,你必须一先一后的渲染这2个对象, 拿上图来说,我需要在MAX 中把手套和手臂脱离,形成一个独立的节点,然后我起码需要新建立2个顶点缓存,并在渲染的过程中设置2次.这对于带宽是个不小的代价.所以我不是很赞成这样去处理,当然,有的时候无法避免了,也会如此..

       如果避免发生Z-Fighting 才是关键. 注意到上面的depth - w 的位平面对应关系. 由于硬件都只能支持一定的深度格式,也就是说,Depth bits 是一定的,假为 D.而顶点的投影深度则毫无限制,他可以是 near_clip ---> far_clip 的任意一个浮点数.因此
      dw/D = (far_clip - near_clip)/near_clip;
    从上面可以看出, 要想dw 更精确,那么 near_clip 必然要更大(适用范围是far_clip >> near_clip).
上面那张存在depth-fighting 的截图当时的情况是 near_clip :0.0001 far_clip : 64000.0
下面的是在near_clip 0.1 far_clip 不变.


继续提高定点投影深度,也不会出现难看的深度冲突了.
posted on 2009-03-27 11:31 @王一伟 阅读(3255) 评论(7)  编辑 收藏 引用

Feedback

# re: 最近做地图遇到Z-buffer精度问题 2009-03-27 11:35 @王一伟
找到一些英文资料
Depth Bias收藏

An application can help ensure that coplanar polygons are rendered properly by adding a bias to the z-values that the system uses when rendering the sets of coplanar polygons. To add a z-bias to a set of polygons, call the SetRenderState method just before rendering them, setting the State parameter to D3DRS_DEPTHBIAS, and the value parameter to a value between 0-16 inclusive. A higher z-bias value increases the likelihood that the polygons you render will be visible when displayed with other coplanar polygons.


Offset = m * D3DRS_SLOPESCALEDEPTHBIAS + D3DRS_DEPTHBIAS

where m is the maximum depth slope of the triangle being rendered.

m = max(abs(delta z / delta x), abs(delta z / delta y))

The units for the D3DRS_DEPTHBIAS and D3DRS_SLOPESCALEDEPTHBIAS render states depend on whether z-buffering or w-buffering is enabled. The application must provide suitable values.

The bias is not applied to any line and point primitive. However, this bias needs to be applied to triangles drawn in wireframe mode.

// RenderStates
D3DRS_SLOPESCALEDEPTHBIAS, // Defaults to zero
D3DRS_DEPTHBIAS, // Defaults to zero

// Caps
D3DPRASTERCAPS_DEPTHBIAS
D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS

  回复  更多评论
  

# re: 最近做地图遇到Z-buffer精度问题 2009-03-27 11:37 @王一伟
另外一篇 英文资料(转自 http://www.intel.com/cd/ids/developer/apac/zho/dc/games/optimization/170939.htm?page=4
使用Z-Bias解决Z-Fighting问题的替代方案
|
目录
Introduction
Alternative Method 1: Projection Matrix
Alternative Method 2: Viewport
Alternative Method 3: Depth Bias
Conclusion
Additional Resources

Alternative Method 3: Depth Bias

The last method addressed in this article uses the DirectX 9 Depth Bias method to solve z-fighting. A check to verify that the graphics card is capable of performing depth bias is needed. Intel Integrated Graphics will support depth bias in the next graphics core code named Grantsdale. After checking the cap bits to verify that depth bias is supported, this technique merely requires setting D3DRS_SLOPESCALEDEPTHBIAS and D3DRS_DEPTHBIAS to the proper values to get the desired effect.

The following code snippet shows the depth-bias alternative to using a DirectX z-bias call:

BOOL m_bDepthBiasCap; // TRUE, if device has DepthBias Caps

// Globals used for Depth Bias
float g_fSlopeScaleDepthBias = 1.0f;
float g_fDepthBias = -0.0005f;
float g_fDefaultDepthBias = 0.0f;

// Check for devices which support the new depth bias caps
if ((pCaps->RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS) &&
(pCaps->RasterCaps & D3DPRASTERCAPS_DEPTHBIAS))
{
m_bDepthBiasCap = true; // TRUE, if DepthBias Caps
}

// Billboards are rendered...

// DepthBias work around
if ( m_bDepthBiasCap ) // TRUE, if DepthBias supported
{
// Used to determine how much bias can be applied
// to co-planar primitives to reduce z fighting
// bias = (max * D3DRS_SLOPESCALEDEPTHBIAS) + D3DRS_DEPTHBIAS,
// where max is the maximum depth slope of the triangle being rendered.
m_pd3dDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(g_fSlopeScaleDepthBias));
m_pd3dDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(g_fDepthBias));
}

// Posters are rendered...

if ( m_bDepthBiasCap ) // TRUE, if DepthBias supported
{
// DepthBias work around
// set it back to zero (default)
m_pd3dDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(g_fDefaultDepthBias));
m_pd3dDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(g_fDefaultDepthBias));
}

. . .

Like the other methods (and like the original z-bias), some tweaking may be necessary, but using D3DRS_SLOPESCALEDEPTHBIAS and D3DRS_DEPTHBIAS is a relatively consistent technique for resolving z-fighting issues across a wide selection of graphics devices. The figure below shows the result of this alternate solution:


Figure 4. Z-fighting solved with depth bias solution.
As Figure 4 shows, care should be taken for adjusting the D3DRS_SLOPESCALEDEPTHBIAS and D3DRS_DEPTHBIAS. They can be very sensitive and lead to other issues like the problem below for distant objects:


Figure 5. Depth-bias solution possible issue: unwanted overlapping polygons.  回复  更多评论
  

# re: 最近做地图遇到Z-buffer精度问题[未登录] 2009-06-16 11:32 dd
dw/D = (far_clip - near_clip)/near_clip;
这个公式怎么得出来的?  回复  更多评论
  

# re: 最近做地图遇到Z-buffer精度问题[未登录] 2009-06-16 11:34 dd
(x,y,z,1) *
xScale 0 0 0
0 yScale 0 0
0 0 zf/(zf-zn) 1
0 0 -zn*zf/(zf-zn) 0
之后,z变为了z'
z' = zf*(z - zn)/(zf-zn)
怎么会是dw/D = (far_clip - near_clip)/near_clip?  回复  更多评论
  

# re: 最近做地图遇到Z-buffer精度问题 2009-09-05 21:44 hi
good  回复  更多评论
  

# re: 最近做地图遇到Z-buffer精度问题 2010-04-02 16:47 tsyat
这个东西好像没法用哦  回复  更多评论
  

# re: 最近做地图遇到Z-buffer精度问题 2011-03-28 20:35 David Lee
懒东西,最近怎么不跟新博客了?  回复  更多评论
  


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理