シェーダーの練習がしたかったのと、意外とやってる人いなさそうだな..と思ったのでタイトル通りの内容をやってみました。
はじめに
今回はこんな感じの動きを実装していきます。
ちょっと今作っているもので作る必要のある機能だったので、検証も含めてやってみます。
画像はいらすとやさんからお借りしました。
CSSで実装する場合
単純なHTMLとCSSで実装する場合の最小サンプルは次のようになります。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
img {
animation: rotation 1s linear infinite;
transform-origin: center;
}
@keyframes rotation {
0% { transform: rotateY(0deg); }
100% { transform: rotateY(360deg); }
}
</style>
<title>Document</title>
</head>
<body>
<div>
<img src="idol_fan_doutan.png" alt="img">
</div>
</body>
</html>
Unityで実装していく
テクスチャのインポートはClampモードにしておく必要があります。
実装の方針としては、テクスチャのUV座標のx座標のみを0.5を中心としてsin関数で回転していきます。
この方法だとテクスチャが反転している時に何も表示されないので、元々反転させたテクスチャを用意して逆位相で回転させています。
テクスチャのUV座標のStartとEndがひっくり返った時にはうまく処理ができていないので、値が変わらないようにしています。
下記のように実装すると、次のようになります。
yais.shader
Shader "Unlit/yaxis"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#define PI 3.141592
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float2 flippedUV = float2(1.0 - i.uv.x, i.uv.y);
float _BlendStartU = 0.5 + 0.5 * (sin(_Time.y ));
float _BlendEndU = 0.5 + 0.5 * (-sin(_Time.y ));
if (_BlendStartU > 0.5){
_BlendEndU = 0.0;
_BlendStartU = 0.0;
}
float2 pos = float2(frac(i.uv.x - _BlendStartU) * 1/(_BlendEndU - _BlendStartU),
frac(i.uv.y) * 1 );
float _BlendStartU_flipped = 0.5 + 0.5 * (sin((_Time.y + PI )));
float _BlendEndU_flipped = 0.5 + 0.5 * (-sin((_Time.y + PI) ));
if(_BlendStartU_flipped > _BlendEndU_flipped){
_BlendEndU_flipped = 0.0;
_BlendStartU_flipped = 0.0;
}
float2 pos_flipped = float2(frac(flippedUV.x - _BlendStartU_flipped) * 1/(_BlendEndU_flipped - _BlendStartU_flipped),
frac(flippedUV.y) * 1 );
fixed4 col = tex2D(_MainTex, pos) + tex2D(_MainTex, pos_flipped);
return col;
}
ENDCG
}
}
}
テクスチャの端がノイズっぽくなってしまうので回避法を探し中です、、
もう少し良い実装方法があったら是非コメントお願いいたします。