threejs- z-fighting 问题

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值

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

深度级别深度范围
00~1.0
11.0~1.1
31.1~1.234
41.234~1.325
51.325~1.55667
61.55667~1.9634
71.9634~5.434
85.434~23.34834
923.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的面便会向前或向后偏移一小段距离,这样就能区分谁前谁后了。

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

设置polygonOffsetFactorpolygonOffsetUnits是有所讲究的:

  • 当面和近平面(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、解释如什么是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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429903.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python2中文字符串遍历乱码_完美解决Python2操作中文名文件乱码的问题

Python2默认是不支持中文的,一般我们在程序的开头加上#-*-coding:utf-8-*-来解决这个问题,但是在我用open()方法打开文件时,中文名字却显示成了乱码。我先给大家说说Python中的编码问题,Python中的字符串的大概分为为str和Unicode…

bower overrides 配置

bower 是一个常用的包管理工具,用起来和npm很相似,但是两者又有一些区别,可以参考 —— What is the difference between Bower and npm。这里不说bower本身,而想说一下bower的overrides配置。 何谓override override 本身是覆盖…

装mysql最后一步没响应_解决MySQL安装到最后一步未响应的三种方法

这种情况一般是你以前安装过MySQL数据库服务项被占用了。解决方法:方法一:安装MySQL的时候在这一步时它默认的服务名是“MySQL” 只需要把这个名字改了就可以了。可以把默认的服务器的名称手动改为你没用过的其他名称。方法二:1、卸载MySQL …

windows下搭建Vagrant+Virtualbox环境

对于开发人员来说,Vagrant就是一个提供标准化开发环境的工具。通过Vagrant: 使每个开发人员电脑上的代码运行环境一致,再也不会出现“在我电脑上运行起来明明没有问题的”这样的开发环境不一致的问题。你可以使用Vagrant在windows下提供linu…

php注释规范

注释在写代码的过程中非常重要,好的注释能让你的代码读起来更轻松,在写代码的时候一定要注意注释的规范。 php里面常见的几种注释方式: 1.文件头的注释,介绍文件名,功能以及作者版本号等信息 /** *文件名简单介绍 * …

aix oracle监听配置_AIX系统中安装ORACLE,客户端连接时,监听会宕掉的问题

一次做实验,在AIX5300-06系统中安装ORACLE10.2.0.1数据库,安装过程都正常,在服务器上不加实例名连接时也很正常,可是客户端一连接,监听就会宕掉。故障现象如下:LSNRCTL> statusConnecting to…

Jenkins主从节点配置

jenkins支持主从模式,这将会把构建任务分发到多个从节点去执行,这样就可以支撑起多个项目的大量构建任务,同时,你可以提供多种环境(如:开发环境、生产环境)来对同一个项目进行测试和构建。想要进…

mac brew 安装php扩展报错:parent directory is world writable but not sticky

$ brew install php70-mcrypt 报错: Error: parent directory is world writable but not sticky 搜索到github的答案 https://github.com/Homebrew/legacy-homebrew/issues/40345 原因:/tmp目录权限不对 $ ls -ld /private/tmp 打印出来 /private/tmp 被…

HTML5 响应式图片

现在上网设备越来越多,各种设备的屏幕千差万别,如果只用一张图片去涵盖所有的设备,一是可能会造成某些设备上显示效果不佳,比如使用了一张低清晰度的图,而网页运行在一个高清大屏里;二是可能会浪费带宽&…

python股票网格交易法详解_干货 | 浅谈网格交易法

原标题:干货 | 浅谈网格交易法网格交易法的基本原理就是把行情的所有日间上下的波动全部囊括,它不会放过任何一次的行情上下波动。不管市场价格如何上下波动,不外3种形态:上涨,盘整,下跌。由于不同的操作方…

SVN代码回滚命令之---svn up ./ -r 版本号---OK

一、改动还没被提交的情况(未commit) 这种情况下,见有的人的做法是删除work copy中文件,然后重新update,恩,这种做法达到了目的,但不优雅,因为这种事没必要麻烦服务端。 其实一个命令…

threejs坐标转换

屏幕坐标转three.js坐标 将屏幕坐标转变成threejs空间坐标: function transToThreeCoord(x,y){let mouse new THREE.Vector3();mouse.x (x/window.innerWidth)*2 -1;mouse.y -(y/window.innerHeight)*2 1;return mouse; }注意:在实际使用中&#x…

每天一个linux命令(24):Linux文件类型与扩展名

Linux文件类型和Linux文件的文件名所代表的意义是两个不同的概念。我们通过一般应用程序而创建的比如file.txt、file.tar.gz ,这些文件虽然要用不同的程序来打开,但放在Linux文件类型中衡量的话,大多是常规文件(也被称为普通文件&…

android socket 发送byte_如何正确地创建和销毁网络通讯程序中的Socket类的对象实例...

软件项目实训及课程设计指导——如何正确地创建和销毁软件应用系统中网络通讯中的Socket类的对象实例1、基于TCP/IP协议的Socket通信相关的基础知识(1)TCP/IP(Transmission Control Protocol传输控制协议/Internet Protocol网间协议)TCP/IP是目前Internet网络中的主要协议&…

H5 使用微信开放标签跳转小程序

微信开放标签是微信公众平台面向网页开发者提供的扩展标签集合,可以在网页上提供跳转小程序、打开 App 等能力。本文梳理使用微信开放标签跳转小程序的过程,以备日后查阅。 参考链接 1. 开放标签说明文档 准备已认证的服务号 开放标签只能绑定已认证…

【网络流24题】No.7 试题库问题 (最大流,二分图多重匹配)

【题意】 假设一个试题库中有 n 道试题。 每道试题都标明了所属类别。 同一道题可能有多个类别属性。现要从题库中抽取 m 道题组成试卷。并要求试卷包含指定类型的试题。 试设计一个满足要求的组卷算法。 输入文件示例input.txt3 153 3 42 1 21 31 31 31 33 1 2 32 2 32 1 31 2…

css3 transform matrix 深入理解

矩阵可以用来表示图形的变换。css3定义了matrix和matrix3d方法,用来表示2维和3维的变换。下文将分析这两个接口的使用方法,并且用下文的思路,实现了一个简单的用js控制css3变换的jquery插件css3js , 变换矩阵和净变换矩阵 matri…

php给留言分配id_简单实现PHP留言板功能

本文实例为大家分享了PHP留言板功能的具体实现代码,供大家参考,具体内容如下HTML代码PHP留言本留言者: {$vo.nickname}|邮箱: {$vo.email}时间: {$vo.replytime}内容: {$vo.content}{$vo.id}楼留言重置function clearDefaultText(){var nickname docume…

所有选择器

*            $("*")          所有元素 #id            $("#lastname")       id"lastname" 的元素 .class           $(".intro")…

随机数公式生成一个负数和正数之间的数_java产生从负数到正数范围的随机数方法...

第四步 完整代码至于调用方法嘛:写个test测试下;(这个方法不好代码看起来很乱,你也可以实例化,然后另写一个test调用)复制代码注意包名需要改成代码所在的包名,我的包名是求平均数package 求平均数;import java.util.A…