以下の内容はhttps://bluebirdofoz.hatenablog.com/entry/2024/12/12/000911より取得しました。


UnityのHLSLシェーダで時間経過でラインが流れるシェーダを作成する

本日はUnityの小ネタ枠です。
UnityのHLSLシェーダで時間経過でラインが流れるシェーダを作成する方法です。

シェーダーの時間変数

ビルトインのシェーダー変数の _Time を参照することでステージロードからの時間(t/20, t, t*2, t*3)をシェーダ内で参照できます。
本変数を使ってシェーダ内で時間経過に応じたアニメーションを実装することができます。
docs.unity3d.com

時間変数には以下の4種類が用意されています。

名前 タイプ Value
_Time float4 ステージのロードからの時間 (t/20, t, t*2, t*3)
_SinTime float4 時間の正弦: (t/8, t/4, t/2, t)
_CosTime float4 時間の余弦: (t/8, t/4, t/2, t)
unity _DeltaTime float4 デルタ時間: (dt, 1/dt, smoothDt, 1/smoothDt)

シェーダでの座標参照

ビルトインのシェーダー変数の unity_ObjectToWorld を利用することでオブジェクト座標からワールド座標を算出できます。
本変数を使ってシェーダ内で座標毎に色彩を変化させる処理を実装することができます。
docs.unity3d.com

頂点シェーダー内で以下のように利用してUnityのワールド座標を算出します。

// オブジェクトの座標(v.vertex)からワールド座標(o.worldPos)を算出する
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

これらの変数を利用してオブジェクトの表面を射線が流れるスキャンのようなシェーダを作成できます。

サンプルシェーダ

ビルトインのシェーダー変数を使って時間経過で射線がスライドするスキャンラインを表示する以下のUnlitシェーダを作成しました。
・ScanLineUnlitShader.shader

Shader "Unlit/ScanLineUnlitShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        
        // <------- ここからがスキャンライン処理の追加部分 ------->
        // ラインの色
        _LineColor ("Line Color", Color) = (1,1,1,1)
        
        // ラインの速度
        _LineSpeed ("Line Speed", Range(0, 10)) = 1
        
        // ラインの密度(0:密度が低い、1:密度が高い)
        _LineDensity ("Line Density", Range(0, 1)) = 0.5
        
        // ラインの幅(0:ライン無し、0.5:半分の幅、1:全面塗りつぶし)
        _LineWidth ("Line Width", Range(0, 1)) = 0.33
        // <------- ここまでスキャンライン処理の追加部分 ------->
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
                // Unity空間座標を取得するための変数
                float3 worldPos : WORLD_POS;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);

                // <------- ここからがスキャンライン処理の追加部分 ------->
                // 世界座標を設定
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                // <------- ここまでスキャンライン処理の追加部分 ------->

                return o;
            }
            
            // <------- ここからがスキャンライン処理の追加部分 ------->
            fixed4 _LineColor;
            float _LineSpeed;
            float _LineDensity;
            float _LineWidth;
            // <------- ここまでスキャンライン処理の追加部分 ------->

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                
                // <------- ここからがスキャンライン処理の追加部分 ------->
                // 時間の係数を作成する
                float timeFactor = _Time.y * _LineSpeed;
                // XYZ座標と時間の合計値を取得して座標ごとの値を作る
                float positionValue = i.worldPos.x + i.worldPos.y + i.worldPos.z + timeFactor;
                // positionValueを0.0~1.0の範囲に正規化する
                float distNormalization = frac(positionValue * _LineDensity);
                // 判定値を満たしていればラインカラーを設定する
                col.rgb = (distNormalization < _LineWidth) ? _LineColor : col.rgb;
                // <------- ここまでスキャンライン処理の追加部分 ------->

                return col;
            }
            ENDCG
        }
    }
}

本シェーダをマテリアルに設定して利用すると、設定したカラーのラインが時間経過でスライドするようになります。




以上の内容はhttps://bluebirdofoz.hatenablog.com/entry/2024/12/12/000911より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14