溫馨提示:本文只是一篇入門聊天,不涉及代碼教程,看不懂代碼就跳過(guò),沒(méi)關(guān)系!
一、什么是uv
1、uv其實(shí)就是一個(gè)二維坐標(biāo)系啊,就倆軸,就跟xy軸一樣。
那為什么不叫xy,反而叫uv呢?
不知道,應(yīng)該是為了跟空間坐標(biāo)系xyz區(qū)別開(kāi)來(lái),以免在工作流程中產(chǎn)生誤解吧吧吧。
2、uv坐標(biāo)用于采樣貼圖,然后把它映射到模型表面。
圖是網(wǎng)上找的,如果侵權(quán)了我立馬刪對(duì)不起對(duì)不起對(duì)不起
3、類比xOy直角坐標(biāo)系,在unity shader中,uv坐標(biāo)原點(diǎn)也是在左下角(0,0)的位置的。
注意,不同的shader體系,它們?cè)O(shè)定的原點(diǎn)坐標(biāo)是不一樣的,比如dirctX的原點(diǎn)就在左上角。
用這個(gè)uv貼圖比較方便觀察。記得再ps里轉(zhuǎn)化成.tga格式再使用)
4、uv坐標(biāo)的原始范圍都是[0,1]。
二、uv變換
1、為什么是uv變換?
???為什么是uv變換,而不是貼圖變換呢?
因?yàn)椋?strong>貼圖是不會(huì)變換的!
uv采樣本質(zhì)上就是用一個(gè)橫向范圍[0,1]和縱向范圍[0,1]的直角坐標(biāo)系去采樣一張圖,然后映射到模型表面上。Shader著色器通過(guò)各種花里胡哨的運(yùn)算改變uv坐標(biāo),從而改變采樣范圍(內(nèi)容),從而使我們看到貼圖變形。
嗯……就好像我們拿望遠(yuǎn)鏡觀察星空,星星(貼圖)當(dāng)晚不會(huì)變,只有我們移動(dòng)望遠(yuǎn)鏡(uv坐標(biāo)),我們看到的星星才會(huì)不同。
甚至,我們還可以在望遠(yuǎn)鏡上裝哈哈鏡(shader),這樣看到的星星也會(huì)不同。
或者,你可以想象你坐在火車上,窗外的風(fēng)景就是貼圖,窗就是uv坐標(biāo)。風(fēng)景不會(huì)跑,只有咱們的窗戶在跟著車平移。
2、加減(平移)
舉例,uv + (0.1, 0.1)
i.uv += float2(0.1, 0.1);
看起來(lái)貼圖向左下角偏移了。
(會(huì)不會(huì)有同學(xué)沒(méi)反應(yīng)過(guò)來(lái),為什么不是偏移一整格呢?因?yàn)檫@圖是8×8格的所以要+0.125才能偏移一整格哈哈哈)
為什么呢?
一開(kāi)始,原點(diǎn)(0,0)采樣的是H1左下角明黃色的點(diǎn)
Uv坐標(biāo)經(jīng)過(guò)加減變換之后,原點(diǎn)(0,0)變成了(0.1, 0.1),坐標(biāo)軸整體向右上角移動(dòng)了,此時(shí)采樣的點(diǎn)是H1接近右上角的明黃色的點(diǎn).
以此類推別的坐標(biāo)點(diǎn)(可以參考上面的坐標(biāo)軸偏移示意圖)
得到的采樣結(jié)果就是這樣啦。
所以,其實(shí)不是貼圖向左下角偏移了,而是坐標(biāo)向右上角偏移了。
嗯呃呃呃有一點(diǎn)相對(duì)論地拗口。
注意,貼圖是循環(huán)平鋪的。也就是說(shuō),原本邊緣處(1, 1)的坐標(biāo)點(diǎn),經(jīng)過(guò)加減變換之后變成了(1.1, 1.1),超出了貼圖大于0小于1的坐標(biāo)范圍,但是,由于貼圖是循環(huán)的,所以(1, 1)–加0.1→(1.1, 1.1)處采樣的點(diǎn)與(0.1, 0.1)處采樣的點(diǎn)是一致的!
但如果我把wrap mode網(wǎng)絡(luò)循環(huán)模式從默認(rèn)的Repeat循環(huán)改為Clamp鉗制(超出范圍的顏色,則與邊緣顏色保持一致,將范圍鉗制在[0, 1]之間),那么,(1, 1)–加0.1→(1.1, 1.1)處采樣的顏色就與(1, 1)處的顏色是一致的。而且(0.9, 0.9)–加0.1→(1, 1),同樣也采了(1, 1)處的顏色。
同理,如果uv - (0.1, 0.1),就是將整個(gè)坐標(biāo)軸向左下角移動(dòng),那么采樣的范圍就會(huì)向左下角偏移,采樣的結(jié)果看起來(lái)就是貼圖向右上角移動(dòng)了。
嘿嘿。
2、乘除(縮放)
坐標(biāo)軸乘以2。
i.uv *= float2(2, 2);
貼圖以坐標(biāo)原點(diǎn)(0,0)為中心縮小了2倍
啊…看得我自己都快眼花了……
然后,還是用剛才相對(duì)的思想去分析。
貼圖是永遠(yuǎn)不會(huì)變的!只有坐標(biāo)軸變大了兩倍。uv坐標(biāo)的范圍變成了[0,2],貼圖的范圍是[0,1],由于貼圖是循環(huán)平鋪的,在[0,2]里就能出現(xiàn)兩次[0,1],在22的坐標(biāo)系里,就可以出現(xiàn)4個(gè)11,也就是4張貼圖。
就這樣,看起來(lái),貼圖縮小了!
同理,坐標(biāo)軸除以2,貼圖放大2倍
Unity內(nèi)置了變換函數(shù)TRANSFORM_TEX,用于計(jì)算uv變換。在參數(shù)面板調(diào)整_MainTex_ST的tilling數(shù)值,結(jié)果也是如此
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
tilling值越大,就縮小;值越小,就變大。
3、 加減和乘除【待訂正】
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
Unity內(nèi)置的變換函數(shù)TRANSFORM_TEX等價(jià)于
fixed2 uv = i.uv * fixed2(_ScaleX, _ScaleY) - fixed2(_OffsetX, _OffsetY); // **先縮放,后移動(dòng)**
half4 var_MainTex = tex2D(_MainTex, uv);
為什么是先縮放后移動(dòng)?
【↓ 我暫時(shí)講不清楚這部分,留個(gè)坑,以后填 ↓】
因?yàn)轫數(shù)鬃儞Q的底層數(shù)學(xué)邏輯 總是 以最原始的原點(diǎn)(0, 0)為操作錨點(diǎn)的。如果先移動(dòng),再縮放,就會(huì)變成這樣…
o.uv = v.uv + float2(0.5, 0.5);
o.uv *= sin(_Time.y) * 0.5 + 1;
用更玄學(xué)的話講,就是,矩陣相乘不滿足交換律…
【↑ 以后一定填嗚嗚 ↑】
Q:如果想讓貼圖以(0.8, 0.7)為中心放大3倍,公式怎么寫?
我們用一個(gè)新的10*10棋盤格貼圖,紅點(diǎn)就是目標(biāo)中心。
A:o.uv = v.uv / 3 + float2(0.8, 0.7) * (3-1)/3 ;
三、搞點(diǎn)事情吧——uv動(dòng)畫
1、基礎(chǔ)動(dòng)畫
最基礎(chǔ)的,就是用全局變量_Time時(shí)間單改變其中一個(gè)數(shù)值,讓貼圖動(dòng)起來(lái)。
我們舉例,改變offset偏移量。
i.uv += float2(_Time.x, 0);
動(dòng)起來(lái)啦!就像坐在火車上看風(fēng)景的比喻一樣。
題外話,為什么是_Time.x捏?其實(shí)_Time有xyzw的,x是每秒+0.05,y是每秒+1,z是每秒+2,w是每秒+3。在這就不一一給大家截gif啦,親自去試試吧很好玩的。
另外,為了防止因時(shí)間過(guò)長(zhǎng)導(dǎo)致數(shù)據(jù)溢出,我們一般會(huì)給_Time取余。
i.uv += float2(frac(_Time.x), 0);
用函數(shù)frac()和運(yùn)算符%都可以。
i.uv += float2(_Time.x % 1, 0);
如果我改變的是縱向的v軸呢,再換一張貼圖呢?
看!是瀑布?是河流?
2、幀動(dòng)畫
幀動(dòng)畫的制作思路就是把uv坐標(biāo)縮小,再移動(dòng)到貼圖中的第一幀,然后用floor向上取整實(shí)現(xiàn)逐幀“跳動(dòng)”。
那豈不是一個(gè)材質(zhì)只能播放一個(gè)動(dòng)畫了?
No,你也可以再次把uv坐標(biāo)放大,這時(shí)候就可以播放多個(gè)動(dòng)畫了,只是,每個(gè)動(dòng)畫的播放進(jìn)度都不一樣。
四、高級(jí)變換
1、極坐標(biāo)變換
就是把直角坐標(biāo)系變成極坐標(biāo)系,就是把正方形變成圓形。莊懂老師說(shuō),這個(gè)一般用于實(shí)現(xiàn)角色腳下的法陣特效,比美術(shù)畫出來(lái)的好使多了。
在這里附上莊懂老師的代碼:
// 直角坐標(biāo)轉(zhuǎn)極坐標(biāo)方法
float2 RectToPolar(float2 uv, float2 centerUV) {
uv = uv - centerUV; // 將原點(diǎn)偏移到中心位置
float theta = atan2(uv.y, uv.x); // atan()的值域?yàn)閇-π/2, π/2],只能畫半圓,一般不用; atan2()的值域?yàn)閇-π, π],剛好畫出一個(gè)完整的圓
float r = length(uv);
return float2(theta, r);
}
// 輸出結(jié)構(gòu)>>>像素
half4 frag(VertexOutput i) : COLOR {
// 直角坐標(biāo)轉(zhuǎn)極坐標(biāo)
float2 thetaR = RectToPolar(i.uv, float2(0.5, 0.5));
// 極坐標(biāo)轉(zhuǎn)紋理采樣UV
float2 polarUV = float2(
thetaR.x / 3.141593 * 0.5 + 0.5, // θ從[-π, π]映射到[0, 1]
thetaR.y + frac(_Time.x * 3.0) // r隨時(shí)間流動(dòng)
);
// 采樣MainTex
half4 var_MainTex = tex2D(_MainTex, polarUV);
// 處理最終輸出
half3 finalRGB = (1 - var_MainTex.rgb) * _Color;
half opacity = (1 - var_MainTex.r) * _Opacity * i.color.r;
// 返回值
return half4(finalRGB * opacity, opacity);
}
因?yàn)樘匦б话闶莃ulingbuling的并且涉及透明度,所以這里有用到AD透明度疊加shader文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-523261.html
原視頻:莊懂的技術(shù)美術(shù)入門課(美術(shù)向)-直播錄屏-第18課_嗶哩嗶哩_bilibili
(幀動(dòng)畫 + 極坐標(biāo)變換)
GitHub源碼:AP01:A向技術(shù)美術(shù)入門課程文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-523261.html
到了這里,關(guān)于你好,uv變換(新手入門向聊天教程)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!