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. 性别年龄的模块封装类 IDSGenderLeviNamedView

    1 IDSGenderLeviNamedView 的实现效果     2 类的封装方法:   IDSGenderLeviNamedView.h   @interface IDSGenderLeviNa ...

  2. 可以用变量指定大小的Bits对象实现

    c++的容器中有位对象bitset,但是个人认为最大的问题是定义是必须指定常数大小,比如 bitset<3> bit; 无法实现 int n = 3; bitset<n> bi ...

  3. jvm(4)---垃圾回收(哪些对象可以被回收)

    1.java堆中几乎放着所有对象的实例,那么什么样子的对象才是可以被回收的呢? 1.1.引用计数法: 给对象添加一个引用计数器,当有地方引用的时候,计数器就+1,引用失效就-1:任何时候当计数器为0, ...

  4. git push 时 failed to push some refs 的解决方案

    我们在利用 GIt 上传代码的时候,往往会遇到这样一个问题,导致我们的代码没有办法正常上传到仓库中 造成这个问题的原因其实很简单,就是因为远程仓库和本地库不一致. 基于这样的一个问题,解决办法自然也就 ...

  5. react 项目全家桶构件流程

    资源:create-react-app.react.react-dom.redux.react-redux.redux-thunk.react-router-dom.antd-mobile/antd. ...

  6. Excel导出打印失败报错 (eg HSSF instead of XSSF)

    错误信息: java.lang.RuntimeException: org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException: ...

  7. Flink中的状态与容错

    1.概述 Flink支持有状态计算,根据支持得不同状态类型,分别有Keyed State和Operator State.针对状态数据得持久化,Flink提供了Checkpoint机制处理:针对状态数据 ...

  8. NEST 6.X升级到7.X

    升级比对可访问 NEST 6.X升级到7.X 查看 ElasticClient-CreateIndex 升级前代码,NEST版本6.6.0 ICreateIndexResponse response ...

  9. Git使用小技巧之多个远程仓库

    想要获取更多文章可以访问我的博客 - 代码无止境. 这是一个普通的工作日,小代正在勤勤恳恳的写代码.这时陈BOSS走到小代身边,跟小代说:"我们的代码需要同时推送到Github和码云两个仓库 ...

  10. django基础知识之后台管理Admin站点:

    Admin站点 通过使用startproject创建的项目模版中,默认Admin被启用 1.创建管理员的用户名和密码 python manage.py createsuperuser 然后按提示填写用 ...