温馨提示本文只是一篇入门聊天不涉及代码教程看不懂代码就跳过没关系一、什么是uv1、uv其实就是一个二维坐标系啊就俩轴就跟xy轴一样。那为什么不叫xy反而叫uv呢不知道应该是为了跟空间坐标系xyz区别开来以免在工作流程中产生误解吧吧吧。2、uv坐标用于采样贴图然后把它映射到模型表面。图是网上找的如果侵权了我立马删对不起对不起对不起3、类比xOy直角坐标系在unity shader中uv坐标原点也是在左下角00的位置的。注意不同的shader体系它们设定的原点坐标是不一样的比如dirctX的原点就在左上角。用这个uv贴图比较方便观察。记得再ps里转化成.tga格式再使用4、uv坐标的原始范围都是[0,1]。二、uv变换1、为什么是uv变换啊为什么是uv变换而不是贴图变换呢因为贴图是不会变换的uv采样本质上就是用一个横向范围[0,1]和纵向范围[0,1]的直角坐标系去采样一张图然后映射到模型表面上。Shader着色器通过各种花里胡哨的运算改变uv坐标从而改变采样范围内容从而使我们看到贴图变形。嗯……就好像我们拿望远镜观察星空星星贴图当晚不会变只有我们移动望远镜uv坐标我们看到的星星才会不同。甚至我们还可以在望远镜上装哈哈镜shader这样看到的星星也会不同。或者你可以想象你坐在火车上窗外的风景就是贴图窗就是uv坐标。风景不会跑只有咱们的窗户在跟着车平移。2、加减平移举例uv (0.1, 0.1)i.uvfloat2(0.1,0.1);看起来贴图向左下角偏移了。就像绿色箭头标注一样。会不会有同学没反应过来为什么不是偏移一整格呢因为这图是8×8格的所以要0.125才能偏移一整格哈哈哈为什么呢一开始原点(0,0)采样的是H1左下角明黄色的点Uv坐标经过加减变换之后原点(0,0)变成了(0.1, 0.1)坐标轴整体向右上角移动了此时采样的点是H1接近右上角的明黄色的点.以此类推别的坐标点可以参考上面的坐标轴偏移示意图得到的采样结果就是这样啦。所以其实不是贴图向左下角偏移了而是坐标向右上角偏移了。嗯呃呃呃有一点相对论地拗口。注意贴图是循环平铺的。也就是说原本边缘处(1, 1的坐标点经过加减变换之后变成了(1.1, 1.1)超出了贴图大于0小于1的坐标范围但是由于贴图是循环的所以(1, 1–加0.1→(1.1, 1.1)处采样的点与(0.1, 0.1)处采样的点是一致的但如果我把wrap mode网络循环模式从默认的Repeat循环改为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)就是将整个坐标轴向左下角移动那么采样的范围就会向左下角偏移采样的结果看起来就是贴图向右上角移动了。嘿嘿。2、乘除缩放坐标轴乘以2。i.uv*float2(2,2);贴图以坐标原点(0,0)为中心缩小了2倍啊…看得我自己都快眼花了……然后还是用刚才相对的思想去分析。贴图是永远不会变的只有坐标轴变大了两倍。uv坐标的范围变成了[0,2]贴图的范围是[0,1]由于贴图是循环平铺的在[0,2]里就能出现两次[0,1]在22的坐标系里就可以出现4个11也就是4张贴图。就这样看起来贴图缩小了同理坐标轴除以2贴图放大2倍Unity内置了变换函数TRANSFORM_TEX用于计算uv变换。在参数面板调整_MainTex_ST的tilling数值结果也是如此o.uvTRANSFORM_TEX(v.uv,_MainTex);tilling值越大就缩小值越小就变大。3、 加减和乘除o.uvTRANSFORM_TEX(v.uv,_MainTex);Unity内置的变换函数TRANSFORM_TEX等价于fixed2 uvi.uv*fixed2(_ScaleX,_ScaleY)-fixed2(_OffsetX,_OffsetY);// **先缩放后移动**half4 var_MainTextex2D(_MainTex,uv);为什么是先缩放后移动因为顶底变换的底层数学逻辑 总是 以最原始的原点(0, 0)为操作锚点的。如果先移动再缩放就会变成这样…o.uvv.uvfloat2(0.5,0.5);o.uv*sin(_Time.y)*0.51;用更玄学的话讲就是矩阵相乘不满足交换律…Q如果想让贴图以(0.8, 0.7)为中心放大3倍公式怎么写我们用一个新的10*10棋盘格贴图红点就是目标中心。Ao.uv v.uv / 3 float2(0.8, 0.7) * (3-1)/3 ;三、搞点事情吧——uv动画1、基础动画最基础的就是用全局变量_Time时间单改变其中一个数值让贴图动起来。我们举例改变offset偏移量。i.uvfloat2(_Time.x,0);动起来啦就像坐在火车上看风景的比喻一样。题外话为什么是_Time.x捏其实_Time有xyzw的x是每秒0.05y是每秒1z是每秒2w是每秒3。在这就不一一给大家截gif啦亲自去试试吧很好玩的。另外为了防止因时间过长导致数据溢出我们一般会给_Time取余。i.uvfloat2(frac(_Time.x),0);用函数frac()和运算符%都可以。i.uvfloat2(_Time.x%1,0);如果我改变的是纵向的v轴呢再换一张贴图呢看是瀑布是河流2、帧动画帧动画的制作思路就是把uv坐标缩小再移动到贴图中的第一帧然后用floor向上取整实现逐帧“跳动”。那岂不是一个材质只能播放一个动画了No你也可以再次把uv坐标放大这时候就可以播放多个动画了只是每个动画的播放进度都不一样。四、高级变换1、极坐标变换就是把直角坐标系变成极坐标系就是把正方形变成圆形。庄懂老师说这个一般用于实现角色脚下的法阵特效比美术画出来的好使多了。在这里附上庄懂老师的代码// 直角坐标转极坐标方法float2RectToPolar(float2 uv,float2 centerUV){uvuv-centerUV;// 将原点偏移到中心位置floatthetaatan2(uv.y,uv.x);// atan()的值域为[-π/2, π/2]只能画半圆一般不用; atan2()的值域为[-π, π]刚好画出一个完整的圆floatrlength(uv);returnfloat2(theta,r);}// 输出结构像素half4frag(VertexOutput i):COLOR{// 直角坐标转极坐标float2 thetaRRectToPolar(i.uv,float2(0.5,0.5));// 极坐标转纹理采样UVfloat2 polarUVfloat2(thetaR.x/3.141593*0.50.5,// θ从[-π, π]映射到[0, 1]thetaR.yfrac(_Time.x*3.0)// r随时间流动);// 采样MainTexhalf4 var_MainTextex2D(_MainTex,polarUV);// 处理最终输出half3 finalRGB(1-var_MainTex.rgb)*_Color;half opacity(1-var_MainTex.r)*_Opacity*i.color.r;// 返回值returnhalf4(finalRGB*opacity,opacity);}因为特效一般是bulingbuling的并且涉及透明度所以这里有用到AD透明度叠加shader原视频庄懂的技术美术入门课(美术向)-直播录屏-第18课_哔哩哔哩_bilibili帧动画 极坐标变换GitHub源码AP01A向技术美术入门课程