Z - Fighting 和 Depth-bias

本文探讨了OpenGL和D3D中的深度缓存精度问题及其对Z-Fighting的影响。介绍了如何通过调整near_clip参数和使用深度偏移来解决深度冲突问题。

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

 Depth-bias操作在clipping之后进行实施,所以depth-bias对几何clipping没有影响。

另外需要注意的是:对一个给定体元(primitive),bias值是一个常量,在进行差值操作之前,它施加在每个顶点上。

偏移操作都是32位浮点运算,还有Bias不能施加在点以及线体元上(除了线框模式的线段)。

 

***************************************************************************************************************

 

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 不变.


继续提高定点投影深度,也不会出现难看的深度冲突了.

转自:http://www.cppblog.com/sunraiing9/archive/2009/03/27/78018.html

计算机图形学综合实验报告 烟台大学 计算机学院 软件工程专业 班 级: 计103-3 学 号: 201058503334 姓 名: 公茂华 指导教师: 孔繁茹 完成日期: 2012.11.10 综合试验:太阳系模型 1. 实验目的与要求 1、学习掌握OpenGL的使用 2、掌握矩阵堆栈的实现方法 3、根据自己的创意实现实验内容,进一步掌握理解OpenGL的使用 2. 实验内容 1、请编写地球围绕太阳自动旋转的方式 2、请再加上一个月亮, 并围绕地球旋转,并添加轨道 3、实现用户通过键盘或鼠标加入或减少行星卫星 3. 实验结果 1. 开始运行 2. 增加地球月亮(按键L或l)或其他任意行星及其若干卫星 3. 按照提示用鼠标键盘增加或减少行星卫星 转换视角: 4. 异常提示:要将Color.txt文件放到当前文件夹下 4. 体会 通过本次试验的实践,使我更加了解初步掌握了OpenGL的用法,对使用OpenGl 绘制球体等图形有了充分认识,并对平移矩阵堆栈旋转矩阵堆栈的使用有了初步的 掌握。虽然以前没有接触过OpenGl,但是通过学习计算机图形学这门课程的知识,以 及通过多次上机实验,已使我对OpenGL有了一定了解,不过具体使用其它方面还需 要进一步理解学习。最后,感谢老师的悉心指导。 5. 源程序 注:红色注释为新加 #include <windows.h> #include <gl/glut.h> #include <stdlib.h> #include <stdio.h> #include <math.h> static float fE = 0.0f; //绕太阳或行星旋转的角度 static int i=0, j=0, m; //for循环计数 static GLint x=7, y=3; //转换视角,以太阳为中心 static int a[8]; //计数第几颗行星的卫星的数量 static bool lag = false; //键盘L(l)增加行星的标志,true为增加 int k[8][3]; //读取文件数据 FILE *fp; void Initial() { glEnable(GL_DEPTH_TEST); //启用深度测试 glClearColor(0.0, 0.0, 0.0, 0.0);//设置背景颜色 } void Change(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h);//设置视区尺寸 glMatrixMode(GL_PROJECTION); //指定当前操作投影矩阵堆栈 glLoadIdentity(); //重置投影矩阵 GLfloat fAspect; fAspect = (float)w/(float)h; gluPerspective(45, fAspect, 1.0, 600.0);//设置透视投影矩阵 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void Satellite() //增加卫星 { for (int n=0; n< a[i]; n++) { glPushMatrix(); glRotatef(30.0f+6*n, 0.0f, 0.0f, 1.0f); //绕z轴旋转30度 glRotatef(fE*10*(3*n+1), 0.0f, 1.0f, 0.0f); //公转速度fE*10*(3*n+1) glTranslated(-5.0f*m, 1.0f, 0.0f); glColor3f(256.0f, 256.0f, 0.0f); glutWireSphere(1.0f, 20, 20); //卫星 glColor3f(0.0f, 0.0f, 0.0f); glPopMatrix(); } } void Planet() //增加行星 { if (lag==true) //键盘L(l)增加行星 i=j-1; else i=0; for (;i<j;i++) { if (i<5) { if (i==3) m=1.9;//模拟火星 else m=i+1; } else m=9-i; glPushMatrix(); //保存当前的模型视图矩阵 glColor3f(0,0,9); glutWireTorus(20.0f*(i+1), 0, 100, 1); //轨道 glRotatef(fE*(9-i), 0.0f, 1.0f, 0.0f); //绕y轴旋转一定的角度 glTranslated(20.0f*(i+1), 0.0f, 0.0f); //平移一段距离 glColor3f(k[i][0], k[i][1], k[i][2]
### VTK 中解决 Z-Fighting 的技术方案 在计算机图形学中,Z-Fighting 是一种由于两个或多个人工几何体共享几乎相同的深度值而导致的视觉伪影现象。这种问题通常发生在 OpenGL 渲染过程中,而 VTK(Visualization Toolkit)作为基于 OpenGL 的可视化库同样会遇到此类问题。 #### 一、Z-Fighting 的成因 当两个多边形非常接近或者完全重叠时,在深度缓冲区计算的过程中可能会因为浮点精度不足导致错误的结果。这使得某些像素可能交替属于不同的多边形,从而形成闪烁或条纹状的现象[^1]。 #### 二、VTK 中防止 Z-Fighting 的方法 ##### 方法一:调整模型位置偏移 (Polygon Offset) 通过设置 `vtkActor` 或者 `vtkProperty` 提供的功能,可以应用一个多边形偏移量来人为地改变绘制顺序以及最终存储到深度缓存中的数值。具体来说: - 使用 `SetOffsetFactor()` `SetOffsetUnits()` 来定义偏移参数。 - 这些函数允许指定一个比例因子单位偏移量,用于影响距离相机较远的对象被稍微向远离观察者的方向移动。 以下是实现该功能的一个简单例子: ```cpp actor->GetProperty()->SetOffsetFactor(-0.5); actor->GetProperty()->SetOffsetUnits(1); ``` 这种方法适用于场景中有意设计好的前后关系明确的情况,并且能够有效减少大多数情况下发生的 Z-Fighting 效果。 ##### 方法二:增加深度缓冲精度 如果硬件支持更高位数的深度缓冲,则可以通过配置窗口系统属性提高其分辨率。例如,在初始化渲染窗口时请求具有更大范围或更精细分级能力的 depth buffer 设置。然而需要注意的是,实际可用选项取决于所使用的显卡驱动程序及其特性支持情况[^2]。 对于 VTK 用户而言,默认已经采用了适合大部分现代 GPU 架构的最佳实践设定;但如果确实存在特殊需求,也可以尝试自定义这些参数以获得更好的表现效果。 ##### 方法三:利用双面光照模式分离正面背面处理逻辑 另一种策略涉及分别对待物体表面朝向摄像机一侧与其他部分的数据流路径区别对待。即开启双侧材质渲染的同时赋予它们略微差异化的 z 值增量规则。这样即使两层材料紧贴在一起也不会轻易引发冲突状况发生。 此操作可通过如下方式完成: ```cpp property->BackfaceCullingOff(); // 关闭背面剔除以便看到背后的内容 // 对于背面对应的额外 offset 调整可进一步细化控制行为特征... ``` 上述代码片段展示了关闭背面剔除的操作步骤之一,后续还可以结合前面提到过的 polygon offsets 技巧共同作用达到理想状态下的消除干扰目标[^3]。 --- ### 总结 综上所述,针对 VTK 平台上的 Z-Fighting 处理提供了三种主要的技术手段——分别是运用 Polygon Offsets 实现精确微调、借助增强型 Depth Buffers 改善基础架构质量水平还有最后依靠独立管理正反两面绘图流程规避潜在风险隐患。每种办法各有优劣之处需依据项目具体情况灵活选用最为合适的解决方案组合形式加以应对挑战。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值