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中深度碰撞方法总结的更多相关文章

  1. DRF框架中链表数据通过ModelSerializer深度查询方法汇总

    DRF框架中链表数据通过ModelSerializer深度查询方法汇总 一.准备测试和理解准备 创建类 class Test1(models.Model): id = models.IntegerFi ...

  2. Day07_37_深度剖析集合中的contains()方法

    深度剖析集合中的 contains()方法 contains()方法查找集合中是否包含某个元素 contains() 底层使用的是 equals()方法 当contains()方法拿到一个对象的时候, ...

  3. WebGL中图片多级处理(FrameBuffer)

    在webgl的使用过程中,我们通常会想对texture进行多级处理并对其贴在表面显示 如对较精准的边缘检测,要先后使用灰度shader.模糊shader.边缘shader来进行处理,而每次的处理对象则 ...

  4. WebGL中的OpenGL着色器语言

    在webgl中,调用了OpenGL-ES-2.0的API,而在OpenGL-ES专为嵌入式设备设计,其和其它设备一样,都是使用GLSL(GL Shading Language)来编写片段程序并执行于G ...

  5. jquery中的clone()方法使用

    clone([Even[,deepEven]]) 描述: 克隆匹配的DOM元素并且选中这些克隆的副本. 在想把DOM文档中元素的副本添加到其他位置时这个函数非常有用. 1:一个布尔值(true 或者 ...

  6. jQuery中的$.extend方法总结

    原文见:jQuery.extend()函数详解 Jquery的扩展方法extend是我们在写插件的过程中常用的方法,但是经常容易搞不清楚以下两个写法的关系: 1.$.extend(dest,src1, ...

  7. ES6中Object.assign() 方法

    ES6中Object.assign() 方法 1. 对象合并Object.assign 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象上.如下代码演示: var targ ...

  8. Java 8 接口中的默认方法与静态方法

    Java 8 接口中的默认方法与静态方法 1. 接口中的默认方法 允许接口中包含具有具体实现的方法,该方法称"默认方法",默认方法使用用 default 关键字修饰. public ...

  9. Html5 中获取镜像图像 - 解决 WebGL 中纹理倒置问题

    Html5 中获取镜像图像 - 解决 WebGL 中纹理倒置问题 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致& ...

随机推荐

  1. 推荐一些C#相关的网站、资源和书籍 (转载自http://blog.csdn.net/chinacsharper/article/details/17514923)

    一.网站 1.http://msdn.microsoft.com/zh-CN/ 微软的官方网站,C#程序员必去的地方.那里有API开发文档,还有各种代码.资源下载. 2.http://social.m ...

  2. asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发3-登录模块开发

    进行本文之前需要在数据库用户表里面增加一条用户数据,直接手动添加即可,未安全考虑密码一定要使用Md5加密后的,这里提供666666的Md5密文为(c831b04de153469d),本文完成登录模块的 ...

  3. linux dll hell--链接库real name, soname, link name

    DLL hell 是指 Windows 系统上动态库的新版本覆盖旧版本,且新版本不能兼容旧版本的问题. 例如:装新软件,但原有的软件运行不起来了.   Linux 系统下也同样面临着和 Windows ...

  4. hive表批处理

    对hive中的表进行批量处理,如下是一个简单的脚本 #给定一个hive数据库名,生成它的所有表的create SQL语句,并导出到文件 create_fun(){ hive -e } #显示一个表中所 ...

  5. Laravel --- 查询字段中使用表达式

    比如: select id, name, count(post) from ... 在laravel中: $user = $this ->select( 'id', 'name', DB::ra ...

  6. 08 JS的事件流的概念(重点)

    在学习jQuery的事件之前,大家必须要对JS的事件有所了解.看下文 事件的概念 HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页面的滚动事件onscroll等等,可以 ...

  7. Google Earth Engine城市水体提取

    Google Earth Engine城市水体提取 大家都知道城市水体提取相比较于山区,丘陵的地区,肯定是比较难的,为什么呢,因为城市水体有很多高层建筑导致的阴影,这个就非常复杂了,而且现在很多高分影 ...

  8. vue路由传参query和params的区别(详解!)

    1.query使用path和name传参都可以,而params只能使用name传参. query传参: 页面: this.$router.push({ path:'/city',name:'City' ...

  9. C++标准库(体系结构与内核分析)(侯捷第一讲)

    一.C++标准库介绍 C++标准库:C++ Standard Library C++标准库与STL有什么关系: STL:Standard Template Library STL包含6大部件,基本占标 ...

  10. 【工具】java发送GET、POST请求

    前项目使用这种HTTP的方式进行数据交互,目前已更换数据交互方式,但是作为接口提供调用来说还是比较简洁高效的: 总体流程就是: 1.发送HTTP请求 2.获取返回的JSON对象 3.JSON转换 pa ...