1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Unity Shader】ボーダーシェーダーを作ってみた

Last updated at Posted at 2025-08-31

概要

ボーダーみたいな見た目のシェーダーを作ってみました。

border

ソースコード

全体図です。

Shader "MyShader/Border"
{
    Properties
    {
        _Color ("Color", Color) = (1, 0, 0, 0.5)
        _Div ("Stripe Division Amount (when parallel to the axis)", Range(1, 1000)) = 10
        _SlopeX ("Stripe Slope X (auto normalized to be Y is positive)", Float) = 1.0
        _SlopeY ("Stripe Slope Y (auto normalized to be Y is positive)", Float) = 1.0
        _MoveSpeed ("Stripe Slope Move Speed (clockwise is negative)", Range(-5, 5)) = 1.0
    }

    SubShader
    {
        Tags{ "RenderType" = "Transparent" "Queue" = "Transparent" }

        Pass
        {
            Cull Back
            ZTest LEqual
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            half4 _Color;
            half _Div;
            half _SlopeX;
            half _SlopeY;
            half _MoveSpeed;

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

            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            v2f vert(appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.pos);
                o.uv = v.uv;
                return o;
            }

            half4 frag(v2f i) : SV_Target
            {
            
                // 使いやすいように初期計算
                half2 slope = normalize(half2(_SlopeX, _SlopeY));
                // - 傾きのy座標は正であってほしいので、もしそうでないなら象限を原点対象に反転する
                slope *= lerp(step(0, slope.y), 1, -1);
                // - 傾きのなす角
                half theta = atan2(slope.y, slope.x);
            
                // UV座標を -theta 回転し、縦方向にストライプがつくようにすれば良い
                half cosTheta = cos(theta), sinTheta = sin(theta);
                half2 uvRotated = half2(
                    cosTheta * i.uv.x + sinTheta * i.uv.y,
                    -sinTheta * i.uv.x + cosTheta * i.uv.y
                );
            
                // _Div 分割し、ストライプの箇所ならそのままのアルファ、
                // そうでないならアルファを0にして透明にする
                // - アルファの係数 (0 or 1)
                half aCoef = step(0.5, frac(uvRotated.y * _Div - _MoveSpeed * _Time.y));
                return half4(_Color.rgb, _Color.a * aCoef);
            }

            ENDCG
        }
    }
}

フラグメントシェーダーの所が重要です。

half4 frag(v2f i) : SV_Target
{

    // 使いやすいように初期計算
    half2 slope = normalize(half2(_SlopeX, _SlopeY));
    // - 傾きのy座標は正であってほしいので、もしそうでないなら象限を原点対象に反転する
    slope *= lerp(step(0, slope.y), 1, -1);
    // - 傾きのなす角
    half theta = atan2(slope.y, slope.x);

    // UV座標を -theta 回転し、縦方向にストライプがつくようにすれば良い
    half cosTheta = cos(theta), sinTheta = sin(theta);
    half2 uvRotated = half2(
        cosTheta * i.uv.x + sinTheta * i.uv.y,
        -sinTheta * i.uv.x + cosTheta * i.uv.y
    );

    // _Div 分割し、ストライプの箇所ならそのままのアルファ、
    // そうでないならアルファを0にして透明にする
    // - アルファの係数 (0 or 1)
    half aCoef = step(0.5, frac(uvRotated.y * _Div - _MoveSpeed * _Time.y));
    return half4(_Color.rgb, _Color.a * aCoef);
}

解説

ストライプを斜めに描画しています。
ストライプの傾きからなす角θが求められ、UV座標をその分回転させています。
時間に応じてUV座標にオフセットを与えています。

まとめ

テクスチャなしでも、数値計算のみで色々と図形が作れる。
透明にする所は discard とかの方がいい?

1
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?