Z-Buffer
在threejs中,使用深度缓冲(Z-Buffer)来完成场景可见性计算,即确定场景哪部分可见,哪部分不可见。深度缓冲(Z-Buffer)是一个二维数组,其中的每一个元素对应屏幕上的一个像素,如果场景中的两个模型在同一个像素生成渲染结果,那么图形处理卡就会比较二者的深度,并且保留距离观察者较近的物体在该像素点的渲染结果,这样就形成了近的模型遮挡远的模型的结果。

上面说到,深度缓冲(Z-Buffer)是一个二维数组,但是数组的元素类型却可以不同,不同的元素类型代表着不同的精度。这和颜色的精度很像,比如GIF图像最多用8bit保存一个颜色,也即GIF最多支持256种色彩。以此类推,如果深度缓冲的也用8bit来保存一个像素的深度,那就是说该深度缓存只有256个深度级别。在threejs中只实现了一种深度缓冲,但是在例子中,又实现了一个精度更高的深度缓冲——logarithmicdepthbuffer,可以看示例webgl_camera_logarithmicdepthbuffer

Z-Fighting
当场景中的两个模型在同一个像素生成的渲染结果对应到一个相同的深度值时,渲染器就不知道该使用哪个模型的渲染结果了,或者说,不知道哪个面在前,哪个面在后,于是便开始“胡作非为”,这次让这个面在前面,下次让那个面在前面,于是模型的重叠部位便不停的闪烁起来。这便是Z-Fighting问题。

这里写图片描述

(图片来自:Three.js/WebGL: Large spheres appear broken at intersection)

解决 Z-Fighting
要解决Z-Fighting问题,有两个思路:

让各模型渲染结果不要在同一个像素出现相同深度值
人为设置渲染顺序,这样即使出现相同深度值,也能正确渲染
这里说一下第二种方法为什么也能解决Z-Fighting,比如有两个模型A和B,A的渲染顺序是0,B的渲染顺序是1,既是先渲染A,再渲染B,所以,如果A和B在某个地方出现了相同的深度值,那么后渲染的B会覆盖掉先渲染的A。下面是按照这两个思路提出的一些解决办法。

别让模型靠得那么近
手动设置一定的偏移即可让这个问题解决,比如下面两个例子:

刻度的z值为0,和尺子处于同一平面,会出现z-fighting问题,可以看到刻度文字不停闪烁

有z-fighting的例子

刻度得z值设置3,和尺子分处不同的平面,无z-fighting问题

无z-fighting的例子

设置合适的near和far值
在创建相机的时候,会有near和far两个参数,用来设置相机的近平面和远平面。这个两个参数其实和深度缓冲(Z-Buffer)也密切相关,深度缓冲其实是非线性的,靠近相机的地方精度更高。什么意思呢?假如你的深度缓冲只有10个深度级别,你的相机的near=1,far=100,那么你的深度缓冲可能是这样的:

深度级别 深度范围
0 0~1.0
1 1.0~1.1
3 1.1~1.234
4 1.234~1.325
5 1.325~1.55667
6 1.55667~1.9634
7 1.9634~5.434
8 5.434~23.34834
9 23.34834~99.999
(数据是杜撰的)

这样的非线性深度缓存可能会造成在离相机较远的地方深度等级的划分过于粗糙,比如上面的深度等级9,离相机的距离从23.34834到99.999的面都属于同一个深度级别,从上面可以,两个面对应到同一个深度级别就可能会出现z-fighting,所以,这个深度缓存出现z-fighting的概率还是挺大的。

一般来说,选择一个稍微大一点的near值效果会明显,比如把near从0.1设为1。

参考:【Z-Fighting】【Three.js/WebGL: Large spheres appear broken at intersection】

设置多边形偏移(polygon offset)
threejs 的 material 定义了三个多边形偏移相关的属性:

polygonOffset 是否开启多边形偏移
polygonOffsetFactor 多边形偏移因子
polygonOffsetUnits 多边形偏移单位
当发生两个面深度值相同时,设置了polygonOffset的面便会向前或向后偏移一小段距离,这样就能区分谁前谁后了。

当polygonOffsetFactor和 polygonOffsetUnits的都是正值时,向远离相机的方向偏移,当两者都是负值时,向靠近相机的地方偏移。

设置polygonOffsetFactor和 polygonOffsetUnits是有所讲究的:

当面和近平面(near)、远平面(far)几乎平行的时候,一个很小的偏移就足够,你可以设置polygonOffsetFactor=0, polygonOffsetUnits=1.0
当面和近平面(near)、远平面(far)有一个明显的角度时,这时候就需要一个较大的偏移和一个较小但非零的偏移因子。这是因为要分开两个交叉的面要比分开两个重合的面要更大的偏移。你可以设置如polygonOffsetFactor=0.75, polygonOffsetUnits=4.0
这部分内容很多都来自Z fighting & polygon offset,原文讲得更好点。

设置 render order
threejs的Object3D对象定义了一个renderOrder属性,可以指定对象的渲染顺序,按renderOrder从小到大排列,小的先渲染,大的后渲染。

设置完renderOrder之后,就算两个面有同样的深度,但是因为有渲染顺序,后渲染的面会覆盖掉先渲染的面。也因为这样,设置正确的渲染顺序很重要。

此外,这种方法更经常用在处理元素透明问题上,详见transparent-objects-in-threejs。

使用 logarithmicDepthBuffer 缓冲
缓冲的级别越多,冲突的概率相应的也就越低,所以,我们可以使用一个精度更高的z缓冲,来代替原有的Z缓冲。对于这个方法,threejs官网已经提供了一个例子webgl_camera_logarithmicdepthbuffer。不过,官网的例子为了演示效果,写得比较复杂,实际上只需要将logarithmicDepthBuffer参数设为true即可:

var renderer = new THREE.WebGLRenderer({ logarithmicDepthBuffer: true });
1
参考文档
1、解释如什么是z-fighting及何用polygon offset
Z fighting & polygon offset

2、讲到了near far 设置的问题
(1)Three.js/WebGL: Large spheres appear broken at intersection

(2)Z-Fighting

3、解释了 depth write的使用
How to use polygonOffset solving Z-fighting poblems

4、讲到了解决透明问题的方法,比较全面
Transparent objects in Threejs
原文访问https://www.cnblogs.com/lst619247/p/9098845.html

threeJs中镜头拉远导致物体闪烁相关推荐

  1. threejs摩尔纹镜头拉远模型贴图出现摩尔纹,纹理贴图闪烁异常解决办法

    threejs镜头拉远模型贴图出现摩尔纹,纹理贴图闪烁异常解决办法 当threejs加载模型时,会遇到有些模型的贴图有密集网格形状,当有密集四方格类,或者其他形状密集条纹类的贴图时,就会出现摩尔纹. ...

  2. threejs中坐标系转换和实现物体跟随鼠标移动

    坐标系转换 下面函数可以将鼠标所在点的屏幕坐标转化成一个Threejs三维坐标: convertTo3DCoordinate(clientX,clientY){var mv = new THREE.V ...

  3. 【Unity】ISO模式下地形Terrian细节丢失/镜头拉远就没细节了

    在ISO(正交)模式下会出现这种状况. 方案1:分辨率选项中,Low Resolution Aspect Radios去掉勾选,如下图: 方案2:另外,分辨率对地形的细节展示程度也有影响.越高越接近编 ...

  4. 射频拉远与光纤直放站有什么区别?

    第二代移动通信系统基站设备的典型设计方案是将接收天线.发射天线安装在室外,将射频收发信机安装在室内,射频收发信机与接收天线.发射天线间用低损耗的射频电缆连接.这就是所谓射频拉远技术.从第三代移动通信系 ...

  5. AVCapture中实现拉近拉远镜头

    自己用avcapture实现自定制相机,系统相机是可以拉近拉远镜头的,网上搜寻了半天始终没有发现,刚才又翻看了半天的api接口,终于找到了,原来他藏在AVCaptureConnection中,vide ...

  6. unity鼠标控制镜头旋转_unity3D鼠标滚轮来实现镜头拉近拉远及视角旋转

    镜头拉近拉远的代码(无限拉远拉近) 代码如下: if( Input.GetAxis("Mouse ScrollWheel") != 0 ) { this.gameObject.tr ...

  7. 航拍拉近拉远镜头_什么是远摄镜头?

    航拍拉近拉远镜头 Telephoto lenses can be incredibly useful, but how is it different from other lenses, and w ...

  8. unity3D实现镜头拉近拉远及视角旋转

    镜头拉近拉远的代码(无限拉远拉近) 代码如下: if( Input.GetAxis("Mouse ScrollWheel") != 0 ) { this.gameObject.tr ...

  9. iOS 镜头变焦,推近或者拉远焦距--ZOOM

    数码相机中,zoom就是缩放意思:也就是镜头变焦的意思,推近或者拉远焦距 /** 调节ZOOM */ - (IBAction)zoomChangeValue:(UISlider *)sender { ...

最新文章

  1. 大数据之“用户行为分析”
  2. 未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage”包 - - 博客频道 - CSDN.NET...
  3. Linux安装好php后找不到php.ini
  4. 51Nod 1043 幸运号码
  5. 计算机系统军训口号,霸气的军训口号大全
  6. 简约自适应APP下载页源码
  7. Jmeter安装教程
  8. 项目十大管理(三)进度管理
  9. python用lda主题_python下进行lda主题挖掘(二)——利用gensim训练LDA模型
  10. 晶体管放大电路与Multisim仿真学习笔记
  11. java opencv 基本操作4
  12. 蓝叠手机模拟器使用技巧
  13. springboot下载resource下的静态资源,下载excel文件损坏
  14. 手机屏幕坏了怎么把数据导出来_苹果手机的语音备忘录怎么导出来?
  15. 贷款计算器- 等额本金、等额本息工具类(Java版)
  16. Java中 9 种常见的 CMS GC 问题分析与解决
  17. 【阅读笔记】针对PyTorch提高神经网络训练速度的方法—《Here are 17 ways of making PyTorch training faster – what did I miss?》
  18. ae表达式修复_AE脚本-AE模板表达式错误修复脚本WINMAC
  19. 使用python爬取天气信息(包括历史天气数据)
  20. ggplot2添加散点图文字标记

热门文章

  1. Excel的VB编程
  2. TK教主:和玄武实验室有关的几个故事 | 人物志
  3. Go执行shell命令
  4. 用友U8案例教程应收管理前台操作
  5. SpringBoot整合SpringSession以及自定义CookieSerializer和RedisSerializer详解
  6. 普元EOS和BPS系统表表结构以及注释说明
  7. 焱融为国家电网打造存算一体的融合基础架构 助推能源行业新基建
  8. 使用免费组件view pdf 文档
  9. Waymo与极氪合作全电动、全自动驾驶出租车;拜耳安必神正式在华上市 | 能动...
  10. 第三方物流概念问题探讨