2
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 1 year has passed since last update.

HLSLでのScanLine Shader(走査線)実装

Last updated at Posted at 2022-03-27

はじめに

今回はScanLine shaderの実装について記事にしたいと思います。

ScanLineはよく見る表現で、次のようなものです。
Scan_Line_Shader_-SampleScene-Windows__Mac__Linux-_Unity_2021_2_1f1_Personal__DX11__2022-03-27_23-31-18_AdobeCreativeCloudExpress.gif
ブラウン管のテレビのような雰囲気を醸し出すことができます。

プログラムはGitHubにて公開しています。

実装

実装は大きく3ステップに分ける事ができます。

ステップ1: 波

上の画像を見ると周期的に波打っている事が分かるので、sin, cosを使います。
白黒じゃつまらないので、rgbのgのみずらします。

float s = sin(i.uv.y * 1000);
float c = cos(i.uv.y * 1000);
col += float3(c, s, c) * _OpacityScanLine;

ステップ2: ノイズ

絵全体にノイズを走らせます。

各画素に対して乱数を割り当てます。
ランダム関数はThe Book of Shadersにて掲載されていたものを用いました。

float random (float2 st) {
    return frac(sin(dot(st.xy, float2(12.9898,78.233)))*43758.5453123);
}
...
float r = random(i.uv*_Time);
col += float3(r, r, r) * _OpacityNoise;

ステップ3: フラッシュ

絵全体をチカチカ光らせます。

これは単純にsinを使って周期的に光らせるだけです。

float flash = sin(_FlickeringSpeed*_Time);
col += float3(flash, flash, flash) * _FlickeringStrength;

コード全文

最後にコード全文載せます。

Shader "Custom/ScanLine"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _OpacityScanLine ("Opacity ScanLine", Range(0, 2)) = 0.8
        _OpacityNoise ("Opacity Noise", Range(0, 1)) = 0.1
        _FlickeringSpeed ("Flickering Speed", Range(0, 1000)) = 600
        _FlickeringStrength ("Flickering Strength", Range(0, 0.1)) = 0.02
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            float random (float2 st) {
                return frac(sin(dot(st.xy, float2(12.9898,78.233)))*43758.5453123);
            }

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

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

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

            sampler2D _MainTex;
            half _OpacityScanLine;
            half _OpacityNoise;
            half _FlickeringSpeed;
            half _FlickeringStrength; 

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 img = tex2D(_MainTex, i.uv);
                float3 col = float3(0, 0, 0);
                float s = sin(i.uv.y * 1000);
                float c = cos(i.uv.y * 1000);
                col += float3(c, s, c) * _OpacityScanLine;

                float r = random(i.uv*_Time);
                col += float3(r, r, r) * _OpacityNoise;

                float flash = sin(_FlickeringSpeed*_Time);
                col += float3(flash, flash, flash) * _FlickeringStrength;
                return img * float4(col, 1.0);
            }
            ENDCG
        }
    }
}

終わりに

shader楽しいです。

参考資料

2
1
1

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
2
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?