LoginSignup
1
2

More than 1 year has passed since last update.

CSSのRotateYみたいな動きをUnityのシェーダーで作る

Last updated at Posted at 2023-05-06

シェーダーの練習がしたかったのと、意外とやってる人いなさそうだな..と思ったのでタイトル通りの内容をやってみました。

はじめに

今回はこんな感じの動きを実装していきます。
ちょっと今作っているもので作る必要のある機能だったので、検証も含めてやってみます。
画像はいらすとやさんからお借りしました。

ezgif.com-gif-maker.gif

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がひっくり返った時にはうまく処理ができていないので、値が変わらないようにしています。

下記のように実装すると、次のようになります。

ezgif.com-resize_unity.gif

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
        }
    }
}

テクスチャの端がノイズっぽくなってしまうので回避法を探し中です、、
もう少し良い実装方法があったら是非コメントお願いいたします。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2