解决osg绘制场景时因Z冲突导致重影或闪烁等不正常情况
目录
1. 问题的提出
2. Z冲突(z-fighting)简介
2.1. Z冲突(z-fighting)产生的原因
2.2. 如何消除Z冲突(z-fighting)
3. 代码实现
1. 问题的提出
今天绘制了一个棋盘格,鼠标在棋盘格上单击,在单击点绘制一个红色的圆,但圆形始终不正常,圆的颜色有的地方有,有的地方没有,如下:

正常的情况下,应该向下面那样:

这个问题是由于OpenGL深度测试带来Z冲突(z-fighting)引起的。起始的绘制圆的代码如下:
// 画点。以小圆表示,其中参数pt表示鼠标单击时的世界坐标
void osgCardinal::drawEllipse(const osg::Vec3d& pt)
{auto pGeometry = new osg::Geometry;auto pVertArray = new osg::Vec3Array;_radius = 0.2;auto twoPi = 2 * 3.1415926;for (auto iAngle = 0.0; iAngle < twoPi; iAngle += 0.001){auto x = pt.x() + _radius * std::cosf(iAngle);auto y = pt.y() + _radius * std::sinf(iAngle);auto z = pt.z(); pVertArray->push_back(osg::Vec3d(x, y, z));}pGeometry->setVertexArray(pVertArray);auto pColorArray = new osg::Vec4Array;pColorArray->push_back(osg::Vec4d(1.0, 0.0, 0.0, 1.0));pGeometry->setColorArray(pColorArray/*, osg::Array::BIND_OVERALL*/);pGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);...... // 其它代码略
}
2. Z冲突(z-fighting)简介
2.1. Z冲突(z-fighting)产生的原因
为什么会产生z-fighting现象?
第一点原因:
场景中渲染多个三维物体的时候,当这多个三维物体摆放的位置很接近时,导致在深度缓冲测试的时候,会产生精度的误差,然后会导致几个物体之间的片段值在通过深度测试时,有时A物体通过,有时B物体通过,导致交替显示这几个物体的颜色值,然后那就会产生闪烁的现象,这种闪烁现象在场景旋转时,尤其明显。
第二点原因:
采用透视投影矩阵渲染的场景,其深度缓冲区存储深度值,ndc空间中也存储了深度值。而ndc空间的深度值是经由透视空间转换过来的,ndc空间的深度值与透视空间的深度值转换并非是线性的,而是非线性。大家都知到,透视空间转换到ndc空间会有一步透视除法,是除以z值。这样就会导致,离视点越近的物体的片段深度值是越精确的,离视点距离越远的物体的片段的深度值是越不精确的。这样就会导致z-fighting问题。
而采用正交透视矩阵渲染场景,其变换是线性的,为什么?因为其透视空间转换为ndc空间的时候采用的透视除法是除以1,所以其片段距离视点的深度值是线性的,这样除非你把两个物体设置的位置非常接近,否则是产生不了z-fighting这种现象的。
2.2. 如何消除Z冲突(z-fighting)
1.第一种方法
第一个也是最重要的技巧是永远不要把多个物体摆得太靠近,以至于它们的一些三角形会重叠。通过在两个物体之间设置一个用户无法注意到的偏移值,你可以完全避免这两个物体之间的深度冲突。在箱子和地板的例子中,我们可以将箱子沿着地板向上方向稍微移动一点。箱子位置的这点微小改变将不太可能被注意到,但它能够完全减少深度冲突的发生。然而,这需要对每个物体都手动调整,并且需要进行彻底的测试来保证场景中没有物体会产生深度冲突。
2.第二种方法
第二个技巧是尽可能将近平面设置远一些。在前面我们提到了精度在靠近近平面时是非常高的,所以如果我们将近平面远离观察者,我们将会对整个平截头体有着更大的精度。然而,将近平面设置太远将会导致近处的物体被裁剪掉,所以这通常需要实验和微调来决定最适合你的场景的近平面距离。
3.第三种方法
另外一个很好的技巧是牺牲一些性能,使用更高精度的深度缓冲。大部分深度缓冲的精度都是24位的,但现在大部分的显卡都支持32位的深度缓冲,这将会极大地提高精度。所以,牺牲掉一些性能,你就能获得更高精度的深度测试,减少深度冲突。
我们上面讨论的三个技术是最普遍也是很容易实现的抗深度冲突技术了。还有一些更复杂的技术,但它们依然不能完全消除深度冲突。深度冲突是一个常见的问题,但如果你组合使用了上面列举出来的技术,你可能不会再需要处理深度冲突了。
3. 代码实现
在1节代码中,加入消除Z冲突的代码如下:
// 画点。以小圆表示,其中参数pt表示鼠标单击时的世界坐标
void osgCardinal::drawEllipse(const osg::Vec3d& pt)
{auto pGeometry = new osg::Geometry;auto pVertArray = new osg::Vec3Array;auto pPgo = new osg::PolygonOffset();pPgo->setFactor(-1.0);pPgo->setUnits(-1.0);pGeometry->getOrCreateStateSet()->setAttributeAndModes(pPgo);_radius = 0.2;auto twoPi = 2 * 3.1415926;for (auto iAngle = 0.0; iAngle < twoPi; iAngle += 0.001){auto x = pt.x() + _radius * std::cosf(iAngle);auto y = pt.y() + _radius * std::sinf(iAngle);auto z = pt.z()/* + 0.001*/; pVertArray->push_back(osg::Vec3d(x, y, z));}pGeometry->setVertexArray(pVertArray);auto pColorArray = new osg::Vec4Array;pColorArray->push_back(osg::Vec4d(1.0, 0.0, 0.0, 1.0));pGeometry->setColorArray(pColorArray/*, osg::Array::BIND_OVERALL*/);pGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);...... // 其它代码略
}
上述代码通过构造osg::PolygonOffset对象,加入了多边形漂移,从而解决了Z冲突问题。osg::PolygonOffse类的功能封装了OPenGL中的glPolygonOffset函数,关于该函数的具体用法,参见如下链接:
- glPolygonOffset用法。
- OpenGL深度测试带来的问题----Z冲突 。
可以不用osg::PolygonOffset类,将16行代码的注释取消,即将z值加个微小的值,这个值自己可以进行微调,直到人眼觉察不到圆和棋盘格脱离且消除了1节中提到的现象为止。
相关文章:
解决osg绘制场景时因Z冲突导致重影或闪烁等不正常情况
目录 1. 问题的提出 2. Z冲突(z-fighting)简介 2.1. Z冲突(z-fighting)产生的原因 2.2. 如何消除Z冲突(z-fighting) 3. 代码实现 1. 问题的提出 今天绘制了一个棋盘格,鼠标在棋盘格上单击…...
adb 获取 Android 设备中已安装的 apk 文件
前言 今天发现手机上一个应用在应用商店已经搜索不到了,想把其推荐给朋友使用,发现不知道从哪里找原始的 apk 安装文件,记录一下。 如何提取 apk 两种方法 MT管理器导出 可以使用 MT管理器(Android 平台逆向神器),它有个 安装…...
学习记录683@类别不平衡问题解决的基本策略之再缩放的数学解释
什么是类别不平衡问题 分类学习方法都有一个共同的基本假设,即不同类别的训练样例数目相当。如果不同类别的训练样例数目稍有差别,通常影响不大,但若差别很大,则会对学习过程造成困扰。例如有998个反例,但正例只有2个…...
2023App测试必掌握的核心测试:UI、功能测试
一、UI测试 UI即User Interface (用户界面)的简称。UI 设计则是指对软件的人机交互、操作逻辑、界面美观的整体设计。好的UI设计不仅是让软件变得有个性有品味,还要让软件的操作变得舒适、简单、自由、充分体现软件的定位和特点。手机APP从启动界面开始, 到运行过程,直至退出,…...
华为荣耀手机,开启开发者选项,hbuilder调试依然找不到
我的手机是华为荣耀50,其他华为手机不知道是不是这个问题哦 解决办法:usb配置,选择音频来源 然后就可以了...
【C++】特殊类实现
一、请设计一个类,不能被拷贝 拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝, 只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 C98 将拷贝构造函数与赋值运算符重载只声明不定义…...
代码随想录打卡第四十四天|● 01 二维背包问题 ●一维背包问题-滚动数组 ● 416. 分割等和子集
什么是01背包 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。 01背包的模板 二维dp数组 dp数组的含义 dp[i][j]含义下标为【0-i】之间…...
燃气管网智能巡检系统
燃气管网维护工作繁杂,涉及人员、资源、巡检等,稍一疏忽就会使我们的工作陷入被动,可见启用燃气管网智能巡检系统是很有必要的。 燃气管网智能巡检系统综合管理智能平台,可对燃气管网数据的统一管理,实现对日常巡查、养…...
【微信小程序开发】运用WXS进行后台数据交互
🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于小程序的相关操作吧 一.wxs是什么 WXS是指"微信小程序云开发"(WeChat Mini Program Cloud Development),是由微信…...
屏幕录像推荐:Apeaksoft Screen Recorder 中文 for mac
Apeaksoft Screen Recorder 是一款功能强大的屏幕录制软件,它允许用户在 Windows 和 Mac 系统上捕捉和录制屏幕活动。无论是记录游戏过程、创建教学视频、制作演示文稿还是捕捉在线流媒体内容,该软件都提供了丰富的功能和工具。 以下是 Apeaksoft Scree…...
ALPHA开发板网络方案说明
一. 简介 正点原子 ALPHA开发板,包括我们移植的 Uboot,都是参考了 NXP(恩智浦)官方的开发板的。 I.MX6UL/ULL 内部有个以太网 MAC 外设,也就是 ENET ,需要外接一个 PHY 芯片来实现网络通信功能&#…...
[Ubuntu 20.04] HEIF图像格式与libheif库及其工具的使用
一、HEIF图像格式 HEIF 是一种高效的图像文件格式,它由 MPEG(Moving Picture Experts Group)组织制定。相较于传统的 JPEG 格式,HEIF 提供了更好的图像质量和更高的压缩率。下面是对 HEIF 格式的详细解析: 图像编码技术:HEIF 使用先进的编码技术来实现更高效的图像压缩。…...
AI驱动的未来:探索人工智能的无限潜力 | 开源专题 No.39
这一系列开源项目代表着多个领域的最新技术成果,包括深度学习、自然语言处理、计算机视觉和分布式训练。它们共同的特点是致力于教育、资源分享、开源精神、多领域应用以及性能和效率的追求,为广大开发者、研究者和学生提供了宝贵的工具和知识࿰…...
vs中C++编译未生成exe
1、新建空工程,添加main.h文件至“头文件”文件夹中,添加mian函数及实现 2、编译工程未有任何提示,不报错,不生成exe,无法执行 对比新建控制台程序发现.vcxproj文件中引用main.h文件为 无法生成: <I…...
Linux自有服务与软件包管理
服务是一些特定的进程,自有服务就是系统开机后就自动运行的一些进程,一旦客户发出请求,这些进程就自动为他们提供服务,windows系统中,把这些自动运行的进程,称为"服务" 举例:当我们使…...
Centos7中redis开机自启动设置
以下亲测实践有效。 进入以下目录 cd usr/local/redis/redis-6.2.6/utils/ 编辑修改以下文件内容 vim redis_init_script #修改redis安装启动目录 REDISPORT6379 #修改安装目录 EXEC/usr/local/redis/redis-6.2.6/src/redis-server CLIEXEC/usr/local/redis/redis-6.2.6/sr…...
STM32F4之系统滴答定时器
一、系统滴答定时器概述 传统定时器:如手机闹钟,闹钟等就是一个简单地计数器。 定时器概念:由时钟源计数器计数值组成的计数单元。 系统嘀嗒定时器首先是存在于内核里,系统嘀嗒时钟假如用的是同一个内核那么里面相关的配置&…...
P4 并发控制
文章目录 Task1 锁管理器LockTableUnLockTableLockRowUnLockRow Task2 死锁检测Task3 并发查询执行器Isolation Levelseq_scan_executorinsert_executordelete_executortransaction_manager Task1 锁管理器 LockManager类包含两个属性类,分别是LockRequest和LockRe…...
友元的介绍
实现外部类和外部函数存取类的私有成员和保护成员的方法。 一、友元函数 可访问类所有成员的外部函数 //求两点间的距离:抽象点——>求距离的函数 #include<iostream> #include<cmath> using namespace std; class Point{private:double x,y;publ…...
新手如何找到Docker容器(redis)中的持久化文件?
具体步骤 要查看Docker容器的dump.rdb和appendonly.aof文件(如果启用了AOF持久化)的位置,我们需要知道容器中Redis配置文件的内容或者容器的数据卷的挂载位置。 这里是一般步骤: 查找容器的数据卷挂载位置 使用docker inspect命令…...
AEUX终极指南:如何简单快速地将Figma和Sketch设计无缝转换为After Effects动画
AEUX终极指南:如何简单快速地将Figma和Sketch设计无缝转换为After Effects动画 【免费下载链接】AEUX Editable After Effects layers from Sketch artboards 项目地址: https://gitcode.com/gh_mirrors/ae/AEUX 还在为设计到动画的繁琐转换过程而烦恼吗&…...
DFM可制造性设计核心原则
DFM可制造性设计:定义、原则与应用实例 1. 定义与核心理念 可制造性设计,是一种将产品设计与其制造工艺深度融合的系统化工程方法。其核心目标是在产品设计阶段,就充分考虑并优化所有相关的制造、装配、测试和成本因素,以确保设…...
【5月会议征稿冲刺 | 5月会议抢先投递】2026年5月下旬优质科研投稿合集,EI会议、Scopus会议(2026年5月22-24日、2026年5月29-31日),精准投稿一键匹配,毕业刚需优先投递!
2026年5月下旬将迎来多场重要国际学术会议,涵盖人工智能、能源、工程等多个领域。5月22-24日,第三届人工智能与电力系统会议(杭州)、数据安全治理研讨会(新加坡)等7场会议同步举行;5月29-31日更…...
5分钟终极指南:使用res-downloader跨平台资源下载器轻松获取网络资源
5分钟终极指南:使用res-downloader跨平台资源下载器轻松获取网络资源 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader …...
别再死磕梯度下降了!用Python遗传算法搞定复杂函数极值,保姆级代码拆解
遗传算法实战:用Python突破传统优化方法的局限性 当面对复杂的优化问题时,工程师们常常会陷入梯度下降等传统方法的困境。想象一下这样的场景:你需要优化的函数像一座崎岖的山脉,有无数个峰谷,而且函数在某些点甚至不可…...
PowerPaint-V1新手入门:基于Gradio的极速图像修复,听得懂人话的AI修图神器
PowerPaint-V1新手入门:基于Gradio的极速图像修复,听得懂人话的AI修图神器 1. 为什么你需要PowerPaint-V1 想象一下这个场景:你刚拍了一张完美的风景照,却发现角落里有个不想要的垃圾桶;或者你找到一张老照片&#x…...
别再手动画湖了!用GEE和Sentinel-2数据,5分钟自动提取武汉东湖最新水域范围
5分钟自动化提取水域范围:基于GEE与Sentinel-2的高效水体识别方案 清晨的湖面泛着微光,水域边界随着季节更替悄然变化。传统的手动勾画方法不仅耗时费力,还难以捕捉这种动态变化。现在,借助Google Earth Engine(GEE&am…...
手把手教你理解ARM SoC中的PPU:电源管理IP的配置与实战避坑指南
手把手教你理解ARM SoC中的PPU:电源管理IP的配置与实战避坑指南 在低功耗SoC设计中,电源管理单元(PPU)扮演着至关重要的角色。作为连接系统控制器与设备电源状态的桥梁,PPU的配置直接影响着芯片的功耗表现和功能稳定性…...
工控主机在机器人应用中的常见问题及解决办法
今天阿强给大家分享下工控主机在机器人应用中的常见问题及解决办法。处理过无数个工控主机在机器人应用中的故障问题。很多时候,机器人出现故障并不是因为机器人本身的问题,而是因为工控主机出现了问题。下面我就给大家总结一下工控主机在机器人应用中的…...
免费CAD软件LitCAD:3分钟上手的轻量级绘图解决方案终极指南
免费CAD软件LitCAD:3分钟上手的轻量级绘图解决方案终极指南 【免费下载链接】LitCAD A very simple CAD developed by C#. 项目地址: https://gitcode.com/gh_mirrors/li/LitCAD 还在为高昂的CAD软件费用而烦恼吗?或者被复杂的设计工具搞得晕头转…...
