Unity インターレースなラインでホログラム風の表現ができるシェーダ


最近必要に迫られてUnityを始めました。
正確にいえば、バージョン3.5くらいの頃少し扱っていたんですが、あのDirectorを思い出させる開発環境になじめず途中で放棄していましたw
と、前置きはこれくらいにして、今回はUnityでカスタムシェーダを作成しての昭和のホログラム風表現です。

今回は適当なモデルもなかったので、ソースをいろいろ見て勉強させていただいていたユニティちゃんステージのユニティちゃん(Candy Rock Star)に登場していただきました。

このインターレース風のラインのシェーダですが、ポストエフェクト用シェーダとして作成しました。
シェーダ部分のソースはこんな感じ。

CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag

#include "UnityCG.cginc"

float _R;
float _G;
float _B;
float _Speed;
float _Power;
float _Density;
sampler2D _MainTex;

fixed4 frag (v2f_img i) : SV_Target
{
   	float4 tex = tex2D(_MainTex, i.uv);
   	fixed2 resolution = _ScreenParams;
    fixed2 position = (i.uv*resolution / resolution.xy );
    fixed stripe = 0.0;
    float time = _Time * _Speed;

	stripe += sin( position.y * cos(time) * 10) + cos( position.y * _Density);
	stripe *= sin( time ) * _Power;

    return tex + fixed4(_R * stripe, _G * stripe, _B * stripe, 1);
}
ENDCG

ラインを作る部分は sin( position.y * cos(time) * 10) + cos( position.y * _Density) なんですが、この position.y を position.x に変えると縦のラインになります。
設定した時間で cos を使ってラインの暗部を上下に揺らして変化させています。
最初の position.y を position.x に変えると暗部の揺れが左右に変わります。

次に、この記事 を参考にしてポストエフェクト用のスクリプトを作成しました。

このポストエフェクト用のスクリプトですが、まずは上記の記事をよく読んで内容を理解したら、この記事にある
CustomImageEffect と同様の基本クラスを作成します。
CustomImageEffect クラスを作成したら、CustomImageEffect を拡張して先ほどのシェーダ用のポストエフェクトスクリプトを作成します。

using UnityEngine;

public class InterlaceLineEffect : CustomImageEffect
{
	[SerializeField]
	[Range(0, 1)]
	public float red;
	[SerializeField]
	[Range(0, 1)]
	public float green;
	[SerializeField]
	[Range(0, 1)]
	public float blue;
	[SerializeField]
	[Range(0, 300)]
	public float speed;
	[SerializeField]
	[Range(0, 1)]
	public float power;
	[SerializeField]
	[Range(100, 1000)]
	public float density;

	public override string ShaderName
	{
		get { return "Custom/InterlaceLine"; }
	}

	protected override void UpdateMaterial()
	{
		Material.SetFloat("_R", red);
		Material.SetFloat("_G", green);
		Material.SetFloat("_B", blue);
		Material.SetFloat("_Speed", speed);
		Material.SetFloat("_Power", power);
		Material.SetFloat("_Density", density);
	}
}

ここまで出来たらあとは、このポストエフェクトをカメラにくっつけて、ブルームなどのイメージエフェクトで調整します。

透明リムライトシェーダのモデルを配置したコンテンツに適用した例

動画の例ではよりホログラム風に見えるように画面からの出力映像をCDケースに反射させていますが、キャラクターのマテリアルををリムライトがついた半透明シェーダなどにすると画面上でもそれっぽく見せることはできますね。

今回参考にさせていただいた記事:http://www.f-sp.com/entry/2015/08/11/185815

—– 2017.03.08 追記 —–

上記のようなケースで自作シェーダを使用する場合、シーンで使用しているマテリアルに自作シェーダを適用している場合はいいのですが、ポストエフェクトのようにスクリプトからシェーダを Find してマテリアルに適用させる場合は、Unityエディタでのプレビューではシェーダが適用されているけど、ビルドするとシェーダが適用されていない事象が発生します。
その場合は、ここ https://docs.unity3d.com/jp/540/Manual/class-GraphicsSettings.html にあるように、Graphics Settings > Always Included Shaders に自作シェーダを登録すれば大丈夫です。


この作品はユニティちゃんライセンス条項の元に提供されています。