5
4

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 5 years have passed since last update.

UGUIとシェーダでカラーフィルムっぽい表現

Last updated at Posted at 2018-03-12

こんなやつ

3つのCubeが並んだ画面にUGUIのImageで色を上乗せしています。
カラーフィルムっぽい表現にはシェーダを利用しており、このImageにシェーダを適用したマテリアルを追加しています。
スクリーンショット 2018-02-21 12.06.33.png
スクリーンショット 2018-02-21 12.24.42.png

Imageにスプライトを適用してあげるとこんな感じ
スクリーンショット 2018-02-21 12.22.42.png

環境

Unity2017.3.1f1
iOSでも動作確認しています。

やってること

Spriteの背景となっている画に対してコントラストの調整とSprite画像の乗算を行って表示しています。

背景の画を取ってくる

シェーダで背景の画を取ってくる場合は、GrabPassをSubShader内に記述し、CGPROGRAM~ENDCG内に**_GrabTexture**を宣言します。

SubShader
{
  GrabPass {}

  Pass
  {
    CGPROGRAM
    ...
    sampler2D _GrabTexture;
    ...
    ENDCG
  }
}

この様な感じで使うのですが、TsumikiTechTimes様のこちらの記事で詳しく書かれていますので詳細は割愛します。

コントラストを調整する

GrabPassで取得した背景の画にコントラスト調整の計算を加えてあげるだけです。
おもちゃラボ様のこちらの記事を参考にさせて頂きました。

Properties 
{
...
  _Contrast ("Contrast", Range(1, 20)) = 10
}

fixed4 frag(v2f i) : SV_Target
{
  ...
  float2 grabUV = float2(i.screenPos.xy / i.screenPos.w);
  grabUV.y = grabUV.y * -1 + 1;

  fixed4 grab = tex2D(_GrabTexture, grabUV);

  half4 cont = 1 / (1 + exp(-_Contrast * (grab - 0.5)));
  ...
}

UI-Defaultシェーダを改造する

あとはこれらの処理をUI-Defaultシェーダに書き加えてあげるだけで完成です。

Shader "UI/Film" 
{
	Properties 
	{
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
		_Contrast ("Contrast", Range(1, 20)) = 10

        _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
	}

	CGINCLUDE
	#include "UnityCG.cginc"
	#include "UnityUI.cginc"

	#pragma multi_compile __ UNITY_UI_CLIP_RECT
    #pragma multi_compile __ UNITY_UI_ALPHACLIP

	sampler2D _GrabTexture;

    sampler2D _MainTex;
    fixed4 _Color;
    fixed4 _TextureSampleAdd;
    float4 _ClipRect;

	float _Contrast;

    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;
		float4 screenPos : TEXCOORD2;
        UNITY_VERTEX_OUTPUT_STEREO
    };

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

        OUT.texcoord = v.texcoord;

        OUT.color = v.color * _Color;

		OUT.screenPos = ComputeScreenPos(OUT.vertex);
        return OUT;
    }

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

		float2 grabUV = float2(i.screenPos.xy / i.screenPos.w);
		grabUV.y = grabUV.y * -1 + 1;

		fixed4 grab = tex2D(_GrabTexture, grabUV);

		#ifdef UNITY_UI_CLIP_RECT
		color.a *= UnityGet2DClipping(i.worldPosition.xy, _ClipRect);
		#endif

		#ifdef UNITY_UI_ALPHACLIP
		clip(color.a - 0.001);
		#endif

		half4 cont = 1 / (1 + exp(-_Contrast * (grab - 0.5)));
		cont = cont * color;
		cont.a = color.a; //AlphaはSpriteのものを適用する

		return cont;
	}

	ENDCG

	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 SrcAlpha OneMinusSrcAlpha
        ColorMask [_ColorMask]

		GrabPass {}

		Pass
		{
			CGPROGRA
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
	}
	FallBack "Diffuse"
}

参考にさせて頂いたサイト

Unity シェーダーチュートリアル - Tsumiki Tech Times
http://tsumikiseisaku.com/blog/shader-tutorial-refraction/

【Unityシェーダ入門】コントラストを調節できるポストエフェクトを作る - おもちゃラボ
http://tsumikiseisaku.com/blog/shader-tutorial-refraction/

ちょっと宣伝

「はちゃめちゃAR!らくがきらんど」というARKitを用いたアプリを現在開発しており、本記事のカラーフィルムっぽい表現を随所で使用しています。

5
4
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
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?