日本电影一区二区_日本va欧美va精品发布_日本黄h兄妹h动漫一区二区三区_日本欧美黄色

threejs-卡通輪廓效果(threejs模型輪廓發(fā)光)

在我的 3D 游戲和設(shè)計(jì)中,我經(jīng)常選擇可愛的低多邊形卡通風(fēng)格。我一直想給我的模型一個(gè)真正的卡通輪廓,所以這就是我們今天要做的工作。在以后的文章中,我們將著眼于為三角形著色以使其看起來也很卡通。

本文是「我正在進(jìn)行的中等難度 ThreeJS 教程系列」的一部分。我一直想要在介紹“如何繪制立方體”和“讓我們用瘋狂的著色器填充屏幕”關(guān)卡之間找到一些東西。所以就在這里。

如果你在網(wǎng)上搜索“OpenGL 輪廓效果”,你會(huì)遇到很多相互矛盾的信息。經(jīng)過大量研究,我確定有兩種常用方法可以使用現(xiàn)代 3D 圖形 API 創(chuàng)建輪廓。

  1. 繪制一個(gè)對(duì)象兩次;一次是輪廓顏色,一次是正常。
  2. 通過在像素級(jí)別檢測(cè)邊緣的后處理效果運(yùn)行整個(gè)場(chǎng)景。

第二種選擇是當(dāng)今 Unity 等現(xiàn)代游戲引擎中最常用的。但是我不想使用它,因?yàn)樗婕岸鄠€(gè)后處理步驟,這在移動(dòng) GPU 上可能很慢并且消耗更多內(nèi)存。此外,后處理和 WebVR 目前還沒有很好地融合,所以我暫時(shí)避免使用它。(當(dāng)我介紹發(fā)光效果時(shí),我們會(huì)重新討論這個(gè))。讓我們關(guān)注第一種方法,兩次繪制同一個(gè)對(duì)象。

兩次渲染一個(gè)對(duì)象可能看起來很浪費(fèi),但請(qǐng)記住,大多數(shù) GPU 都是帶寬有限的。一旦你把幾何圖形傳到 GPU 上,它就可以一遍又一遍地渲染同樣的東西,幾乎沒有成本。在大多數(shù)情況下,我想概述的東西是靜態(tài)幾何。

讓我們從兩次渲染圓環(huán)結(jié)開始,一次是黑色,一次是黃色。完成這項(xiàng)工作的這個(gè)技巧是縮放輪廓,使其比主要對(duì)象略大。

//create a cubeobj = new THREE.Group()const c1 = new THREE.Mesh( new THREE.TorusKnotBufferGeometry(0.6,0.1), new THREE.MeshLambertMaterial({ color:’black’, }))const s = 1.03c1.scale.set(s,s,s)obj.add(c1)obj.add(new THREE.Mesh( new THREE.TorusKnotBufferGeometry(0.6,0.1), new THREE.MeshPhongMaterial({ color:’yellow’, })))

運(yùn)行它,看看會(huì)發(fā)生什么。唔。根據(jù)您使用的幾何形狀,您將看到全黑或雙色調(diào)、部分黑色和部分黃色的東西。還注意到一些從黃色中突出的黑色三角形嗎?這就是所謂的z戰(zhàn)斗。那么問題是什么。

threejs-卡通輪廓效果(threejs模型輪廓發(fā)光)

實(shí)際上,這有點(diǎn)道理。黑結(jié)略微擴(kuò)大,因此在看不到黃色的地方,黑夜就在它的前面。那么我們?cè)撊绾谓鉀Q呢?

15 秒內(nèi)解釋剔除

我們將利用一個(gè)小技巧。

當(dāng) GPU 渲染三角形時(shí),它通常只渲染正面的三角形。這些是面向相機(jī)的三角形。根據(jù)定義,任何背對(duì)相機(jī)的三角形都是不可見的,因此無需費(fèi)心繪制它們。如果我們有一個(gè)球體,那么實(shí)際上只會(huì)繪制前半球。GPU 已「剔除」構(gòu)成背面半球的三角形。

對(duì)于輪廓效果,我們希望僅使用正面幾何圖形繪制常規(guī)對(duì)象。這已經(jīng)在發(fā)生。但是,對(duì)于輪廓,我們只希望繪制背面的三角形。然后它們將位于規(guī)則形狀的后面,僅在邊緣可見。

碰巧的是,ThreeJS 已經(jīng)知道如何繪制正面和背面。我們只需要告訴它我們想要什么。下面的代碼和上面一樣,只是side正確設(shè)置了兩種材質(zhì)的屬性。

obj = new THREE.Group()const c1 = new THREE.Mesh( new THREE.TorusKnotBufferGeometry(0.6,0.1), new THREE.MeshLambertMaterial({ color:’black’, side: THREE.BackSide }))const s = 1.03c1.scale.set(s,s,s)obj.add(c1)obj.add(new THREE.Mesh( new THREE.TorusKnotBufferGeometry(0.6,0.1), new THREE.MeshPhongMaterial({ color:’yellow’, side: THREE.FrontSide })))

現(xiàn)在看起來像這樣:

threejs-卡通輪廓效果(threejs模型輪廓發(fā)光)

image.png

完美的!

修復(fù)法線

實(shí)際上不,它不是很完美。如果你仔細(xì)觀察,你會(huì)發(fā)現(xiàn)物體背面的輪廓比正面的輪廓要細(xì)。那是因?yàn)槲覀冎皇窃诜糯笳麄€(gè)對(duì)象。這種幼稚的方法只適用于像球體這樣的完美凸面物體。對(duì)于結(jié)或任何真實(shí)模型,我們需要正確地加厚幾何圖形。

碰巧大多數(shù)幾何圖形上已經(jīng)有法線。這些法線垂直于幾何體的表面。如果我們?cè)诜ň€方向上擴(kuò)展點(diǎn),那么一切都應(yīng)該正常工作。我們可以通過稍微修改的頂點(diǎn)著色器來做到這一點(diǎn)。有關(guān)自定義頂點(diǎn)著色器的說明,請(qǐng)參閱其他文章。

//create a cubeconst mat = new THREE.MeshLambertMaterial({ color:’black’, side:THREE.BackSide })mat.onBeforeCompile = (shader) => { const token = ‘#include <begin_vertex>’ const customTransform = ` vec3 transformed = position objectNormal*0.02; ` shader.vertexShader = shader.vertexShader.replace(token,customTransform)}

上面的代碼為輪廓對(duì)象創(chuàng)建了一個(gè)自定義材質(zhì)。其余與之前相同。在著色器內(nèi)部,它objectNormal向每個(gè)頂點(diǎn)的位置添加一小部分,將其向外擴(kuò)展。將 更改0.02為更大的值以獲得更粗的輪廓。

現(xiàn)在看起來像這樣:

threejs-卡通輪廓效果(threejs模型輪廓發(fā)光)

image.png

壯麗的。您已經(jīng)創(chuàng)建了一個(gè)類似于卡通的輪廓。

相關(guān)新聞

聯(lián)系我們
聯(lián)系我們
公眾號(hào)
公眾號(hào)
在線咨詢
分享本頁(yè)
返回頂部
金山区| 阿图什市| 汾阳市| 辰溪县| 连山| 阳原县| 平邑县| 镇远县| 北宁市| 贡山| 祁门县| 扎鲁特旗| 英山县| 平潭县| 华蓥市| 新竹市| 阿鲁科尔沁旗| 怀集县| 县级市| 张掖市| 平安县| 佳木斯市| 博客| 通化市| 康平县| 抚顺市| 洛浦县| 体育| 乌海市| 东宁县| 金寨县| 樟树市| 阳信县| 济南市| 通山县| 策勒县| 澄城县| 石泉县| 堆龙德庆县| 迭部县| 织金县|