Unity趣味Shader系列之《3D涂鴉》
很多3D休閑益智類(lèi)游戲經(jīng)常的一個(gè)玩法就是涂鴉,用戶(hù)通過(guò)操作把顏色涂上去。我們還見(jiàn)過(guò)有些游戲,在雪地里面行走過(guò)后,留下了腳印,這些都可以用今天的的技術(shù)原理來(lái)解決,先來(lái)看下今天的效果:

要實(shí)現(xiàn)這個(gè)效果,其實(shí)不難,主要做好下面的幾個(gè)方面。接下來(lái)我們一起分析一下。
1: 3D涂鴉實(shí)現(xiàn)原理與思路
寫(xiě)代碼思路很重要,把思路搞明白了,才知道如何去做。涂鴉就是要實(shí)時(shí)的改變紋理貼圖的顏色,把觸摸過(guò)的位置對(duì)應(yīng)的紋理的顏色特定的顏色。涂鴉的時(shí)候,我們首先能獲取的觸摸坐標(biāo)(屏幕坐標(biāo)), 獲取觸摸坐標(biāo)以后,接下來(lái)就要計(jì)算出來(lái)我們觸摸坐標(biāo)對(duì)應(yīng)的模型上的3D模型坐標(biāo)點(diǎn)。接下來(lái)我們要把這個(gè)模型坐標(biāo)點(diǎn)對(duì)應(yīng)的紋理坐標(biāo)算出來(lái)。通過(guò)3D模型坐標(biāo),我們可以找出這個(gè)模型點(diǎn)所在的三角形的面,就可以知道這個(gè)三角形的面的3個(gè)頂點(diǎn)的模型坐標(biāo), 法線(xiàn)數(shù)據(jù),紋理坐標(biāo)等。我們通過(guò)插值就可以計(jì)算出來(lái)觸摸對(duì)應(yīng)的3D模型點(diǎn)的uv坐標(biāo)。uv坐標(biāo)確認(rèn)后,根據(jù)紋理的大小,我們就能確認(rèn)要涂鴉的紋理的位置。最后,我們以這個(gè)位置為中心,把涂上的顏色或貼圖數(shù)據(jù)寫(xiě)入到紋理內(nèi)存里面。把思路總結(jié)一下:
step1: 將觸摸坐標(biāo)轉(zhuǎn)成對(duì)應(yīng)的模型的3D坐標(biāo);
step2: 通過(guò)模型的3D坐標(biāo),計(jì)算出來(lái)這個(gè)點(diǎn)對(duì)應(yīng)的UV坐標(biāo);
step3: 將uv坐標(biāo)+紋理,得到紋理中的像素坐標(biāo),根據(jù)像素坐標(biāo)來(lái)改變顏色。
2: 如何通過(guò)觸摸獲取模型坐標(biāo)點(diǎn)
這個(gè)思路很簡(jiǎn)單,一般使用物理引擎的射線(xiàn)檢測(cè),從攝像機(jī)到屏幕觸摸位置,發(fā)射一條射線(xiàn),如果這個(gè)射線(xiàn)撞到了物體的表面的哪個(gè)點(diǎn),那么就得到了碰撞點(diǎn)的世界坐標(biāo),世界坐標(biāo)有了以后,再把世界坐標(biāo)通過(guò)坐標(biāo)系轉(zhuǎn)換,轉(zhuǎn)換到本地坐標(biāo)系中。這樣我們就獲得了觸摸點(diǎn)鎖對(duì)應(yīng)的模型坐標(biāo)。
3: 3D模型坐標(biāo)轉(zhuǎn)為紋理UV坐標(biāo)
這個(gè)過(guò)程是整個(gè)計(jì)算里面最復(fù)雜的,首先我們要根據(jù)3D模型坐標(biāo)點(diǎn),計(jì)算出來(lái)這個(gè)模型點(diǎn)所在的三角形的面。這樣我們就能獲得這個(gè)面對(duì)應(yīng)的3個(gè)頂點(diǎn)的頂點(diǎn)數(shù)據(jù)(坐標(biāo),紋理,法線(xiàn)等)。接下來(lái)我們要結(jié)合當(dāng)前游戲攝像機(jī),對(duì)這個(gè)面的3個(gè)頂點(diǎn)進(jìn)行投影變化,得到投影坐標(biāo),然后根據(jù)3個(gè)頂點(diǎn)的UV坐標(biāo),結(jié)合插值算法,計(jì)算出當(dāng)前模型點(diǎn)對(duì)應(yīng)的UV坐標(biāo)。UV坐標(biāo)出來(lái)以后,我們就可以結(jié)合紋理對(duì)象的大小,找到紋理中對(duì)應(yīng)的像素顏色,紋理的Width*U 就是紋理的x坐標(biāo), 紋理的Height*V就是紋理的y坐標(biāo),那么我們觸摸的中心點(diǎn),對(duì)應(yīng)紋理中的像素就是(x, y)。
4: 涂鴉顏色到目標(biāo)紋理
我們做涂鴉的時(shí)候,肯定不能是一個(gè)像素,一般我們得處理是以這個(gè)像素為中心,以一個(gè)合適的半徑,來(lái)做一個(gè)圓,把圓范圍內(nèi)的都涂成我們的目標(biāo)顏色。如何涂一個(gè)圓呢?算法其實(shí)很簡(jiǎn)單,假設(shè)半徑為R,那么我們遍歷以(x, y)為中心的上下左右[-R, R]的范圍的每個(gè)點(diǎn), 如果x^2 + y^2 <= R,我們就把這個(gè)點(diǎn)涂上顏色,否者我們就跳過(guò)。如果我們是要涂上一個(gè)小貼圖,比如行走在雪地中的腳印,我們就從(x -R, y -R)這個(gè)點(diǎn)開(kāi)始,把腳印的紋理數(shù)據(jù)copy到目標(biāo)紋理對(duì)象,這樣這個(gè)腳印就貼圖上去了。

好了,整個(gè)涂鴉的技術(shù)流程就給大家分析清楚了,需要源碼的同學(xué)可以加我們的老師來(lái)領(lǐng)取,注明"3D涂鴉源碼"。
附視頻教程 點(diǎn)擊可直接學(xué)習(xí)
Unity游戲開(kāi)發(fā)課程 / Shader專(zhuān)題進(jìn)階
趣味Shader系列: 3D涂鴉原理與實(shí)現(xiàn)
https://bycwedu.vipwan.cn/promotion_channels/2068059994
為視頻教程制作者Blake老師打CALL?