To completely understand this blog, basic Shader knowledge is necessary. I am writing my shader in CG ( i don't use graphs :P). I personally believe that we can have more control over shaders with CG rather than using graphs. Graphs can restrict our possibilities.
Now as we already know vertex and fragment are two most important types of shaders in computer graphics. Here as we are dealing with the flag animation, it means we are displacing vertices of that flag mesh - so we use Vertex Shader for this.
As we can see the waving of the flag animation is a sin/cos wave(I am assuming you already know basic trigonometry and graphs, Shaders is all about Math :) ).
But how can we achieve flag waving animation? what vertices of flag we have to displace? on basis of what? Hm, i am gonna answer all there here.
Firstly we are gonna generate sin wave using texture space of that flag - sin(texcoorg.x).
Texture space is for the texture which is applied on to the flag. Any model comes with the texture space values for each of its vertices. As shown in the below diagram, we are gonna change the vertices values of the model along y-axis, in the sin(texcoord.x) form.
so ,
v.vertex.y = v.vertex.y + sin(texcoorg.x).
But by using the above equation, we can only generate a static sin wave. Out goal is to shift the wave(frequency) with the time. This can be achieved using _Time variable provided by unity for shader animation.
v.vertex.y = v.vertex.y + sin(texcoorg.x - _Time.y).
Now we get waving flag. To add more believable effect to the animation we multiply this with texcoorg.x value, so that the flag doesn't animate at position where is is attached to the pole.
v.vertex.y = v.vertex.y + sin(texcoorg.x - _Time.y) * texcoorg.x;
Lets control frequency, amplitude and speed of this flag animation. It is rather simple if you know basic trigonometry.
v.vertex.y = v.vertex.y + sin((texcoorg.x - _Time.y * speed) * frequency) * texcoorg.x * Amplitude;
This is the final Shader code:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "ShaderLearning/WavingFlag"
{
Properties
{
_Color("Main Color", Color) = (1,1,1,1)
_Texture("Basic Texture", 2D) = "white" {}
_Frequency("Frequency of flag wave", float) = 0
_Amplitude("Amplitude of flag wave", float) = 0
_Speed("Speed of flag wave", float) = 0
}
Subshader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform half4 _Color;
uniform sampler2D _Texture;
uniform float4 _Texture_ST;
uniform float _Frequency;
uniform float _Amplitude;
uniform float _Speed;
struct vertexInput
{
float4 vertex: POSITION;
float4 texcoorda: TEXCOORD0;
};
struct vertexOutput
{
float4 pos : SV_POSITION;
float4 texcoorda: TEXCOORD0;
};
float4 vertexFlagAnimation(float4 vertexPos, float2 uv)
{
vertexPos.y = vertexPos.y + (sin((uv.x - (_Time.y * _Speed)) * _Frequency)) * _Amplitude * uv.x ;
return vertexPos;
}
vertexOutput vert(vertexInput v)
{
vertexOutput o;
v.vertex = vertexFlagAnimation(v.vertex, v.texcoorda);
o.pos = UnityObjectToClipPos(v.vertex);
o.texcoorda.xy = v.texcoorda + _Texture_ST.wz;
return o;
}
half4 frag(vertexOutput i) : COLOR
{
return tex2D(_Texture,i.texcoorda) * _Color.rgba;
}
ENDCG
}
}
}
Final Output:
link to download the below flag model : https://drive.google.com/drive/folders/1PIFdEvSxjaZ7rHVubMaSrAnqhZexu0Cx?usp=sharing
Comentarios