Unity 3 D古いテレビフィルターsharderの実現例


構想を実現する
古いテレビの後処理効果を実現するなら、古いテレビの表示効果を思い出してシミュレーションすればいいです。
1.まずあのようなプリクラテレビの一般的なスクリーンには曲率があります。完全な平面ではなく、外側に突起するのが普通です。このような突起は中間の表示領域がもとよりもっと近くなり、エッジの表示領域がもとよりもっと遠くなります。この効果を直接簡単な二次関数で実現した。
2.あの古いテレビは絶えず動き続ける騒音があります。直接騒音関数を使って時間変数を加えて実現します。
3.スクリーンにはいくつかのストライプの効果があります。このような周期的なストライプの効果は一般的に三角関数で実現されます。
もちろんシミュレーションは完全に正確ではない。完全に正確には話せませんでした。古いテレビに対する印象は人それぞれですから、私のところも印象の効果だけを実現します。
コードを実現
まず第一点を実現して、スクリーンの曲率を実現します。
この(0.5,0.5)のuv座標は実際にはスクリーンの中心点として見られます。距離を計算した後、この距離の大きさに基づいてuvをオフセットします。これには一つのパラメータ_が使われています。Expandはオフセットの距離です。
注意が必要なのはdot関数に同じベクトルを2回記入して算出したのはベクトルモードの平方であり、ベクトルのモードではないが、これはまさに私たちが必要としているものであり、平方減衰の効果を達成することができる。

 float d2 = dot(i.uv - half2(0.5, 0.5), i.uv - half2(0.5, 0.5));
        half2 coord = (i.uv - half2(0.5, 0.5)) * (_Expand + d2 * (1 - _Expand)) + half2(0.5, 0.5);
続いて,このオフセット後のuv座標を用いてテクスチャをサンプリングした。

half4 color = tex2D(_MainTex, coord);
パラメータを調整すると、画面が浮き出てくる効果があります。もちろんここでは全体の表示範囲も小さくなります。ここでは元の範囲を表示するには、必要な数式が複雑すぎて、簡単な数式を使用したためです。
原図
在这里插入图片描述
sharerを追加した後
在这里插入图片描述
次に雑音を添加して,一つの変数で雑音強度を制御し,同時に着信時間変数で雑音が常に変化する効果を得た。

   float n = simpleNoise(coord.xy * _Time.x);
   half3 result = color.rgb * (1-_NoiseIntensity) + _NoiseIntensity * n;
騒音の関数の具体的な実現は以下の通りです。
なぜこの関数は雑音を得ることができますか?実は説明しにくいです。大体sin関数が倍増した後に小数を取るfrac関数を加えて近似して1種の乱数の効果を得ることができます。

    float simpleNoise(float2 uv)
    {
        return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);
    }
効果は以下の通りです
在这里插入图片描述
最後にストライプの効果を追加します。
この公式はそれほど厳密に導き出された公式ではないですが、周期的に現れるストライプの効果が必要なので、sinとcos関数を使いたいです。適当に調整してください。

half2 sc = half2((sin(coord.y * _StripeIntensity) + 1) / 2, (cos(coord.y * _StripeIntensity) + 1) / 2);
result += color.rgb * sc.xyx;
ストライプを追加した後
在这里插入图片描述
効果2
在这里插入图片描述
完全コード
cxiコード

namespace Colorful
{
    using UnityEngine;


    [ExecuteInEditMode]
    public class OldTV : MonoBehaviour
    {
        public               Shader shader;
        [Range(0, 1)] public float  Expand          = 0.7f;
        [Range(0, 1)] public float  NoiseIntensity  = 0.3f;
        public               int    StripeIntensity = 500;


        protected void OnRenderImage(RenderTexture source, RenderTexture destination)
        {
            Material material = new Material(shader);
            material.SetFloat("_Expand", Expand);
            material.SetFloat("_NoiseIntensity", NoiseIntensity);
            material.SetInt("_StripeIntensity", StripeIntensity);
            Graphics.Blit(source, destination, material, 0);
        }
    }
}
シャダコード

Shader "LX/OldTV"
{
    Properties
    {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }

    CGINCLUDE
    #include "UnityCG.cginc"

    sampler2D _MainTex;

    float _Expand;
    float _NoiseIntensity;
    int _StripeIntensity;

    float simpleNoise(float2 uv)
    {
        return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);
    }


    half4 frag(v2f_img i) : SV_Target
    {
        float d2 = dot(i.uv - half2(0.5, 0.5), i.uv - half2(0.5, 0.5));
        half2 coord = (i.uv - half2(0.5, 0.5)) * (_Expand + d2 * (1 - _Expand)) + half2(0.5, 0.5);
        half4 color = tex2D(_MainTex, coord);

        float n = simpleNoise(coord.xy * _Time.x);
        half3 result = color.rgb * (1-_NoiseIntensity) + _NoiseIntensity * n;

        half2 sc = half2((sin(coord.y * _StripeIntensity) + 1) / 2, (cos(coord.y * _StripeIntensity) + 1) / 2);
        result += color.rgb * sc.xyx;

        return half4(result, color.a);
    }
    ENDCG

    SubShader
    {
        ZTest Always Cull Off ZWrite Off
        Fog
        {
            Mode off
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            ENDCG
        }
    }

    FallBack off
}
またコードもgithub倉庫に届きました。みなさんも注目してください。
私のgithub
ここで、Unity 3 Dテレビフィルタの実現例についての記事を紹介します。Unity 3 D古いテレビフィルターのsharderの内容については、以前の記事を検索したり、下記の関連記事を見たりしてください。これからもよろしくお願いします。