z-fighting问题是三维渲染中常见的问题,本文根据实际工作中遇到的一些场景,进行了系统的总结

一个实际工作中的问题

当两个面离得太近就会发生深度碰撞问题,比如:

遇到深度检测问题,最重要的是先搞明白是哪两个面离得太近导致的问题。比如上面这个问题,一直以来我都以为是柱子的面跟底图基础底面的问题。所以尝试了各种解决深度检测的问题都没起作用。

直到后面一次偶然的尝试,开启了CULL_FACE后,这个深度碰撞正常了。思考了很久才想到原来它发生深度碰撞的原因不是跟地图底面,而是柱子的上顶面跟下顶面离得太近发生的碰撞。恍然大悟!

这张图的表现很有欺骗性,底面是黑色的,而刚好碰撞部分也是一部分蓝,一部分发暗,所以很让人想当然的认为是底图跟柱子之间的问题。这个原因是因为默认没有面剔除,导致底面也被绘制了,而底面的法线方向与光线方向夹角很大,导致最后计算的颜色发暗。所以碰撞部分一部分明亮,一部分发暗。

换个了底图样式,仍然是这种结果,可以证明上述原因。

最终这个问题的解决方式是,开启CULL_FACE,剔除背面三角形,同时在着色中为顶点增加一点偏移

let parameters = {
[GL.DEPTH_TEST]: true,
[GL.CULL_FACE]: true,
[GL.CULL_FACE_MODE]: GL.FRONT
};
// 计算cube该顶点的位置, cube的X坐标范围是-1~1,(rotatedPosition.x * coverage + 1.0) / 2.0坐标范围在0~1之间
// cube的Z坐标范围是-1~1,(rotatedPosition.z * coverage - 1.0) / 2.0坐标范围在-1~0之间
// cubeTopLeftPosition在cube局部坐标系的(-1, 0, -1)位置
vec4 vertexPosition = cubeTopLeftPosition + vec4(
vec2(
(rotatedPosition.x * coverage + 1.0) / 2.0 * useRadius,
(rotatedPosition.z * coverage - 1.0) / 2.0 * useRadius
),
1.0, 1.0
);

深度检测根本原因

由于z-buffer的精度并不是线性相关的,而是在靠近near平面是精度非常大,但是靠近远平面时精度非常低,所如果平面离着相机非常远,那么就很可能出现深度检测问题。

解决方法

1.      首先搞明白是哪两个面发生的深度碰撞

2.      数据层面永远不要把两个物体靠的太近,最好在用户不太注意的地方稍微加一点偏移

3.      将near设置的大一些,这样使得场景中的物体都在高精度范围内,但这种方式也是需要调整,near设置的太大,会导致一些应当在视野范围内的物体被裁切掉

4.      在着色器中适当增加一个小的偏移

5.      利用depthRange来调整深度缓冲范围

6.      修改投影矩阵的第十位,增加一个小的偏移(http://note.youdao.com/noteshare?id=43a15cadb1afebb1b4ad24a4c159d1e0&sub=37ECF8DF031440D99B69D9CE60850F8A

最新文章

  1. JAVA之IO流(字符流)
  2. 第9章 Java类的三大特性之一:继承
  3. 51nod1228 序列求和(自然数幂和)
  4. tomcat 7/8 启动非常慢的解决方法
  5. HTML5基础知识(3)--required属性
  6. SQL的主键和外键
  7. navicat的简单应用
  8. DNS笔记 DNS区域集成到 Active Directory
  9. Android为ListView的Item设置不同的布局
  10. linux下修改ip地址,默认网关以及DNS
  11. Elasticsearch安装ik中文分词插件(四)
  12. 解决CentOS7中文乱码(包括Tomcat日志乱码)问题
  13. 爬虫实战:爬虫之 web 自动化终极杀手 ( 上)
  14. composer安装。
  15. Ubuntu 18.04 下 Redis 环境搭建
  16. Mysql 5.7 安装 解压缩版 忘记密码
  17. JavaScript中函数的继承
  18. SQL Server2005/2008 作业执行失败的解决办法
  19. Sqlserver的Transaction做Rollback的时候要小心(转载)
  20. 项目管理心经——正确的使用Microsoft Project

热门文章

  1. Python print不换行输出的替代方法
  2. 深入理解JVM(一)虚拟机内存
  3. 高并发 Nginx+Lua OpenResty系列(4)——Lua 模块开发
  4. 解决wireshark打开错误
  5. 在vuejs 中使用axios不能获取属性data的解决方法
  6. spring boot 2.0 thymeleaf调试时正常,打包后运行报错. 找不到模板文件.
  7. .netcore Control调用View方法
  8. 项目中遇到的Redis缓存问题
  9. 使用Minikube部署本地Kubernetes集群(二十八)
  10. while循环的初始以及编码的初始