こんなやつ
3つのCubeが並んだ画面にUGUIのImageで色を上乗せしています。
カラーフィルムっぽい表現にはシェーダを利用しており、このImageにシェーダを適用したマテリアルを追加しています。
環境
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を用いたアプリを現在開発しており、本記事のカラーフィルムっぽい表現を随所で使用しています。
ついに…AppStoreで公開されました!!!
— はちゃめちゃARらくがきらんど開発 (@rakugakiland) 2018年3月9日
ARを使用した、3Dらくがきアプリです!
現在アーリーアクセス価格となっております!是非とも遊んでみてください!#ARKit #AppStore #iOS #madewithunity https://t.co/vKZwm7SWHa