本篇主要用于记录自己的实战操作,以及一些碎碎念(观后感),如果有什么好想法或者本篇出现什么错误,请多指教~
本篇的内容参考视频:庄懂的技术美术入门课(美术向)
使用软件:Unity 2019 3.6f1 ,ShaderForge
本篇内容主要包括:顶点动画平移,缩放,旋转,幽灵案例
一.平移
效果:
制作:
- 为了先做成幽灵酱,先和平时一样将AB(透明度混合)的代码搬过来;
- 然后对其增加一点点的处理,我们在顶点着色器前写一个用来平移的函数来控制顶点位移,并在顶点着色器里调用它;
#define TWO_PI 6.283185
void Translation(inout float3 vertex){
vertex.y += sin(frac(_Time.z*_MoveSpeed)*TWO_PI)*_MoveRange;
}
补充:
- 如上面的代码,我们选择Sin函数来作为偏移值基础,MoveSpeed和MoveRange分别对应移动速度和范围,安排的位置可参考初中学的Sin函数,分别控制频率与振幅;
- inout:修饰词,参数的“出入许可”;
- 为了防止随时间增长导致纹理变花,我们使用frac对其取余,但此时因为横轴限制在0到1走不完一个sin函数全程,会造成抖动,因此我们再对其乘上2π;
完整代码:
Shader "Unlit/co16-Trans"{
Properties {
_MainTex ("RGB:颜色 A:透贴", 2d) = "gray"{}
_Opacity ("透明度", range(0, 1)) = 0.5
_MoveRange("移动范围",range(0.0,3.0))=1.0
_MoveSpeed("移动速度",range(0.0,3.0))=1.0
}
SubShader {
Tags {
"Queue"="Transparent" // 调整渲染顺序
"RenderType"="Transparent" // 对应改为Cutout
"ForceNoShadowCasting"="True" // 关闭阴影投射
"IgnoreProjector"="True" // 不响应投射器
}
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
Blend One OneMinusSrcAlpha // 修改混合方式One/SrcAlpha OneMinusSrcAlpha
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;
uniform half _Opacity;
uniform half _MoveRange;
uniform half _MoveSpeed;
struct VertexInput {
float4 vertex : POSITION; // 顶点位置 总是必要
float2 uv : TEXCOORD0; // UV信息 采样贴图用
};
struct VertexOutput {
float4 pos : SV_POSITION; // 顶点位置 总是必要
float2 uv : TEXCOORD0; // UV信息 采样贴图用
};
#define TWO_PI 6.283185
void Translation(inout float3 vertex){
vertex.y += sin(frac(_Time.z*_MoveSpeed)*TWO_PI)*_MoveRange;
}
VertexOutput vert (VertexInput v) {
VertexOutput o ;
Translation(v.vertex.xyz);
o.pos = UnityObjectToClipPos( v.vertex); // 顶点位置 OS>CS
o.uv = TRANSFORM_TEX(v.uv, _MainTex); // UV信息 支持TilingOffset
return o;
}
half4 frag(VertexOutput i) : COLOR {
half4 var_MainTex = tex2D(_MainTex, i.uv); // 采样贴图 RGB颜色 A透贴
half3 finalRGB = var_MainTex.rgb;
half opacity = var_MainTex.a * _Opacity;
return half4(finalRGB * opacity, opacity); // 返回值
}
ENDCG
}
}
}
二.缩放
效果如下:
制作:
- 类比平移,在AB的基础上添加缩放的速度和大小范围;
- 同样是基于sin函数来制作顶点动画效果但对操作进行了部分处理,缩放函数如下;
#define TWO_PI 6.283185
void Scaling(inout float3 vertex){
vertex*=1+ sin(frac(_Time.z*_ScaleSpeed)*TWO_PI)*_ScaleRange;
}
完整代码参考上面的改函数和变量名即可;
三.旋转
效果如下:
制作:一如上面的操作;
补充:
- 不同于缩放和平移,旋转需要涉及到向量相加的相关知识,如下图,当向量为(x,z)旋转后其向量值为(xcosθ-zsinθ,xsinθ+zcosθ)
- 相关代码为
#define TWO_PI 6.283185
void Rotation(inout float3 vertex){
float angleY = sin(frac(_Time.z*_RotateSpeed)*TWO_PI)*_RotateRange;
float radY = radians(angleY);//弧度值转换,方便后面运算
float sinY,cosY=0;
sincos(radY,sinY,cosY);//等价于sinY=sin(radY),cosY=cos(radY),这种写法据说较省
vertex.xz = float2(
vertex.x*cosY-vertex.z*sinY,
vertex.x*sinY+vertex.z*cosY
);
}
四.幽灵案例
效果如下:
分析:天使圈大小有缩放,身体是摆动,头部旋转,全身上下起伏;
准备:头部加绿通道遮罩,身体红通道遮罩;
相关代码:
void Anime(inout float3 vertex , inout float3 color){
float scale = color.g*sin(frac(_Time.z*_ScaleParams.y)*TWO_PI)*_ScaleParams.x;
vertex.xyz *= 1.0+scale;//上面两行是缩放,乘绿色遮罩,只有绿色才缩放
vertex.y -=_ScreenParams.z*scale;//天使光环的中心还在模型中心,在缩小时会向下拉,放大时向上拉,故而来减个修正值
float swingX =sin(frac(_Time.z*_SwingXParams.y+_SwingXParams.z*vertex.y)*TWO_PI)*_SwingXParams.x;//sin函数里加了个根据y轴值乘波动影响,从而使得高度上形成sin波
float swingZ =sin(frac(_Time.z*_SwingZParams.y+_SwingZParams.z*vertex.y)*TWO_PI)*_SwingZParams.x;
vertex.xz +=color.r*float2(swingX,swingZ);
float radY =radians(_SnakeYParams.x)*(1.0-color.r)*sin(frac(_Time.z*_SnakeYParams.y-_SnakeYParams.z*color.g)*TWO_PI);//sin函数中减掉的值用于对天使圈做一个滞后效果
float sinY,cosY=0;
sincos(radY,sinY,cosY);//等价于sinY=sin(radY),cosY=cos(radY),这种写法据说较省
vertex.xz = float2(
vertex.x*cosY-vertex.z*sinY,
vertex.x*sinY+vertex.z*cosY
);
float swingY=_SwingYParams.x*sin(frac(_Time.z*_SwingYParams.y-_SwingYParams.z*color.g)*TWO_PI);
vertex.y += swingY;
float lightness=1.0+color.g*1.0+scale*2.0;//天使圈顶点绿通道提亮,
color =float3(lightness,lightness,lightness);
}
整体代码还是和之前几个类似,不过加了一个顶点色,用于做遮罩以及天使环的发光效果;