日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

threejs- z-fighting 问题

發(fā)布時(shí)間:2023/12/10 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 threejs- z-fighting 问题 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Z-Buffer

在threejs中,使用深度緩沖(Z-Buffer)來(lái)完成場(chǎng)景可見性計(jì)算,即確定場(chǎng)景哪部分可見,哪部分不可見。深度緩沖(Z-Buffer)是一個(gè)二維數(shù)組,其中的每一個(gè)元素對(duì)應(yīng)屏幕上的一個(gè)像素,如果場(chǎng)景中的兩個(gè)模型在同一個(gè)像素生成渲染結(jié)果,那么圖形處理卡就會(huì)比較二者的深度,并且保留距離觀察者較近的物體在該像素點(diǎn)的渲染結(jié)果,這樣就形成了近的模型遮擋遠(yuǎn)的模型的結(jié)果。

上面說(shuō)到,深度緩沖(Z-Buffer)是一個(gè)二維數(shù)組,但是數(shù)組的元素類型卻可以不同,不同的元素類型代表著不同的精度。這和顏色的精度很像,比如GIF圖像最多用8bit保存一個(gè)顏色,也即GIF最多支持256種色彩。以此類推,如果深度緩沖的也用8bit來(lái)保存一個(gè)像素的深度,那就是說(shuō)該深度緩存只有256個(gè)深度級(jí)別。在threejs中只實(shí)現(xiàn)了一種深度緩沖,但是在例子中,又實(shí)現(xiàn)了一個(gè)精度更高的深度緩沖——logarithmicdepthbuffer,可以看示例webgl_camera_logarithmicdepthbuffer

Z-Fighting

當(dāng)場(chǎng)景中的兩個(gè)模型在同一個(gè)像素生成的渲染結(jié)果對(duì)應(yīng)到一個(gè)相同的深度值時(shí),渲染器就不知道該使用哪個(gè)模型的渲染結(jié)果了,或者說(shuō),不知道哪個(gè)面在前,哪個(gè)面在后,于是便開始“胡作非為”,這次讓這個(gè)面在前面,下次讓那個(gè)面在前面,于是模型的重疊部位便不停的閃爍起來(lái)。這便是Z-Fighting問題。

(圖片來(lái)自:Three.js/WebGL: Large spheres appear broken at intersection)

解決 Z-Fighting

要解決Z-Fighting問題,有兩個(gè)思路:

  • 讓各模型渲染結(jié)果不要在同一個(gè)像素出現(xiàn)相同深度值
  • 人為設(shè)置渲染順序,這樣即使出現(xiàn)相同深度值,也能正確渲染

這里說(shuō)一下第二種方法為什么也能解決Z-Fighting,比如有兩個(gè)模型A和B,A的渲染順序是0,B的渲染順序是1,既是先渲染A,再渲染B,所以,如果A和B在某個(gè)地方出現(xiàn)了相同的深度值,那么后渲染的B會(huì)覆蓋掉先渲染的A。下面是按照這兩個(gè)思路提出的一些解決辦法。

別讓模型靠得那么近

手動(dòng)設(shè)置一定的偏移即可讓這個(gè)問題解決,比如下面兩個(gè)例子:

  • 刻度的z值為0,和尺子處于同一平面,會(huì)出現(xiàn)z-fighting問題,可以看到刻度文字不停閃爍

    有z-fighting的例子

  • 刻度得z值設(shè)置3,和尺子分處不同的平面,無(wú)z-fighting問題

    無(wú)z-fighting的例子

設(shè)置合適的near和far值

在創(chuàng)建相機(jī)的時(shí)候,會(huì)有near和far兩個(gè)參數(shù),用來(lái)設(shè)置相機(jī)的近平面和遠(yuǎn)平面。這個(gè)兩個(gè)參數(shù)其實(shí)和深度緩沖(Z-Buffer)也密切相關(guān),深度緩沖其實(shí)是非線性的,靠近相機(jī)的地方精度更高。什么意思呢?假如你的深度緩沖只有10個(gè)深度級(jí)別,你的相機(jī)的near=1,far=100,那么你的深度緩沖可能是這樣的:

深度級(jí)別深度范圍
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

(數(shù)據(jù)是杜撰的)

這樣的非線性深度緩存可能會(huì)造成在離相機(jī)較遠(yuǎn)的地方深度等級(jí)的劃分過于粗糙,比如上面的深度等級(jí)9,離相機(jī)的距離從23.34834到99.999的面都屬于同一個(gè)深度級(jí)別,從上面可以,兩個(gè)面對(duì)應(yīng)到同一個(gè)深度級(jí)別就可能會(huì)出現(xiàn)z-fighting,所以,這個(gè)深度緩存出現(xiàn)z-fighting的概率還是挺大的。

一般來(lái)說(shuō),選擇一個(gè)稍微大一點(diǎn)的near值效果會(huì)明顯,比如把near從0.1設(shè)為1。

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

設(shè)置多邊形偏移(polygon offset)

threejs 的 material 定義了三個(gè)多邊形偏移相關(guān)的屬性:

  • polygonOffset 是否開啟多邊形偏移
  • polygonOffsetFactor 多邊形偏移因子
  • polygonOffsetUnits 多邊形偏移單位

當(dāng)發(fā)生兩個(gè)面深度值相同時(shí),設(shè)置了polygonOffset的面便會(huì)向前或向后偏移一小段距離,這樣就能區(qū)分誰(shuí)前誰(shuí)后了。

當(dāng)polygonOffsetFactor和 polygonOffsetUnits的都是正值時(shí),向遠(yuǎn)離相機(jī)的方向偏移,當(dāng)兩者都是負(fù)值時(shí),向靠近相機(jī)的地方偏移。

設(shè)置polygonOffsetFactor和 polygonOffsetUnits是有所講究的:

  • 當(dāng)面和近平面(near)、遠(yuǎn)平面(far)幾乎平行的時(shí)候,一個(gè)很小的偏移就足夠,你可以設(shè)置polygonOffsetFactor=0, polygonOffsetUnits=1.0
  • 當(dāng)面和近平面(near)、遠(yuǎn)平面(far)有一個(gè)明顯的角度時(shí),這時(shí)候就需要一個(gè)較大的偏移和一個(gè)較小但非零的偏移因子。這是因?yàn)橐珠_兩個(gè)交叉的面要比分開兩個(gè)重合的面要更大的偏移。你可以設(shè)置如polygonOffsetFactor=0.75, polygonOffsetUnits=4.0

這部分內(nèi)容很多都來(lái)自Z fighting & polygon offset,原文講得更好點(diǎn)。

設(shè)置 render order

threejs的Object3D對(duì)象定義了一個(gè)renderOrder屬性,可以指定對(duì)象的渲染順序,按renderOrder從小到大排列,小的先渲染,大的后渲染。

設(shè)置完renderOrder之后,就算兩個(gè)面有同樣的深度,但是因?yàn)橛袖秩卷樞?#xff0c;后渲染的面會(huì)覆蓋掉先渲染的面。也因?yàn)檫@樣,設(shè)置正確的渲染順序很重要。

此外,這種方法更經(jīng)常用在處理元素透明問題上,詳見transparent-objects-in-threejs。

使用 logarithmicDepthBuffer 緩沖

緩沖的級(jí)別越多,沖突的概率相應(yīng)的也就越低,所以,我們可以使用一個(gè)精度更高的z緩沖,來(lái)代替原有的Z緩沖。對(duì)于這個(gè)方法,threejs官網(wǎng)已經(jīng)提供了一個(gè)例子webgl_camera_logarithmicdepthbuffer。不過,官網(wǎng)的例子為了演示效果,寫得比較復(fù)雜,實(shí)際上只需要將logarithmicDepthBuffer參數(shù)設(shè)為true即可:

var renderer = new THREE.WebGLRenderer({ logarithmicDepthBuffer: true });

參考文檔

1、解釋如什么是z-fighting及何用polygon offset
Z fighting & polygon offset

2、講到了near far 設(shè)置的問題
(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

總結(jié)

以上是生活随笔為你收集整理的threejs- z-fighting 问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。