0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

放射状の模様を描画するシェーダ(くり抜き有り)

Last updated at Posted at 2021-03-07

twitterで貼った、放射状エフェクトを描画するシェーダのコードを貼っておきます

コード

今回のシェーダはBuiltInShaderのUI-Defaultをベースに作成しています。UI用です。

UiRadiation.shader
Shader "ScreenPocket/UI/Radiation"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _Angle ("Angle", Float) = 0
        _LineCount ("Line Count", Float) = 32
        _LineRate ("Line Rate", Range(-1,1)) = 0
        
        [Header(Clipping)]
        _Radius ("Radius", Range(0,1)) = 1
        
        [Header(UI Default Parameter)]
        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 0
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255

        _ColorMask ("Color Mask", Float) = 15

        [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }

        Cull Off
        Lighting Off
        ZWrite Off
        ZTest [unity_GUIZTestMode]
        Blend One OneMinusSrcAlpha
        ColorMask [_ColorMask]

        Pass
        {
            Name "Default"
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0

            #include "UnityCG.cginc"

            #pragma multi_compile_local _ UNITY_UI_CLIP_RECT
            #pragma multi_compile_local _ UNITY_UI_ALPHACLIP

            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord  : TEXCOORD0;
                float4 worldPosition : TEXCOORD1;
                half4  mask : TEXCOORD2;
                UNITY_VERTEX_OUTPUT_STEREO
            };

            sampler2D _MainTex;
            half4 _Color;
            half4 _TextureSampleAdd;
            float4 _ClipRect;
            float4 _MainTex_ST;
            float _MaskSoftnessX;
            float _MaskSoftnessY;
            float _Angle;
            float _Radius;
            float _LineCount;
            float _LineRate;

            v2f vert(appdata_t v)
            {
                v2f OUT;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
                float4 vPosition = UnityObjectToClipPos(v.vertex);
                OUT.worldPosition = v.vertex;
                OUT.vertex = vPosition;

                float2 pixelSize = vPosition.w;
                pixelSize /= float2(1, 1) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));

                float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
                float2 maskUV = (v.vertex.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
                OUT.texcoord = float4(v.texcoord.x, v.texcoord.y, maskUV.x, maskUV.y);
                OUT.mask = half4(v.vertex.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + abs(pixelSize.xy)));

                OUT.color = v.color;
                return OUT;
            }

            half4 frag(v2f IN) : SV_Target
            {
                half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd);

                //座標を円周角度に変換
                float2 uv = float2(IN.texcoord.x-0.5, -IN.texcoord.y+0.5);
                float radian = atan2(uv.x, uv.y);
                //円周角度の繰り返し数とズラし角度を加味してsinにする
                float sinRate = sin(radian * _LineCount + _Angle);
                //sin波を0,1に切り分ける(パキッと切りたくないならceil()を止める)
                sinRate = ceil( saturate(sinRate + _LineRate) );
                color *= lerp( _Color, IN.color, sinRate);

                #ifdef UNITY_UI_CLIP_RECT
                half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
                color.a *= m.x * m.y;
                #endif

                //円形にくり抜く
                float l = length(uv);
                color.a = saturate(color.a * floor(l*2+(1 - _Radius)));
                
                #ifdef UNITY_UI_ALPHACLIP
                clip (color.a - 0.001);
                #endif

                color.rgb *= color.a;

                return color;
            }
        ENDCG
        }
    }
}

使い方

使い方としては、上記のシェーダを充てたマテリアルをUIのImageかRawImageに設定する事で放射を表示する事が出来ます。
スクリーンショット 2021-03-07 205609.png
各パラメータの用法は下記の感じです

パラメータ名 用法
_Color 放射の帯の色を決めます。この色とアタッチしたGraphic(Image、RawImage)のColorを繰り返した放射模様となります
_Angle 放射の帯の角度をズラせます。加算し続ける事で放射が回転します
_LineCount 放射の帯の数を指定出来ます。少数を指定すると帯の境目が見えてしまうので整数指定の方が良いです
_LineRate 放射の帯とそうでない分の塗りつぶし割合を指定できます。0でどちらも同じ幅です
_Radius 中心をくり抜く際の割合を指定できます
_Radiusは放射描画とは無関係な処理ではありますが、せっかくなので残しておきます。
下記の用例キャプチャの様に、トランジション表現でくり抜きたい場合などでご利用ください。

使用上の注意

使用の際は、諸外国で怒られないようにお気を付けください。
※本記事のシェーダによる表現で政治的な意図を見出されて使用者が不利益を被ったとしても、作者は責任を負わない物とさせて頂きますので了承した上でご利用ください。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?