WebGL中深度碰撞方法总结
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)
WebGL中深度碰撞方法总结的更多相关文章
- DRF框架中链表数据通过ModelSerializer深度查询方法汇总
DRF框架中链表数据通过ModelSerializer深度查询方法汇总 一.准备测试和理解准备 创建类 class Test1(models.Model): id = models.IntegerFi ...
- Day07_37_深度剖析集合中的contains()方法
深度剖析集合中的 contains()方法 contains()方法查找集合中是否包含某个元素 contains() 底层使用的是 equals()方法 当contains()方法拿到一个对象的时候, ...
- WebGL中图片多级处理(FrameBuffer)
在webgl的使用过程中,我们通常会想对texture进行多级处理并对其贴在表面显示 如对较精准的边缘检测,要先后使用灰度shader.模糊shader.边缘shader来进行处理,而每次的处理对象则 ...
- WebGL中的OpenGL着色器语言
在webgl中,调用了OpenGL-ES-2.0的API,而在OpenGL-ES专为嵌入式设备设计,其和其它设备一样,都是使用GLSL(GL Shading Language)来编写片段程序并执行于G ...
- jquery中的clone()方法使用
clone([Even[,deepEven]]) 描述: 克隆匹配的DOM元素并且选中这些克隆的副本. 在想把DOM文档中元素的副本添加到其他位置时这个函数非常有用. 1:一个布尔值(true 或者 ...
- jQuery中的$.extend方法总结
原文见:jQuery.extend()函数详解 Jquery的扩展方法extend是我们在写插件的过程中常用的方法,但是经常容易搞不清楚以下两个写法的关系: 1.$.extend(dest,src1, ...
- ES6中Object.assign() 方法
ES6中Object.assign() 方法 1. 对象合并Object.assign 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象上.如下代码演示: var targ ...
- Java 8 接口中的默认方法与静态方法
Java 8 接口中的默认方法与静态方法 1. 接口中的默认方法 允许接口中包含具有具体实现的方法,该方法称"默认方法",默认方法使用用 default 关键字修饰. public ...
- Html5 中获取镜像图像 - 解决 WebGL 中纹理倒置问题
Html5 中获取镜像图像 - 解决 WebGL 中纹理倒置问题 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致& ...
随机推荐
- hadoop之hive集合数据类型
除了string,boolean,date等基本数据类型之外,hive还支持三种高级数据类型: 1.ARRAY ARRAY类型是由一系列相同数据类型的元素组成,这些元素可以通过下标来访问.比如有一个A ...
- Python连载11-Python中os.path模块简介
一.os.path(和路径相关的木块) 1.函数:abspath() (1)含义:将路径转化为绝对路径的形式(absolute path) (2)格式:os.path.abspath(相对路径) (3 ...
- RSA der加密 p12解密以及配合AES使用详解
在前面的文章中我有说过AES和RSA这两种加密方式,正好在前段时间再项目中有使用到,在这里再把这两种加密方式综合在一起写一下,具体到他们的使用,以及RSA各种加密文件的生成. 一: RSA各种加密相关 ...
- element-ui源码之组件通信那些事
最近在用element-ui重构前端项目,无意之中翻阅到一个比较好用的组件间通信方式,借助于vue的封装的发布-订阅消息模式与mixin语法.在开始之前先总结下vue常用的组件间通信方式,具体如下: ...
- 01 Javascript简介(了解)
Web前端有三层: HTML:从语义的角度,描述页面结构 CSS:从审美的角度,描述样式(美化页面) JavaScript:从交互的角度,描述行为(提升用户体验) JavaScript历史背景介绍 布 ...
- 【Go】使用压缩文件优化io (一)
原文连接:https://blog.thinkeridea.com/201906/go/compress_file_io_optimization1.html 最近遇到一个日志备份 io 过高的问题, ...
- Hexo+NexT(二):Hexo站点配置详解
阅读本篇之前,假定读者已经有了Node.js的基础,如需要补充Node.js知识的,请自行百度. Hexo是在Node.js框架下的一个项目,利用Node.js提供的强大功能,完成从Markdown到 ...
- 移动IM开发指南3:如何优化登录模块
<移动IM开发指南>系列文章将会介绍一个IM APP的方方面面,包括技术选型.登陆优化等.此外,本文作者会结合他在网易云信多年iOS IM SDK开发的经验,深度分析实际开发中的各种常见问 ...
- c# 自己实现可迭代的容器
在c#中我们经常使用到foreach语句来遍历容器,如数组,List,为什么使用foreach语句能够遍历一个这些容器呢,首先的一个前提是这些容器都实现了IEnumerable接口,通过IEnumer ...
- Python 爬虫从入门到进阶之路(十二)
之前的文章我们介绍了 re 模块和 lxml 模块来做爬虫,本章我们再来看一个 bs4 模块来做爬虫. 和 lxml 一样,Beautiful Soup 也是一个HTML/XML的解析器,主要的功能也 ...