前言
前面两篇文章说的都是对UV进行修改实现shader的动态效果,这一篇来说一下通过顶点的偏移实现动态shader。
对于顶点常用的偏移操作有移动、旋转、缩放这三种,下面分别来介绍。
顶点移动
顶点的移动比较简单,就是在顶点shader中,直接对顶点位置进行偏移,下面的代码是一个y轴上下移动的shader。
// shader的路径和名称 Shader "Shader Forge/VertixTranslation" { // 暴露属性到面板 Properties { _MainTex("RGB: Color A:Alpha", 2d) = "gray"{} _Opacity("Opacity", range(0.0, 1.0)) = 1.0 _MoveRange("Move Range", range(0.0, 2.0)) = 1.0 _MoveSpeed("Move Speed", range(0.0, 3.0)) = 1.0 } SubShader { Tags { "Queue"="Transparent" //调整渲染顺序 "RenderType"="Transparent" //改为对应的 "ForceNoShadowCasting"="True" //关闭阴影投射 "IgnoreProjector"="True" //不响应投射器 } Pass { Name "FORWARD" Tags { "LightMode"="ForwardBase" } Blend One OneMinusSrcAlpha //修改混合模式 Cull Off //双面显示 CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #pragma multi_compile_fwdbase_fullshadows #pragma target 3.0 // 声明变量 uniform sampler2D _MainTex; uniform float4 _MainTex_ST; //支持UV TillingOffset uniform half _Opacity; uniform half _MoveRange; uniform half _MoveSpeed; // 输入结构 struct VertexInput { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; // 输出结构 struct VertexOutput { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; }; // 声明常量 #define TwoPi 6.283185 // 顶点动画方法 void Translation(inout float3 vertex){ //inout表示在函数内直接修改此传入变量 vertex.y += _MoveRange * sin(frac(_Time.z * _MoveSpeed) * TwoPi); //sin()用于产生周期波动,sin()的完整周期是0到2π,frac()取余的值域是0到1,因此需要乘TwoPi } // 顶点shader VertexOutput vert (VertexInput v) { VertexOutput o = (VertexOutput)0; Translation(v.vertex.xyz); o.pos = UnityObjectToClipPos( v.vertex ); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } // 像素shader float4 frag(VertexOutput i) : COLOR { half4 var_MainTex = tex2D(_MainTex, i.uv); half finalOpacity = var_MainTex.a * _Opacity; return half4(var_MainTex.rgb * finalOpacity,finalOpacity); } ENDCG } } FallBack "Diffuse" }
注意sin()的完整周期是2π,因此如果不乘2π会造成动画卡顿闪烁。
效果如下
顶点缩放
顶点的缩放和顶点的移动是相同的原理,代码也类似。
// shader的路径和名称 Shader "Shader Forge/VertexScale" { // 暴露属性到面板 Properties { _MainTex("RGB: Color A:Alpha", 2d) = "gray"{} _Opacity("Opacity", range(0.0, 1.0)) = 1.0 _ScaleRange("Scale Range", range(0.0, 2.0)) = 1.0 _ScaleSpeed("Scale Speed", range(0.0, 3.0)) = 1.0 } SubShader { Tags { "Queue"="Transparent" //调整渲染顺序 "RenderType"="Transparent" //改为对应的 "ForceNoShadowCasting"="True" //关闭阴影投射 "IgnoreProjector"="True" //不响应投射器 } Pass { Name "FORWARD" Tags { "LightMode"="ForwardBase" } Blend One OneMinusSrcAlpha //修改混合模式 Cull Off //双面显示 CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #pragma multi_compile_fwdbase_fullshadows #pragma target 3.0 // 声明变量 uniform sampler2D _MainTex; uniform float4 _MainTex_ST; //支持UV TillingOffset uniform half _Opacity; uniform half _ScaleRange; uniform half _ScaleSpeed; // 输入结构 struct VertexInput { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; // 输出结构 struct VertexOutput { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; }; // 声明常量 #define TwoPi 6.283185 // 顶点动画方法 void Scaling(inout float3 vertex){ //inout表示在函数内直接修改此传入变量 vertex *= 1.0 + _ScaleRange * sin(frac(_Time.z * _ScaleSpeed) * TwoPi); //sin()用于产生周期波动,sin()的完整周期是0到2π,frac()取余的值域是0到1,因此需要乘TwoPi } // 顶点shader VertexOutput vert (VertexInput v) { VertexOutput o = (VertexOutput)0; Scaling(v.vertex.xyz); o.pos = UnityObjectToClipPos( v.vertex ); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } // 像素shader float4 frag(VertexOutput i) : COLOR { half4 var_MainTex = tex2D(_MainTex, i.uv); half finalOpacity = var_MainTex.a * _Opacity; return half4(var_MainTex.rgb * finalOpacity,finalOpacity); } ENDCG } } FallBack "Diffuse" }
区别就是+=换成*=,修改的轴向由单个y轴改成xyz三轴整体,效果如下。
顶点旋转
顶点的旋转相对于移动和缩放要复杂一些,需要了解向量的旋转原理。
首先将问题简化一下,顶点绕Y轴旋转时,此时y坐标不变,可以视为[x, y]二维向量绕原点旋转,求旋转后的红色箭头处的XZ坐标,下面的图展示了这种方式的计算方法。
通过三角函数配合向量的加减运算即可得到旋转后的坐标,具体代码如下:
// shader的路径和名称 Shader "Shader Forge/VertexRotate" { // 暴露属性到面板 Properties { _MainTex("RGB: Color A:Alpha", 2d) = "gray"{} _Opacity("Opacity", range(0.0, 1.0)) = 1.0 _RotateRange("Rotate Range", range(0.0, 90.0)) = 30.0 _RotateSpeed("Rotate Speed", range(0.0, 3.0)) = 1.0 } SubShader { Tags { "Queue"="Transparent" //调整渲染顺序 "RenderType"="Transparent" //改为对应的 "ForceNoShadowCasting"="True" //关闭阴影投射 "IgnoreProjector"="True" //不响应投射器 } Pass { Name "FORWARD" Tags { "LightMode"="ForwardBase" } Blend One OneMinusSrcAlpha //修改混合模式 Cull Off //双面显示 CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #pragma multi_compile_fwdbase_fullshadows #pragma target 3.0 // 声明变量 uniform sampler2D _MainTex; uniform float4 _MainTex_ST; //支持UV TillingOffset uniform half _Opacity; uniform half _RotateRange; uniform half _RotateSpeed; // 输入结构 struct VertexInput { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; // 输出结构 struct VertexOutput { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; }; // 声明常量 #define TwoPi 6.283185 // 顶点动画方法 void Rotation(inout float3 vertex){ //inout表示在函数内直接修改此传入变量 float angelY = _RotateRange * sin(frac(_Time.z * _RotateSpeed) * TwoPi); //旋转范围 float radY = radians(angelY); //计算弧度 float sinY, cosY = 0; sincos(radY, sinY, cosY); //根据弧度计算sin和cos vertex.xz = float2(vertex.x * cosY - vertex.z * sinY, vertex.x * sinY + vertex.z * cosY); //计算偏移量 } // 顶点shader VertexOutput vert (VertexInput v) { VertexOutput o = (VertexOutput)0; Rotation(v.vertex.xyz); o.pos = UnityObjectToClipPos( v.vertex ); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } // 像素shader float4 frag(VertexOutput i) : COLOR { half4 var_MainTex = tex2D(_MainTex, i.uv); half finalOpacity = var_MainTex.a * _Opacity; return half4(var_MainTex.rgb * finalOpacity,finalOpacity); } ENDCG } } FallBack "Diffuse" }
效果如下
注意
注意下图中,当选择三个应用了不同定点动画的模型时,可以发现三个物体实际仍在原来的位置,也就是说顶点动画可以使用静态物体实现动态的效果,在大量物体进行随机运动的情况下,可以避免由CPU处理这些transform信息,减少DrawCall压力,也就是所谓的静态合批。
顶点动画由于实现简单、效果容易控制、节省CPU资源等优点,因此在草丛、建筑等大量随机散布物体,特别是移动平台上被大量使用。
目前动画虽然已经实现,但默认的阴影由于调用的是原始的顶点位置进行计算,会导致有顶点动画的物体投影不正确,为了修复这个问题,需要自定义一个ShadowCaster Pass,在这个Pass中,进行同样的顶点变换过程。这一部分之后会单独开篇介绍。
本文同样参考自B站庄懂的技术美术入门课,感谢。
梦想养活不起你的时候,
你得养着梦想啊。
——小林一茶
评论
I will immediately grab your rss as I can not in finding your e-mail subscription hyperlink or e-newsletter service. Do you’ve any? Kindly permit me recognize so that I may subscribe. Thanks.
https://youtu.be/TxwSrEuBDoY
I was just seeking this info for some time. After six hours of continuous Googleing, finally I got it in your website. I wonder what is the lack of Google strategy that don’t rank this type of informative sites in top of the list. Normally the top sites are full of garbage.
https://www.fuduku.com/hire-a-hacker-for-instagram/
Howdy! Someone in my Myspace group shared this website with us so I came to check it out. I’m definitely loving the information. I’m book-marking and will be tweeting this to my followers! Great blog and terrific design and style.
https://youtu.be/209DcrYTa5o
I like this web site very much, Its a rattling nice billet to read and receive information.
https://youtu.be/XPwygCshVpI
I am impressed with this website , real I am a big fan .
https://www.axilusonline.com/professional-cell-phone-hackers/
Great ?V I should certainly pronounce, impressed with your web site. I had no trouble navigating through all the tabs as well as related info ended up being truly easy to do to access. I recently found what I hoped for before you know it in the least. Reasonably unusual. Is likely to appreciate it for those who add forums or anything, web site theme . a tones way for your client to communicate. Nice task..
https://youtu.be/th1Lrr8dubQ
With havin so much content do you ever run into any issues of plagorism or copyright violation? My site has a lot of exclusive content I’ve either written myself or outsourced but it appears a lot of it is popping it up all over the internet without my permission. Do you know any solutions to help stop content from being stolen? I’d really appreciate it.
https://youtu.be/NJ5SsQSXd_w
This website is mostly a walk-via for the entire data you wanted about this and didn’t know who to ask. Glimpse right here, and you’ll definitely discover it.
https://youtu.be/pT3_IVg6L-I
As a Newbie, I am permanently browsing online for articles that can benefit me. Thank you
https://www.bigzh.com/hire-a-hacker-for-snapchat/
I¦ll immediately seize your rss feed as I can’t find your e-mail subscription link or e-newsletter service. Do you’ve any? Please permit me recognize so that I could subscribe. Thanks.
https://youtu.be/TXkLvlTOUAA
Hey just wanted to give you a quick heads up. The text in your article seem to be running off the screen in Opera. I’m not sure if this is a formatting issue or something to do with browser compatibility but I figured I’d post to let you know. The design and style look great though! Hope you get the issue solved soon. Cheers
https://youtu.be/wjVY7-CUm90