做营销看的网站有哪些内容,台州企业自助建站,建网站的手续,网站模板素材Z-Buffer
在threejs中#xff0c;使用深度缓冲#xff08;Z-Buffer#xff09;来完成场景可见性计算#xff0c;即确定场景哪部分可见#xff0c;哪部分不可见。深度缓冲#xff08;Z-Buffer#xff09;是一个二维数组#xff0c;其中的每一个元素对应屏幕上的一个像素…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和BA的渲染顺序是0B的渲染顺序是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个深度级别你的相机的near1far100那么你的深度缓冲可能是这样的
深度级别深度范围00~1.011.0~1.131.1~1.23441.234~1.32551.325~1.5566761.55667~1.963471.9634~5.43485.434~23.34834923.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几乎平行的时候一个很小的偏移就足够你可以设置polygonOffsetFactor0, polygonOffsetUnits1.0当面和近平面near、远平面far有一个明显的角度时这时候就需要一个较大的偏移和一个较小但非零的偏移因子。这是因为要分开两个交叉的面要比分开两个重合的面要更大的偏移。你可以设置如polygonOffsetFactor0.75, polygonOffsetUnits4.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 设置的问题 1Three.js/WebGL: Large spheres appear broken at intersection
2Z-Fighting
3、解释了 depth write的使用 How to use polygonOffset solving Z-fighting poblems
4、讲到了解决透明问题的方法比较全面 Transparent objects in Threejs